diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 591a81f61265e..1f758b6787a9f 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1,4 +1,64 @@ import * as ts from "./_namespaces/ts"; +import { + __String, AccessExpression, addRelatedInfo, append, appendIfUnique, ArrayBindingElement, ArrayLiteralExpression, + ArrowFunction, AssignmentDeclarationKind, BinaryExpression, BinaryOperatorToken, BindableAccessExpression, + BindableObjectDefinePropertyCall, BindablePropertyAssignmentExpression, BindableStaticAccessExpression, + BindableStaticNameExpression, BindableStaticPropertyAssignmentExpression, BindingElement, Block, + BreakOrContinueStatement, CallChain, CallExpression, CaseBlock, CaseClause, cast, CatchClause, ClassLikeDeclaration, + ClassStaticBlockDeclaration, CompilerOptions, concatenate, ConditionalExpression, ConditionalTypeNode, contains, + createBinaryExpressionTrampoline, createDiagnosticForNodeInSourceFile, createFileDiagnostic, createQueue, + createSymbolTable, Debug, Declaration, declarationNameToString, DeleteExpression, DestructuringAssignment, + DiagnosticCategory, DiagnosticMessage, DiagnosticRelatedInformation, Diagnostics, DiagnosticWithLocation, + DoStatement, DynamicNamedDeclaration, ElementAccessChain, ElementAccessExpression, EntityNameExpression, + EnumDeclaration, escapeLeadingUnderscores, ESMap, every, ExportAssignment, exportAssignmentIsAlias, + ExportDeclaration, ExportSpecifier, Expression, ExpressionStatement, findAncestor, FlowFlags, FlowLabel, FlowNode, + FlowReduceLabel, forEach, forEachChild, ForInOrOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, GetAccessorDeclaration, getAssignedExpandoInitializer, getAssignmentDeclarationKind, + getAssignmentDeclarationPropertyAccessKind, getCombinedModifierFlags, getCombinedNodeFlags, getContainingClass, + getEffectiveContainerForJSDocTemplateTag, getElementOrPropertyAccessName, getEmitScriptTarget, + getEnclosingBlockScopeContainer, getErrorSpanForNode, getEscapedTextOfIdentifierOrLiteral, getExpandoInitializer, + getHostSignatureFromJSDoc, getImmediatelyInvokedFunctionExpression, getJSDocTypeTag, getLeftmostAccessExpression, + getNameOfDeclaration, getNameOrArgument, getNodeId, getRangesWhere, getRightMostAssignedExpression, + getSourceFileOfNode, getSourceTextOfNodeFromSourceFile, getSpanOfTokenAtPosition, getStrictOptionValue, + getSymbolNameForPrivateIdentifier, getTextOfIdentifierOrLiteral, getThisContainer, getTokenPosOfNode, + hasDynamicName, hasJSDocNodes, hasSyntacticModifier, Identifier, idText, IfStatement, ImportClause, + InternalSymbolName, isAliasableExpression, isAmbientModule, isAssignmentExpression, isAssignmentOperator, + isAssignmentTarget, isAsyncFunction, isAutoAccessorPropertyDeclaration, isBinaryExpression, + isBindableObjectDefinePropertyCall, isBindableStaticAccessExpression, isBindableStaticNameExpression, + isBindingPattern, isBlock, isBlockOrCatchScoped, isCallExpression, isClassStaticBlockDeclaration, + isConditionalTypeNode, isDeclaration, isDeclarationStatement, isDestructuringAssignment, isDottedName, + isElementAccessExpression, isEmptyObjectLiteral, isEntityNameExpression, isEnumConst, isEnumDeclaration, + isExportAssignment, isExportDeclaration, isExportsIdentifier, isExportSpecifier, isExpression, + isExpressionOfOptionalChainRoot, isExternalModule, isExternalOrCommonJsModule, isForInOrOfStatement, + isFunctionDeclaration, isFunctionLike, isFunctionLikeDeclaration, isFunctionLikeOrClassStaticBlockDeclaration, + isFunctionSymbol, isGlobalScopeAugmentation, isIdentifier, isIdentifierName, isInJSFile, isInTopLevelContext, + isJSDocConstructSignature, isJSDocEnumTag, isJSDocTemplateTag, isJSDocTypeAlias, isJsonSourceFile, + isLeftHandSideExpression, isLogicalOrCoalescingAssignmentOperator, isModuleAugmentationExternal, isModuleBlock, + isModuleDeclaration, isModuleExportsAccessExpression, isNamedDeclaration, isNamespaceExport, isNonNullExpression, + isNullishCoalesce, isObjectLiteralExpression, isObjectLiteralMethod, + isObjectLiteralOrClassExpressionMethodOrAccessor, isOmittedExpression, isOptionalChain, isOptionalChainRoot, + isOutermostOptionalChain, isParameterDeclaration, isParameterPropertyDeclaration, isParenthesizedExpression, + isPartOfTypeQuery, isPrefixUnaryExpression, isPrivateIdentifier, isPrologueDirective, + isPropertyAccessEntityNameExpression, isPropertyAccessExpression, isPropertyNameLiteral, isPrototypeAccess, + isPushOrUnshiftIdentifier, isRequireCall, isShorthandPropertyAssignment, isSignedNumericLiteral, isSourceFile, + isSpecialPropertyDeclaration, isStatement, isStatementButNotDeclaration, isStatic, isString, isStringLiteralLike, + isStringOrNumericLiteralLike, isThisInitializedDeclaration, isTypeAliasDeclaration, isTypeOfExpression, + isVariableDeclaration, isVariableDeclarationInitializedToBareOrAccessedRequire, isVariableStatement, + JSDocCallbackTag, JSDocClassTag, JSDocEnumTag, JSDocFunctionType, JSDocParameterTag, JSDocPropertyLikeTag, + JSDocSignature, JSDocTypedefTag, JSDocTypeLiteral, JsxAttribute, JsxAttributes, LabeledStatement, length, + LiteralLikeElementAccessExpression, Map, MappedTypeNode, MethodDeclaration, ModifierFlags, ModuleBlock, + ModuleDeclaration, Mutable, NamespaceExportDeclaration, Node, NodeArray, NodeFlags, nodeHasName, nodeIsMissing, + nodeIsPresent, NonNullChain, NonNullExpression, NumericLiteral, objectAllocator, ObjectLiteralExpression, + OptionalChain, ParameterDeclaration, ParenthesizedExpression, Pattern, PatternAmbientModule, perfLogger, + PostfixUnaryExpression, PrefixUnaryExpression, PrivateIdentifier, PropertyAccessChain, PropertyAccessExpression, + PropertyDeclaration, PropertySignature, removeFileExtension, ReturnStatement, ScriptTarget, Set, + SetAccessorDeclaration, setParent, setParentRecursive, setValueDeclaration, ShorthandPropertyAssignment, + shouldPreserveConstEnums, SignatureDeclaration, skipParentheses, sliceAfter, some, SourceFile, SpreadElement, + Statement, StringLiteral, SwitchStatement, Symbol, SymbolFlags, symbolName, SymbolTable, SyntaxKind, TextRange, + ThrowStatement, TokenFlags, tokenToString, tracing, TracingNode, tryCast, tryParsePattern, TryStatement, + TypeLiteralNode, TypeOfExpression, TypeParameterDeclaration, unescapeLeadingUnderscores, unreachableCodeIsError, + unusedLabelIsError, VariableDeclaration, WhileStatement, WithStatement, +} from "./_namespaces/ts"; /** @internal */ export const enum ModuleInstanceState { @@ -9,24 +69,24 @@ export const enum ModuleInstanceState { interface ActiveLabel { next: ActiveLabel | undefined; - name: ts.__String; - breakTarget: ts.FlowLabel; - continueTarget: ts.FlowLabel | undefined; + name: __String; + breakTarget: FlowLabel; + continueTarget: FlowLabel | undefined; referenced: boolean; } /** @internal */ -export function getModuleInstanceState(node: ts.ModuleDeclaration, visited?: ts.ESMap): ModuleInstanceState { +export function getModuleInstanceState(node: ModuleDeclaration, visited?: ESMap): ModuleInstanceState { if (node.body && !node.body.parent) { // getModuleInstanceStateForAliasTarget needs to walk up the parent chain, so parent pointers must be set on this tree already - ts.setParent(node.body, node); - ts.setParentRecursive(node.body, /*incremental*/ false); + setParent(node.body, node); + setParentRecursive(node.body, /*incremental*/ false); } return node.body ? getModuleInstanceStateCached(node.body, visited) : ModuleInstanceState.Instantiated; } -function getModuleInstanceStateCached(node: ts.Node, visited = new ts.Map()) { - const nodeId = ts.getNodeId(node); +function getModuleInstanceStateCached(node: Node, visited = new Map()) { + const nodeId = getNodeId(node); if (visited.has(nodeId)) { return visited.get(nodeId) || ModuleInstanceState.NonInstantiated; } @@ -36,30 +96,30 @@ function getModuleInstanceStateCached(node: ts.Node, visited = new ts.Map): ModuleInstanceState { +function getModuleInstanceStateWorker(node: Node, visited: ESMap): ModuleInstanceState { // A module is uninstantiated if it contains only switch (node.kind) { // 1. interface declarations, type alias declarations - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: return ModuleInstanceState.NonInstantiated; // 2. const enum declarations - case ts.SyntaxKind.EnumDeclaration: - if (ts.isEnumConst(node as ts.EnumDeclaration)) { + case SyntaxKind.EnumDeclaration: + if (isEnumConst(node as EnumDeclaration)) { return ModuleInstanceState.ConstEnumOnly; } break; // 3. non-exported import declarations - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - if (!(ts.hasSyntacticModifier(node, ts.ModifierFlags.Export))) { + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + if (!(hasSyntacticModifier(node, ModifierFlags.Export))) { return ModuleInstanceState.NonInstantiated; } break; // 4. Export alias declarations pointing at only uninstantiated modules or things uninstantiated modules contain - case ts.SyntaxKind.ExportDeclaration: - const exportDeclaration = node as ts.ExportDeclaration; - if (!exportDeclaration.moduleSpecifier && exportDeclaration.exportClause && exportDeclaration.exportClause.kind === ts.SyntaxKind.NamedExports) { + case SyntaxKind.ExportDeclaration: + const exportDeclaration = node as ExportDeclaration; + if (!exportDeclaration.moduleSpecifier && exportDeclaration.exportClause && exportDeclaration.exportClause.kind === SyntaxKind.NamedExports) { let state = ModuleInstanceState.NonInstantiated; for (const specifier of exportDeclaration.exportClause.elements) { const specifierState = getModuleInstanceStateForAliasTarget(specifier, visited); @@ -74,9 +134,9 @@ function getModuleInstanceStateWorker(node: ts.Node, visited: ts.ESMap { + forEachChild(node, n => { const childState = getModuleInstanceStateCached(n, visited); switch (childState) { case ModuleInstanceState.NonInstantiated: @@ -91,35 +151,35 @@ function getModuleInstanceStateWorker(node: ts.Node, visited: ts.ESMap) { +function getModuleInstanceStateForAliasTarget(specifier: ExportSpecifier, visited: ESMap) { const name = specifier.propertyName || specifier.name; - let p: ts.Node | undefined = specifier.parent; + let p: Node | undefined = specifier.parent; while (p) { - if (ts.isBlock(p) || ts.isModuleBlock(p) || ts.isSourceFile(p)) { + if (isBlock(p) || isModuleBlock(p) || isSourceFile(p)) { const statements = p.statements; let found: ModuleInstanceState | undefined; for (const statement of statements) { - if (ts.nodeHasName(statement, name)) { + if (nodeHasName(statement, name)) { if (!statement.parent) { - ts.setParent(statement, p); - ts.setParentRecursive(statement, /*incremental*/ false); + setParent(statement, p); + setParentRecursive(statement, /*incremental*/ false); } const state = getModuleInstanceStateCached(statement, visited); if (found === undefined || state > found) { @@ -167,49 +227,49 @@ const enum ContainerFlags { IsObjectLiteralOrClassExpressionMethodOrAccessor = 1 << 7, } -function initFlowNode(node: T) { - ts.Debug.attachFlowNodeDebugInfo(node); +function initFlowNode(node: T) { + Debug.attachFlowNodeDebugInfo(node); return node; } const binder = createBinder(); /** @internal */ -export function bindSourceFile(file: ts.SourceFile, options: ts.CompilerOptions) { +export function bindSourceFile(file: SourceFile, options: CompilerOptions) { ts.performance.mark("beforeBind"); - ts.perfLogger.logStartBindFile("" + file.fileName); + perfLogger.logStartBindFile("" + file.fileName); binder(file, options); - ts.perfLogger.logStopBindFile(); + perfLogger.logStopBindFile(); ts.performance.mark("afterBind"); ts.performance.measure("Bind", "beforeBind", "afterBind"); } -function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => void { - let file: ts.SourceFile; - let options: ts.CompilerOptions; - let languageVersion: ts.ScriptTarget; - let parent: ts.Node; - let container: ts.Node; - let thisParentContainer: ts.Node; // Container one level up - let blockScopeContainer: ts.Node; - let lastContainer: ts.Node; - let delayedTypeAliases: (ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocEnumTag)[]; +function createBinder(): (file: SourceFile, options: CompilerOptions) => void { + let file: SourceFile; + let options: CompilerOptions; + let languageVersion: ScriptTarget; + let parent: Node; + let container: Node; + let thisParentContainer: Node; // Container one level up + let blockScopeContainer: Node; + let lastContainer: Node; + let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[]; let seenThisKeyword: boolean; // state used by control flow analysis - let currentFlow: ts.FlowNode; - let currentBreakTarget: ts.FlowLabel | undefined; - let currentContinueTarget: ts.FlowLabel | undefined; - let currentReturnTarget: ts.FlowLabel | undefined; - let currentTrueTarget: ts.FlowLabel | undefined; - let currentFalseTarget: ts.FlowLabel | undefined; - let currentExceptionTarget: ts.FlowLabel | undefined; - let preSwitchCaseFlow: ts.FlowNode | undefined; + let currentFlow: FlowNode; + let currentBreakTarget: FlowLabel | undefined; + let currentContinueTarget: FlowLabel | undefined; + let currentReturnTarget: FlowLabel | undefined; + let currentTrueTarget: FlowLabel | undefined; + let currentFalseTarget: FlowLabel | undefined; + let currentExceptionTarget: FlowLabel | undefined; + let preSwitchCaseFlow: FlowNode | undefined; let activeLabelList: ActiveLabel | undefined; let hasExplicitReturn: boolean; // state used for emit helpers - let emitFlags: ts.NodeFlags; + let emitFlags: NodeFlags; // If this file is an external module, then it is automatically in strict-mode according to // ES6. If it is not an external module, then we'll determine if it is in strict mode or @@ -222,11 +282,11 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v let symbolCount = 0; - let Symbol: new (flags: ts.SymbolFlags, name: ts.__String) => ts.Symbol; - let classifiableNames: ts.Set; + let Symbol: new (flags: SymbolFlags, name: __String) => Symbol; + let classifiableNames: Set<__String>; - const unreachableFlow: ts.FlowNode = { flags: ts.FlowFlags.Unreachable }; - const reportedUnreachableFlow: ts.FlowNode = { flags: ts.FlowFlags.Unreachable }; + const unreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; + const reportedUnreachableFlow: FlowNode = { flags: FlowFlags.Unreachable }; const bindBinaryExpressionFlow = createBindBinaryExpressionFlow(); /** @@ -234,28 +294,28 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v * If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node) * This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations. */ - function createDiagnosticForNode(node: ts.Node, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): ts.DiagnosticWithLocation { - return ts.createDiagnosticForNodeInSourceFile(ts.getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2); + function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation { + return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2); } - function bindSourceFile(f: ts.SourceFile, opts: ts.CompilerOptions) { + function bindSourceFile(f: SourceFile, opts: CompilerOptions) { file = f; options = opts; - languageVersion = ts.getEmitScriptTarget(options); + languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = new ts.Set(); + classifiableNames = new Set(); symbolCount = 0; - Symbol = ts.objectAllocator.getSymbolConstructor(); + Symbol = objectAllocator.getSymbolConstructor(); // Attach debugging information if necessary - ts.Debug.attachFlowNodeDebugInfo(unreachableFlow); - ts.Debug.attachFlowNodeDebugInfo(reportedUnreachableFlow); + Debug.attachFlowNodeDebugInfo(unreachableFlow); + Debug.attachFlowNodeDebugInfo(reportedUnreachableFlow); if (!file.locals) { - ts.tracing?.push(ts.tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true); + tracing?.push(tracing.Phase.Bind, "bindSourceFile", { path: file.path }, /*separateBeginAndEnd*/ true); bind(file); - ts.tracing?.pop(); + tracing?.pop(); file.symbolCount = symbolCount; file.classifiableNames = classifiableNames; delayedBindJSDocTypedefTag(); @@ -281,13 +341,13 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v activeLabelList = undefined; hasExplicitReturn = false; inAssignmentPattern = false; - emitFlags = ts.NodeFlags.None; + emitFlags = NodeFlags.None; } return bindSourceFile; - function bindInStrictMode(file: ts.SourceFile, opts: ts.CompilerOptions): boolean { - if (ts.getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { + function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean { + if (getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { // bind in strict mode source files with alwaysStrict option return true; } @@ -296,112 +356,112 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function createSymbol(flags: ts.SymbolFlags, name: ts.__String): ts.Symbol { + function createSymbol(flags: SymbolFlags, name: __String): Symbol { symbolCount++; return new Symbol(flags, name); } - function addDeclarationToSymbol(symbol: ts.Symbol, node: ts.Declaration, symbolFlags: ts.SymbolFlags) { + function addDeclarationToSymbol(symbol: Symbol, node: Declaration, symbolFlags: SymbolFlags) { symbol.flags |= symbolFlags; node.symbol = symbol; - symbol.declarations = ts.appendIfUnique(symbol.declarations, node); + symbol.declarations = appendIfUnique(symbol.declarations, node); - if (symbolFlags & (ts.SymbolFlags.Class | ts.SymbolFlags.Enum | ts.SymbolFlags.Module | ts.SymbolFlags.Variable) && !symbol.exports) { - symbol.exports = ts.createSymbolTable(); + if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) { + symbol.exports = createSymbolTable(); } - if (symbolFlags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface | ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.ObjectLiteral) && !symbol.members) { - symbol.members = ts.createSymbolTable(); + if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && !symbol.members) { + symbol.members = createSymbolTable(); } // On merge of const enum module with class or function, reset const enum only flag (namespaces will already recalculate) - if (symbol.constEnumOnlyModule && (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Class | ts.SymbolFlags.RegularEnum))) { + if (symbol.constEnumOnlyModule && (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) { symbol.constEnumOnlyModule = false; } - if (symbolFlags & ts.SymbolFlags.Value) { - ts.setValueDeclaration(symbol, node); + if (symbolFlags & SymbolFlags.Value) { + setValueDeclaration(symbol, node); } } // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. - function getDeclarationName(node: ts.Declaration): ts.__String | undefined { - if (node.kind === ts.SyntaxKind.ExportAssignment) { - return (node as ts.ExportAssignment).isExportEquals ? ts.InternalSymbolName.ExportEquals : ts.InternalSymbolName.Default; + function getDeclarationName(node: Declaration): __String | undefined { + if (node.kind === SyntaxKind.ExportAssignment) { + return (node as ExportAssignment).isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; } - const name = ts.getNameOfDeclaration(node); + const name = getNameOfDeclaration(node); if (name) { - if (ts.isAmbientModule(node)) { - const moduleName = ts.getTextOfIdentifierOrLiteral(name as ts.Identifier | ts.StringLiteral); - return (ts.isGlobalScopeAugmentation(node as ts.ModuleDeclaration) ? "__global" : `"${moduleName}"`) as ts.__String; + if (isAmbientModule(node)) { + const moduleName = getTextOfIdentifierOrLiteral(name as Identifier | StringLiteral); + return (isGlobalScopeAugmentation(node as ModuleDeclaration) ? "__global" : `"${moduleName}"`) as __String; } - if (name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (name.kind === SyntaxKind.ComputedPropertyName) { const nameExpression = name.expression; // treat computed property names where expression is string/numeric literal as just string/numeric literal - if (ts.isStringOrNumericLiteralLike(nameExpression)) { - return ts.escapeLeadingUnderscores(nameExpression.text); + if (isStringOrNumericLiteralLike(nameExpression)) { + return escapeLeadingUnderscores(nameExpression.text); } - if (ts.isSignedNumericLiteral(nameExpression)) { - return ts.tokenToString(nameExpression.operator) + nameExpression.operand.text as ts.__String; + if (isSignedNumericLiteral(nameExpression)) { + return tokenToString(nameExpression.operator) + nameExpression.operand.text as __String; } else { - ts.Debug.fail("Only computed properties with literal names have declaration names"); + Debug.fail("Only computed properties with literal names have declaration names"); } } - if (ts.isPrivateIdentifier(name)) { + if (isPrivateIdentifier(name)) { // containingClass exists because private names only allowed inside classes - const containingClass = ts.getContainingClass(node); + const containingClass = getContainingClass(node); if (!containingClass) { // we can get here in cases where there is already a parse error. return undefined; } const containingClassSymbol = containingClass.symbol; - return ts.getSymbolNameForPrivateIdentifier(containingClassSymbol, name.escapedText); + return getSymbolNameForPrivateIdentifier(containingClassSymbol, name.escapedText); } - return ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; + return isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } switch (node.kind) { - case ts.SyntaxKind.Constructor: - return ts.InternalSymbolName.Constructor; - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.JSDocSignature: - return ts.InternalSymbolName.Call; - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ConstructSignature: - return ts.InternalSymbolName.New; - case ts.SyntaxKind.IndexSignature: - return ts.InternalSymbolName.Index; - case ts.SyntaxKind.ExportDeclaration: - return ts.InternalSymbolName.ExportStar; - case ts.SyntaxKind.SourceFile: + case SyntaxKind.Constructor: + return InternalSymbolName.Constructor; + case SyntaxKind.FunctionType: + case SyntaxKind.CallSignature: + case SyntaxKind.JSDocSignature: + return InternalSymbolName.Call; + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + return InternalSymbolName.New; + case SyntaxKind.IndexSignature: + return InternalSymbolName.Index; + case SyntaxKind.ExportDeclaration: + return InternalSymbolName.ExportStar; + case SyntaxKind.SourceFile: // json file should behave as // module.exports = ... - return ts.InternalSymbolName.ExportEquals; - case ts.SyntaxKind.BinaryExpression: - if (ts.getAssignmentDeclarationKind(node as ts.BinaryExpression) === ts.AssignmentDeclarationKind.ModuleExports) { + return InternalSymbolName.ExportEquals; + case SyntaxKind.BinaryExpression: + if (getAssignmentDeclarationKind(node as BinaryExpression) === AssignmentDeclarationKind.ModuleExports) { // module.exports = ... - return ts.InternalSymbolName.ExportEquals; + return InternalSymbolName.ExportEquals; } - ts.Debug.fail("Unknown binary declaration kind"); + Debug.fail("Unknown binary declaration kind"); break; - case ts.SyntaxKind.JSDocFunctionType: - return (ts.isJSDocConstructSignature(node) ? ts.InternalSymbolName.New : ts.InternalSymbolName.Call); - case ts.SyntaxKind.Parameter: + case SyntaxKind.JSDocFunctionType: + return (isJSDocConstructSignature(node) ? InternalSymbolName.New : InternalSymbolName.Call); + case SyntaxKind.Parameter: // Parameters with names are handled at the top of this function. Parameters // without names can only come from JSDocFunctionTypes. - ts.Debug.assert(node.parent.kind === ts.SyntaxKind.JSDocFunctionType, "Impossible parameter parent kind", () => `parent is: ${ts.Debug.formatSyntaxKind(node.parent.kind)}, expected JSDocFunctionType`); - const functionType = node.parent as ts.JSDocFunctionType; - const index = functionType.parameters.indexOf(node as ts.ParameterDeclaration); - return "arg" + index as ts.__String; + Debug.assert(node.parent.kind === SyntaxKind.JSDocFunctionType, "Impossible parameter parent kind", () => `parent is: ${Debug.formatSyntaxKind(node.parent.kind)}, expected JSDocFunctionType`); + const functionType = node.parent as JSDocFunctionType; + const index = functionType.parameters.indexOf(node as ParameterDeclaration); + return "arg" + index as __String; } } - function getDisplayName(node: ts.Declaration): string { - return ts.isNamedDeclaration(node) ? ts.declarationNameToString(node.name) : ts.unescapeLeadingUnderscores(ts.Debug.checkDefined(getDeclarationName(node))); + function getDisplayName(node: Declaration): string { + return isNamedDeclaration(node) ? declarationNameToString(node.name) : unescapeLeadingUnderscores(Debug.checkDefined(getDeclarationName(node))); } /** @@ -412,19 +472,19 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. */ - function declareSymbol(symbolTable: ts.SymbolTable, parent: ts.Symbol | undefined, node: ts.Declaration, includes: ts.SymbolFlags, excludes: ts.SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): ts.Symbol { - ts.Debug.assert(isComputedName || !ts.hasDynamicName(node)); + function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): Symbol { + Debug.assert(isComputedName || !hasDynamicName(node)); - const isDefaultExport = ts.hasSyntacticModifier(node, ts.ModifierFlags.Default) || ts.isExportSpecifier(node) && node.name.escapedText === "default"; + const isDefaultExport = hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node) && node.name.escapedText === "default"; // The exported symbol for an export default function/class node is always named "default" - const name = isComputedName ? ts.InternalSymbolName.Computed - : isDefaultExport && parent ? ts.InternalSymbolName.Default + const name = isComputedName ? InternalSymbolName.Computed + : isDefaultExport && parent ? InternalSymbolName.Default : getDeclarationName(node); - let symbol: ts.Symbol | undefined; + let symbol: Symbol | undefined; if (name === undefined) { - symbol = createSymbol(ts.SymbolFlags.None, ts.InternalSymbolName.Missing); + symbol = createSymbol(SymbolFlags.None, InternalSymbolName.Missing); } else { // Check and see if the symbol table already has a symbol with this name. If not, @@ -452,12 +512,12 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // just add this node into the declarations list of the symbol. symbol = symbolTable.get(name); - if (includes & ts.SymbolFlags.Classifiable) { + if (includes & SymbolFlags.Classifiable) { classifiableNames.add(name); } if (!symbol) { - symbolTable.set(name, symbol = createSymbol(ts.SymbolFlags.None, name)); + symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); if (isReplaceableByMethod) symbol.isReplaceableByMethod = true; } else if (isReplaceableByMethod && !symbol.isReplaceableByMethod) { @@ -468,32 +528,32 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v if (symbol.isReplaceableByMethod) { // Javascript constructor-declared symbols can be discarded in favor of // prototype symbols like methods. - symbolTable.set(name, symbol = createSymbol(ts.SymbolFlags.None, name)); + symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name)); } - else if (!(includes & ts.SymbolFlags.Variable && symbol.flags & ts.SymbolFlags.Assignment)) { + else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.Assignment)) { // Assignment declarations are allowed to merge with variables, no matter what other flags they have. - if (ts.isNamedDeclaration(node)) { - ts.setParent(node.name, node); + if (isNamedDeclaration(node)) { + setParent(node.name, node); } // Report errors every position with duplicate declaration // Report errors on previous encountered declarations - let message = symbol.flags & ts.SymbolFlags.BlockScopedVariable - ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; + let message = symbol.flags & SymbolFlags.BlockScopedVariable + ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; let messageNeedsName = true; - if (symbol.flags & ts.SymbolFlags.Enum || includes & ts.SymbolFlags.Enum) { - message = ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; + if (symbol.flags & SymbolFlags.Enum || includes & SymbolFlags.Enum) { + message = Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations; messageNeedsName = false; } let multipleDefaultExports = false; - if (ts.length(symbol.declarations)) { + if (length(symbol.declarations)) { // If the current node is a default export of some sort, then check if // there are any other default exports that we need to error on. // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set. if (isDefaultExport) { - message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; + message = Diagnostics.A_module_cannot_have_multiple_default_exports; messageNeedsName = false; multipleDefaultExports = true; } @@ -503,43 +563,43 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) if (symbol.declarations && symbol.declarations.length && - (node.kind === ts.SyntaxKind.ExportAssignment && !(node as ts.ExportAssignment).isExportEquals)) { - message = ts.Diagnostics.A_module_cannot_have_multiple_default_exports; + (node.kind === SyntaxKind.ExportAssignment && !(node as ExportAssignment).isExportEquals)) { + message = Diagnostics.A_module_cannot_have_multiple_default_exports; messageNeedsName = false; multipleDefaultExports = true; } } } - const relatedInformation: ts.DiagnosticRelatedInformation[] = []; - if (ts.isTypeAliasDeclaration(node) && ts.nodeIsMissing(node.type) && ts.hasSyntacticModifier(node, ts.ModifierFlags.Export) && symbol.flags & (ts.SymbolFlags.Alias | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace)) { + const relatedInformation: DiagnosticRelatedInformation[] = []; + if (isTypeAliasDeclaration(node) && nodeIsMissing(node.type) && hasSyntacticModifier(node, ModifierFlags.Export) && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace)) { // export type T; - may have meant export type { T }? - relatedInformation.push(createDiagnosticForNode(node, ts.Diagnostics.Did_you_mean_0, `export type { ${ts.unescapeLeadingUnderscores(node.name.escapedText)} }`)); + relatedInformation.push(createDiagnosticForNode(node, Diagnostics.Did_you_mean_0, `export type { ${unescapeLeadingUnderscores(node.name.escapedText)} }`)); } - const declarationName = ts.getNameOfDeclaration(node) || node; - ts.forEach(symbol.declarations, (declaration, index) => { - const decl = ts.getNameOfDeclaration(declaration) || declaration; + const declarationName = getNameOfDeclaration(node) || node; + forEach(symbol.declarations, (declaration, index) => { + const decl = getNameOfDeclaration(declaration) || declaration; const diag = createDiagnosticForNode(decl, message, messageNeedsName ? getDisplayName(declaration) : undefined); file.bindDiagnostics.push( - multipleDefaultExports ? ts.addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? ts.Diagnostics.Another_export_default_is_here : ts.Diagnostics.and_here)) : diag + multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag ); if (multipleDefaultExports) { - relatedInformation.push(createDiagnosticForNode(decl, ts.Diagnostics.The_first_export_default_is_here)); + relatedInformation.push(createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here)); } }); const diag = createDiagnosticForNode(declarationName, message, messageNeedsName ? getDisplayName(node) : undefined); - file.bindDiagnostics.push(ts.addRelatedInfo(diag, ...relatedInformation)); + file.bindDiagnostics.push(addRelatedInfo(diag, ...relatedInformation)); - symbol = createSymbol(ts.SymbolFlags.None, name); + symbol = createSymbol(SymbolFlags.None, name); } } } addDeclarationToSymbol(symbol, node, includes); if (symbol.parent) { - ts.Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one"); + Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one"); } else { symbol.parent = parent; @@ -548,10 +608,10 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return symbol; } - function declareModuleMember(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags): ts.Symbol { - const hasExportModifier = !!(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) || jsdocTreatAsExported(node); - if (symbolFlags & ts.SymbolFlags.Alias) { - if (node.kind === ts.SyntaxKind.ExportSpecifier || (node.kind === ts.SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { + function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol { + const hasExportModifier = !!(getCombinedModifierFlags(node) & ModifierFlags.Export) || jsdocTreatAsExported(node); + if (symbolFlags & SymbolFlags.Alias) { + if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); } else { @@ -574,12 +634,12 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // during global merging in the checker. Why? The only case when ambient module is permitted inside another module is module augmentation // and this case is specially handled. Module augmentations should only be merged with original module definition // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. - if (ts.isJSDocTypeAlias(node)) ts.Debug.assert(ts.isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. - if (!ts.isAmbientModule(node) && (hasExportModifier || container.flags & ts.NodeFlags.ExportContext)) { - if (!container.locals || (ts.hasSyntacticModifier(node, ts.ModifierFlags.Default) && !getDeclarationName(node))) { + if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. + if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) { + if (!container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } - const exportKind = symbolFlags & ts.SymbolFlags.Value ? ts.SymbolFlags.ExportValue : 0; + const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); node.localSymbol = local; @@ -591,19 +651,19 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function jsdocTreatAsExported(node: ts.Node) { - if (node.parent && ts.isModuleDeclaration(node)) { + function jsdocTreatAsExported(node: Node) { + if (node.parent && isModuleDeclaration(node)) { node = node.parent; } - if (!ts.isJSDocTypeAlias(node)) return false; + if (!isJSDocTypeAlias(node)) return false; // jsdoc typedef handling is a bit of a doozy, but to summarize, treat the typedef as exported if: // 1. It has an explicit name (since by default typedefs are always directly exported, either at the top level or in a container), or - if (!ts.isJSDocEnumTag(node) && !!node.fullName) return true; + if (!isJSDocEnumTag(node) && !!node.fullName) return true; // 2. The thing a nameless typedef pulls its name from is implicitly a direct export (either by assignment or actual export flag). - const declName = ts.getNameOfDeclaration(node); + const declName = getNameOfDeclaration(node); if (!declName) return false; - if (ts.isPropertyAccessEntityNameExpression(declName.parent) && isTopLevelNamespaceAssignment(declName.parent)) return true; - if (ts.isDeclaration(declName.parent) && ts.getCombinedModifierFlags(declName.parent) & ts.ModifierFlags.Export) return true; + if (isPropertyAccessEntityNameExpression(declName.parent) && isTopLevelNamespaceAssignment(declName.parent)) return true; + if (isDeclaration(declName.parent) && getCombinedModifierFlags(declName.parent) & ModifierFlags.Export) return true; // This could potentially be simplified by having `delayedBindJSDocTypedefTag` pass in an override for `hasExportModifier`, since it should // already have calculated and branched on most of this. return false; @@ -612,7 +672,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // All container nodes are kept on a linked list in declaration order. This list is used by // the getLocalNameOfContainer function in the type checker to validate that the local name // used for a container is unique. - function bindContainer(node: ts.Mutable, containerFlags: ContainerFlags) { + function bindContainer(node: Mutable, containerFlags: ContainerFlags) { // Before we recurse into a node's children, we first save the existing parent, container // and block-container. Then after we pop out of processing the children, we restore // these saved values. @@ -638,12 +698,12 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // for it. We must clear this so we don't accidentally move any stale data forward from // a previous compilation. if (containerFlags & ContainerFlags.IsContainer) { - if (node.kind !== ts.SyntaxKind.ArrowFunction) { + if (node.kind !== SyntaxKind.ArrowFunction) { thisParentContainer = container; } container = blockScopeContainer = node; if (containerFlags & ContainerFlags.HasLocals) { - container.locals = ts.createSymbolTable(); + container.locals = createSymbolTable(); } addToContainerChain(container); } @@ -661,21 +721,21 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v const saveHasExplicitReturn = hasExplicitReturn; const isImmediatelyInvoked = (containerFlags & ContainerFlags.IsFunctionExpression && - !ts.hasSyntacticModifier(node, ts.ModifierFlags.Async) && - !(node as ts.FunctionLikeDeclaration).asteriskToken && - !!ts.getImmediatelyInvokedFunctionExpression(node)) || - node.kind === ts.SyntaxKind.ClassStaticBlockDeclaration; + !hasSyntacticModifier(node, ModifierFlags.Async) && + !(node as FunctionLikeDeclaration).asteriskToken && + !!getImmediatelyInvokedFunctionExpression(node)) || + node.kind === SyntaxKind.ClassStaticBlockDeclaration; // A non-async, non-generator IIFE is considered part of the containing control flow. Return statements behave // similarly to break statements that exit to a label just past the statement body. if (!isImmediatelyInvoked) { - currentFlow = initFlowNode({ flags: ts.FlowFlags.Start }); + currentFlow = initFlowNode({ flags: FlowFlags.Start }); if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor)) { - currentFlow.node = node as ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration; + currentFlow.node = node as FunctionExpression | ArrowFunction | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration; } } // We create a return control flow graph for IIFEs and constructors. For constructors // we use the return control flow graph in strict property initialization checks. - currentReturnTarget = isImmediatelyInvoked || node.kind === ts.SyntaxKind.Constructor || (ts.isInJSFile(node) && (node.kind === ts.SyntaxKind.FunctionDeclaration || node.kind === ts.SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined; + currentReturnTarget = isImmediatelyInvoked || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined; currentExceptionTarget = undefined; currentBreakTarget = undefined; currentContinueTarget = undefined; @@ -683,22 +743,22 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v hasExplicitReturn = false; bindChildren(node); // Reset all reachability check related flags on node (for incremental scenarios) - node.flags &= ~ts.NodeFlags.ReachabilityAndEmitFlags; - if (!(currentFlow.flags & ts.FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && ts.nodeIsPresent((node as ts.FunctionLikeDeclaration | ts.ClassStaticBlockDeclaration).body)) { - node.flags |= ts.NodeFlags.HasImplicitReturn; - if (hasExplicitReturn) node.flags |= ts.NodeFlags.HasExplicitReturn; - (node as ts.FunctionLikeDeclaration | ts.ClassStaticBlockDeclaration).endFlowNode = currentFlow; + node.flags &= ~NodeFlags.ReachabilityAndEmitFlags; + if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).body)) { + node.flags |= NodeFlags.HasImplicitReturn; + if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn; + (node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).endFlowNode = currentFlow; } - if (node.kind === ts.SyntaxKind.SourceFile) { + if (node.kind === SyntaxKind.SourceFile) { node.flags |= emitFlags; - (node as ts.SourceFile).endFlowNode = currentFlow; + (node as SourceFile).endFlowNode = currentFlow; } if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); currentFlow = finishFlowLabel(currentReturnTarget); - if (node.kind === ts.SyntaxKind.Constructor || node.kind === ts.SyntaxKind.ClassStaticBlockDeclaration || (ts.isInJSFile(node) && (node.kind === ts.SyntaxKind.FunctionDeclaration || node.kind === ts.SyntaxKind.FunctionExpression))) { - (node as ts.FunctionLikeDeclaration | ts.ClassStaticBlockDeclaration).returnFlowNode = currentFlow; + if (node.kind === SyntaxKind.Constructor || node.kind === SyntaxKind.ClassStaticBlockDeclaration || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) { + (node as FunctionLikeDeclaration | ClassStaticBlockDeclaration).returnFlowNode = currentFlow; } } if (!isImmediatelyInvoked) { @@ -714,7 +774,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v else if (containerFlags & ContainerFlags.IsInterface) { seenThisKeyword = false; bindChildren(node); - node.flags = seenThisKeyword ? node.flags | ts.NodeFlags.ContainsThis : node.flags & ~ts.NodeFlags.ContainsThis; + node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis; } else { bindChildren(node); @@ -725,24 +785,24 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v blockScopeContainer = savedBlockScopeContainer; } - function bindEachFunctionsFirst(nodes: ts.NodeArray | undefined): void { - bindEach(nodes, n => n.kind === ts.SyntaxKind.FunctionDeclaration ? bind(n) : undefined); - bindEach(nodes, n => n.kind !== ts.SyntaxKind.FunctionDeclaration ? bind(n) : undefined); + function bindEachFunctionsFirst(nodes: NodeArray | undefined): void { + bindEach(nodes, n => n.kind === SyntaxKind.FunctionDeclaration ? bind(n) : undefined); + bindEach(nodes, n => n.kind !== SyntaxKind.FunctionDeclaration ? bind(n) : undefined); } - function bindEach(nodes: ts.NodeArray | undefined, bindFunction: (node: ts.Node) => void = bind): void { + function bindEach(nodes: NodeArray | undefined, bindFunction: (node: Node) => void = bind): void { if (nodes === undefined) { return; } - ts.forEach(nodes, bindFunction); + forEach(nodes, bindFunction); } - function bindEachChild(node: ts.Node) { - ts.forEachChild(node, bind, bindEach); + function bindEachChild(node: Node) { + forEachChild(node, bind, bindEach); } - function bindChildren(node: ts.Node): void { + function bindChildren(node: Node): void { const saveInAssignmentPattern = inAssignmentPattern; // Most nodes aren't valid in an assignment pattern, so we clear the value here // and set it before we descend into nodes that could actually be part of an assignment pattern. @@ -753,112 +813,112 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v inAssignmentPattern = saveInAssignmentPattern; return; } - if (node.kind >= ts.SyntaxKind.FirstStatement && node.kind <= ts.SyntaxKind.LastStatement && !options.allowUnreachableCode) { + if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && !options.allowUnreachableCode) { node.flowNode = currentFlow; } switch (node.kind) { - case ts.SyntaxKind.WhileStatement: - bindWhileStatement(node as ts.WhileStatement); + case SyntaxKind.WhileStatement: + bindWhileStatement(node as WhileStatement); break; - case ts.SyntaxKind.DoStatement: - bindDoStatement(node as ts.DoStatement); + case SyntaxKind.DoStatement: + bindDoStatement(node as DoStatement); break; - case ts.SyntaxKind.ForStatement: - bindForStatement(node as ts.ForStatement); + case SyntaxKind.ForStatement: + bindForStatement(node as ForStatement); break; - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - bindForInOrForOfStatement(node as ts.ForInOrOfStatement); + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + bindForInOrForOfStatement(node as ForInOrOfStatement); break; - case ts.SyntaxKind.IfStatement: - bindIfStatement(node as ts.IfStatement); + case SyntaxKind.IfStatement: + bindIfStatement(node as IfStatement); break; - case ts.SyntaxKind.ReturnStatement: - case ts.SyntaxKind.ThrowStatement: - bindReturnOrThrow(node as ts.ReturnStatement | ts.ThrowStatement); + case SyntaxKind.ReturnStatement: + case SyntaxKind.ThrowStatement: + bindReturnOrThrow(node as ReturnStatement | ThrowStatement); break; - case ts.SyntaxKind.BreakStatement: - case ts.SyntaxKind.ContinueStatement: - bindBreakOrContinueStatement(node as ts.BreakOrContinueStatement); + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + bindBreakOrContinueStatement(node as BreakOrContinueStatement); break; - case ts.SyntaxKind.TryStatement: - bindTryStatement(node as ts.TryStatement); + case SyntaxKind.TryStatement: + bindTryStatement(node as TryStatement); break; - case ts.SyntaxKind.SwitchStatement: - bindSwitchStatement(node as ts.SwitchStatement); + case SyntaxKind.SwitchStatement: + bindSwitchStatement(node as SwitchStatement); break; - case ts.SyntaxKind.CaseBlock: - bindCaseBlock(node as ts.CaseBlock); + case SyntaxKind.CaseBlock: + bindCaseBlock(node as CaseBlock); break; - case ts.SyntaxKind.CaseClause: - bindCaseClause(node as ts.CaseClause); + case SyntaxKind.CaseClause: + bindCaseClause(node as CaseClause); break; - case ts.SyntaxKind.ExpressionStatement: - bindExpressionStatement(node as ts.ExpressionStatement); + case SyntaxKind.ExpressionStatement: + bindExpressionStatement(node as ExpressionStatement); break; - case ts.SyntaxKind.LabeledStatement: - bindLabeledStatement(node as ts.LabeledStatement); + case SyntaxKind.LabeledStatement: + bindLabeledStatement(node as LabeledStatement); break; - case ts.SyntaxKind.PrefixUnaryExpression: - bindPrefixUnaryExpressionFlow(node as ts.PrefixUnaryExpression); + case SyntaxKind.PrefixUnaryExpression: + bindPrefixUnaryExpressionFlow(node as PrefixUnaryExpression); break; - case ts.SyntaxKind.PostfixUnaryExpression: - bindPostfixUnaryExpressionFlow(node as ts.PostfixUnaryExpression); + case SyntaxKind.PostfixUnaryExpression: + bindPostfixUnaryExpressionFlow(node as PostfixUnaryExpression); break; - case ts.SyntaxKind.BinaryExpression: - if (ts.isDestructuringAssignment(node)) { + case SyntaxKind.BinaryExpression: + if (isDestructuringAssignment(node)) { // Carry over whether we are in an assignment pattern to // binary expressions that could actually be an initializer inAssignmentPattern = saveInAssignmentPattern; bindDestructuringAssignmentFlow(node); return; } - bindBinaryExpressionFlow(node as ts.BinaryExpression); + bindBinaryExpressionFlow(node as BinaryExpression); break; - case ts.SyntaxKind.DeleteExpression: - bindDeleteExpressionFlow(node as ts.DeleteExpression); + case SyntaxKind.DeleteExpression: + bindDeleteExpressionFlow(node as DeleteExpression); break; - case ts.SyntaxKind.ConditionalExpression: - bindConditionalExpressionFlow(node as ts.ConditionalExpression); + case SyntaxKind.ConditionalExpression: + bindConditionalExpressionFlow(node as ConditionalExpression); break; - case ts.SyntaxKind.VariableDeclaration: - bindVariableDeclarationFlow(node as ts.VariableDeclaration); + case SyntaxKind.VariableDeclaration: + bindVariableDeclarationFlow(node as VariableDeclaration); break; - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - bindAccessExpressionFlow(node as ts.AccessExpression); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + bindAccessExpressionFlow(node as AccessExpression); break; - case ts.SyntaxKind.CallExpression: - bindCallExpressionFlow(node as ts.CallExpression); + case SyntaxKind.CallExpression: + bindCallExpressionFlow(node as CallExpression); break; - case ts.SyntaxKind.NonNullExpression: - bindNonNullExpressionFlow(node as ts.NonNullExpression); + case SyntaxKind.NonNullExpression: + bindNonNullExpressionFlow(node as NonNullExpression); break; - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: - bindJSDocTypeAlias(node as ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocEnumTag); + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); break; // In source files and blocks, bind functions first to match hoisting that occurs at runtime - case ts.SyntaxKind.SourceFile: { - bindEachFunctionsFirst((node as ts.SourceFile).statements); - bind((node as ts.SourceFile).endOfFileToken); + case SyntaxKind.SourceFile: { + bindEachFunctionsFirst((node as SourceFile).statements); + bind((node as SourceFile).endOfFileToken); break; } - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - bindEachFunctionsFirst((node as ts.Block).statements); + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + bindEachFunctionsFirst((node as Block).statements); break; - case ts.SyntaxKind.BindingElement: - bindBindingElementFlow(node as ts.BindingElement); + case SyntaxKind.BindingElement: + bindBindingElementFlow(node as BindingElement); break; - case ts.SyntaxKind.Parameter: - bindParameterFlow(node as ts.ParameterDeclaration); + case SyntaxKind.Parameter: + bindParameterFlow(node as ParameterDeclaration); break; - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ArrayLiteralExpression: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.SpreadElement: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.SpreadElement: // Carry over whether we are in an assignment pattern of Object and Array literals // as well as their children that are valid assignment targets. inAssignmentPattern = saveInAssignmentPattern; @@ -871,42 +931,42 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v inAssignmentPattern = saveInAssignmentPattern; } - function isNarrowingExpression(expr: ts.Expression): boolean { + function isNarrowingExpression(expr: Expression): boolean { switch (expr.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PrivateIdentifier: - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return containsNarrowableReference(expr); - case ts.SyntaxKind.CallExpression: - return hasNarrowableArgument(expr as ts.CallExpression); - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.NonNullExpression: - return isNarrowingExpression((expr as ts.ParenthesizedExpression | ts.NonNullExpression).expression); - case ts.SyntaxKind.BinaryExpression: - return isNarrowingBinaryExpression(expr as ts.BinaryExpression); - case ts.SyntaxKind.PrefixUnaryExpression: - return (expr as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.ExclamationToken && isNarrowingExpression((expr as ts.PrefixUnaryExpression).operand); - case ts.SyntaxKind.TypeOfExpression: - return isNarrowingExpression((expr as ts.TypeOfExpression).expression); + case SyntaxKind.CallExpression: + return hasNarrowableArgument(expr as CallExpression); + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NonNullExpression: + return isNarrowingExpression((expr as ParenthesizedExpression | NonNullExpression).expression); + case SyntaxKind.BinaryExpression: + return isNarrowingBinaryExpression(expr as BinaryExpression); + case SyntaxKind.PrefixUnaryExpression: + return (expr as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken && isNarrowingExpression((expr as PrefixUnaryExpression).operand); + case SyntaxKind.TypeOfExpression: + return isNarrowingExpression((expr as TypeOfExpression).expression); } return false; } - function isNarrowableReference(expr: ts.Expression): boolean { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.CommaToken && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + function isNarrowableReference(expr: Expression): boolean { + return isDottedName(expr) + || (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) + || isBinaryExpression(expr) && expr.operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference(expr.right) + || isElementAccessExpression(expr) && (isStringOrNumericLiteralLike(expr.argumentExpression) || isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) + || isAssignmentExpression(expr) && isNarrowableReference(expr.left); } - function containsNarrowableReference(expr: ts.Expression): boolean { - return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); + function containsNarrowableReference(expr: Expression): boolean { + return isNarrowableReference(expr) || isOptionalChain(expr) && containsNarrowableReference(expr.expression); } - function hasNarrowableArgument(expr: ts.CallExpression) { + function hasNarrowableArgument(expr: CallExpression) { if (expr.arguments) { for (const argument of expr.arguments) { if (containsNarrowableReference(argument)) { @@ -914,89 +974,89 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } } - if (expr.expression.kind === ts.SyntaxKind.PropertyAccessExpression && - containsNarrowableReference((expr.expression as ts.PropertyAccessExpression).expression)) { + if (expr.expression.kind === SyntaxKind.PropertyAccessExpression && + containsNarrowableReference((expr.expression as PropertyAccessExpression).expression)) { return true; } return false; } - function isNarrowingTypeofOperands(expr1: ts.Expression, expr2: ts.Expression) { - return ts.isTypeOfExpression(expr1) && isNarrowableOperand(expr1.expression) && ts.isStringLiteralLike(expr2); + function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) { + return isTypeOfExpression(expr1) && isNarrowableOperand(expr1.expression) && isStringLiteralLike(expr2); } - function isNarrowingBinaryExpression(expr: ts.BinaryExpression) { + function isNarrowingBinaryExpression(expr: BinaryExpression) { switch (expr.operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.BarBarEqualsToken: - case ts.SyntaxKind.AmpersandAmpersandEqualsToken: - case ts.SyntaxKind.QuestionQuestionEqualsToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return containsNarrowableReference(expr.left); - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) || isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right); - case ts.SyntaxKind.InstanceOfKeyword: + case SyntaxKind.InstanceOfKeyword: return isNarrowableOperand(expr.left); - case ts.SyntaxKind.InKeyword: + case SyntaxKind.InKeyword: return isNarrowingExpression(expr.right); - case ts.SyntaxKind.CommaToken: + case SyntaxKind.CommaToken: return isNarrowingExpression(expr.right); } return false; } - function isNarrowableOperand(expr: ts.Expression): boolean { + function isNarrowableOperand(expr: Expression): boolean { switch (expr.kind) { - case ts.SyntaxKind.ParenthesizedExpression: - return isNarrowableOperand((expr as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.BinaryExpression: - switch ((expr as ts.BinaryExpression).operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - return isNarrowableOperand((expr as ts.BinaryExpression).left); - case ts.SyntaxKind.CommaToken: - return isNarrowableOperand((expr as ts.BinaryExpression).right); + case SyntaxKind.ParenthesizedExpression: + return isNarrowableOperand((expr as ParenthesizedExpression).expression); + case SyntaxKind.BinaryExpression: + switch ((expr as BinaryExpression).operatorToken.kind) { + case SyntaxKind.EqualsToken: + return isNarrowableOperand((expr as BinaryExpression).left); + case SyntaxKind.CommaToken: + return isNarrowableOperand((expr as BinaryExpression).right); } } return containsNarrowableReference(expr); } - function createBranchLabel(): ts.FlowLabel { - return initFlowNode({ flags: ts.FlowFlags.BranchLabel, antecedents: undefined }); + function createBranchLabel(): FlowLabel { + return initFlowNode({ flags: FlowFlags.BranchLabel, antecedents: undefined }); } - function createLoopLabel(): ts.FlowLabel { - return initFlowNode({ flags: ts.FlowFlags.LoopLabel, antecedents: undefined }); + function createLoopLabel(): FlowLabel { + return initFlowNode({ flags: FlowFlags.LoopLabel, antecedents: undefined }); } - function createReduceLabel(target: ts.FlowLabel, antecedents: ts.FlowNode[], antecedent: ts.FlowNode): ts.FlowReduceLabel { - return initFlowNode({ flags: ts.FlowFlags.ReduceLabel, target, antecedents, antecedent }); + function createReduceLabel(target: FlowLabel, antecedents: FlowNode[], antecedent: FlowNode): FlowReduceLabel { + return initFlowNode({ flags: FlowFlags.ReduceLabel, target, antecedents, antecedent }); } - function setFlowNodeReferenced(flow: ts.FlowNode) { + function setFlowNodeReferenced(flow: FlowNode) { // On first reference we set the Referenced flag, thereafter we set the Shared flag - flow.flags |= flow.flags & ts.FlowFlags.Referenced ? ts.FlowFlags.Shared : ts.FlowFlags.Referenced; + flow.flags |= flow.flags & FlowFlags.Referenced ? FlowFlags.Shared : FlowFlags.Referenced; } - function addAntecedent(label: ts.FlowLabel, antecedent: ts.FlowNode): void { - if (!(antecedent.flags & ts.FlowFlags.Unreachable) && !ts.contains(label.antecedents, antecedent)) { + function addAntecedent(label: FlowLabel, antecedent: FlowNode): void { + if (!(antecedent.flags & FlowFlags.Unreachable) && !contains(label.antecedents, antecedent)) { (label.antecedents || (label.antecedents = [])).push(antecedent); setFlowNodeReferenced(antecedent); } } - function createFlowCondition(flags: ts.FlowFlags, antecedent: ts.FlowNode, expression: ts.Expression | undefined): ts.FlowNode { - if (antecedent.flags & ts.FlowFlags.Unreachable) { + function createFlowCondition(flags: FlowFlags, antecedent: FlowNode, expression: Expression | undefined): FlowNode { + if (antecedent.flags & FlowFlags.Unreachable) { return antecedent; } if (!expression) { - return flags & ts.FlowFlags.TrueCondition ? antecedent : unreachableFlow; + return flags & FlowFlags.TrueCondition ? antecedent : unreachableFlow; } - if ((expression.kind === ts.SyntaxKind.TrueKeyword && flags & ts.FlowFlags.FalseCondition || - expression.kind === ts.SyntaxKind.FalseKeyword && flags & ts.FlowFlags.TrueCondition) && - !ts.isExpressionOfOptionalChainRoot(expression) && !ts.isNullishCoalesce(expression.parent)) { + if ((expression.kind === SyntaxKind.TrueKeyword && flags & FlowFlags.FalseCondition || + expression.kind === SyntaxKind.FalseKeyword && flags & FlowFlags.TrueCondition) && + !isExpressionOfOptionalChainRoot(expression) && !isNullishCoalesce(expression.parent)) { return unreachableFlow; } if (!isNarrowingExpression(expression)) { @@ -1006,12 +1066,12 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return initFlowNode({ flags, antecedent, node: expression }); } - function createFlowSwitchClause(antecedent: ts.FlowNode, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number): ts.FlowNode { + function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode { setFlowNodeReferenced(antecedent); - return initFlowNode({ flags: ts.FlowFlags.SwitchClause, antecedent, switchStatement, clauseStart, clauseEnd }); + return initFlowNode({ flags: FlowFlags.SwitchClause, antecedent, switchStatement, clauseStart, clauseEnd }); } - function createFlowMutation(flags: ts.FlowFlags, antecedent: ts.FlowNode, node: ts.Expression | ts.VariableDeclaration | ts.ArrayBindingElement): ts.FlowNode { + function createFlowMutation(flags: FlowFlags, antecedent: FlowNode, node: Expression | VariableDeclaration | ArrayBindingElement): FlowNode { setFlowNodeReferenced(antecedent); const result = initFlowNode({ flags, antecedent, node }); if (currentExceptionTarget) { @@ -1020,12 +1080,12 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return result; } - function createFlowCall(antecedent: ts.FlowNode, node: ts.CallExpression): ts.FlowNode { + function createFlowCall(antecedent: FlowNode, node: CallExpression): FlowNode { setFlowNodeReferenced(antecedent); - return initFlowNode({ flags: ts.FlowFlags.Call, antecedent, node }); + return initFlowNode({ flags: FlowFlags.Call, antecedent, node }); } - function finishFlowLabel(flow: ts.FlowLabel): ts.FlowNode { + function finishFlowLabel(flow: FlowLabel): FlowNode { const antecedents = flow.antecedents; if (!antecedents) { return unreachableFlow; @@ -1036,53 +1096,53 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return flow; } - function isStatementCondition(node: ts.Node) { + function isStatementCondition(node: Node) { const parent = node.parent; switch (parent.kind) { - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.DoStatement: - return (parent as ts.IfStatement | ts.WhileStatement | ts.DoStatement).expression === node; - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ConditionalExpression: - return (parent as ts.ForStatement | ts.ConditionalExpression).condition === node; + case SyntaxKind.IfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.DoStatement: + return (parent as IfStatement | WhileStatement | DoStatement).expression === node; + case SyntaxKind.ForStatement: + case SyntaxKind.ConditionalExpression: + return (parent as ForStatement | ConditionalExpression).condition === node; } return false; } - function isLogicalExpression(node: ts.Node) { + function isLogicalExpression(node: Node) { while (true) { - if (node.kind === ts.SyntaxKind.ParenthesizedExpression) { - node = (node as ts.ParenthesizedExpression).expression; + if (node.kind === SyntaxKind.ParenthesizedExpression) { + node = (node as ParenthesizedExpression).expression; } - else if (node.kind === ts.SyntaxKind.PrefixUnaryExpression && (node as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.ExclamationToken) { - node = (node as ts.PrefixUnaryExpression).operand; + else if (node.kind === SyntaxKind.PrefixUnaryExpression && (node as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken) { + node = (node as PrefixUnaryExpression).operand; } else { - return node.kind === ts.SyntaxKind.BinaryExpression && ( - (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || - (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.BarBarToken || - (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken); + return node.kind === SyntaxKind.BinaryExpression && ( + (node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || + (node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || + (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken); } } } - function isLogicalAssignmentExpression(node: ts.Node) { - node = ts.skipParentheses(node); - return ts.isBinaryExpression(node) && ts.isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind); + function isLogicalAssignmentExpression(node: Node) { + node = skipParentheses(node); + return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind); } - function isTopLevelLogicalExpression(node: ts.Node): boolean { - while (ts.isParenthesizedExpression(node.parent) || - ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === ts.SyntaxKind.ExclamationToken) { + function isTopLevelLogicalExpression(node: Node): boolean { + while (isParenthesizedExpression(node.parent) || + isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken) { node = node.parent; } return !isStatementCondition(node) && !isLogicalExpression(node.parent) && - !(ts.isOptionalChain(node.parent) && node.parent.expression === node); + !(isOptionalChain(node.parent) && node.parent.expression === node); } - function doWithConditionalBranches(action: (value: T) => void, value: T, trueTarget: ts.FlowLabel, falseTarget: ts.FlowLabel) { + function doWithConditionalBranches(action: (value: T) => void, value: T, trueTarget: FlowLabel, falseTarget: FlowLabel) { const savedTrueTarget = currentTrueTarget; const savedFalseTarget = currentFalseTarget; currentTrueTarget = trueTarget; @@ -1092,15 +1152,15 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFalseTarget = savedFalseTarget; } - function bindCondition(node: ts.Expression | undefined, trueTarget: ts.FlowLabel, falseTarget: ts.FlowLabel) { + function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(ts.isOptionalChain(node) && ts.isOutermostOptionalChain(node))) { - addAntecedent(trueTarget, createFlowCondition(ts.FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(ts.FlowFlags.FalseCondition, currentFlow, node)); + if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) { + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } } - function bindIterativeStatement(node: ts.Statement, breakTarget: ts.FlowLabel, continueTarget: ts.FlowLabel): void { + function bindIterativeStatement(node: Statement, breakTarget: FlowLabel, continueTarget: FlowLabel): void { const saveBreakTarget = currentBreakTarget; const saveContinueTarget = currentContinueTarget; currentBreakTarget = breakTarget; @@ -1110,9 +1170,9 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentContinueTarget = saveContinueTarget; } - function setContinueTarget(node: ts.Node, target: ts.FlowLabel) { + function setContinueTarget(node: Node, target: FlowLabel) { let label = activeLabelList; - while (label && node.parent.kind === ts.SyntaxKind.LabeledStatement) { + while (label && node.parent.kind === SyntaxKind.LabeledStatement) { label.continueTarget = target; label = label.next; node = node.parent; @@ -1120,7 +1180,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return target; } - function bindWhileStatement(node: ts.WhileStatement): void { + function bindWhileStatement(node: WhileStatement): void { const preWhileLabel = setContinueTarget(node, createLoopLabel()); const preBodyLabel = createBranchLabel(); const postWhileLabel = createBranchLabel(); @@ -1133,7 +1193,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postWhileLabel); } - function bindDoStatement(node: ts.DoStatement): void { + function bindDoStatement(node: DoStatement): void { const preDoLabel = createLoopLabel(); const preConditionLabel = setContinueTarget(node, createBranchLabel()); const postDoLabel = createBranchLabel(); @@ -1146,7 +1206,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postDoLabel); } - function bindForStatement(node: ts.ForStatement): void { + function bindForStatement(node: ForStatement): void { const preLoopLabel = setContinueTarget(node, createLoopLabel()); const preBodyLabel = createBranchLabel(); const postLoopLabel = createBranchLabel(); @@ -1161,18 +1221,18 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postLoopLabel); } - function bindForInOrForOfStatement(node: ts.ForInOrOfStatement): void { + function bindForInOrForOfStatement(node: ForInOrOfStatement): void { const preLoopLabel = setContinueTarget(node, createLoopLabel()); const postLoopLabel = createBranchLabel(); bind(node.expression); addAntecedent(preLoopLabel, currentFlow); currentFlow = preLoopLabel; - if (node.kind === ts.SyntaxKind.ForOfStatement) { + if (node.kind === SyntaxKind.ForOfStatement) { bind(node.awaitModifier); } addAntecedent(postLoopLabel, currentFlow); bind(node.initializer); - if (node.initializer.kind !== ts.SyntaxKind.VariableDeclarationList) { + if (node.initializer.kind !== SyntaxKind.VariableDeclarationList) { bindAssignmentTargetFlow(node.initializer); } bindIterativeStatement(node.statement, postLoopLabel, preLoopLabel); @@ -1180,7 +1240,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postLoopLabel); } - function bindIfStatement(node: ts.IfStatement): void { + function bindIfStatement(node: IfStatement): void { const thenLabel = createBranchLabel(); const elseLabel = createBranchLabel(); const postIfLabel = createBranchLabel(); @@ -1194,9 +1254,9 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postIfLabel); } - function bindReturnOrThrow(node: ts.ReturnStatement | ts.ThrowStatement): void { + function bindReturnOrThrow(node: ReturnStatement | ThrowStatement): void { bind(node.expression); - if (node.kind === ts.SyntaxKind.ReturnStatement) { + if (node.kind === SyntaxKind.ReturnStatement) { hasExplicitReturn = true; if (currentReturnTarget) { addAntecedent(currentReturnTarget, currentFlow); @@ -1205,7 +1265,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = unreachableFlow; } - function findActiveLabel(name: ts.__String) { + function findActiveLabel(name: __String) { for (let label = activeLabelList; label; label = label.next) { if (label.name === name) { return label; @@ -1214,15 +1274,15 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return undefined; } - function bindBreakOrContinueFlow(node: ts.BreakOrContinueStatement, breakTarget: ts.FlowLabel | undefined, continueTarget: ts.FlowLabel | undefined) { - const flowLabel = node.kind === ts.SyntaxKind.BreakStatement ? breakTarget : continueTarget; + function bindBreakOrContinueFlow(node: BreakOrContinueStatement, breakTarget: FlowLabel | undefined, continueTarget: FlowLabel | undefined) { + const flowLabel = node.kind === SyntaxKind.BreakStatement ? breakTarget : continueTarget; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; } } - function bindBreakOrContinueStatement(node: ts.BreakOrContinueStatement): void { + function bindBreakOrContinueStatement(node: BreakOrContinueStatement): void { bind(node.label); if (node.label) { const activeLabel = findActiveLabel(node.label.escapedText); @@ -1236,7 +1296,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindTryStatement(node: ts.TryStatement): void { + function bindTryStatement(node: TryStatement): void { // We conservatively assume that *any* code in the try block can cause an exception, but we only need // to track code that causes mutations (because only mutations widen the possible control flow type of // a variable). The exceptionLabel is the target label for control flows that result from exceptions. @@ -1285,10 +1345,10 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // set of antecedents for the pre-finally label. As control flow analysis passes by a ReduceLabel // node, the pre-finally label is temporarily switched to the reduced antecedent set. const finallyLabel = createBranchLabel(); - finallyLabel.antecedents = ts.concatenate(ts.concatenate(normalExitLabel.antecedents, exceptionLabel.antecedents), returnLabel.antecedents); + finallyLabel.antecedents = concatenate(concatenate(normalExitLabel.antecedents, exceptionLabel.antecedents), returnLabel.antecedents); currentFlow = finallyLabel; bind(node.finallyBlock); - if (currentFlow.flags & ts.FlowFlags.Unreachable) { + if (currentFlow.flags & FlowFlags.Unreachable) { // If the end of the finally block is unreachable, the end of the entire try statement is unreachable. currentFlow = unreachableFlow; } @@ -1314,7 +1374,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindSwitchStatement(node: ts.SwitchStatement): void { + function bindSwitchStatement(node: SwitchStatement): void { const postSwitchLabel = createBranchLabel(); bind(node.expression); const saveBreakTarget = currentBreakTarget; @@ -1323,7 +1383,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v preSwitchCaseFlow = currentFlow; bind(node.caseBlock); addAntecedent(postSwitchLabel, currentFlow); - const hasDefault = ts.forEach(node.caseBlock.clauses, c => c.kind === ts.SyntaxKind.DefaultClause); + const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause); // We mark a switch statement as possibly exhaustive if it has no default clause and if all // case clauses have unreachable end points (e.g. they all return). Note, we no longer need // this property in control flow analysis, it's there only for backwards compatibility. @@ -1336,7 +1396,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postSwitchLabel); } - function bindCaseBlock(node: ts.CaseBlock): void { + function bindCaseBlock(node: CaseBlock): void { const clauses = node.clauses; const isNarrowingSwitch = isNarrowingExpression(node.parent.expression); let fallthroughFlow = unreachableFlow; @@ -1353,13 +1413,13 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v const clause = clauses[i]; bind(clause); fallthroughFlow = currentFlow; - if (!(currentFlow.flags & ts.FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { + if (!(currentFlow.flags & FlowFlags.Unreachable) && i !== clauses.length - 1 && options.noFallthroughCasesInSwitch) { clause.fallthroughFlowNode = currentFlow; } } } - function bindCaseClause(node: ts.CaseClause): void { + function bindCaseClause(node: CaseClause): void { const saveCurrentFlow = currentFlow; currentFlow = preSwitchCaseFlow!; bind(node.expression); @@ -1367,23 +1427,23 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v bindEach(node.statements); } - function bindExpressionStatement(node: ts.ExpressionStatement): void { + function bindExpressionStatement(node: ExpressionStatement): void { bind(node.expression); maybeBindExpressionFlowIfCall(node.expression); } - function maybeBindExpressionFlowIfCall(node: ts.Expression) { + function maybeBindExpressionFlowIfCall(node: Expression) { // A top level or comma expression call expression with a dotted function name and at least one argument // is potentially an assertion and is therefore included in the control flow. - if (node.kind === ts.SyntaxKind.CallExpression) { - const call = node as ts.CallExpression; - if (call.expression.kind !== ts.SyntaxKind.SuperKeyword && ts.isDottedName(call.expression)) { + if (node.kind === SyntaxKind.CallExpression) { + const call = node as CallExpression; + if (call.expression.kind !== SyntaxKind.SuperKeyword && isDottedName(call.expression)) { currentFlow = createFlowCall(currentFlow, call); } } } - function bindLabeledStatement(node: ts.LabeledStatement): void { + function bindLabeledStatement(node: LabeledStatement): void { const postStatementLabel = createBranchLabel(); activeLabelList = { next: activeLabelList, @@ -1395,54 +1455,54 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v bind(node.label); bind(node.statement); if (!activeLabelList.referenced && !options.allowUnusedLabels) { - errorOrSuggestionOnNode(ts.unusedLabelIsError(options), node.label, ts.Diagnostics.Unused_label); + errorOrSuggestionOnNode(unusedLabelIsError(options), node.label, Diagnostics.Unused_label); } activeLabelList = activeLabelList.next; addAntecedent(postStatementLabel, currentFlow); currentFlow = finishFlowLabel(postStatementLabel); } - function bindDestructuringTargetFlow(node: ts.Expression) { - if (node.kind === ts.SyntaxKind.BinaryExpression && (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken) { - bindAssignmentTargetFlow((node as ts.BinaryExpression).left); + function bindDestructuringTargetFlow(node: Expression) { + if (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + bindAssignmentTargetFlow((node as BinaryExpression).left); } else { bindAssignmentTargetFlow(node); } } - function bindAssignmentTargetFlow(node: ts.Expression) { + function bindAssignmentTargetFlow(node: Expression) { if (isNarrowableReference(node)) { - currentFlow = createFlowMutation(ts.FlowFlags.Assignment, currentFlow, node); + currentFlow = createFlowMutation(FlowFlags.Assignment, currentFlow, node); } - else if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) { - for (const e of (node as ts.ArrayLiteralExpression).elements) { - if (e.kind === ts.SyntaxKind.SpreadElement) { - bindAssignmentTargetFlow((e as ts.SpreadElement).expression); + else if (node.kind === SyntaxKind.ArrayLiteralExpression) { + for (const e of (node as ArrayLiteralExpression).elements) { + if (e.kind === SyntaxKind.SpreadElement) { + bindAssignmentTargetFlow((e as SpreadElement).expression); } else { bindDestructuringTargetFlow(e); } } } - else if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { - for (const p of (node as ts.ObjectLiteralExpression).properties) { - if (p.kind === ts.SyntaxKind.PropertyAssignment) { + else if (node.kind === SyntaxKind.ObjectLiteralExpression) { + for (const p of (node as ObjectLiteralExpression).properties) { + if (p.kind === SyntaxKind.PropertyAssignment) { bindDestructuringTargetFlow(p.initializer); } - else if (p.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + else if (p.kind === SyntaxKind.ShorthandPropertyAssignment) { bindAssignmentTargetFlow(p.name); } - else if (p.kind === ts.SyntaxKind.SpreadAssignment) { + else if (p.kind === SyntaxKind.SpreadAssignment) { bindAssignmentTargetFlow(p.expression); } } } } - function bindLogicalLikeExpression(node: ts.BinaryExpression, trueTarget: ts.FlowLabel, falseTarget: ts.FlowLabel) { + function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) { const preRightLabel = createBranchLabel(); - if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandEqualsToken) { + if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) { bindCondition(node.left, preRightLabel, falseTarget); } else { @@ -1451,20 +1511,20 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(preRightLabel); bind(node.operatorToken); - if (ts.isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) { + if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) { doWithConditionalBranches(bind, node.right, trueTarget, falseTarget); bindAssignmentTargetFlow(node.left); - addAntecedent(trueTarget, createFlowCondition(ts.FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(ts.FlowFlags.FalseCondition, currentFlow, node)); + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } else { bindCondition(node.right, trueTarget, falseTarget); } } - function bindPrefixUnaryExpressionFlow(node: ts.PrefixUnaryExpression) { - if (node.operator === ts.SyntaxKind.ExclamationToken) { + function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) { + if (node.operator === SyntaxKind.ExclamationToken) { const saveTrueTarget = currentTrueTarget; currentTrueTarget = currentFalseTarget; currentFalseTarget = saveTrueTarget; @@ -1474,20 +1534,20 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } else { bindEachChild(node); - if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) { + if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { bindAssignmentTargetFlow(node.operand); } } } - function bindPostfixUnaryExpressionFlow(node: ts.PostfixUnaryExpression) { + function bindPostfixUnaryExpressionFlow(node: PostfixUnaryExpression) { bindEachChild(node); - if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) { + if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { bindAssignmentTargetFlow(node.operand); } } - function bindDestructuringAssignmentFlow(node: ts.DestructuringAssignment) { + function bindDestructuringAssignmentFlow(node: DestructuringAssignment) { if (inAssignmentPattern) { inAssignmentPattern = false; bind(node.operatorToken); @@ -1510,17 +1570,17 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v stackIndex: number; skip: boolean; inStrictModeStack: (boolean | undefined)[]; - parentStack: (ts.Node | undefined)[]; + parentStack: (Node | undefined)[]; } - return ts.createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, /*foldState*/ undefined); + return createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, /*foldState*/ undefined); - function onEnter(node: ts.BinaryExpression, state: WorkArea | undefined) { + function onEnter(node: BinaryExpression, state: WorkArea | undefined) { if (state) { state.stackIndex++; // Emulate the work that `bind` does before reaching `bindChildren`. A normal call to // `bindBinaryExpressionFlow` will already have done this work. - ts.setParent(node, parent); + setParent(node, parent); const saveInStrictMode = inStrictMode; bindWorker(node); const saveParent = parent; @@ -1541,10 +1601,10 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too // For now, though, since the common cases are chained `+`, leaving it recursive is fine const operator = node.operatorToken.kind; - if (operator === ts.SyntaxKind.AmpersandAmpersandToken || - operator === ts.SyntaxKind.BarBarToken || - operator === ts.SyntaxKind.QuestionQuestionToken || - ts.isLogicalOrCoalescingAssignmentOperator(operator)) { + if (operator === SyntaxKind.AmpersandAmpersandToken || + operator === SyntaxKind.BarBarToken || + operator === SyntaxKind.QuestionQuestionToken || + isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); @@ -1558,41 +1618,41 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return state; } - function onLeft(left: ts.Expression, state: WorkArea, node: ts.BinaryExpression) { + function onLeft(left: Expression, state: WorkArea, node: BinaryExpression) { if (!state.skip) { const maybeBound = maybeBind(left); - if (node.operatorToken.kind === ts.SyntaxKind.CommaToken) { + if (node.operatorToken.kind === SyntaxKind.CommaToken) { maybeBindExpressionFlowIfCall(left); } return maybeBound; } } - function onOperator(operatorToken: ts.BinaryOperatorToken, state: WorkArea, _node: ts.BinaryExpression) { + function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, _node: BinaryExpression) { if (!state.skip) { bind(operatorToken); } } - function onRight(right: ts.Expression, state: WorkArea, node: ts.BinaryExpression) { + function onRight(right: Expression, state: WorkArea, node: BinaryExpression) { if (!state.skip) { const maybeBound = maybeBind(right); - if (node.operatorToken.kind === ts.SyntaxKind.CommaToken) { + if (node.operatorToken.kind === SyntaxKind.CommaToken) { maybeBindExpressionFlowIfCall(right); } return maybeBound; } } - function onExit(node: ts.BinaryExpression, state: WorkArea) { + function onExit(node: BinaryExpression, state: WorkArea) { if (!state.skip) { const operator = node.operatorToken.kind; - if (ts.isAssignmentOperator(operator) && !ts.isAssignmentTarget(node)) { + if (isAssignmentOperator(operator) && !isAssignmentTarget(node)) { bindAssignmentTargetFlow(node.left); - if (operator === ts.SyntaxKind.EqualsToken && node.left.kind === ts.SyntaxKind.ElementAccessExpression) { - const elementAccess = node.left as ts.ElementAccessExpression; + if (operator === SyntaxKind.EqualsToken && node.left.kind === SyntaxKind.ElementAccessExpression) { + const elementAccess = node.left as ElementAccessExpression; if (isNarrowableOperand(elementAccess.expression)) { - currentFlow = createFlowMutation(ts.FlowFlags.ArrayMutation, currentFlow, node); + currentFlow = createFlowMutation(FlowFlags.ArrayMutation, currentFlow, node); } } } @@ -1609,22 +1669,22 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v state.stackIndex--; } - function maybeBind(node: ts.Node) { - if (node && ts.isBinaryExpression(node) && !ts.isDestructuringAssignment(node)) { + function maybeBind(node: Node) { + if (node && isBinaryExpression(node) && !isDestructuringAssignment(node)) { return node; } bind(node); } } - function bindDeleteExpressionFlow(node: ts.DeleteExpression) { + function bindDeleteExpressionFlow(node: DeleteExpression) { bindEachChild(node); - if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (node.expression.kind === SyntaxKind.PropertyAccessExpression) { bindAssignmentTargetFlow(node.expression); } } - function bindConditionalExpressionFlow(node: ts.ConditionalExpression) { + function bindConditionalExpressionFlow(node: ConditionalExpression) { const trueLabel = createBranchLabel(); const falseLabel = createBranchLabel(); const postExpressionLabel = createBranchLabel(); @@ -1640,26 +1700,26 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(postExpressionLabel); } - function bindInitializedVariableFlow(node: ts.VariableDeclaration | ts.ArrayBindingElement) { - const name = !ts.isOmittedExpression(node) ? node.name : undefined; - if (ts.isBindingPattern(name)) { + function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) { + const name = !isOmittedExpression(node) ? node.name : undefined; + if (isBindingPattern(name)) { for (const child of name.elements) { bindInitializedVariableFlow(child); } } else { - currentFlow = createFlowMutation(ts.FlowFlags.Assignment, currentFlow, node); + currentFlow = createFlowMutation(FlowFlags.Assignment, currentFlow, node); } } - function bindVariableDeclarationFlow(node: ts.VariableDeclaration) { + function bindVariableDeclarationFlow(node: VariableDeclaration) { bindEachChild(node); - if (node.initializer || ts.isForInOrOfStatement(node.parent.parent)) { + if (node.initializer || isForInOrOfStatement(node.parent.parent)) { bindInitializedVariableFlow(node); } } - function bindBindingElementFlow(node: ts.BindingElement) { + function bindBindingElementFlow(node: BindingElement) { // When evaluating a binding pattern, the initializer is evaluated before the binding pattern, per: // - https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-iteratorbindinginitialization // - `BindingElement: BindingPattern Initializer?` @@ -1671,7 +1731,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v bind(node.name); } - function bindParameterFlow(node: ts.ParameterDeclaration) { + function bindParameterFlow(node: ParameterDeclaration) { bindEach(node.modifiers); bind(node.dotDotDotToken); bind(node.questionToken); @@ -1681,7 +1741,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } // a BindingElement/Parameter does not have side effects if initializers are not evaluated and used. (see GH#49759) - function bindInitializer(node: ts.Expression | undefined) { + function bindInitializer(node: Expression | undefined) { if (!node) { return; } @@ -1696,45 +1756,45 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v currentFlow = finishFlowLabel(exitFlow); } - function bindJSDocTypeAlias(node: ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocEnumTag) { + function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) { bind(node.tagName); - if (node.kind !== ts.SyntaxKind.JSDocEnumTag && node.fullName) { + if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) { // don't bind the type name yet; that's delayed until delayedBindJSDocTypedefTag - ts.setParent(node.fullName, node); - ts.setParentRecursive(node.fullName, /*incremental*/ false); + setParent(node.fullName, node); + setParentRecursive(node.fullName, /*incremental*/ false); } if (typeof node.comment !== "string") { bindEach(node.comment); } } - function bindJSDocClassTag(node: ts.JSDocClassTag) { + function bindJSDocClassTag(node: JSDocClassTag) { bindEachChild(node); - const host = ts.getHostSignatureFromJSDoc(node); - if (host && host.kind !== ts.SyntaxKind.MethodDeclaration) { - addDeclarationToSymbol(host.symbol, host, ts.SymbolFlags.Class); + const host = getHostSignatureFromJSDoc(node); + if (host && host.kind !== SyntaxKind.MethodDeclaration) { + addDeclarationToSymbol(host.symbol, host, SymbolFlags.Class); } } - function bindOptionalExpression(node: ts.Expression, trueTarget: ts.FlowLabel, falseTarget: ts.FlowLabel) { + function bindOptionalExpression(node: Expression, trueTarget: FlowLabel, falseTarget: FlowLabel) { doWithConditionalBranches(bind, node, trueTarget, falseTarget); - if (!ts.isOptionalChain(node) || ts.isOutermostOptionalChain(node)) { - addAntecedent(trueTarget, createFlowCondition(ts.FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(ts.FlowFlags.FalseCondition, currentFlow, node)); + if (!isOptionalChain(node) || isOutermostOptionalChain(node)) { + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } } - function bindOptionalChainRest(node: ts.OptionalChain) { + function bindOptionalChainRest(node: OptionalChain) { switch (node.kind) { - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAccessExpression: bind(node.questionDotToken); bind(node.name); break; - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.ElementAccessExpression: bind(node.questionDotToken); bind(node.argumentExpression); break; - case ts.SyntaxKind.CallExpression: + case SyntaxKind.CallExpression: bind(node.questionDotToken); bindEach(node.typeArguments); bindEach(node.arguments); @@ -1742,7 +1802,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindOptionalChain(node: ts.OptionalChain, trueTarget: ts.FlowLabel, falseTarget: ts.FlowLabel) { + function bindOptionalChain(node: OptionalChain, trueTarget: FlowLabel, falseTarget: FlowLabel) { // For an optional chain, we emulate the behavior of a logical expression: // // a?.b -> a && a.b @@ -1754,19 +1814,19 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // and build it's CFA graph as if it were the first condition (`a && ...`). Then we bind the rest // of the node as part of the "true" branch, and continue to do so as we ascend back up to the outermost // chain node. We then treat the entire node as the right side of the expression. - const preChainLabel = ts.isOptionalChainRoot(node) ? createBranchLabel() : undefined; + const preChainLabel = isOptionalChainRoot(node) ? createBranchLabel() : undefined; bindOptionalExpression(node.expression, preChainLabel || trueTarget, falseTarget); if (preChainLabel) { currentFlow = finishFlowLabel(preChainLabel); } doWithConditionalBranches(bindOptionalChainRest, node, trueTarget, falseTarget); - if (ts.isOutermostOptionalChain(node)) { - addAntecedent(trueTarget, createFlowCondition(ts.FlowFlags.TrueCondition, currentFlow, node)); - addAntecedent(falseTarget, createFlowCondition(ts.FlowFlags.FalseCondition, currentFlow, node)); + if (isOutermostOptionalChain(node)) { + addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node)); + addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node)); } } - function bindOptionalChainFlow(node: ts.OptionalChain) { + function bindOptionalChainFlow(node: OptionalChain) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); bindOptionalChain(node, postExpressionLabel, postExpressionLabel); @@ -1777,8 +1837,8 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindNonNullExpressionFlow(node: ts.NonNullExpression | ts.NonNullChain) { - if (ts.isOptionalChain(node)) { + function bindNonNullExpressionFlow(node: NonNullExpression | NonNullChain) { + if (isOptionalChain(node)) { bindOptionalChainFlow(node); } else { @@ -1786,8 +1846,8 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindAccessExpressionFlow(node: ts.AccessExpression | ts.PropertyAccessChain | ts.ElementAccessChain) { - if (ts.isOptionalChain(node)) { + function bindAccessExpressionFlow(node: AccessExpression | PropertyAccessChain | ElementAccessChain) { + if (isOptionalChain(node)) { bindOptionalChainFlow(node); } else { @@ -1795,94 +1855,94 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function bindCallExpressionFlow(node: ts.CallExpression | ts.CallChain) { - if (ts.isOptionalChain(node)) { + function bindCallExpressionFlow(node: CallExpression | CallChain) { + if (isOptionalChain(node)) { bindOptionalChainFlow(node); } else { // If the target of the call expression is a function expression or arrow function we have // an immediately invoked function expression (IIFE). Initialize the flowNode property to // the current control flow (which includes evaluation of the IIFE arguments). - const expr = ts.skipParentheses(node.expression); - if (expr.kind === ts.SyntaxKind.FunctionExpression || expr.kind === ts.SyntaxKind.ArrowFunction) { + const expr = skipParentheses(node.expression); + if (expr.kind === SyntaxKind.FunctionExpression || expr.kind === SyntaxKind.ArrowFunction) { bindEach(node.typeArguments); bindEach(node.arguments); bind(node.expression); } else { bindEachChild(node); - if (node.expression.kind === ts.SyntaxKind.SuperKeyword) { + if (node.expression.kind === SyntaxKind.SuperKeyword) { currentFlow = createFlowCall(currentFlow, node); } } } - if (node.expression.kind === ts.SyntaxKind.PropertyAccessExpression) { - const propertyAccess = node.expression as ts.PropertyAccessExpression; - if (ts.isIdentifier(propertyAccess.name) && isNarrowableOperand(propertyAccess.expression) && ts.isPushOrUnshiftIdentifier(propertyAccess.name)) { - currentFlow = createFlowMutation(ts.FlowFlags.ArrayMutation, currentFlow, node); + if (node.expression.kind === SyntaxKind.PropertyAccessExpression) { + const propertyAccess = node.expression as PropertyAccessExpression; + if (isIdentifier(propertyAccess.name) && isNarrowableOperand(propertyAccess.expression) && isPushOrUnshiftIdentifier(propertyAccess.name)) { + currentFlow = createFlowMutation(FlowFlags.ArrayMutation, currentFlow, node); } } } - function getContainerFlags(node: ts.Node): ContainerFlags { + function getContainerFlags(node: Node): ContainerFlags { switch (node.kind) { - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.JSDocTypeLiteral: - case ts.SyntaxKind.JsxAttributes: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JsxAttributes: return ContainerFlags.IsContainer; - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.InterfaceDeclaration: return ContainerFlags.IsContainer | ContainerFlags.IsInterface; - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.MappedType: - case ts.SyntaxKind.IndexSignature: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.MappedType: + case SyntaxKind.IndexSignature: return ContainerFlags.IsContainer | ContainerFlags.HasLocals; - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals; - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: - if (ts.isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + if (isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor; } // falls through - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.JSDocSignature: - case ts.SyntaxKind.JSDocFunctionType: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.JSDocSignature: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructorType: + case SyntaxKind.ClassStaticBlockDeclaration: return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike; - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression; - case ts.SyntaxKind.ModuleBlock: + case SyntaxKind.ModuleBlock: return ContainerFlags.IsControlFlowContainer; - case ts.SyntaxKind.PropertyDeclaration: - return (node as ts.PropertyDeclaration).initializer ? ContainerFlags.IsControlFlowContainer : 0; - - case ts.SyntaxKind.CatchClause: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.CaseBlock: + case SyntaxKind.PropertyDeclaration: + return (node as PropertyDeclaration).initializer ? ContainerFlags.IsControlFlowContainer : 0; + + case SyntaxKind.CatchClause: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.CaseBlock: return ContainerFlags.IsBlockScopedContainer; - case ts.SyntaxKind.Block: + case SyntaxKind.Block: // do not treat blocks directly inside a function as a block-scoped-container. // Locals that reside in this block should go to the function locals. Otherwise 'x' // would not appear to be a redeclaration of a block scoped local in the following @@ -1899,13 +1959,13 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // By not creating a new block-scoped-container here, we ensure that both 'var x' // and 'let x' go into the Function-container's locals, and we do get a collision // conflict. - return ts.isFunctionLike(node.parent) || ts.isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer; + return isFunctionLike(node.parent) || isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer; } return ContainerFlags.None; } - function addToContainerChain(next: ts.Node) { + function addToContainerChain(next: Node) { if (lastContainer) { lastContainer.nextContainer = next; } @@ -1913,30 +1973,30 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v lastContainer = next; } - function declareSymbolAndAddToSymbolTable(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags): ts.Symbol | undefined { + function declareSymbolAndAddToSymbolTable(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol | undefined { switch (container.kind) { // Modules, source files, and classes need specialized handling for how their // members are declared (for example, a member of a class will go into a specific // symbol table depending on if it is static or not). We defer to specialized // handlers to take care of declaring these child members. - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.ModuleDeclaration: return declareModuleMember(node, symbolFlags, symbolExcludes); - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: return declareSourceFileMember(node, symbolFlags, symbolExcludes); - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: return declareClassMember(node, symbolFlags, symbolExcludes); - case ts.SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumDeclaration: return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.JSDocTypeLiteral: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.JsxAttributes: + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.JsxAttributes: // Interface/Object-types always have their children added to the 'members' of // their container. They are only accessible through an instance of their // container, and are never in scope otherwise (even inside the body of the @@ -1944,26 +2004,26 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // which are in scope without qualification (similar to 'locals'). return declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.JSDocSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.JSDocFunctionType: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.ClassStaticBlockDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.MappedType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.JSDocSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.MappedType: // All the children of these container types are never visible through another // symbol (i.e. through another symbol's 'exports' or 'members'). Instead, // they're only accessed 'lexically' (i.e. from code that exists underneath @@ -1974,55 +2034,55 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function declareClassMember(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags) { - return ts.isStatic(node) + function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { + return isStatic(node) ? declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes) : declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); } - function declareSourceFileMember(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags) { - return ts.isExternalModule(file) + function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { + return isExternalModule(file) ? declareModuleMember(node, symbolFlags, symbolExcludes) : declareSymbol(file.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } - function hasExportDeclarations(node: ts.ModuleDeclaration | ts.SourceFile): boolean { - const body = ts.isSourceFile(node) ? node : ts.tryCast(node.body, ts.isModuleBlock); - return !!body && body.statements.some(s => ts.isExportDeclaration(s) || ts.isExportAssignment(s)); + function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean { + const body = isSourceFile(node) ? node : tryCast(node.body, isModuleBlock); + return !!body && body.statements.some(s => isExportDeclaration(s) || isExportAssignment(s)); } - function setExportContextFlag(node: ts.Mutable) { + function setExportContextFlag(node: Mutable) { // A declaration source file or ambient module declaration that contains no export declarations (but possibly regular // declarations with export modifiers) is an export context in which declarations are implicitly exported. - if (node.flags & ts.NodeFlags.Ambient && !hasExportDeclarations(node)) { - node.flags |= ts.NodeFlags.ExportContext; + if (node.flags & NodeFlags.Ambient && !hasExportDeclarations(node)) { + node.flags |= NodeFlags.ExportContext; } else { - node.flags &= ~ts.NodeFlags.ExportContext; + node.flags &= ~NodeFlags.ExportContext; } } - function bindModuleDeclaration(node: ts.ModuleDeclaration) { + function bindModuleDeclaration(node: ModuleDeclaration) { setExportContextFlag(node); - if (ts.isAmbientModule(node)) { - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.Export)) { - errorOnFirstToken(node, ts.Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); + if (isAmbientModule(node)) { + if (hasSyntacticModifier(node, ModifierFlags.Export)) { + errorOnFirstToken(node, Diagnostics.export_modifier_cannot_be_applied_to_ambient_modules_and_module_augmentations_since_they_are_always_visible); } - if (ts.isModuleAugmentationExternal(node)) { + if (isModuleAugmentationExternal(node)) { declareModuleSymbol(node); } else { - let pattern: string | ts.Pattern | undefined; - if (node.name.kind === ts.SyntaxKind.StringLiteral) { + let pattern: string | Pattern | undefined; + if (node.name.kind === SyntaxKind.StringLiteral) { const { text } = node.name; - pattern = ts.tryParsePattern(text); + pattern = tryParsePattern(text); if (pattern === undefined) { - errorOnFirstToken(node.name, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); + errorOnFirstToken(node.name, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, text); } } - const symbol = declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.ValueModule, ts.SymbolFlags.ValueModuleExcludes)!; - file.patternAmbientModules = ts.append(file.patternAmbientModules, pattern && !ts.isString(pattern) ? { pattern, symbol } : undefined); + const symbol = declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes)!; + file.patternAmbientModules = append(file.patternAmbientModules, pattern && !isString(pattern) ? { pattern, symbol } : undefined); } } else { @@ -2030,7 +2090,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v if (state !== ModuleInstanceState.NonInstantiated) { const { symbol } = node; // if module was already merged with some function, class or non-const enum, treat it as non-const-enum-only - symbol.constEnumOnlyModule = (!(symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Class | ts.SymbolFlags.RegularEnum))) + symbol.constEnumOnlyModule = (!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum))) // Current must be `const enum` only && state === ModuleInstanceState.ConstEnumOnly // Can't have been set to 'false' in a previous merged symbol. ('undefined' OK) @@ -2039,66 +2099,66 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function declareModuleSymbol(node: ts.ModuleDeclaration): ModuleInstanceState { + function declareModuleSymbol(node: ModuleDeclaration): ModuleInstanceState { const state = getModuleInstanceState(node); const instantiated = state !== ModuleInstanceState.NonInstantiated; declareSymbolAndAddToSymbolTable(node, - instantiated ? ts.SymbolFlags.ValueModule : ts.SymbolFlags.NamespaceModule, - instantiated ? ts.SymbolFlags.ValueModuleExcludes : ts.SymbolFlags.NamespaceModuleExcludes); + instantiated ? SymbolFlags.ValueModule : SymbolFlags.NamespaceModule, + instantiated ? SymbolFlags.ValueModuleExcludes : SymbolFlags.NamespaceModuleExcludes); return state; } - function bindFunctionOrConstructorType(node: ts.SignatureDeclaration | ts.JSDocSignature): void { + function bindFunctionOrConstructorType(node: SignatureDeclaration | JSDocSignature): void { // For a given function symbol "<...>(...) => T" we want to generate a symbol identical // to the one we would get for: { <...>(...): T } // // We do that by making an anonymous type literal symbol, and then setting the function // symbol as its sole member. To the rest of the system, this symbol will be indistinguishable // from an actual type literal symbol you would have gotten had you used the long form. - const symbol = createSymbol(ts.SymbolFlags.Signature, getDeclarationName(node)!); // TODO: GH#18217 - addDeclarationToSymbol(symbol, node, ts.SymbolFlags.Signature); + const symbol = createSymbol(SymbolFlags.Signature, getDeclarationName(node)!); // TODO: GH#18217 + addDeclarationToSymbol(symbol, node, SymbolFlags.Signature); - const typeLiteralSymbol = createSymbol(ts.SymbolFlags.TypeLiteral, ts.InternalSymbolName.Type); - addDeclarationToSymbol(typeLiteralSymbol, node, ts.SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = ts.createSymbolTable(); + const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); + addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); + typeLiteralSymbol.members = createSymbolTable(); typeLiteralSymbol.members.set(symbol.escapedName, symbol); } - function bindObjectLiteralExpression(node: ts.ObjectLiteralExpression) { - return bindAnonymousDeclaration(node, ts.SymbolFlags.ObjectLiteral, ts.InternalSymbolName.Object); + function bindObjectLiteralExpression(node: ObjectLiteralExpression) { + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, InternalSymbolName.Object); } - function bindJsxAttributes(node: ts.JsxAttributes) { - return bindAnonymousDeclaration(node, ts.SymbolFlags.ObjectLiteral, ts.InternalSymbolName.JSXAttributes); + function bindJsxAttributes(node: JsxAttributes) { + return bindAnonymousDeclaration(node, SymbolFlags.ObjectLiteral, InternalSymbolName.JSXAttributes); } - function bindJsxAttribute(node: ts.JsxAttribute, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags) { + function bindJsxAttribute(node: JsxAttribute, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function bindAnonymousDeclaration(node: ts.Declaration, symbolFlags: ts.SymbolFlags, name: ts.__String) { + function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: __String) { const symbol = createSymbol(symbolFlags, name); - if (symbolFlags & (ts.SymbolFlags.EnumMember | ts.SymbolFlags.ClassMember)) { + if (symbolFlags & (SymbolFlags.EnumMember | SymbolFlags.ClassMember)) { symbol.parent = container.symbol; } addDeclarationToSymbol(symbol, node, symbolFlags); return symbol; } - function bindBlockScopedDeclaration(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags) { + function bindBlockScopedDeclaration(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { switch (blockScopeContainer.kind) { - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.ModuleDeclaration: declareModuleMember(node, symbolFlags, symbolExcludes); break; - case ts.SyntaxKind.SourceFile: - if (ts.isExternalOrCommonJsModule(container as ts.SourceFile)) { + case SyntaxKind.SourceFile: + if (isExternalOrCommonJsModule(container as SourceFile)) { declareModuleMember(node, symbolFlags, symbolExcludes); break; } // falls through default: if (!blockScopeContainer.locals) { - blockScopeContainer.locals = ts.createSymbolTable(); + blockScopeContainer.locals = createSymbolTable(); addToContainerChain(blockScopeContainer); } declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); @@ -2116,52 +2176,52 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v const saveCurrentFlow = currentFlow; for (const typeAlias of delayedTypeAliases) { const host = typeAlias.parent.parent; - container = ts.findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) || file; - blockScopeContainer = ts.getEnclosingBlockScopeContainer(host) || file; - currentFlow = initFlowNode({ flags: ts.FlowFlags.Start }); + container = findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) || file; + blockScopeContainer = getEnclosingBlockScopeContainer(host) || file; + currentFlow = initFlowNode({ flags: FlowFlags.Start }); parent = typeAlias; bind(typeAlias.typeExpression); - const declName = ts.getNameOfDeclaration(typeAlias); - if ((ts.isJSDocEnumTag(typeAlias) || !typeAlias.fullName) && declName && ts.isPropertyAccessEntityNameExpression(declName.parent)) { + const declName = getNameOfDeclaration(typeAlias); + if ((isJSDocEnumTag(typeAlias) || !typeAlias.fullName) && declName && isPropertyAccessEntityNameExpression(declName.parent)) { // typedef anchored to an A.B.C assignment - we need to bind into B's namespace under name C const isTopLevel = isTopLevelNamespaceAssignment(declName.parent); if (isTopLevel) { bindPotentiallyMissingNamespaces(file.symbol, declName.parent, isTopLevel, - !!ts.findAncestor(declName, d => ts.isPropertyAccessExpression(d) && d.name.escapedText === "prototype"), /*containerIsClass*/ false); + !!findAncestor(declName, d => isPropertyAccessExpression(d) && d.name.escapedText === "prototype"), /*containerIsClass*/ false); const oldContainer = container; - switch (ts.getAssignmentDeclarationPropertyAccessKind(declName.parent)) { - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.ModuleExports: - if (!ts.isExternalOrCommonJsModule(file)) { + switch (getAssignmentDeclarationPropertyAccessKind(declName.parent)) { + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ModuleExports: + if (!isExternalOrCommonJsModule(file)) { container = undefined!; } else { container = file; } break; - case ts.AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.ThisProperty: container = declName.parent.expression; break; - case ts.AssignmentDeclarationKind.PrototypeProperty: - container = (declName.parent.expression as ts.PropertyAccessExpression).name; + case AssignmentDeclarationKind.PrototypeProperty: + container = (declName.parent.expression as PropertyAccessExpression).name; break; - case ts.AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.Property: container = isExportsOrModuleExportsOrAlias(file, declName.parent.expression) ? file - : ts.isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name + : isPropertyAccessExpression(declName.parent.expression) ? declName.parent.expression.name : declName.parent.expression; break; - case ts.AssignmentDeclarationKind.None: - return ts.Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration"); + case AssignmentDeclarationKind.None: + return Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration"); } if (container) { - declareModuleMember(typeAlias, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.TypeAliasExcludes); + declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); } container = oldContainer; } } - else if (ts.isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === ts.SyntaxKind.Identifier) { + else if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) { parent = typeAlias.parent; - bindBlockScopedDeclaration(typeAlias, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.TypeAliasExcludes); + bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); } else { bind(typeAlias.fullName); @@ -2177,75 +2237,75 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized // check for reserved words used as identifiers in strict mode code, as well as `yield` or `await` in // [Yield] or [Await] contexts, respectively. - function checkContextualIdentifier(node: ts.Identifier) { + function checkContextualIdentifier(node: Identifier) { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length && - !(node.flags & ts.NodeFlags.Ambient) && - !(node.flags & ts.NodeFlags.JSDoc) && - !ts.isIdentifierName(node)) { + !(node.flags & NodeFlags.Ambient) && + !(node.flags & NodeFlags.JSDoc) && + !isIdentifierName(node)) { // strict mode identifiers if (inStrictMode && - node.originalKeywordKind! >= ts.SyntaxKind.FirstFutureReservedWord && - node.originalKeywordKind! <= ts.SyntaxKind.LastFutureReservedWord) { + node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord && + node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) { file.bindDiagnostics.push(createDiagnosticForNode(node, - getStrictModeIdentifierMessage(node), ts.declarationNameToString(node))); + getStrictModeIdentifierMessage(node), declarationNameToString(node))); } - else if (node.originalKeywordKind === ts.SyntaxKind.AwaitKeyword) { - if (ts.isExternalModule(file) && ts.isInTopLevelContext(node)) { + else if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) { + if (isExternalModule(file) && isInTopLevelContext(node)) { file.bindDiagnostics.push(createDiagnosticForNode(node, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, - ts.declarationNameToString(node))); + Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, + declarationNameToString(node))); } - else if (node.flags & ts.NodeFlags.AwaitContext) { + else if (node.flags & NodeFlags.AwaitContext) { file.bindDiagnostics.push(createDiagnosticForNode(node, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, - ts.declarationNameToString(node))); + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, + declarationNameToString(node))); } } - else if (node.originalKeywordKind === ts.SyntaxKind.YieldKeyword && node.flags & ts.NodeFlags.YieldContext) { + else if (node.originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) { file.bindDiagnostics.push(createDiagnosticForNode(node, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, - ts.declarationNameToString(node))); + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, + declarationNameToString(node))); } } } - function getStrictModeIdentifierMessage(node: ts.Node) { + function getStrictModeIdentifierMessage(node: Node) { // Provide specialized messages to help the user understand why we think they're in // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; + if (getContainingClass(node)) { + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode; } if (file.externalModuleIndicator) { - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode; } - return ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; + return Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode; } // The binder visits every node, so this is a good place to check for // the reserved private name (there is only one) - function checkPrivateIdentifier(node: ts.PrivateIdentifier) { + function checkPrivateIdentifier(node: PrivateIdentifier) { if (node.escapedText === "#constructor") { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { file.bindDiagnostics.push(createDiagnosticForNode(node, - ts.Diagnostics.constructor_is_a_reserved_word, ts.declarationNameToString(node))); + Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node))); } } } - function checkStrictModeBinaryExpression(node: ts.BinaryExpression) { - if (inStrictMode && ts.isLeftHandSideExpression(node.left) && ts.isAssignmentOperator(node.operatorToken.kind)) { + function checkStrictModeBinaryExpression(node: BinaryExpression) { + if (inStrictMode && isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operatorToken.kind)) { // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an // Assignment operator(11.13) or of a PostfixExpression(11.3) - checkStrictModeEvalOrArguments(node, node.left as ts.Identifier); + checkStrictModeEvalOrArguments(node, node.left as Identifier); } } - function checkStrictModeCatchClause(node: ts.CatchClause) { + function checkStrictModeCatchClause(node: CatchClause) { // It is a SyntaxError if a TryStatement with a Catch occurs within strict code and the Identifier of the // Catch production is eval or arguments if (inStrictMode && node.variableDeclaration) { @@ -2253,153 +2313,153 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } - function checkStrictModeDeleteExpression(node: ts.DeleteExpression) { + function checkStrictModeDeleteExpression(node: DeleteExpression) { // Grammar checking - if (inStrictMode && node.expression.kind === ts.SyntaxKind.Identifier) { + if (inStrictMode && node.expression.kind === SyntaxKind.Identifier) { // When a delete operator occurs within strict mode code, a SyntaxError is thrown if its // UnaryExpression is a direct reference to a variable, function argument, or function name - const span = ts.getErrorSpanForNode(file, node.expression); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); + const span = getErrorSpanForNode(file, node.expression); + file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode)); } } - function isEvalOrArgumentsIdentifier(node: ts.Node): boolean { - return ts.isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments"); + function isEvalOrArgumentsIdentifier(node: Node): boolean { + return isIdentifier(node) && (node.escapedText === "eval" || node.escapedText === "arguments"); } - function checkStrictModeEvalOrArguments(contextNode: ts.Node, name: ts.Node | undefined) { - if (name && name.kind === ts.SyntaxKind.Identifier) { - const identifier = name as ts.Identifier; + function checkStrictModeEvalOrArguments(contextNode: Node, name: Node | undefined) { + if (name && name.kind === SyntaxKind.Identifier) { + const identifier = name as Identifier; if (isEvalOrArgumentsIdentifier(identifier)) { // We check first if the name is inside class declaration or class expression; if so give explicit message // otherwise report generic error message. - const span = ts.getErrorSpanForNode(file, name); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, - getStrictModeEvalOrArgumentsMessage(contextNode), ts.idText(identifier))); + const span = getErrorSpanForNode(file, name); + file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, + getStrictModeEvalOrArgumentsMessage(contextNode), idText(identifier))); } } } - function getStrictModeEvalOrArgumentsMessage(node: ts.Node) { + function getStrictModeEvalOrArgumentsMessage(node: Node) { // Provide specialized messages to help the user understand why we think they're in // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode; + if (getContainingClass(node)) { + return Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode; } if (file.externalModuleIndicator) { - return ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; + return Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode; } - return ts.Diagnostics.Invalid_use_of_0_in_strict_mode; + return Diagnostics.Invalid_use_of_0_in_strict_mode; } - function checkStrictModeFunctionName(node: ts.FunctionLikeDeclaration) { + function checkStrictModeFunctionName(node: FunctionLikeDeclaration) { if (inStrictMode) { // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a strict mode FunctionDeclaration or FunctionExpression (13.1)) checkStrictModeEvalOrArguments(node, node.name); } } - function getStrictModeBlockScopeFunctionDeclarationMessage(node: ts.Node) { + function getStrictModeBlockScopeFunctionDeclarationMessage(node: Node) { // Provide specialized messages to help the user understand why we think they're in // strict mode. - if (ts.getContainingClass(node)) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; + if (getContainingClass(node)) { + return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode; } if (file.externalModuleIndicator) { - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; + return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode; } - return ts.Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; + return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5; } - function checkStrictModeFunctionDeclaration(node: ts.FunctionDeclaration) { - if (languageVersion < ts.ScriptTarget.ES2015) { + function checkStrictModeFunctionDeclaration(node: FunctionDeclaration) { + if (languageVersion < ScriptTarget.ES2015) { // Report error if function is not top level function declaration - if (blockScopeContainer.kind !== ts.SyntaxKind.SourceFile && - blockScopeContainer.kind !== ts.SyntaxKind.ModuleDeclaration && - !ts.isFunctionLikeOrClassStaticBlockDeclaration(blockScopeContainer)) { + if (blockScopeContainer.kind !== SyntaxKind.SourceFile && + blockScopeContainer.kind !== SyntaxKind.ModuleDeclaration && + !isFunctionLikeOrClassStaticBlockDeclaration(blockScopeContainer)) { // We check first if the name is inside class declaration or class expression; if so give explicit message // otherwise report generic error message. - const errorSpan = ts.getErrorSpanForNode(file, node); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, errorSpan.start, errorSpan.length, + const errorSpan = getErrorSpanForNode(file, node); + file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length, getStrictModeBlockScopeFunctionDeclarationMessage(node))); } } } - function checkStrictModeNumericLiteral(node: ts.NumericLiteral) { - if (languageVersion < ts.ScriptTarget.ES5 && inStrictMode && node.numericLiteralFlags & ts.TokenFlags.Octal) { - file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); + function checkStrictModeNumericLiteral(node: NumericLiteral) { + if (languageVersion < ScriptTarget.ES5 && inStrictMode && node.numericLiteralFlags & TokenFlags.Octal) { + file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode)); } } - function checkStrictModePostfixUnaryExpression(node: ts.PostfixUnaryExpression) { + function checkStrictModePostfixUnaryExpression(node: PostfixUnaryExpression) { // Grammar checking // The identifier eval or arguments may not appear as the LeftHandSideExpression of an // Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression // operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator. if (inStrictMode) { - checkStrictModeEvalOrArguments(node, node.operand as ts.Identifier); + checkStrictModeEvalOrArguments(node, node.operand as Identifier); } } - function checkStrictModePrefixUnaryExpression(node: ts.PrefixUnaryExpression) { + function checkStrictModePrefixUnaryExpression(node: PrefixUnaryExpression) { // Grammar checking if (inStrictMode) { - if (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken) { - checkStrictModeEvalOrArguments(node, node.operand as ts.Identifier); + if (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) { + checkStrictModeEvalOrArguments(node, node.operand as Identifier); } } } - function checkStrictModeWithStatement(node: ts.WithStatement) { + function checkStrictModeWithStatement(node: WithStatement) { // Grammar checking for withStatement if (inStrictMode) { - errorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode); + errorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_strict_mode); } } - function checkStrictModeLabeledStatement(node: ts.LabeledStatement) { + function checkStrictModeLabeledStatement(node: LabeledStatement) { // Grammar checking for labeledStatement - if (inStrictMode && ts.getEmitScriptTarget(options) >= ts.ScriptTarget.ES2015) { - if (ts.isDeclarationStatement(node.statement) || ts.isVariableStatement(node.statement)) { - errorOnFirstToken(node.label, ts.Diagnostics.A_label_is_not_allowed_here); + if (inStrictMode && getEmitScriptTarget(options) >= ScriptTarget.ES2015) { + if (isDeclarationStatement(node.statement) || isVariableStatement(node.statement)) { + errorOnFirstToken(node.label, Diagnostics.A_label_is_not_allowed_here); } } } - function errorOnFirstToken(node: ts.Node, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) { - const span = ts.getSpanOfTokenAtPosition(file, node.pos); - file.bindDiagnostics.push(ts.createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); + function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) { + const span = getSpanOfTokenAtPosition(file, node.pos); + file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2)); } - function errorOrSuggestionOnNode(isError: boolean, node: ts.Node, message: ts.DiagnosticMessage): void { + function errorOrSuggestionOnNode(isError: boolean, node: Node, message: DiagnosticMessage): void { errorOrSuggestionOnRange(isError, node, node, message); } - function errorOrSuggestionOnRange(isError: boolean, startNode: ts.Node, endNode: ts.Node, message: ts.DiagnosticMessage): void { - addErrorOrSuggestionDiagnostic(isError, { pos: ts.getTokenPosOfNode(startNode, file), end: endNode.end }, message); + function errorOrSuggestionOnRange(isError: boolean, startNode: Node, endNode: Node, message: DiagnosticMessage): void { + addErrorOrSuggestionDiagnostic(isError, { pos: getTokenPosOfNode(startNode, file), end: endNode.end }, message); } - function addErrorOrSuggestionDiagnostic(isError: boolean, range: ts.TextRange, message: ts.DiagnosticMessage): void { - const diag = ts.createFileDiagnostic(file, range.pos, range.end - range.pos, message); + function addErrorOrSuggestionDiagnostic(isError: boolean, range: TextRange, message: DiagnosticMessage): void { + const diag = createFileDiagnostic(file, range.pos, range.end - range.pos, message); if (isError) { file.bindDiagnostics.push(diag); } else { - file.bindSuggestionDiagnostics = ts.append(file.bindSuggestionDiagnostics, { ...diag, category: ts.DiagnosticCategory.Suggestion }); + file.bindSuggestionDiagnostics = append(file.bindSuggestionDiagnostics, { ...diag, category: DiagnosticCategory.Suggestion }); } } - function bind(node: ts.Node | undefined): void { + function bind(node: Node | undefined): void { if (!node) { return; } - ts.setParent(node, parent); - if (ts.tracing) (node as ts.TracingNode).tracingPath = file.path; + setParent(node, parent); + if (tracing) (node as TracingNode).tracingPath = file.path; const saveInStrictMode = inStrictMode; // Even though in the AST the jsdoc @typedef node belongs to the current node, @@ -2428,7 +2488,7 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // the current 'container' node when it changes. This helps us know which symbol table // a local should go into for example. Since terminal nodes are known not to have // children, as an optimization we don't process those. - if (node.kind > ts.SyntaxKind.LastToken) { + if (node.kind > SyntaxKind.LastToken) { const saveParent = parent; parent = node; const containerFlags = getContainerFlags(node); @@ -2442,37 +2502,37 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } else { const saveParent = parent; - if (node.kind === ts.SyntaxKind.EndOfFileToken) parent = node; + if (node.kind === SyntaxKind.EndOfFileToken) parent = node; bindJSDoc(node); parent = saveParent; } inStrictMode = saveInStrictMode; } - function bindJSDoc(node: ts.Node) { - if (ts.hasJSDocNodes(node)) { - if (ts.isInJSFile(node)) { + function bindJSDoc(node: Node) { + if (hasJSDocNodes(node)) { + if (isInJSFile(node)) { for (const j of node.jsDoc!) { bind(j); } } else { for (const j of node.jsDoc!) { - ts.setParent(j, node); - ts.setParentRecursive(j, /*incremental*/ false); + setParent(j, node); + setParentRecursive(j, /*incremental*/ false); } } } } - function updateStrictModeStatementList(statements: ts.NodeArray) { + function updateStrictModeStatementList(statements: NodeArray) { if (!inStrictMode) { for (const statement of statements) { - if (!ts.isPrologueDirective(statement)) { + if (!isPrologueDirective(statement)) { return; } - if (isUseStrictPrologueDirective(statement as ts.ExpressionStatement)) { + if (isUseStrictPrologueDirective(statement as ExpressionStatement)) { inStrictMode = true; return; } @@ -2481,350 +2541,350 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } /// Should be called only on prologue directives (isPrologueDirective(node) should be true) - function isUseStrictPrologueDirective(node: ts.ExpressionStatement): boolean { - const nodeText = ts.getSourceTextOfNodeFromSourceFile(file, node.expression); + function isUseStrictPrologueDirective(node: ExpressionStatement): boolean { + const nodeText = getSourceTextOfNodeFromSourceFile(file, node.expression); // Note: the node text must be exactly "use strict" or 'use strict'. It is not ok for the // string to contain unicode escapes (as per ES5). return nodeText === '"use strict"' || nodeText === "'use strict'"; } - function bindWorker(node: ts.Node) { + function bindWorker(node: Node) { switch (node.kind) { /* Strict mode checks */ - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: // for typedef type names with namespaces, bind the new jsdoc type symbol here // because it requires all containing namespaces to be in effect, namely the // current "blockScopeContainer" needs to be set to its immediate namespace parent. - if ((node as ts.Identifier).isInJSDocNamespace) { + if ((node as Identifier).isInJSDocNamespace) { let parentNode = node.parent; - while (parentNode && !ts.isJSDocTypeAlias(parentNode)) { + while (parentNode && !isJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; } - bindBlockScopedDeclaration(parentNode as ts.Declaration, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.TypeAliasExcludes); + bindBlockScopedDeclaration(parentNode as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); break; } // falls through - case ts.SyntaxKind.ThisKeyword: - if (currentFlow && (ts.isExpression(node) || parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment)) { + case SyntaxKind.ThisKeyword: + if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) { node.flowNode = currentFlow; } - return checkContextualIdentifier(node as ts.Identifier); - case ts.SyntaxKind.QualifiedName: - if (currentFlow && ts.isPartOfTypeQuery(node)) { + return checkContextualIdentifier(node as Identifier); + case SyntaxKind.QualifiedName: + if (currentFlow && isPartOfTypeQuery(node)) { node.flowNode = currentFlow; } break; - case ts.SyntaxKind.MetaProperty: - case ts.SyntaxKind.SuperKeyword: + case SyntaxKind.MetaProperty: + case SyntaxKind.SuperKeyword: node.flowNode = currentFlow; break; - case ts.SyntaxKind.PrivateIdentifier: - return checkPrivateIdentifier(node as ts.PrivateIdentifier); - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - const expr = node as ts.PropertyAccessExpression | ts.ElementAccessExpression; + case SyntaxKind.PrivateIdentifier: + return checkPrivateIdentifier(node as PrivateIdentifier); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const expr = node as PropertyAccessExpression | ElementAccessExpression; if (currentFlow && isNarrowableReference(expr)) { expr.flowNode = currentFlow; } - if (ts.isSpecialPropertyDeclaration(expr)) { + if (isSpecialPropertyDeclaration(expr)) { bindSpecialPropertyDeclaration(expr); } - if (ts.isInJSFile(expr) && + if (isInJSFile(expr) && file.commonJsModuleIndicator && - ts.isModuleExportsAccessExpression(expr) && - !lookupSymbolForName(blockScopeContainer, "module" as ts.__String)) { + isModuleExportsAccessExpression(expr) && + !lookupSymbolForName(blockScopeContainer, "module" as __String)) { declareSymbol(file.locals!, /*parent*/ undefined, expr.expression, - ts.SymbolFlags.FunctionScopedVariable | ts.SymbolFlags.ModuleExports, ts.SymbolFlags.FunctionScopedVariableExcludes); + SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes); } break; - case ts.SyntaxKind.BinaryExpression: - const specialKind = ts.getAssignmentDeclarationKind(node as ts.BinaryExpression); + case SyntaxKind.BinaryExpression: + const specialKind = getAssignmentDeclarationKind(node as BinaryExpression); switch (specialKind) { - case ts.AssignmentDeclarationKind.ExportsProperty: - bindExportsPropertyAssignment(node as ts.BindableStaticPropertyAssignmentExpression); + case AssignmentDeclarationKind.ExportsProperty: + bindExportsPropertyAssignment(node as BindableStaticPropertyAssignmentExpression); break; - case ts.AssignmentDeclarationKind.ModuleExports: - bindModuleExportsAssignment(node as ts.BindablePropertyAssignmentExpression); + case AssignmentDeclarationKind.ModuleExports: + bindModuleExportsAssignment(node as BindablePropertyAssignmentExpression); break; - case ts.AssignmentDeclarationKind.PrototypeProperty: - bindPrototypePropertyAssignment((node as ts.BindableStaticPropertyAssignmentExpression).left, node); + case AssignmentDeclarationKind.PrototypeProperty: + bindPrototypePropertyAssignment((node as BindableStaticPropertyAssignmentExpression).left, node); break; - case ts.AssignmentDeclarationKind.Prototype: - bindPrototypeAssignment(node as ts.BindableStaticPropertyAssignmentExpression); + case AssignmentDeclarationKind.Prototype: + bindPrototypeAssignment(node as BindableStaticPropertyAssignmentExpression); break; - case ts.AssignmentDeclarationKind.ThisProperty: - bindThisPropertyAssignment(node as ts.BindablePropertyAssignmentExpression); + case AssignmentDeclarationKind.ThisProperty: + bindThisPropertyAssignment(node as BindablePropertyAssignmentExpression); break; - case ts.AssignmentDeclarationKind.Property: - const expression = ((node as ts.BinaryExpression).left as ts.AccessExpression).expression; - if (ts.isInJSFile(node) && ts.isIdentifier(expression)) { + case AssignmentDeclarationKind.Property: + const expression = ((node as BinaryExpression).left as AccessExpression).expression; + if (isInJSFile(node) && isIdentifier(expression)) { const symbol = lookupSymbolForName(blockScopeContainer, expression.escapedText); - if (ts.isThisInitializedDeclaration(symbol?.valueDeclaration)) { - bindThisPropertyAssignment(node as ts.BindablePropertyAssignmentExpression); + if (isThisInitializedDeclaration(symbol?.valueDeclaration)) { + bindThisPropertyAssignment(node as BindablePropertyAssignmentExpression); break; } } - bindSpecialPropertyAssignment(node as ts.BindablePropertyAssignmentExpression); + bindSpecialPropertyAssignment(node as BindablePropertyAssignmentExpression); break; - case ts.AssignmentDeclarationKind.None: + case AssignmentDeclarationKind.None: // Nothing to do break; default: - ts.Debug.fail("Unknown binary expression special property assignment kind"); - } - return checkStrictModeBinaryExpression(node as ts.BinaryExpression); - case ts.SyntaxKind.CatchClause: - return checkStrictModeCatchClause(node as ts.CatchClause); - case ts.SyntaxKind.DeleteExpression: - return checkStrictModeDeleteExpression(node as ts.DeleteExpression); - case ts.SyntaxKind.NumericLiteral: - return checkStrictModeNumericLiteral(node as ts.NumericLiteral); - case ts.SyntaxKind.PostfixUnaryExpression: - return checkStrictModePostfixUnaryExpression(node as ts.PostfixUnaryExpression); - case ts.SyntaxKind.PrefixUnaryExpression: - return checkStrictModePrefixUnaryExpression(node as ts.PrefixUnaryExpression); - case ts.SyntaxKind.WithStatement: - return checkStrictModeWithStatement(node as ts.WithStatement); - case ts.SyntaxKind.LabeledStatement: - return checkStrictModeLabeledStatement(node as ts.LabeledStatement); - case ts.SyntaxKind.ThisType: + Debug.fail("Unknown binary expression special property assignment kind"); + } + return checkStrictModeBinaryExpression(node as BinaryExpression); + case SyntaxKind.CatchClause: + return checkStrictModeCatchClause(node as CatchClause); + case SyntaxKind.DeleteExpression: + return checkStrictModeDeleteExpression(node as DeleteExpression); + case SyntaxKind.NumericLiteral: + return checkStrictModeNumericLiteral(node as NumericLiteral); + case SyntaxKind.PostfixUnaryExpression: + return checkStrictModePostfixUnaryExpression(node as PostfixUnaryExpression); + case SyntaxKind.PrefixUnaryExpression: + return checkStrictModePrefixUnaryExpression(node as PrefixUnaryExpression); + case SyntaxKind.WithStatement: + return checkStrictModeWithStatement(node as WithStatement); + case SyntaxKind.LabeledStatement: + return checkStrictModeLabeledStatement(node as LabeledStatement); + case SyntaxKind.ThisType: seenThisKeyword = true; return; - case ts.SyntaxKind.TypePredicate: + case SyntaxKind.TypePredicate: break; // Binding the children will handle everything - case ts.SyntaxKind.TypeParameter: - return bindTypeParameter(node as ts.TypeParameterDeclaration); - case ts.SyntaxKind.Parameter: - return bindParameter(node as ts.ParameterDeclaration); - case ts.SyntaxKind.VariableDeclaration: - return bindVariableDeclarationOrBindingElement(node as ts.VariableDeclaration); - case ts.SyntaxKind.BindingElement: + case SyntaxKind.TypeParameter: + return bindTypeParameter(node as TypeParameterDeclaration); + case SyntaxKind.Parameter: + return bindParameter(node as ParameterDeclaration); + case SyntaxKind.VariableDeclaration: + return bindVariableDeclarationOrBindingElement(node as VariableDeclaration); + case SyntaxKind.BindingElement: node.flowNode = currentFlow; - return bindVariableDeclarationOrBindingElement(node as ts.BindingElement); - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - return bindPropertyWorker(node as ts.PropertyDeclaration | ts.PropertySignature); - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - return bindPropertyOrMethodOrAccessor(node as ts.Declaration, ts.SymbolFlags.Property, ts.SymbolFlags.PropertyExcludes); - case ts.SyntaxKind.EnumMember: - return bindPropertyOrMethodOrAccessor(node as ts.Declaration, ts.SymbolFlags.EnumMember, ts.SymbolFlags.EnumMemberExcludes); - - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.IndexSignature: - return declareSymbolAndAddToSymbolTable(node as ts.Declaration, ts.SymbolFlags.Signature, ts.SymbolFlags.None); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: + return bindVariableDeclarationOrBindingElement(node as BindingElement); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return bindPropertyWorker(node as PropertyDeclaration | PropertySignature); + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + case SyntaxKind.EnumMember: + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); + + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Signature, SymbolFlags.None); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: // If this is an ObjectLiteralExpression method, then it sits in the same space // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - return bindPropertyOrMethodOrAccessor(node as ts.Declaration, ts.SymbolFlags.Method | ((node as ts.MethodDeclaration).questionToken ? ts.SymbolFlags.Optional : ts.SymbolFlags.None), - ts.isObjectLiteralMethod(node) ? ts.SymbolFlags.PropertyExcludes : ts.SymbolFlags.MethodExcludes); - case ts.SyntaxKind.FunctionDeclaration: - return bindFunctionDeclaration(node as ts.FunctionDeclaration); - case ts.SyntaxKind.Constructor: - return declareSymbolAndAddToSymbolTable(node as ts.Declaration, ts.SymbolFlags.Constructor, /*symbolExcludes:*/ ts.SymbolFlags.None); - case ts.SyntaxKind.GetAccessor: - return bindPropertyOrMethodOrAccessor(node as ts.Declaration, ts.SymbolFlags.GetAccessor, ts.SymbolFlags.GetAccessorExcludes); - case ts.SyntaxKind.SetAccessor: - return bindPropertyOrMethodOrAccessor(node as ts.Declaration, ts.SymbolFlags.SetAccessor, ts.SymbolFlags.SetAccessorExcludes); - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.JSDocFunctionType: - case ts.SyntaxKind.JSDocSignature: - case ts.SyntaxKind.ConstructorType: - return bindFunctionOrConstructorType(node as ts.SignatureDeclaration | ts.JSDocSignature); - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.JSDocTypeLiteral: - case ts.SyntaxKind.MappedType: - return bindAnonymousTypeWorker(node as ts.TypeLiteralNode | ts.MappedTypeNode | ts.JSDocTypeLiteral); - case ts.SyntaxKind.JSDocClassTag: - return bindJSDocClassTag(node as ts.JSDocClassTag); - case ts.SyntaxKind.ObjectLiteralExpression: - return bindObjectLiteralExpression(node as ts.ObjectLiteralExpression); - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - return bindFunctionExpression(node as ts.FunctionExpression); - - case ts.SyntaxKind.CallExpression: - const assignmentKind = ts.getAssignmentDeclarationKind(node as ts.CallExpression); + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Method | ((node as MethodDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), + isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); + case SyntaxKind.FunctionDeclaration: + return bindFunctionDeclaration(node as FunctionDeclaration); + case SyntaxKind.Constructor: + return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); + case SyntaxKind.GetAccessor: + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); + case SyntaxKind.SetAccessor: + return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); + case SyntaxKind.FunctionType: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocSignature: + case SyntaxKind.ConstructorType: + return bindFunctionOrConstructorType(node as SignatureDeclaration | JSDocSignature); + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.MappedType: + return bindAnonymousTypeWorker(node as TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral); + case SyntaxKind.JSDocClassTag: + return bindJSDocClassTag(node as JSDocClassTag); + case SyntaxKind.ObjectLiteralExpression: + return bindObjectLiteralExpression(node as ObjectLiteralExpression); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return bindFunctionExpression(node as FunctionExpression); + + case SyntaxKind.CallExpression: + const assignmentKind = getAssignmentDeclarationKind(node as CallExpression); switch (assignmentKind) { - case ts.AssignmentDeclarationKind.ObjectDefinePropertyValue: - return bindObjectDefinePropertyAssignment(node as ts.BindableObjectDefinePropertyCall); - case ts.AssignmentDeclarationKind.ObjectDefinePropertyExports: - return bindObjectDefinePropertyExport(node as ts.BindableObjectDefinePropertyCall); - case ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty: - return bindObjectDefinePrototypeProperty(node as ts.BindableObjectDefinePropertyCall); - case ts.AssignmentDeclarationKind.None: + case AssignmentDeclarationKind.ObjectDefinePropertyValue: + return bindObjectDefinePropertyAssignment(node as BindableObjectDefinePropertyCall); + case AssignmentDeclarationKind.ObjectDefinePropertyExports: + return bindObjectDefinePropertyExport(node as BindableObjectDefinePropertyCall); + case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: + return bindObjectDefinePrototypeProperty(node as BindableObjectDefinePropertyCall); + case AssignmentDeclarationKind.None: break; // Nothing to do default: - return ts.Debug.fail("Unknown call expression assignment declaration kind"); + return Debug.fail("Unknown call expression assignment declaration kind"); } - if (ts.isInJSFile(node)) { - bindCallExpression(node as ts.CallExpression); + if (isInJSFile(node)) { + bindCallExpression(node as CallExpression); } break; // Members of classes, interfaces, and modules - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: // All classes are automatically in strict mode in ES6. inStrictMode = true; - return bindClassLikeDeclaration(node as ts.ClassLikeDeclaration); - case ts.SyntaxKind.InterfaceDeclaration: - return bindBlockScopedDeclaration(node as ts.Declaration, ts.SymbolFlags.Interface, ts.SymbolFlags.InterfaceExcludes); - case ts.SyntaxKind.TypeAliasDeclaration: - return bindBlockScopedDeclaration(node as ts.Declaration, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.TypeAliasExcludes); - case ts.SyntaxKind.EnumDeclaration: - return bindEnumDeclaration(node as ts.EnumDeclaration); - case ts.SyntaxKind.ModuleDeclaration: - return bindModuleDeclaration(node as ts.ModuleDeclaration); + return bindClassLikeDeclaration(node as ClassLikeDeclaration); + case SyntaxKind.InterfaceDeclaration: + return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); + case SyntaxKind.TypeAliasDeclaration: + return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + case SyntaxKind.EnumDeclaration: + return bindEnumDeclaration(node as EnumDeclaration); + case SyntaxKind.ModuleDeclaration: + return bindModuleDeclaration(node as ModuleDeclaration); // Jsx-attributes - case ts.SyntaxKind.JsxAttributes: - return bindJsxAttributes(node as ts.JsxAttributes); - case ts.SyntaxKind.JsxAttribute: - return bindJsxAttribute(node as ts.JsxAttribute, ts.SymbolFlags.Property, ts.SymbolFlags.PropertyExcludes); + case SyntaxKind.JsxAttributes: + return bindJsxAttributes(node as JsxAttributes); + case SyntaxKind.JsxAttribute: + return bindJsxAttribute(node as JsxAttribute, SymbolFlags.Property, SymbolFlags.PropertyExcludes); // Imports and exports - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - return declareSymbolAndAddToSymbolTable(node as ts.Declaration, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); - case ts.SyntaxKind.NamespaceExportDeclaration: - return bindNamespaceExportDeclaration(node as ts.NamespaceExportDeclaration); - case ts.SyntaxKind.ImportClause: - return bindImportClause(node as ts.ImportClause); - case ts.SyntaxKind.ExportDeclaration: - return bindExportDeclaration(node as ts.ExportDeclaration); - case ts.SyntaxKind.ExportAssignment: - return bindExportAssignment(node as ts.ExportAssignment); - case ts.SyntaxKind.SourceFile: - updateStrictModeStatementList((node as ts.SourceFile).statements); + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + case SyntaxKind.NamespaceExportDeclaration: + return bindNamespaceExportDeclaration(node as NamespaceExportDeclaration); + case SyntaxKind.ImportClause: + return bindImportClause(node as ImportClause); + case SyntaxKind.ExportDeclaration: + return bindExportDeclaration(node as ExportDeclaration); + case SyntaxKind.ExportAssignment: + return bindExportAssignment(node as ExportAssignment); + case SyntaxKind.SourceFile: + updateStrictModeStatementList((node as SourceFile).statements); return bindSourceFileIfExternalModule(); - case ts.SyntaxKind.Block: - if (!ts.isFunctionLikeOrClassStaticBlockDeclaration(node.parent)) { + case SyntaxKind.Block: + if (!isFunctionLikeOrClassStaticBlockDeclaration(node.parent)) { return; } // falls through - case ts.SyntaxKind.ModuleBlock: - return updateStrictModeStatementList((node as ts.Block | ts.ModuleBlock).statements); + case SyntaxKind.ModuleBlock: + return updateStrictModeStatementList((node as Block | ModuleBlock).statements); - case ts.SyntaxKind.JSDocParameterTag: - if (node.parent.kind === ts.SyntaxKind.JSDocSignature) { - return bindParameter(node as ts.JSDocParameterTag); + case SyntaxKind.JSDocParameterTag: + if (node.parent.kind === SyntaxKind.JSDocSignature) { + return bindParameter(node as JSDocParameterTag); } - if (node.parent.kind !== ts.SyntaxKind.JSDocTypeLiteral) { + if (node.parent.kind !== SyntaxKind.JSDocTypeLiteral) { break; } // falls through - case ts.SyntaxKind.JSDocPropertyTag: - const propTag = node as ts.JSDocPropertyLikeTag; - const flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === ts.SyntaxKind.JSDocOptionalType ? - ts.SymbolFlags.Property | ts.SymbolFlags.Optional : - ts.SymbolFlags.Property; - return declareSymbolAndAddToSymbolTable(propTag, flags, ts.SymbolFlags.PropertyExcludes); - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: - return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocEnumTag); + case SyntaxKind.JSDocPropertyTag: + const propTag = node as JSDocPropertyLikeTag; + const flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? + SymbolFlags.Property | SymbolFlags.Optional : + SymbolFlags.Property; + return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes); + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); } } - function bindPropertyWorker(node: ts.PropertyDeclaration | ts.PropertySignature) { - const isAutoAccessor = ts.isAutoAccessorPropertyDeclaration(node); - const includes = isAutoAccessor ? ts.SymbolFlags.Accessor : ts.SymbolFlags.Property; - const excludes = isAutoAccessor ? ts.SymbolFlags.AccessorExcludes : ts.SymbolFlags.PropertyExcludes; - return bindPropertyOrMethodOrAccessor(node, includes | (node.questionToken ? ts.SymbolFlags.Optional : ts.SymbolFlags.None), excludes); + function bindPropertyWorker(node: PropertyDeclaration | PropertySignature) { + const isAutoAccessor = isAutoAccessorPropertyDeclaration(node); + const includes = isAutoAccessor ? SymbolFlags.Accessor : SymbolFlags.Property; + const excludes = isAutoAccessor ? SymbolFlags.AccessorExcludes : SymbolFlags.PropertyExcludes; + return bindPropertyOrMethodOrAccessor(node, includes | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), excludes); } - function bindAnonymousTypeWorker(node: ts.TypeLiteralNode | ts.MappedTypeNode | ts.JSDocTypeLiteral) { - return bindAnonymousDeclaration(node as ts.Declaration, ts.SymbolFlags.TypeLiteral, ts.InternalSymbolName.Type); + function bindAnonymousTypeWorker(node: TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral) { + return bindAnonymousDeclaration(node as Declaration, SymbolFlags.TypeLiteral, InternalSymbolName.Type); } function bindSourceFileIfExternalModule() { setExportContextFlag(file); - if (ts.isExternalModule(file)) { + if (isExternalModule(file)) { bindSourceFileAsExternalModule(); } - else if (ts.isJsonSourceFile(file)) { + else if (isJsonSourceFile(file)) { bindSourceFileAsExternalModule(); // Create symbol equivalent for the module.exports = {} const originalSymbol = file.symbol; - declareSymbol(file.symbol.exports!, file.symbol, file, ts.SymbolFlags.Property, ts.SymbolFlags.All); + declareSymbol(file.symbol.exports!, file.symbol, file, SymbolFlags.Property, SymbolFlags.All); file.symbol = originalSymbol; } } function bindSourceFileAsExternalModule() { - bindAnonymousDeclaration(file, ts.SymbolFlags.ValueModule, `"${ts.removeFileExtension(file.fileName)}"` as ts.__String); + bindAnonymousDeclaration(file, SymbolFlags.ValueModule, `"${removeFileExtension(file.fileName)}"` as __String); } - function bindExportAssignment(node: ts.ExportAssignment) { + function bindExportAssignment(node: ExportAssignment) { if (!container.symbol || !container.symbol.exports) { // Incorrect export assignment in some sort of block construct - bindAnonymousDeclaration(node, ts.SymbolFlags.Value, getDeclarationName(node)!); + bindAnonymousDeclaration(node, SymbolFlags.Value, getDeclarationName(node)!); } else { - const flags = ts.exportAssignmentIsAlias(node) + const flags = exportAssignmentIsAlias(node) // An export default clause with an EntityNameExpression or a class expression exports all meanings of that identifier or expression; - ? ts.SymbolFlags.Alias + ? SymbolFlags.Alias // An export default clause with any other expression exports a value - : ts.SymbolFlags.Property; + : SymbolFlags.Property; // If there is an `export default x;` alias declaration, can't `export default` anything else. // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) - const symbol = declareSymbol(container.symbol.exports, container.symbol, node, flags, ts.SymbolFlags.All); + const symbol = declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); if (node.isExportEquals) { // Will be an error later, since the module already has other exports. Just make sure this has a valueDeclaration set. - ts.setValueDeclaration(symbol, node); + setValueDeclaration(symbol, node); } } } - function bindNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration) { - if (ts.some(node.modifiers)) { - file.bindDiagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Modifiers_cannot_appear_here)); + function bindNamespaceExportDeclaration(node: NamespaceExportDeclaration) { + if (some(node.modifiers)) { + file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Modifiers_cannot_appear_here)); } - const diag = !ts.isSourceFile(node.parent) ? ts.Diagnostics.Global_module_exports_may_only_appear_at_top_level - : !ts.isExternalModule(node.parent) ? ts.Diagnostics.Global_module_exports_may_only_appear_in_module_files - : !node.parent.isDeclarationFile ? ts.Diagnostics.Global_module_exports_may_only_appear_in_declaration_files + const diag = !isSourceFile(node.parent) ? Diagnostics.Global_module_exports_may_only_appear_at_top_level + : !isExternalModule(node.parent) ? Diagnostics.Global_module_exports_may_only_appear_in_module_files + : !node.parent.isDeclarationFile ? Diagnostics.Global_module_exports_may_only_appear_in_declaration_files : undefined; if (diag) { file.bindDiagnostics.push(createDiagnosticForNode(node, diag)); } else { - file.symbol.globalExports = file.symbol.globalExports || ts.createSymbolTable(); - declareSymbol(file.symbol.globalExports, file.symbol, node, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); + file.symbol.globalExports = file.symbol.globalExports || createSymbolTable(); + declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } } - function bindExportDeclaration(node: ts.ExportDeclaration) { + function bindExportDeclaration(node: ExportDeclaration) { if (!container.symbol || !container.symbol.exports) { // Export * in some sort of block construct - bindAnonymousDeclaration(node, ts.SymbolFlags.ExportStar, getDeclarationName(node)!); + bindAnonymousDeclaration(node, SymbolFlags.ExportStar, getDeclarationName(node)!); } else if (!node.exportClause) { // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, ts.SymbolFlags.ExportStar, ts.SymbolFlags.None); + declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.ExportStar, SymbolFlags.None); } - else if (ts.isNamespaceExport(node.exportClause)) { + else if (isNamespaceExport(node.exportClause)) { // declareSymbol walks up parents to find name text, parent _must_ be set // but won't be set by the normal binder walk until `bindChildren` later on. - ts.setParent(node.exportClause, node); - declareSymbol(container.symbol.exports, container.symbol, node.exportClause, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); + setParent(node.exportClause, node); + declareSymbol(container.symbol.exports, container.symbol, node.exportClause, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } } - function bindImportClause(node: ts.ImportClause) { + function bindImportClause(node: ImportClause) { if (node.name) { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } } - function setCommonJsModuleIndicator(node: ts.Node) { + function setCommonJsModuleIndicator(node: Node) { if (file.externalModuleIndicator && file.externalModuleIndicator !== true) { return false; } @@ -2837,23 +2897,23 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v return true; } - function bindObjectDefinePropertyExport(node: ts.BindableObjectDefinePropertyCall) { + function bindObjectDefinePropertyExport(node: BindableObjectDefinePropertyCall) { if (!setCommonJsModuleIndicator(node)) { return; } const symbol = forEachIdentifierInEntityName(node.arguments[0], /*parent*/ undefined, (id, symbol) => { if (symbol) { - addDeclarationToSymbol(symbol, id, ts.SymbolFlags.Module | ts.SymbolFlags.Assignment); + addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } return symbol; }); if (symbol) { - const flags = ts.SymbolFlags.Property | ts.SymbolFlags.ExportValue; - declareSymbol(symbol.exports!, symbol, node, flags, ts.SymbolFlags.None); + const flags = SymbolFlags.Property | SymbolFlags.ExportValue; + declareSymbol(symbol.exports!, symbol, node, flags, SymbolFlags.None); } } - function bindExportsPropertyAssignment(node: ts.BindableStaticPropertyAssignmentExpression) { + function bindExportsPropertyAssignment(node: BindableStaticPropertyAssignmentExpression) { // When we create a property via 'exports.foo = bar', the 'exports.foo' property access // expression is the declaration if (!setCommonJsModuleIndicator(node)) { @@ -2861,19 +2921,19 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } const symbol = forEachIdentifierInEntityName(node.left.expression, /*parent*/ undefined, (id, symbol) => { if (symbol) { - addDeclarationToSymbol(symbol, id, ts.SymbolFlags.Module | ts.SymbolFlags.Assignment); + addDeclarationToSymbol(symbol, id, SymbolFlags.Module | SymbolFlags.Assignment); } return symbol; }); if (symbol) { - const isAlias = ts.isAliasableExpression(node.right) && (ts.isExportsIdentifier(node.left.expression) || ts.isModuleExportsAccessExpression(node.left.expression)); - const flags = isAlias ? ts.SymbolFlags.Alias : ts.SymbolFlags.Property | ts.SymbolFlags.ExportValue; - ts.setParent(node.left, node); - declareSymbol(symbol.exports!, symbol, node.left, flags, ts.SymbolFlags.None); + const isAlias = isAliasableExpression(node.right) && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression)); + const flags = isAlias ? SymbolFlags.Alias : SymbolFlags.Property | SymbolFlags.ExportValue; + setParent(node.left, node); + declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None); } } - function bindModuleExportsAssignment(node: ts.BindablePropertyAssignmentExpression) { + function bindModuleExportsAssignment(node: BindablePropertyAssignmentExpression) { // A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports' // is still pointing to 'module.exports'. // We do not want to consider this as 'export=' since a module can have only one of these. @@ -2881,115 +2941,115 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v if (!setCommonJsModuleIndicator(node)) { return; } - const assignedExpression = ts.getRightMostAssignedExpression(node.right); - if (ts.isEmptyObjectLiteral(assignedExpression) || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression)) { + const assignedExpression = getRightMostAssignedExpression(node.right); + if (isEmptyObjectLiteral(assignedExpression) || container === file && isExportsOrModuleExportsOrAlias(file, assignedExpression)) { return; } - if (ts.isObjectLiteralExpression(assignedExpression) && ts.every(assignedExpression.properties, ts.isShorthandPropertyAssignment)) { - ts.forEach(assignedExpression.properties, bindExportAssignedObjectMemberAlias); + if (isObjectLiteralExpression(assignedExpression) && every(assignedExpression.properties, isShorthandPropertyAssignment)) { + forEach(assignedExpression.properties, bindExportAssignedObjectMemberAlias); return; } // 'module.exports = expr' assignment - const flags = ts.exportAssignmentIsAlias(node) - ? ts.SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class - : ts.SymbolFlags.Property | ts.SymbolFlags.ExportValue | ts.SymbolFlags.ValueModule; - const symbol = declareSymbol(file.symbol.exports!, file.symbol, node, flags | ts.SymbolFlags.Assignment, ts.SymbolFlags.None); - ts.setValueDeclaration(symbol, node); + const flags = exportAssignmentIsAlias(node) + ? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class + : SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule; + const symbol = declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None); + setValueDeclaration(symbol, node); } - function bindExportAssignedObjectMemberAlias(node: ts.ShorthandPropertyAssignment) { - declareSymbol(file.symbol.exports!, file.symbol, node, ts.SymbolFlags.Alias | ts.SymbolFlags.Assignment, ts.SymbolFlags.None); + function bindExportAssignedObjectMemberAlias(node: ShorthandPropertyAssignment) { + declareSymbol(file.symbol.exports!, file.symbol, node, SymbolFlags.Alias | SymbolFlags.Assignment, SymbolFlags.None); } - function bindThisPropertyAssignment(node: ts.BindablePropertyAssignmentExpression | ts.PropertyAccessExpression | ts.LiteralLikeElementAccessExpression) { - ts.Debug.assert(ts.isInJSFile(node)); + function bindThisPropertyAssignment(node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression) { + Debug.assert(isInJSFile(node)); // private identifiers *must* be declared (even in JS files) - const hasPrivateIdentifier = (ts.isBinaryExpression(node) && ts.isPropertyAccessExpression(node.left) && ts.isPrivateIdentifier(node.left.name)) - || (ts.isPropertyAccessExpression(node) && ts.isPrivateIdentifier(node.name)); + const hasPrivateIdentifier = (isBinaryExpression(node) && isPropertyAccessExpression(node.left) && isPrivateIdentifier(node.left.name)) + || (isPropertyAccessExpression(node) && isPrivateIdentifier(node.name)); if (hasPrivateIdentifier) { return; } - const thisContainer = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false); switch (thisContainer.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - let constructorSymbol: ts.Symbol | undefined = thisContainer.symbol; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + let constructorSymbol: Symbol | undefined = thisContainer.symbol; // For `f.prototype.m = function() { this.x = 0; }`, `this.x = 0` should modify `f`'s members, not the function expression. - if (ts.isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { + if (isBinaryExpression(thisContainer.parent) && thisContainer.parent.operatorToken.kind === SyntaxKind.EqualsToken) { const l = thisContainer.parent.left; - if (ts.isBindableStaticAccessExpression(l) && ts.isPrototypeAccess(l.expression)) { + if (isBindableStaticAccessExpression(l) && isPrototypeAccess(l.expression)) { constructorSymbol = lookupSymbolForPropertyAccess(l.expression.expression, thisParentContainer); } } if (constructorSymbol && constructorSymbol.valueDeclaration) { // Declare a 'member' if the container is an ES5 class or ES6 constructor - constructorSymbol.members = constructorSymbol.members || ts.createSymbolTable(); + constructorSymbol.members = constructorSymbol.members || createSymbolTable(); // It's acceptable for multiple 'this' assignments of the same identifier to occur - if (ts.hasDynamicName(node)) { + if (hasDynamicName(node)) { bindDynamicallyNamedThisPropertyAssignment(node, constructorSymbol, constructorSymbol.members); } else { - declareSymbol(constructorSymbol.members, constructorSymbol, node, ts.SymbolFlags.Property | ts.SymbolFlags.Assignment, ts.SymbolFlags.PropertyExcludes & ~ts.SymbolFlags.Property); + declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); } - addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, ts.SymbolFlags.Class); + addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class); } break; - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.ClassStaticBlockDeclaration: // this.foo assignment in a JavaScript class // Bind this property to the containing class const containingClass = thisContainer.parent; - const symbolTable = ts.isStatic(thisContainer) ? containingClass.symbol.exports! : containingClass.symbol.members!; - if (ts.hasDynamicName(node)) { + const symbolTable = isStatic(thisContainer) ? containingClass.symbol.exports! : containingClass.symbol.members!; + if (hasDynamicName(node)) { bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol, symbolTable); } else { - declareSymbol(symbolTable, containingClass.symbol, node, ts.SymbolFlags.Property | ts.SymbolFlags.Assignment, ts.SymbolFlags.None, /*isReplaceableByMethod*/ true); + declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true); } break; - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: // this.property = assignment in a source file -- declare symbol in exports for a module, in locals for a script - if (ts.hasDynamicName(node)) { + if (hasDynamicName(node)) { break; } - else if ((thisContainer as ts.SourceFile).commonJsModuleIndicator) { - declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, ts.SymbolFlags.Property | ts.SymbolFlags.ExportValue, ts.SymbolFlags.None); + else if ((thisContainer as SourceFile).commonJsModuleIndicator) { + declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.FunctionScopedVariable, ts.SymbolFlags.FunctionScopedVariableExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); } break; default: - ts.Debug.failBadSyntaxKind(thisContainer); + Debug.failBadSyntaxKind(thisContainer); } } - function bindDynamicallyNamedThisPropertyAssignment(node: ts.BinaryExpression | ts.DynamicNamedDeclaration, symbol: ts.Symbol, symbolTable: ts.SymbolTable) { - declareSymbol(symbolTable, symbol, node, ts.SymbolFlags.Property, ts.SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true); + function bindDynamicallyNamedThisPropertyAssignment(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol, symbolTable: SymbolTable) { + declareSymbol(symbolTable, symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true); addLateBoundAssignmentDeclarationToSymbol(node, symbol); } - function addLateBoundAssignmentDeclarationToSymbol(node: ts.BinaryExpression | ts.DynamicNamedDeclaration, symbol: ts.Symbol | undefined) { + function addLateBoundAssignmentDeclarationToSymbol(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol | undefined) { if (symbol) { - (symbol.assignmentDeclarationMembers || (symbol.assignmentDeclarationMembers = new ts.Map())).set(ts.getNodeId(node), node); + (symbol.assignmentDeclarationMembers || (symbol.assignmentDeclarationMembers = new Map())).set(getNodeId(node), node); } } - function bindSpecialPropertyDeclaration(node: ts.PropertyAccessExpression | ts.LiteralLikeElementAccessExpression) { - if (node.expression.kind === ts.SyntaxKind.ThisKeyword) { + function bindSpecialPropertyDeclaration(node: PropertyAccessExpression | LiteralLikeElementAccessExpression) { + if (node.expression.kind === SyntaxKind.ThisKeyword) { bindThisPropertyAssignment(node); } - else if (ts.isBindableStaticAccessExpression(node) && node.parent.parent.kind === ts.SyntaxKind.SourceFile) { - if (ts.isPrototypeAccess(node.expression)) { + else if (isBindableStaticAccessExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) { + if (isPrototypeAccess(node.expression)) { bindPrototypePropertyAssignment(node, node.parent); } else { @@ -2999,17 +3059,17 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ - function bindPrototypeAssignment(node: ts.BindableStaticPropertyAssignmentExpression) { - ts.setParent(node.left, node); - ts.setParent(node.right, node); + function bindPrototypeAssignment(node: BindableStaticPropertyAssignmentExpression) { + setParent(node.left, node); + setParent(node.right, node); bindPropertyAssignment(node.left.expression, node.left, /*isPrototypeProperty*/ false, /*containerIsClass*/ true); } - function bindObjectDefinePrototypeProperty(node: ts.BindableObjectDefinePropertyCall) { - const namespaceSymbol = lookupSymbolForPropertyAccess((node.arguments[0] as ts.PropertyAccessExpression).expression as ts.EntityNameExpression); + function bindObjectDefinePrototypeProperty(node: BindableObjectDefinePropertyCall) { + const namespaceSymbol = lookupSymbolForPropertyAccess((node.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression); if (namespaceSymbol && namespaceSymbol.valueDeclaration) { // Ensure the namespace symbol becomes class-like - addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, ts.SymbolFlags.Class); + addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class); } bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ true); } @@ -3018,53 +3078,53 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v * For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared. * Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration. */ - function bindPrototypePropertyAssignment(lhs: ts.BindableStaticAccessExpression, parent: ts.Node) { + function bindPrototypePropertyAssignment(lhs: BindableStaticAccessExpression, parent: Node) { // Look up the function in the local scope, since prototype assignments should // follow the function declaration - const classPrototype = lhs.expression as ts.BindableStaticAccessExpression; + const classPrototype = lhs.expression as BindableStaticAccessExpression; const constructorFunction = classPrototype.expression; // Fix up parent pointers since we're going to use these nodes before we bind into them - ts.setParent(constructorFunction, classPrototype); - ts.setParent(classPrototype, lhs); - ts.setParent(lhs, parent); + setParent(constructorFunction, classPrototype); + setParent(classPrototype, lhs); + setParent(lhs, parent); bindPropertyAssignment(constructorFunction, lhs, /*isPrototypeProperty*/ true, /*containerIsClass*/ true); } - function bindObjectDefinePropertyAssignment(node: ts.BindableObjectDefinePropertyCall) { + function bindObjectDefinePropertyAssignment(node: BindableObjectDefinePropertyCall) { let namespaceSymbol = lookupSymbolForPropertyAccess(node.arguments[0]); - const isToplevel = node.parent.parent.kind === ts.SyntaxKind.SourceFile; + const isToplevel = node.parent.parent.kind === SyntaxKind.SourceFile; namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, node.arguments[0], isToplevel, /*isPrototypeProperty*/ false, /*containerIsClass*/ false); bindPotentiallyNewExpandoMemberToNamespace(node, namespaceSymbol, /*isPrototypeProperty*/ false); } - function bindSpecialPropertyAssignment(node: ts.BindablePropertyAssignmentExpression) { + function bindSpecialPropertyAssignment(node: BindablePropertyAssignmentExpression) { // Class declarations in Typescript do not allow property declarations const parentSymbol = lookupSymbolForPropertyAccess(node.left.expression, container) || lookupSymbolForPropertyAccess(node.left.expression, blockScopeContainer) ; - if (!ts.isInJSFile(node) && !ts.isFunctionSymbol(parentSymbol)) { + if (!isInJSFile(node) && !isFunctionSymbol(parentSymbol)) { return; } - const rootExpr = ts.getLeftmostAccessExpression(node.left); - if (ts.isIdentifier(rootExpr) && lookupSymbolForName(container, rootExpr.escapedText)?.flags! & ts.SymbolFlags.Alias) { + const rootExpr = getLeftmostAccessExpression(node.left); + if (isIdentifier(rootExpr) && lookupSymbolForName(container, rootExpr.escapedText)?.flags! & SymbolFlags.Alias) { return; } // Fix up parent pointers since we're going to use these nodes before we bind into them - ts.setParent(node.left, node); - ts.setParent(node.right, node); - if (ts.isIdentifier(node.left.expression) && container === file && isExportsOrModuleExportsOrAlias(file, node.left.expression)) { + setParent(node.left, node); + setParent(node.right, node); + if (isIdentifier(node.left.expression) && container === file && isExportsOrModuleExportsOrAlias(file, node.left.expression)) { // This can be an alias for the 'exports' or 'module.exports' names, e.g. // var util = module.exports; // util.property = function ... - bindExportsPropertyAssignment(node as ts.BindableStaticPropertyAssignmentExpression); + bindExportsPropertyAssignment(node as BindableStaticPropertyAssignmentExpression); } - else if (ts.hasDynamicName(node)) { - bindAnonymousDeclaration(node, ts.SymbolFlags.Property | ts.SymbolFlags.Assignment, ts.InternalSymbolName.Computed); + else if (hasDynamicName(node)) { + bindAnonymousDeclaration(node, SymbolFlags.Property | SymbolFlags.Assignment, InternalSymbolName.Computed); const sym = bindPotentiallyMissingNamespaces(parentSymbol, node.left.expression, isTopLevelNamespaceAssignment(node.left), /*isPrototype*/ false, /*containerIsClass*/ false); addLateBoundAssignmentDeclarationToSymbol(node, sym); } else { - bindStaticPropertyAssignment(ts.cast(node.left, ts.isBindableStaticNameExpression)); + bindStaticPropertyAssignment(cast(node.left, isBindableStaticNameExpression)); } } @@ -3072,20 +3132,20 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v * For nodes like `x.y = z`, declare a member 'y' on 'x' if x is a function (or IIFE) or class or {}, or not declared. * Also works for expression statements preceded by JSDoc, like / ** @type number * / x.y; */ - function bindStaticPropertyAssignment(node: ts.BindableStaticNameExpression) { - ts.Debug.assert(!ts.isIdentifier(node)); - ts.setParent(node.expression, node); + function bindStaticPropertyAssignment(node: BindableStaticNameExpression) { + Debug.assert(!isIdentifier(node)); + setParent(node.expression, node); bindPropertyAssignment(node.expression, node, /*isPrototypeProperty*/ false, /*containerIsClass*/ false); } - function bindPotentiallyMissingNamespaces(namespaceSymbol: ts.Symbol | undefined, entityName: ts.BindableStaticNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) { - if (namespaceSymbol?.flags! & ts.SymbolFlags.Alias) { + function bindPotentiallyMissingNamespaces(namespaceSymbol: Symbol | undefined, entityName: BindableStaticNameExpression, isToplevel: boolean, isPrototypeProperty: boolean, containerIsClass: boolean) { + if (namespaceSymbol?.flags! & SymbolFlags.Alias) { return namespaceSymbol; } if (isToplevel && !isPrototypeProperty) { // make symbols or add declarations for intermediate containers - const flags = ts.SymbolFlags.Module | ts.SymbolFlags.Assignment; - const excludeFlags = ts.SymbolFlags.ValueModuleExcludes & ~ts.SymbolFlags.Assignment; + const flags = SymbolFlags.Module | SymbolFlags.Assignment; + const excludeFlags = SymbolFlags.ValueModuleExcludes & ~SymbolFlags.Assignment; namespaceSymbol = forEachIdentifierInEntityName(entityName, namespaceSymbol, (id, symbol, parent) => { if (symbol) { addDeclarationToSymbol(symbol, id, flags); @@ -3093,69 +3153,69 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } else { const table = parent ? parent.exports! : - file.jsGlobalAugmentations || (file.jsGlobalAugmentations = ts.createSymbolTable()); + file.jsGlobalAugmentations || (file.jsGlobalAugmentations = createSymbolTable()); return declareSymbol(table, parent, id, flags, excludeFlags); } }); } if (containerIsClass && namespaceSymbol && namespaceSymbol.valueDeclaration) { - addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, ts.SymbolFlags.Class); + addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class); } return namespaceSymbol; } - function bindPotentiallyNewExpandoMemberToNamespace(declaration: ts.BindableStaticAccessExpression | ts.CallExpression, namespaceSymbol: ts.Symbol | undefined, isPrototypeProperty: boolean) { + function bindPotentiallyNewExpandoMemberToNamespace(declaration: BindableStaticAccessExpression | CallExpression, namespaceSymbol: Symbol | undefined, isPrototypeProperty: boolean) { if (!namespaceSymbol || !isExpandoSymbol(namespaceSymbol)) { return; } // Set up the members collection if it doesn't exist already const symbolTable = isPrototypeProperty ? - (namespaceSymbol.members || (namespaceSymbol.members = ts.createSymbolTable())) : - (namespaceSymbol.exports || (namespaceSymbol.exports = ts.createSymbolTable())); + (namespaceSymbol.members || (namespaceSymbol.members = createSymbolTable())) : + (namespaceSymbol.exports || (namespaceSymbol.exports = createSymbolTable())); - let includes = ts.SymbolFlags.None; - let excludes = ts.SymbolFlags.None; + let includes = SymbolFlags.None; + let excludes = SymbolFlags.None; // Method-like - if (ts.isFunctionLikeDeclaration(ts.getAssignedExpandoInitializer(declaration)!)) { - includes = ts.SymbolFlags.Method; - excludes = ts.SymbolFlags.MethodExcludes; + if (isFunctionLikeDeclaration(getAssignedExpandoInitializer(declaration)!)) { + includes = SymbolFlags.Method; + excludes = SymbolFlags.MethodExcludes; } // Maybe accessor-like - else if (ts.isCallExpression(declaration) && ts.isBindableObjectDefinePropertyCall(declaration)) { - if (ts.some(declaration.arguments[2].properties, p => { - const id = ts.getNameOfDeclaration(p); - return !!id && ts.isIdentifier(id) && ts.idText(id) === "set"; + else if (isCallExpression(declaration) && isBindableObjectDefinePropertyCall(declaration)) { + if (some(declaration.arguments[2].properties, p => { + const id = getNameOfDeclaration(p); + return !!id && isIdentifier(id) && idText(id) === "set"; })) { // We mix in `SymbolFLags.Property` so in the checker `getTypeOfVariableParameterOrProperty` is used for this // symbol, instead of `getTypeOfAccessor` (which will assert as there is no real accessor declaration) - includes |= ts.SymbolFlags.SetAccessor | ts.SymbolFlags.Property; - excludes |= ts.SymbolFlags.SetAccessorExcludes; + includes |= SymbolFlags.SetAccessor | SymbolFlags.Property; + excludes |= SymbolFlags.SetAccessorExcludes; } - if (ts.some(declaration.arguments[2].properties, p => { - const id = ts.getNameOfDeclaration(p); - return !!id && ts.isIdentifier(id) && ts.idText(id) === "get"; + if (some(declaration.arguments[2].properties, p => { + const id = getNameOfDeclaration(p); + return !!id && isIdentifier(id) && idText(id) === "get"; })) { - includes |= ts.SymbolFlags.GetAccessor | ts.SymbolFlags.Property; - excludes |= ts.SymbolFlags.GetAccessorExcludes; + includes |= SymbolFlags.GetAccessor | SymbolFlags.Property; + excludes |= SymbolFlags.GetAccessorExcludes; } } - if (includes === ts.SymbolFlags.None) { - includes = ts.SymbolFlags.Property; - excludes = ts.SymbolFlags.PropertyExcludes; + if (includes === SymbolFlags.None) { + includes = SymbolFlags.Property; + excludes = SymbolFlags.PropertyExcludes; } - declareSymbol(symbolTable, namespaceSymbol, declaration, includes | ts.SymbolFlags.Assignment, excludes & ~ts.SymbolFlags.Assignment); + declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment); } - function isTopLevelNamespaceAssignment(propertyAccess: ts.BindableAccessExpression) { - return ts.isBinaryExpression(propertyAccess.parent) - ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === ts.SyntaxKind.SourceFile - : propertyAccess.parent.parent.kind === ts.SyntaxKind.SourceFile; + function isTopLevelNamespaceAssignment(propertyAccess: BindableAccessExpression) { + return isBinaryExpression(propertyAccess.parent) + ? getParentOfBinaryExpression(propertyAccess.parent).parent.kind === SyntaxKind.SourceFile + : propertyAccess.parent.parent.kind === SyntaxKind.SourceFile; } - function bindPropertyAssignment(name: ts.BindableStaticNameExpression, propertyAccess: ts.BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) { + function bindPropertyAssignment(name: BindableStaticNameExpression, propertyAccess: BindableStaticAccessExpression, isPrototypeProperty: boolean, containerIsClass: boolean) { let namespaceSymbol = lookupSymbolForPropertyAccess(name, container) || lookupSymbolForPropertyAccess(name, blockScopeContainer); const isToplevel = isTopLevelNamespaceAssignment(propertyAccess); namespaceSymbol = bindPotentiallyMissingNamespaces(namespaceSymbol, propertyAccess.expression, isToplevel, isPrototypeProperty, containerIsClass); @@ -3172,77 +3232,77 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v * - with empty object literals * - with non-empty object literals if assigned to the prototype property */ - function isExpandoSymbol(symbol: ts.Symbol): boolean { - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Class | ts.SymbolFlags.NamespaceModule)) { + function isExpandoSymbol(symbol: Symbol): boolean { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.NamespaceModule)) { return true; } const node = symbol.valueDeclaration; - if (node && ts.isCallExpression(node)) { - return !!ts.getAssignedExpandoInitializer(node); + if (node && isCallExpression(node)) { + return !!getAssignedExpandoInitializer(node); } let init = !node ? undefined : - ts.isVariableDeclaration(node) ? node.initializer : - ts.isBinaryExpression(node) ? node.right : - ts.isPropertyAccessExpression(node) && ts.isBinaryExpression(node.parent) ? node.parent.right : + isVariableDeclaration(node) ? node.initializer : + isBinaryExpression(node) ? node.right : + isPropertyAccessExpression(node) && isBinaryExpression(node.parent) ? node.parent.right : undefined; - init = init && ts.getRightMostAssignedExpression(init); + init = init && getRightMostAssignedExpression(init); if (init) { - const isPrototypeAssignment = ts.isPrototypeAccess(ts.isVariableDeclaration(node!) ? node.name : ts.isBinaryExpression(node!) ? node.left : node!); - return !!ts.getExpandoInitializer(ts.isBinaryExpression(init) && (init.operatorToken.kind === ts.SyntaxKind.BarBarToken || init.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) ? init.right : init, isPrototypeAssignment); + const isPrototypeAssignment = isPrototypeAccess(isVariableDeclaration(node!) ? node.name : isBinaryExpression(node!) ? node.left : node!); + return !!getExpandoInitializer(isBinaryExpression(init) && (init.operatorToken.kind === SyntaxKind.BarBarToken || init.operatorToken.kind === SyntaxKind.QuestionQuestionToken) ? init.right : init, isPrototypeAssignment); } return false; } - function getParentOfBinaryExpression(expr: ts.Node) { - while (ts.isBinaryExpression(expr.parent)) { + function getParentOfBinaryExpression(expr: Node) { + while (isBinaryExpression(expr.parent)) { expr = expr.parent; } return expr.parent; } - function lookupSymbolForPropertyAccess(node: ts.BindableStaticNameExpression, lookupContainer: ts.Node = container): ts.Symbol | undefined { - if (ts.isIdentifier(node)) { + function lookupSymbolForPropertyAccess(node: BindableStaticNameExpression, lookupContainer: Node = container): Symbol | undefined { + if (isIdentifier(node)) { return lookupSymbolForName(lookupContainer, node.escapedText); } else { const symbol = lookupSymbolForPropertyAccess(node.expression); - return symbol && symbol.exports && symbol.exports.get(ts.getElementOrPropertyAccessName(node)); + return symbol && symbol.exports && symbol.exports.get(getElementOrPropertyAccessName(node)); } } - function forEachIdentifierInEntityName(e: ts.BindableStaticNameExpression, parent: ts.Symbol | undefined, action: (e: ts.Declaration, symbol: ts.Symbol | undefined, parent: ts.Symbol | undefined) => ts.Symbol | undefined): ts.Symbol | undefined { + function forEachIdentifierInEntityName(e: BindableStaticNameExpression, parent: Symbol | undefined, action: (e: Declaration, symbol: Symbol | undefined, parent: Symbol | undefined) => Symbol | undefined): Symbol | undefined { if (isExportsOrModuleExportsOrAlias(file, e)) { return file.symbol; } - else if (ts.isIdentifier(e)) { + else if (isIdentifier(e)) { return action(e, lookupSymbolForPropertyAccess(e), parent); } else { const s = forEachIdentifierInEntityName(e.expression, parent, action); - const name = ts.getNameOrArgument(e); + const name = getNameOrArgument(e); // unreachable - if (ts.isPrivateIdentifier(name)) { - ts.Debug.fail("unexpected PrivateIdentifier"); + if (isPrivateIdentifier(name)) { + Debug.fail("unexpected PrivateIdentifier"); } - return action(name, s && s.exports && s.exports.get(ts.getElementOrPropertyAccessName(e)), s); + return action(name, s && s.exports && s.exports.get(getElementOrPropertyAccessName(e)), s); } } - function bindCallExpression(node: ts.CallExpression) { + function bindCallExpression(node: CallExpression) { // We're only inspecting call expressions to detect CommonJS modules, so we can skip // this check if we've already seen the module indicator - if (!file.commonJsModuleIndicator && ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { + if (!file.commonJsModuleIndicator && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ false)) { setCommonJsModuleIndicator(node); } } - function bindClassLikeDeclaration(node: ts.ClassLikeDeclaration) { - if (node.kind === ts.SyntaxKind.ClassDeclaration) { - bindBlockScopedDeclaration(node, ts.SymbolFlags.Class, ts.SymbolFlags.ClassExcludes); + function bindClassLikeDeclaration(node: ClassLikeDeclaration) { + if (node.kind === SyntaxKind.ClassDeclaration) { + bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { - const bindingName = node.name ? node.name.escapedText : ts.InternalSymbolName.Class; - bindAnonymousDeclaration(node, ts.SymbolFlags.Class, bindingName); + const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Class; + bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName); // Add name of class expression into the map for semantic classifier if (node.name) { classifiableNames.add(node.name.escapedText); @@ -3260,42 +3320,42 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // Note: we check for this here because this class may be merging into a module. The // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. - const prototypeSymbol = createSymbol(ts.SymbolFlags.Property | ts.SymbolFlags.Prototype, "prototype" as ts.__String); + const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype" as __String); const symbolExport = symbol.exports!.get(prototypeSymbol.escapedName); if (symbolExport) { if (node.name) { - ts.setParent(node.name, node); + setParent(node.name, node); } - file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations![0], ts.Diagnostics.Duplicate_identifier_0, ts.symbolName(prototypeSymbol))); + file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations![0], Diagnostics.Duplicate_identifier_0, symbolName(prototypeSymbol))); } symbol.exports!.set(prototypeSymbol.escapedName, prototypeSymbol); prototypeSymbol.parent = symbol; } - function bindEnumDeclaration(node: ts.EnumDeclaration) { - return ts.isEnumConst(node) - ? bindBlockScopedDeclaration(node, ts.SymbolFlags.ConstEnum, ts.SymbolFlags.ConstEnumExcludes) - : bindBlockScopedDeclaration(node, ts.SymbolFlags.RegularEnum, ts.SymbolFlags.RegularEnumExcludes); + function bindEnumDeclaration(node: EnumDeclaration) { + return isEnumConst(node) + ? bindBlockScopedDeclaration(node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes) + : bindBlockScopedDeclaration(node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes); } - function bindVariableDeclarationOrBindingElement(node: ts.VariableDeclaration | ts.BindingElement) { + function bindVariableDeclarationOrBindingElement(node: VariableDeclaration | BindingElement) { if (inStrictMode) { checkStrictModeEvalOrArguments(node, node.name); } - if (!ts.isBindingPattern(node.name)) { - const possibleVariableDecl = node.kind === ts.SyntaxKind.VariableDeclaration ? node : node.parent.parent; - if (ts.isInJSFile(node) && - ts.isVariableDeclarationInitializedToBareOrAccessedRequire(possibleVariableDecl) && - !ts.getJSDocTypeTag(node) && - !(ts.getCombinedModifierFlags(node) & ts.ModifierFlags.Export) + if (!isBindingPattern(node.name)) { + const possibleVariableDecl = node.kind === SyntaxKind.VariableDeclaration ? node : node.parent.parent; + if (isInJSFile(node) && + isVariableDeclarationInitializedToBareOrAccessedRequire(possibleVariableDecl) && + !getJSDocTypeTag(node) && + !(getCombinedModifierFlags(node) & ModifierFlags.Export) ) { - declareSymbolAndAddToSymbolTable(node as ts.Declaration, ts.SymbolFlags.Alias, ts.SymbolFlags.AliasExcludes); + declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } - else if (ts.isBlockOrCatchScoped(node)) { - bindBlockScopedDeclaration(node, ts.SymbolFlags.BlockScopedVariable, ts.SymbolFlags.BlockScopedVariableExcludes); + else if (isBlockOrCatchScoped(node)) { + bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes); } - else if (ts.isParameterDeclaration(node)) { + else if (isParameterDeclaration(node)) { // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration // because its parent chain has already been set up, since parents are set before descending into children. // @@ -3305,138 +3365,138 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // function foo([a,a]) {} // Duplicate Identifier error // function bar(a,a) {} // Duplicate Identifier error, parameter declaration in this case is handled in bindParameter // // which correctly set excluded symbols - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.FunctionScopedVariable, ts.SymbolFlags.ParameterExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes); } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.FunctionScopedVariable, ts.SymbolFlags.FunctionScopedVariableExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); } } } - function bindParameter(node: ts.ParameterDeclaration | ts.JSDocParameterTag) { - if (node.kind === ts.SyntaxKind.JSDocParameterTag && container.kind !== ts.SyntaxKind.JSDocSignature) { + function bindParameter(node: ParameterDeclaration | JSDocParameterTag) { + if (node.kind === SyntaxKind.JSDocParameterTag && container.kind !== SyntaxKind.JSDocSignature) { return; } - if (inStrictMode && !(node.flags & ts.NodeFlags.Ambient)) { + if (inStrictMode && !(node.flags & NodeFlags.Ambient)) { // It is a SyntaxError if the identifier eval or arguments appears within a FormalParameterList of a // strict mode FunctionLikeDeclaration or FunctionExpression(13.1) checkStrictModeEvalOrArguments(node, node.name); } - if (ts.isBindingPattern(node.name)) { - bindAnonymousDeclaration(node, ts.SymbolFlags.FunctionScopedVariable, "__" + (node as ts.ParameterDeclaration).parent.parameters.indexOf(node as ts.ParameterDeclaration) as ts.__String); + if (isBindingPattern(node.name)) { + bindAnonymousDeclaration(node, SymbolFlags.FunctionScopedVariable, "__" + (node as ParameterDeclaration).parent.parameters.indexOf(node as ParameterDeclaration) as __String); } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.FunctionScopedVariable, ts.SymbolFlags.ParameterExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes); } // If this is a property-parameter, then also declare the property symbol into the // containing class. - if (ts.isParameterPropertyDeclaration(node, node.parent)) { + if (isParameterPropertyDeclaration(node, node.parent)) { const classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, ts.SymbolFlags.Property | (node.questionToken ? ts.SymbolFlags.Optional : ts.SymbolFlags.None), ts.SymbolFlags.PropertyExcludes); + declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); } } - function bindFunctionDeclaration(node: ts.FunctionDeclaration) { - if (!file.isDeclarationFile && !(node.flags & ts.NodeFlags.Ambient)) { - if (ts.isAsyncFunction(node)) { - emitFlags |= ts.NodeFlags.HasAsyncFunctions; + function bindFunctionDeclaration(node: FunctionDeclaration) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient)) { + if (isAsyncFunction(node)) { + emitFlags |= NodeFlags.HasAsyncFunctions; } } checkStrictModeFunctionName(node); if (inStrictMode) { checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, ts.SymbolFlags.Function, ts.SymbolFlags.FunctionExcludes); + bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes); } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.Function, ts.SymbolFlags.FunctionExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes); } } - function bindFunctionExpression(node: ts.FunctionExpression) { - if (!file.isDeclarationFile && !(node.flags & ts.NodeFlags.Ambient)) { - if (ts.isAsyncFunction(node)) { - emitFlags |= ts.NodeFlags.HasAsyncFunctions; + function bindFunctionExpression(node: FunctionExpression) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient)) { + if (isAsyncFunction(node)) { + emitFlags |= NodeFlags.HasAsyncFunctions; } } if (currentFlow) { node.flowNode = currentFlow; } checkStrictModeFunctionName(node); - const bindingName = node.name ? node.name.escapedText : ts.InternalSymbolName.Function; - return bindAnonymousDeclaration(node, ts.SymbolFlags.Function, bindingName); + const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Function; + return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName); } - function bindPropertyOrMethodOrAccessor(node: ts.Declaration, symbolFlags: ts.SymbolFlags, symbolExcludes: ts.SymbolFlags) { - if (!file.isDeclarationFile && !(node.flags & ts.NodeFlags.Ambient) && ts.isAsyncFunction(node)) { - emitFlags |= ts.NodeFlags.HasAsyncFunctions; + function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { + if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient) && isAsyncFunction(node)) { + emitFlags |= NodeFlags.HasAsyncFunctions; } - if (currentFlow && ts.isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { + if (currentFlow && isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { node.flowNode = currentFlow; } - return ts.hasDynamicName(node) - ? bindAnonymousDeclaration(node, symbolFlags, ts.InternalSymbolName.Computed) + return hasDynamicName(node) + ? bindAnonymousDeclaration(node, symbolFlags, InternalSymbolName.Computed) : declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes); } - function getInferTypeContainer(node: ts.Node): ts.ConditionalTypeNode | undefined { - const extendsType = ts.findAncestor(node, n => n.parent && ts.isConditionalTypeNode(n.parent) && n.parent.extendsType === n); - return extendsType && extendsType.parent as ts.ConditionalTypeNode; + function getInferTypeContainer(node: Node): ConditionalTypeNode | undefined { + const extendsType = findAncestor(node, n => n.parent && isConditionalTypeNode(n.parent) && n.parent.extendsType === n); + return extendsType && extendsType.parent as ConditionalTypeNode; } - function bindTypeParameter(node: ts.TypeParameterDeclaration) { - if (ts.isJSDocTemplateTag(node.parent)) { - const container = ts.getEffectiveContainerForJSDocTemplateTag(node.parent); + function bindTypeParameter(node: TypeParameterDeclaration) { + if (isJSDocTemplateTag(node.parent)) { + const container = getEffectiveContainerForJSDocTemplateTag(node.parent); if (container) { if (!container.locals) { - container.locals = ts.createSymbolTable(); + container.locals = createSymbolTable(); } - declareSymbol(container.locals, /*parent*/ undefined, node, ts.SymbolFlags.TypeParameter, ts.SymbolFlags.TypeParameterExcludes); + declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.TypeParameter, ts.SymbolFlags.TypeParameterExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } } - else if (node.parent.kind === ts.SyntaxKind.InferType) { + else if (node.parent.kind === SyntaxKind.InferType) { const container = getInferTypeContainer(node.parent); if (container) { if (!container.locals) { - container.locals = ts.createSymbolTable(); + container.locals = createSymbolTable(); } - declareSymbol(container.locals, /*parent*/ undefined, node, ts.SymbolFlags.TypeParameter, ts.SymbolFlags.TypeParameterExcludes); + declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { - bindAnonymousDeclaration(node, ts.SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217 + bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217 } } else { - declareSymbolAndAddToSymbolTable(node, ts.SymbolFlags.TypeParameter, ts.SymbolFlags.TypeParameterExcludes); + declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } } // reachability checks - function shouldReportErrorOnModuleDeclaration(node: ts.ModuleDeclaration): boolean { + function shouldReportErrorOnModuleDeclaration(node: ModuleDeclaration): boolean { const instanceState = getModuleInstanceState(node); - return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && ts.shouldPreserveConstEnums(options)); + return instanceState === ModuleInstanceState.Instantiated || (instanceState === ModuleInstanceState.ConstEnumOnly && shouldPreserveConstEnums(options)); } - function checkUnreachable(node: ts.Node): boolean { - if (!(currentFlow.flags & ts.FlowFlags.Unreachable)) { + function checkUnreachable(node: Node): boolean { + if (!(currentFlow.flags & FlowFlags.Unreachable)) { return false; } if (currentFlow === unreachableFlow) { const reportError = // report error on all statements except empty ones - (ts.isStatementButNotDeclaration(node) && node.kind !== ts.SyntaxKind.EmptyStatement) || + (isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) || // report error on class declarations - node.kind === ts.SyntaxKind.ClassDeclaration || + node.kind === SyntaxKind.ClassDeclaration || // report error on instantiated modules or const-enums only modules if preserveConstEnums is set - (node.kind === ts.SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(node as ts.ModuleDeclaration)); + (node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(node as ModuleDeclaration)); if (reportError) { currentFlow = reportedUnreachableFlow; @@ -3452,15 +3512,15 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v // Rationale: we don't want to report errors on non-initialized var's since they are hoisted // On the other side we do want to report errors on non-initialized 'lets' because of TDZ const isError = - ts.unreachableCodeIsError(options) && - !(node.flags & ts.NodeFlags.Ambient) && + unreachableCodeIsError(options) && + !(node.flags & NodeFlags.Ambient) && ( - !ts.isVariableStatement(node) || - !!(ts.getCombinedNodeFlags(node.declarationList) & ts.NodeFlags.BlockScoped) || + !isVariableStatement(node) || + !!(getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) || node.declarationList.declarations.some(d => !!d.initializer) ); - eachUnreachableRange(node, (start, end) => errorOrSuggestionOnRange(isError, start, end, ts.Diagnostics.Unreachable_code_detected)); + eachUnreachableRange(node, (start, end) => errorOrSuggestionOnRange(isError, start, end, Diagnostics.Unreachable_code_detected)); } } } @@ -3468,55 +3528,55 @@ function createBinder(): (file: ts.SourceFile, options: ts.CompilerOptions) => v } } -function eachUnreachableRange(node: ts.Node, cb: (start: ts.Node, last: ts.Node) => void): void { - if (ts.isStatement(node) && isExecutableStatement(node) && ts.isBlock(node.parent)) { +function eachUnreachableRange(node: Node, cb: (start: Node, last: Node) => void): void { + if (isStatement(node) && isExecutableStatement(node) && isBlock(node.parent)) { const { statements } = node.parent; - const slice = ts.sliceAfter(statements, node); - ts.getRangesWhere(slice, isExecutableStatement, (start, afterEnd) => cb(slice[start], slice[afterEnd - 1])); + const slice = sliceAfter(statements, node); + getRangesWhere(slice, isExecutableStatement, (start, afterEnd) => cb(slice[start], slice[afterEnd - 1])); } else { cb(node, node); } } // As opposed to a pure declaration like an `interface` -function isExecutableStatement(s: ts.Statement): boolean { +function isExecutableStatement(s: Statement): boolean { // Don't remove statements that can validly be used before they appear. - return !ts.isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !ts.isEnumDeclaration(s) && + return !isFunctionDeclaration(s) && !isPurelyTypeDeclaration(s) && !isEnumDeclaration(s) && // `var x;` may declare a variable used above - !(ts.isVariableStatement(s) && !(ts.getCombinedNodeFlags(s) & (ts.NodeFlags.Let | ts.NodeFlags.Const)) && s.declarationList.declarations.some(d => !d.initializer)); + !(isVariableStatement(s) && !(getCombinedNodeFlags(s) & (NodeFlags.Let | NodeFlags.Const)) && s.declarationList.declarations.some(d => !d.initializer)); } -function isPurelyTypeDeclaration(s: ts.Statement): boolean { +function isPurelyTypeDeclaration(s: Statement): boolean { switch (s.kind) { - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: return true; - case ts.SyntaxKind.ModuleDeclaration: - return getModuleInstanceState(s as ts.ModuleDeclaration) !== ModuleInstanceState.Instantiated; - case ts.SyntaxKind.EnumDeclaration: - return ts.hasSyntacticModifier(s, ts.ModifierFlags.Const); + case SyntaxKind.ModuleDeclaration: + return getModuleInstanceState(s as ModuleDeclaration) !== ModuleInstanceState.Instantiated; + case SyntaxKind.EnumDeclaration: + return hasSyntacticModifier(s, ModifierFlags.Const); default: return false; } } /** @internal */ -export function isExportsOrModuleExportsOrAlias(sourceFile: ts.SourceFile, node: ts.Expression): boolean { +export function isExportsOrModuleExportsOrAlias(sourceFile: SourceFile, node: Expression): boolean { let i = 0; - const q = ts.createQueue(); + const q = createQueue(); q.enqueue(node); while (!q.isEmpty() && i < 100) { i++; node = q.dequeue(); - if (ts.isExportsIdentifier(node) || ts.isModuleExportsAccessExpression(node)) { + if (isExportsIdentifier(node) || isModuleExportsAccessExpression(node)) { return true; } - else if (ts.isIdentifier(node)) { + else if (isIdentifier(node)) { const symbol = lookupSymbolForName(sourceFile, node.escapedText); - if (!!symbol && !!symbol.valueDeclaration && ts.isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) { + if (!!symbol && !!symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && !!symbol.valueDeclaration.initializer) { const init = symbol.valueDeclaration.initializer; q.enqueue(init); - if (ts.isAssignmentExpression(init, /*excludeCompoundAssignment*/ true)) { + if (isAssignmentExpression(init, /*excludeCompoundAssignment*/ true)) { q.enqueue(init.left); q.enqueue(init.right); } @@ -3526,12 +3586,12 @@ export function isExportsOrModuleExportsOrAlias(sourceFile: ts.SourceFile, node: return false; } -function lookupSymbolForName(container: ts.Node, name: ts.__String): ts.Symbol | undefined { +function lookupSymbolForName(container: Node, name: __String): Symbol | undefined { const local = container.locals && container.locals.get(name); if (local) { return local.exportSymbol || local; } - if (ts.isSourceFile(container) && container.jsGlobalAugmentations && container.jsGlobalAugmentations.has(name)) { + if (isSourceFile(container) && container.jsGlobalAugmentations && container.jsGlobalAugmentations.has(name)) { return container.jsGlobalAugmentations.get(name); } return container.symbol && container.symbol.exports && container.symbol.exports.get(name); diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 1fa1e1c71974d..dfc492c78086c 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -1,4 +1,20 @@ import * as ts from "./_namespaces/ts"; +import { + addRange, AffectedFileResult, arrayFrom, arrayToMap, BuilderProgram, BuilderProgramHost, BuilderState, BuildInfo, + BundleBuildInfo, CancellationToken, CommandLineOption, compareStringsCaseSensitive, compareValues, CompilerHost, + CompilerOptions, compilerOptionsAffectDeclarationPath, compilerOptionsAffectEmit, + compilerOptionsAffectSemanticDiagnostics, CompilerOptionsValue, concatenate, convertToOptionsWithAbsolutePaths, + createBuildInfo, createGetCanonicalFileName, createProgram, CustomTransformers, Debug, Diagnostic, + DiagnosticCategory, DiagnosticMessageChain, DiagnosticRelatedInformation, DiagnosticWithLocation, + EmitAndSemanticDiagnosticsBuilderProgram, EmitOnly, EmitResult, emitSkippedWithNoDiagnostics, emptyArray, + ensurePathIsNonModuleName, ESMap, filterSemanticDiagnostics, forEach, forEachEntry, forEachKey, generateDjb2Hash, + GetCanonicalFileName, getDirectoryPath, getEmitDeclarations, getNormalizedAbsolutePath, getOptionsNameMap, + getOwnKeys, getRelativePathFromDirectory, getTsBuildInfoEmitOutputFilePath, handleNoEmitOptions, isArray, + isDeclarationFileName, isJsonSourceFile, isNumber, isString, map, Map, mapDefined, maybeBind, noop, notImplemented, + outFile, Path, Program, ProjectReference, ReadBuildProgramHost, ReadonlyCollection, ReadonlyESMap, ReadonlySet, + returnFalse, returnUndefined, SemanticDiagnosticsBuilderProgram, Set, skipTypeChecking, some, SourceFile, + sourceFileMayBeEmitted, SourceMapEmitResult, toPath, tryAddToSet, WriteFileCallback, WriteFileCallbackData, +} from "./_namespaces/ts"; /** @internal */ export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation { @@ -7,12 +23,12 @@ export interface ReusableDiagnostic extends ReusableDiagnosticRelatedInformation reportDeprecated?: {} source?: string; relatedInformation?: ReusableDiagnosticRelatedInformation[]; - skippedOn?: keyof ts.CompilerOptions; + skippedOn?: keyof CompilerOptions; } /** @internal */ export interface ReusableDiagnosticRelatedInformation { - category: ts.DiagnosticCategory; + category: DiagnosticCategory; code: number; file: string | undefined; start: number | undefined; @@ -21,34 +37,34 @@ export interface ReusableDiagnosticRelatedInformation { } /** @internal */ -export type ReusableDiagnosticMessageChain = ts.DiagnosticMessageChain; +export type ReusableDiagnosticMessageChain = DiagnosticMessageChain; /** @internal */ /** Signature (Hash of d.ts emitted), is string if it was emitted using same d.ts.map option as what compilerOptions indicate, otherwise tuple of string */ export type EmitSignature = string | [signature: string]; /** @internal */ -export interface ReusableBuilderProgramState extends ts.BuilderState { +export interface ReusableBuilderProgramState extends BuilderState { /** * Cache of bind and check diagnostics for files with their Path being the key */ - semanticDiagnosticsPerFile?: ts.ESMap | undefined; + semanticDiagnosticsPerFile?: ESMap | undefined; /** * The map has key by source file's path that has been changed */ - changedFilesSet?: ts.Set; + changedFilesSet?: Set; /** * program corresponding to this state */ - program?: ts.Program | undefined; + program?: Program | undefined; /** * compilerOptions for the program */ - compilerOptions: ts.CompilerOptions; + compilerOptions: CompilerOptions; /** * Files pending to be emitted */ - affectedFilesPendingEmit?: ts.ReadonlyESMap; + affectedFilesPendingEmit?: ReadonlyESMap; /** * emitKind pending for a program with --out */ @@ -60,7 +76,7 @@ export interface ReusableBuilderProgramState extends ts.BuilderState { /** * Hash of d.ts emitted for the file, use to track when emit of d.ts changes */ - emitSignatures?: ts.ESMap; + emitSignatures?: ESMap; /** * Hash of d.ts emit with --out */ @@ -72,7 +88,7 @@ export interface ReusableBuilderProgramState extends ts.BuilderState { /** * Bundle information either from oldState or current one so it can be used to complete the information in buildInfo when emitting only js or dts files */ - bundle?: ts.BundleBuildInfo; + bundle?: BundleBuildInfo; } /** @internal */ @@ -94,19 +110,19 @@ export const enum BuilderFileEmit { * State to store the changed files, affected files and cache semantic diagnostics */ // TODO: GH#18217 Properties of this interface are frequently asserted to be defined. -export interface BuilderProgramState extends ts.BuilderState, ReusableBuilderProgramState { +export interface BuilderProgramState extends BuilderState, ReusableBuilderProgramState { /** * Cache of bind and check diagnostics for files with their Path being the key */ - semanticDiagnosticsPerFile: ts.ESMap | undefined; + semanticDiagnosticsPerFile: ESMap | undefined; /** * The map has key by source file's path that has been changed */ - changedFilesSet: ts.Set; + changedFilesSet: Set; /** * Set of affected files being iterated */ - affectedFiles?: readonly ts.SourceFile[] | undefined; + affectedFiles?: readonly SourceFile[] | undefined; /** * Current index to retrieve affected file from */ @@ -114,11 +130,11 @@ export interface BuilderProgramState extends ts.BuilderState, ReusableBuilderPro /** * Current changed file for iterating over affected files */ - currentChangedFilePath?: ts.Path | undefined; + currentChangedFilePath?: Path | undefined; /** * Already seen affected files */ - seenAffectedFiles: ts.Set | undefined; + seenAffectedFiles: Set | undefined; /** * whether this program has cleaned semantic diagnostics cache for lib files */ @@ -126,7 +142,7 @@ export interface BuilderProgramState extends ts.BuilderState, ReusableBuilderPro /** * True if the semantic diagnostics were copied from the old state */ - semanticDiagnosticsFromOldState?: ts.Set; + semanticDiagnosticsFromOldState?: Set; /** * Records if change in dts emit was detected */ @@ -134,7 +150,7 @@ export interface BuilderProgramState extends ts.BuilderState, ReusableBuilderPro /** * Files pending to be emitted */ - affectedFilesPendingEmit?: ts.ESMap; + affectedFilesPendingEmit?: ESMap; /** * true if build info is emitted */ @@ -142,9 +158,9 @@ export interface BuilderProgramState extends ts.BuilderState, ReusableBuilderPro /** * Already seen emitted files */ - seenEmittedFiles: ts.ESMap | undefined; + seenEmittedFiles: ESMap | undefined; /** Stores list of files that change signature during emit - test only */ - filesChangingSignature?: ts.Set; + filesChangingSignature?: Set; } /** @internal */ @@ -160,11 +176,11 @@ export type SavedBuildProgramEmitState = Pick | undefined, map2: ts.ReadonlyCollection | undefined): boolean { +function hasSameKeys(map1: ReadonlyCollection | undefined, map2: ReadonlyCollection | undefined): boolean { // Has same size and every key is present in both maps - return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !ts.forEachKey(map1, key => !map2.has(key)); + return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); } /** * Create the state so that we can iterate on changedFiles/affected files */ -function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: ts.GetCanonicalFileName, oldState: Readonly | undefined, disableUseFileVersionAsSignature: boolean | undefined): BuilderProgramState { - const state = ts.BuilderState.create(newProgram, getCanonicalFileName, oldState, disableUseFileVersionAsSignature) as BuilderProgramState; +function createBuilderProgramState(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState: Readonly | undefined, disableUseFileVersionAsSignature: boolean | undefined): BuilderProgramState { + const state = BuilderState.create(newProgram, getCanonicalFileName, oldState, disableUseFileVersionAsSignature) as BuilderProgramState; state.program = newProgram; const compilerOptions = newProgram.getCompilerOptions(); state.compilerOptions = compilerOptions; - const outFilePath = ts.outFile(compilerOptions); + const outFilePath = outFile(compilerOptions); // With --out or --outFile, any change affects all semantic diagnostics so no need to cache them if (!outFilePath) { - state.semanticDiagnosticsPerFile = new ts.Map(); + state.semanticDiagnosticsPerFile = new Map(); } - else if (compilerOptions.composite && oldState?.outSignature && outFilePath === ts.outFile(oldState?.compilerOptions)) { + else if (compilerOptions.composite && oldState?.outSignature && outFilePath === outFile(oldState?.compilerOptions)) { state.outSignature = oldState.outSignature && getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldState.outSignature); } - state.changedFilesSet = new ts.Set(); + state.changedFilesSet = new Set(); state.latestChangedDtsFile = compilerOptions.composite ? oldState?.latestChangedDtsFile : undefined; - const useOldState = ts.BuilderState.canReuseOldState(state.referencedMap, oldState); + const useOldState = BuilderState.canReuseOldState(state.referencedMap, oldState); const oldCompilerOptions = useOldState ? oldState!.compilerOptions : undefined; const canCopySemanticDiagnostics = useOldState && oldState!.semanticDiagnosticsPerFile && !!state.semanticDiagnosticsPerFile && - !ts.compilerOptionsAffectSemanticDiagnostics(compilerOptions, oldCompilerOptions!); + !compilerOptionsAffectSemanticDiagnostics(compilerOptions, oldCompilerOptions!); // We can only reuse emit signatures (i.e. .d.ts signatures) if the .d.ts file is unchanged, // which will eg be depedent on change in options like declarationDir and outDir options are unchanged. // We need to look in oldState.compilerOptions, rather than oldCompilerOptions (i.e.we need to disregard useOldState) because @@ -223,13 +239,13 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: const canCopyEmitSignatures = compilerOptions.composite && oldState?.emitSignatures && !outFilePath && - !ts.compilerOptionsAffectDeclarationPath(compilerOptions, oldState.compilerOptions); + !compilerOptionsAffectDeclarationPath(compilerOptions, oldState.compilerOptions); if (useOldState) { // Copy old state's changed files set oldState!.changedFilesSet?.forEach(value => state.changedFilesSet.add(value)); if (!outFilePath && oldState!.affectedFilesPendingEmit?.size) { - state.affectedFilesPendingEmit = new ts.Map(oldState!.affectedFilesPendingEmit); - state.seenAffectedFiles = new ts.Set(); + state.affectedFilesPendingEmit = new Map(oldState!.affectedFilesPendingEmit); + state.seenAffectedFiles = new Set(); } state.programEmitPending = oldState!.programEmitPending; } @@ -244,8 +260,8 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: const copyDeclarationFileDiagnostics = canCopySemanticDiagnostics && !compilerOptions.skipLibCheck === !oldCompilerOptions!.skipLibCheck; const copyLibFileDiagnostics = copyDeclarationFileDiagnostics && !compilerOptions.skipDefaultLibCheck === !oldCompilerOptions!.skipDefaultLibCheck; state.fileInfos.forEach((info, sourceFilePath) => { - let oldInfo: Readonly | undefined; - let newReferences: ts.ReadonlySet | undefined; + let oldInfo: Readonly | undefined; + let newReferences: ReadonlySet | undefined; // if not using old state, every file is changed if (!useOldState || @@ -258,7 +274,7 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: // Referenced files changed !hasSameKeys(newReferences = referencedMap && referencedMap.getValues(sourceFilePath), oldReferencedMap && oldReferencedMap.getValues(sourceFilePath)) || // Referenced file was deleted in the new program - newReferences && ts.forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) { + newReferences && forEachKey(newReferences, path => !state.fileInfos.has(path) && oldState!.fileInfos.has(path))) { // Register file as changed file and do not copy semantic diagnostics, since all changed files need to be re-evaluated addFileToChangeSet(state, sourceFilePath); } @@ -271,9 +287,9 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: // Unchanged file copy diagnostics const diagnostics = oldState!.semanticDiagnosticsPerFile!.get(sourceFilePath); if (diagnostics) { - state.semanticDiagnosticsPerFile!.set(sourceFilePath, oldState!.hasReusableDiagnostic ? convertToDiagnostics(diagnostics as readonly ReusableDiagnostic[], newProgram, getCanonicalFileName) : diagnostics as readonly ts.Diagnostic[]); + state.semanticDiagnosticsPerFile!.set(sourceFilePath, oldState!.hasReusableDiagnostic ? convertToDiagnostics(diagnostics as readonly ReusableDiagnostic[], newProgram, getCanonicalFileName) : diagnostics as readonly Diagnostic[]); if (!state.semanticDiagnosticsFromOldState) { - state.semanticDiagnosticsFromOldState = new ts.Set(); + state.semanticDiagnosticsFromOldState = new Set(); } state.semanticDiagnosticsFromOldState.add(sourceFilePath); } @@ -281,20 +297,20 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: if (canCopyEmitSignatures) { const oldEmitSignature = oldState.emitSignatures.get(sourceFilePath); if (oldEmitSignature) { - (state.emitSignatures ??= new ts.Map()).set(sourceFilePath, getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldEmitSignature)); + (state.emitSignatures ??= new Map()).set(sourceFilePath, getEmitSignatureFromOldSignature(compilerOptions, oldState.compilerOptions, oldEmitSignature)); } } }); // If the global file is removed, add all files as changed - if (useOldState && ts.forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => (outFilePath || info.affectsGlobalScope) && !state.fileInfos.has(sourceFilePath))) { - ts.BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined) + if (useOldState && forEachEntry(oldState!.fileInfos, (info, sourceFilePath) => (outFilePath || info.affectsGlobalScope) && !state.fileInfos.has(sourceFilePath))) { + BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined) .forEach(file => addFileToChangeSet(state, file.resolvedPath)); } else if (oldCompilerOptions) { // If options affect emit, then we need to do complete emit per compiler options // otherwise only the js or dts that needs to emitted because its different from previously emitted options - const pendingEmitKind = ts.compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions) ? + const pendingEmitKind = compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions) ? getBuilderFileEmit(compilerOptions) : getPendingEmitKind(compilerOptions, oldCompilerOptions); if (pendingEmitKind !== BuilderFileEmit.None) { @@ -310,8 +326,8 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: ); } }); - ts.Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size); - state.seenAffectedFiles = state.seenAffectedFiles || new ts.Set(); + Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size); + state.seenAffectedFiles = state.seenAffectedFiles || new Set(); state.buildInfoEmitPending = true; } else { @@ -325,12 +341,12 @@ function createBuilderProgramState(newProgram: ts.Program, getCanonicalFileName: // Copy the bundle information from old state so we can patch it later if we are doing partial emit if (useOldState) state.bundle = oldState!.bundle; // If this program has prepend references, always emit since we wont know if files on disk are correct unless we check file hash for correctness - if (ts.some(newProgram.getProjectReferences(), ref => !!ref.prepend)) state.programEmitPending = getBuilderFileEmit(compilerOptions); + if (some(newProgram.getProjectReferences(), ref => !!ref.prepend)) state.programEmitPending = getBuilderFileEmit(compilerOptions); } return state; } -function addFileToChangeSet(state: BuilderProgramState, path: ts.Path) { +function addFileToChangeSet(state: BuilderProgramState, path: Path) { state.changedFilesSet.add(path); state.buildInfoEmitPending = true; // Setting this to undefined as changed files means full emit so no need to track emit explicitly @@ -341,19 +357,19 @@ function addFileToChangeSet(state: BuilderProgramState, path: ts.Path) { * Covert to Emit signature based on oldOptions and EmitSignature format * If d.ts map options differ then swap the format, otherwise use as is */ -function getEmitSignatureFromOldSignature(options: ts.CompilerOptions, oldOptions: ts.CompilerOptions, oldEmitSignature: EmitSignature): EmitSignature { +function getEmitSignatureFromOldSignature(options: CompilerOptions, oldOptions: CompilerOptions, oldEmitSignature: EmitSignature): EmitSignature { return !!options.declarationMap === !!oldOptions.declarationMap ? // Use same format of signature oldEmitSignature : // Convert to different format - ts.isString(oldEmitSignature) ? [oldEmitSignature] : oldEmitSignature[0]; + isString(oldEmitSignature) ? [oldEmitSignature] : oldEmitSignature[0]; } -function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newProgram: ts.Program, getCanonicalFileName: ts.GetCanonicalFileName): readonly ts.Diagnostic[] { - if (!diagnostics.length) return ts.emptyArray; - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(ts.getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory())); +function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newProgram: Program, getCanonicalFileName: GetCanonicalFileName): readonly Diagnostic[] { + if (!diagnostics.length) return emptyArray; + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(newProgram.getCompilerOptions())!, newProgram.getCurrentDirectory())); return diagnostics.map(diagnostic => { - const result: ts.Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram, toPath); + const result: Diagnostic = convertToDiagnosticRelatedInformation(diagnostic, newProgram, toPath); result.reportsUnnecessary = diagnostic.reportsUnnecessary; result.reportsDeprecated = diagnostic.reportDeprecated; result.source = diagnostic.source; @@ -372,7 +388,7 @@ function convertToDiagnostics(diagnostics: readonly ReusableDiagnostic[], newPro } } -function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRelatedInformation, newProgram: ts.Program, toPath: (path: string) => ts.Path): ts.DiagnosticRelatedInformation { +function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRelatedInformation, newProgram: Program, toPath: (path: string) => Path): DiagnosticRelatedInformation { const { file } = diagnostic; return { ...diagnostic, @@ -384,23 +400,23 @@ function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRel * Releases program and other related not needed properties */ function releaseCache(state: BuilderProgramState) { - ts.BuilderState.releaseCache(state); + BuilderState.releaseCache(state); state.program = undefined; } function backupBuilderProgramEmitState(state: Readonly): SavedBuildProgramEmitState { - const outFilePath = ts.outFile(state.compilerOptions); + const outFilePath = outFile(state.compilerOptions); // Only in --out changeFileSet is kept around till emit - ts.Debug.assert(!state.changedFilesSet.size || outFilePath); + Debug.assert(!state.changedFilesSet.size || outFilePath); return { - affectedFilesPendingEmit: state.affectedFilesPendingEmit && new ts.Map(state.affectedFilesPendingEmit), - seenEmittedFiles: state.seenEmittedFiles && new ts.Map(state.seenEmittedFiles), + affectedFilesPendingEmit: state.affectedFilesPendingEmit && new Map(state.affectedFilesPendingEmit), + seenEmittedFiles: state.seenEmittedFiles && new Map(state.seenEmittedFiles), programEmitPending: state.programEmitPending, - emitSignatures: state.emitSignatures && new ts.Map(state.emitSignatures), + emitSignatures: state.emitSignatures && new Map(state.emitSignatures), outSignature: state.outSignature, latestChangedDtsFile: state.latestChangedDtsFile, hasChangedEmitSignature: state.hasChangedEmitSignature, - changedFilesSet: outFilePath ? new ts.Set(state.changedFilesSet) : undefined, + changedFilesSet: outFilePath ? new Set(state.changedFilesSet) : undefined, }; } @@ -418,8 +434,8 @@ function restoreBuilderProgramEmitState(state: BuilderProgramState, savedEmitSta /** * Verifies that source file is ok to be used in calls that arent handled by next */ -function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: ts.SourceFile | undefined) { - ts.Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath)); +function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, sourceFile: SourceFile | undefined) { + Debug.assert(!sourceFile || !state.affectedFiles || state.affectedFiles[state.affectedFilesIndex! - 1] !== sourceFile || !state.semanticDiagnosticsPerFile!.has(sourceFile.resolvedPath)); } /** @@ -430,11 +446,11 @@ function assertSourceFileOkWithoutNextAffectedCall(state: BuilderProgramState, s */ function getNextAffectedFile( state: BuilderProgramState, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost -): ts.SourceFile | ts.Program | undefined { + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost +): SourceFile | Program | undefined { while (true) { const { affectedFiles } = state; if (affectedFiles) { @@ -477,15 +493,15 @@ function getNextAffectedFile( // With --out or --outFile all outputs go into single file // so operations are performed directly on program, return program - const program = ts.Debug.checkDefined(state.program); + const program = Debug.checkDefined(state.program); const compilerOptions = program.getCompilerOptions(); - if (ts.outFile(compilerOptions)) { - ts.Debug.assert(!state.semanticDiagnosticsPerFile); + if (outFile(compilerOptions)) { + Debug.assert(!state.semanticDiagnosticsPerFile); return program; } // Get next batch of affected files - state.affectedFiles = ts.BuilderState.getFilesAffectedByWithOldState( + state.affectedFiles = BuilderState.getFilesAffectedByWithOldState( state, program, nextKey.value, @@ -495,7 +511,7 @@ function getNextAffectedFile( ); state.currentChangedFilePath = nextKey.value; state.affectedFilesIndex = 0; - if (!state.seenAffectedFiles) state.seenAffectedFiles = new ts.Set(); + if (!state.seenAffectedFiles) state.seenAffectedFiles = new Set(); } } @@ -515,9 +531,9 @@ function clearAffectedFilesPendingEmit(state: BuilderProgramState, emitOnlyDtsFi */ function getNextAffectedFilePendingEmit(state: BuilderProgramState, emitOnlyDtsFiles: boolean | undefined) { if (!state.affectedFilesPendingEmit?.size) return undefined; - return ts.forEachEntry(state.affectedFilesPendingEmit, (emitKind, path) => { + return forEachEntry(state.affectedFilesPendingEmit, (emitKind, path) => { const affectedFile = state.program!.getSourceFileByPath(path); - if (!affectedFile || !ts.sourceFileMayBeEmitted(affectedFile, state.program!)) { + if (!affectedFile || !sourceFileMayBeEmitted(affectedFile, state.program!)) { state.affectedFilesPendingEmit!.delete(path); return undefined; } @@ -531,11 +547,11 @@ function getNextAffectedFilePendingEmit(state: BuilderProgramState, emitOnlyDtsF function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) { if (!state.cleanedDiagnosticsOfLibFiles) { state.cleanedDiagnosticsOfLibFiles = true; - const program = ts.Debug.checkDefined(state.program); + const program = Debug.checkDefined(state.program); const options = program.getCompilerOptions(); - ts.forEach(program.getSourceFiles(), f => + forEach(program.getSourceFiles(), f => program.isSourceFileDefaultLibrary(f) && - !ts.skipTypeChecking(f, options, program) && + !skipTypeChecking(f, options, program) && removeSemanticDiagnosticsOf(state, f.resolvedPath) ); } @@ -547,11 +563,11 @@ function removeDiagnosticsOfLibraryFiles(state: BuilderProgramState) { */ function handleDtsMayChangeOfAffectedFile( state: BuilderProgramState, - affectedFile: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost, + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost, ) { removeSemanticDiagnosticsOf(state, affectedFile.resolvedPath); @@ -561,9 +577,9 @@ function handleDtsMayChangeOfAffectedFile( // When a change affects the global scope, all files are considered to be affected without updating their signature // That means when affected file is handled, its signature can be out of date // To avoid this, ensure that we update the signature for any affected file in this scenario. - ts.BuilderState.updateShapeSignature( + BuilderState.updateShapeSignature( state, - ts.Debug.checkDefined(state.program), + Debug.checkDefined(state.program), affectedFile, cancellationToken, computeHash, @@ -588,16 +604,16 @@ function handleDtsMayChangeOfAffectedFile( */ function handleDtsMayChangeOf( state: BuilderProgramState, - path: ts.Path, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost + path: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost ): void { removeSemanticDiagnosticsOf(state, path); if (!state.changedFilesSet.has(path)) { - const program = ts.Debug.checkDefined(state.program); + const program = Debug.checkDefined(state.program); const sourceFile = program.getSourceFileByPath(path); if (sourceFile) { // Even though the js emit doesnt change and we are already handling dts emit and semantic diagnostics @@ -605,7 +621,7 @@ function handleDtsMayChangeOf( // This ensures that we dont later during incremental builds considering wrong signature. // Eg where this also is needed to ensure that .tsbuildinfo generated by incremental build should be same as if it was first fresh build // But we avoid expensive full shape computation, as using file version as shape is enough for correctness. - ts.BuilderState.updateShapeSignature( + BuilderState.updateShapeSignature( state, program, sourceFile, @@ -615,7 +631,7 @@ function handleDtsMayChangeOf( !host.disableUseFileVersionAsSignature ); // If not dts emit, nothing more to do - if (ts.getEmitDeclarations(state.compilerOptions)) { + if (getEmitDeclarations(state.compilerOptions)) { addToAffectedFilesPendingEmit(state, path, state.compilerOptions.declarationMap ? BuilderFileEmit.AllDts : BuilderFileEmit.Dts); } } @@ -626,7 +642,7 @@ function handleDtsMayChangeOf( * Removes semantic diagnostics for path and * returns true if there are no more semantic diagnostics from the old state */ -function removeSemanticDiagnosticsOf(state: BuilderProgramState, path: ts.Path) { +function removeSemanticDiagnosticsOf(state: BuilderProgramState, path: Path) { if (!state.semanticDiagnosticsFromOldState) { return true; } @@ -635,23 +651,23 @@ function removeSemanticDiagnosticsOf(state: BuilderProgramState, path: ts.Path) return !state.semanticDiagnosticsFromOldState.size; } -function isChangedSignature(state: BuilderProgramState, path: ts.Path) { - const oldSignature = ts.Debug.checkDefined(state.oldSignatures).get(path) || undefined; - const newSignature = ts.Debug.checkDefined(state.fileInfos.get(path)).signature; +function isChangedSignature(state: BuilderProgramState, path: Path) { + const oldSignature = Debug.checkDefined(state.oldSignatures).get(path) || undefined; + const newSignature = Debug.checkDefined(state.fileInfos.get(path)).signature; return newSignature !== oldSignature; } function handleDtsMayChangeOfGlobalScope( state: BuilderProgramState, - filePath: ts.Path, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost, + filePath: Path, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost, ): boolean { if (!state.fileInfos.get(filePath)?.affectsGlobalScope) return false; // Every file needs to be handled - ts.BuilderState.getAllFilesExcludingDefaultLibraryFile(state, state.program!, /*firstSourceFile*/ undefined) + BuilderState.getAllFilesExcludingDefaultLibraryFile(state, state.program!, /*firstSourceFile*/ undefined) .forEach(file => handleDtsMayChangeOf( state, file.resolvedPath, @@ -669,11 +685,11 @@ function handleDtsMayChangeOfGlobalScope( */ function handleDtsMayChangeOfReferencingExportOfAffectedFile( state: BuilderProgramState, - affectedFile: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost + affectedFile: SourceFile, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost ) { // If there was change in signature (dts output) for the changed file, // then only we need to handle pending file emit @@ -683,9 +699,9 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile( // Since isolated modules dont change js files, files affected by change in signature is itself // But we need to cleanup semantic diagnostics and queue dts emit for affected files if (state.compilerOptions.isolatedModules) { - const seenFileNamesMap = new ts.Map(); + const seenFileNamesMap = new Map(); seenFileNamesMap.set(affectedFile.resolvedPath, true); - const queue = ts.BuilderState.getReferencedByPaths(state, affectedFile.resolvedPath); + const queue = BuilderState.getReferencedByPaths(state, affectedFile.resolvedPath); while (queue.length > 0) { const currentPath = queue.pop()!; if (!seenFileNamesMap.has(currentPath)) { @@ -693,20 +709,20 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile( if (handleDtsMayChangeOfGlobalScope(state, currentPath, cancellationToken, computeHash, getCanonicalFileName, host)) return; handleDtsMayChangeOf(state, currentPath, cancellationToken, computeHash, getCanonicalFileName, host); if (isChangedSignature(state, currentPath)) { - const currentSourceFile = ts.Debug.checkDefined(state.program).getSourceFileByPath(currentPath)!; - queue.push(...ts.BuilderState.getReferencedByPaths(state, currentSourceFile.resolvedPath)); + const currentSourceFile = Debug.checkDefined(state.program).getSourceFileByPath(currentPath)!; + queue.push(...BuilderState.getReferencedByPaths(state, currentSourceFile.resolvedPath)); } } } } - const seenFileAndExportsOfFile = new ts.Set(); + const seenFileAndExportsOfFile = new Set(); // Go through exported modules from cache first // If exported modules has path, all files referencing file exported from are affected state.exportedModulesMap.getKeys(affectedFile.resolvedPath)?.forEach(exportedFromPath => { if (handleDtsMayChangeOfGlobalScope(state, exportedFromPath, cancellationToken, computeHash, getCanonicalFileName, host)) return true; const references = state.referencedMap!.getKeys(exportedFromPath); - return references && ts.forEachKey(references, filePath => + return references && forEachKey(references, filePath => handleDtsMayChangeOfFileAndExportsOfFile( state, filePath, @@ -726,14 +742,14 @@ function handleDtsMayChangeOfReferencingExportOfAffectedFile( */ function handleDtsMayChangeOfFileAndExportsOfFile( state: BuilderProgramState, - filePath: ts.Path, - seenFileAndExportsOfFile: ts.Set, - cancellationToken: ts.CancellationToken | undefined, - computeHash: ts.BuilderState.ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - host: ts.BuilderProgramHost, + filePath: Path, + seenFileAndExportsOfFile: Set, + cancellationToken: CancellationToken | undefined, + computeHash: BuilderState.ComputeHash, + getCanonicalFileName: GetCanonicalFileName, + host: BuilderProgramHost, ): boolean | undefined { - if (!ts.tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; + if (!tryAddToSet(seenFileAndExportsOfFile, filePath)) return undefined; if (handleDtsMayChangeOfGlobalScope(state, filePath, cancellationToken, computeHash, getCanonicalFileName, host)) return true; handleDtsMayChangeOf(state, filePath, cancellationToken, computeHash, getCanonicalFileName, host); @@ -770,10 +786,10 @@ function handleDtsMayChangeOfFileAndExportsOfFile( * Gets semantic diagnostics for the file which are * bindAndCheckDiagnostics (from cache) and program diagnostics */ -function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { - return ts.concatenate( +function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { + return concatenate( getBinderAndCheckerDiagnosticsOfFile(state, sourceFile, cancellationToken), - ts.Debug.checkDefined(state.program).getProgramDiagnostics(sourceFile) + Debug.checkDefined(state.program).getProgramDiagnostics(sourceFile) ); } @@ -781,22 +797,22 @@ function getSemanticDiagnosticsOfFile(state: BuilderProgramState, sourceFile: ts * Gets the binder and checker diagnostics either from cache if present, or otherwise from program and caches it * Note that it is assumed that when asked about binder and checker diagnostics, the file has been taken out of affected files/changed file set */ -function getBinderAndCheckerDiagnosticsOfFile(state: BuilderProgramState, sourceFile: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { +function getBinderAndCheckerDiagnosticsOfFile(state: BuilderProgramState, sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { const path = sourceFile.resolvedPath; if (state.semanticDiagnosticsPerFile) { const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path); // Report the bind and check diagnostics from the cache if we already have those diagnostics present if (cachedDiagnostics) { - return ts.filterSemanticDiagnostics(cachedDiagnostics, state.compilerOptions); + return filterSemanticDiagnostics(cachedDiagnostics, state.compilerOptions); } } // Diagnostics werent cached, get them from program, and cache the result - const diagnostics = ts.Debug.checkDefined(state.program).getBindAndCheckDiagnostics(sourceFile, cancellationToken); + const diagnostics = Debug.checkDefined(state.program).getBindAndCheckDiagnostics(sourceFile, cancellationToken); if (state.semanticDiagnosticsPerFile) { state.semanticDiagnosticsPerFile.set(path, diagnostics); } - return ts.filterSemanticDiagnostics(diagnostics, state.compilerOptions); + return filterSemanticDiagnostics(diagnostics, state.compilerOptions); } /** @internal */ @@ -815,7 +831,7 @@ export type ProgramBuilderInfoFilePendingEmit = ProgramBuildInfoFileId | [fileId /** @internal */ export type ProgramBuildInfoReferencedMap = [fileId: ProgramBuildInfoFileId, fileIdListId: ProgramBuildInfoFileIdListId][]; /** @internal */ -export type ProgramMultiFileEmitBuildInfoBuilderStateFileInfo = Omit & { +export type ProgramMultiFileEmitBuildInfoBuilderStateFileInfo = Omit & { /** * Signature is * - undefined if FileInfo.version === FileInfo.signature @@ -839,7 +855,7 @@ export type ProgramMultiFileEmitBuildInfoFileInfo = string | ProgramMultiFileEmi export interface ProgramMultiFileEmitBuildInfo { fileNames: readonly string[]; fileInfos: readonly ProgramMultiFileEmitBuildInfoFileInfo[]; - options: ts.CompilerOptions | undefined; + options: CompilerOptions | undefined; fileIdsList: readonly (readonly ProgramBuildInfoFileId[])[] | undefined; referencedMap: ProgramBuildInfoReferencedMap | undefined; exportedModulesMap: ProgramBuildInfoReferencedMap | undefined; @@ -854,7 +870,7 @@ export interface ProgramMultiFileEmitBuildInfo { /** * ProgramBundleEmitBuildInfoFileInfo is string if !FileInfo.impliedFormat otherwise encoded FileInfo */ -export type ProgramBundleEmitBuildInfoFileInfo = string | ts.BuilderState.FileInfo; +export type ProgramBundleEmitBuildInfoFileInfo = string | BuilderState.FileInfo; /** @internal */ /** * false if it is the emit corresponding to compilerOptions @@ -865,7 +881,7 @@ export type ProgramBuildInfoBundlePendingEmit = BuilderFileEmit | false; export interface ProgramBundleEmitBuildInfo { fileNames: readonly string[]; fileInfos: readonly ProgramBundleEmitBuildInfoFileInfo[]; - options: ts.CompilerOptions | undefined; + options: CompilerOptions | undefined; outSignature: EmitSignature | undefined; latestChangedDtsFile: string | undefined; pendingEmit: ProgramBuildInfoBundlePendingEmit | undefined; @@ -876,23 +892,23 @@ export type ProgramBuildInfo = ProgramMultiFileEmitBuildInfo | ProgramBundleEmit /** @internal */ export function isProgramBundleEmitBuildInfo(info: ProgramBuildInfo): info is ProgramBundleEmitBuildInfo { - return !!ts.outFile(info.options || {}); + return !!outFile(info.options || {}); } /** * Gets the program information to be emitted in buildInfo so that we can use it to create new program */ -function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCanonicalFileName, bundle: ts.BundleBuildInfo | undefined): ts.BuildInfo { - const currentDirectory = ts.Debug.checkDefined(state.program).getCurrentDirectory(); - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(ts.getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory)); +function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: GetCanonicalFileName, bundle: BundleBuildInfo | undefined): BuildInfo { + const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory(); + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory)); // Convert the file name to Path here if we set the fileName instead to optimize multiple d.ts file emits and having to compute Canonical path const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : undefined; const fileNames: string[] = []; - const fileNameToFileId = new ts.Map(); - if (ts.outFile(state.compilerOptions)) { + const fileNameToFileId = new Map(); + if (outFile(state.compilerOptions)) { // Copy all fileInfo, version and impliedFormat // Affects global scope and signature doesnt matter because with --out they arent calculated or needed to determine upto date ness - const fileInfos = ts.arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { + const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { // Ensure fileId toFileId(key); return value.impliedFormat ? @@ -917,29 +933,29 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa commonSourceDirectory, sourceFiles, js: js || (!state.compilerOptions.emitDeclarationOnly ? state.bundle?.js : undefined), - dts: dts || (ts.getEmitDeclarations(state.compilerOptions) ? state.bundle?.dts : undefined), + dts: dts || (getEmitDeclarations(state.compilerOptions) ? state.bundle?.dts : undefined), }; - return ts.createBuildInfo(program, bundle); + return createBuildInfo(program, bundle); } let fileIdsList: (readonly ProgramBuildInfoFileId[])[] | undefined; - let fileNamesToFileIdListId: ts.ESMap | undefined; + let fileNamesToFileIdListId: ESMap | undefined; let emitSignatures: ProgramBuildInfoEmitSignature[] | undefined; - const fileInfos = ts.arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { + const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { // Ensure fileId const fileId = toFileId(key); - ts.Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); + Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); const oldSignature = state.oldSignatures?.get(key); const actualSignature = oldSignature !== undefined ? oldSignature || undefined : value.signature; if (state.compilerOptions.composite) { const file = state.program!.getSourceFileByPath(key)!; - if (!ts.isJsonSourceFile(file) && ts.sourceFileMayBeEmitted(file, state.program!)) { + if (!isJsonSourceFile(file) && sourceFileMayBeEmitted(file, state.program!)) { const emitSignature = state.emitSignatures?.get(key); if (emitSignature !== actualSignature) { (emitSignatures ||= []).push(emitSignature === undefined ? fileId : // There is no emit, encode as false // fileId, signature: emptyArray if signature only differs in dtsMap option than our own compilerOptions otherwise EmitSignature - [fileId, !ts.isString(emitSignature) && emitSignature[0] === actualSignature ? ts.emptyArray as [] : emitSignature]); + [fileId, !isString(emitSignature) && emitSignature[0] === actualSignature ? emptyArray as [] : emitSignature]); } } } @@ -961,7 +977,7 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa let referencedMap: ProgramBuildInfoReferencedMap | undefined; if (state.referencedMap) { - referencedMap = ts.arrayFrom(state.referencedMap.keys()).sort(ts.compareStringsCaseSensitive).map(key => [ + referencedMap = arrayFrom(state.referencedMap.keys()).sort(compareStringsCaseSensitive).map(key => [ toFileId(key), toFileIdListId(state.referencedMap!.getValues(key)!) ]); @@ -969,7 +985,7 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa let exportedModulesMap: ProgramBuildInfoReferencedMap | undefined; if (state.exportedModulesMap) { - exportedModulesMap = ts.mapDefined(ts.arrayFrom(state.exportedModulesMap.keys()).sort(ts.compareStringsCaseSensitive), key => { + exportedModulesMap = mapDefined(arrayFrom(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { const oldValue = state.oldExportedModulesMap?.get(key); // Not in temporary cache, use existing value if (oldValue === undefined) return [toFileId(key), toFileIdListId(state.exportedModulesMap!.getValues(key)!)]; @@ -980,7 +996,7 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa let semanticDiagnosticsPerFile: ProgramBuildInfoDiagnostic[] | undefined; if (state.semanticDiagnosticsPerFile) { - for (const key of ts.arrayFrom(state.semanticDiagnosticsPerFile.keys()).sort(ts.compareStringsCaseSensitive)) { + for (const key of arrayFrom(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { const value = state.semanticDiagnosticsPerFile.get(key)!; (semanticDiagnosticsPerFile ||= []).push( value.length ? @@ -996,11 +1012,11 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa let affectedFilesPendingEmit: ProgramBuilderInfoFilePendingEmit[] | undefined; if (state.affectedFilesPendingEmit?.size) { const fullEmitForOptions = getBuilderFileEmit(state.compilerOptions); - const seenFiles = new ts.Set(); - for (const path of ts.arrayFrom(state.affectedFilesPendingEmit.keys()).sort(ts.compareStringsCaseSensitive)) { - if (ts.tryAddToSet(seenFiles, path)) { + const seenFiles = new Set(); + for (const path of arrayFrom(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { + if (tryAddToSet(seenFiles, path)) { const file = state.program!.getSourceFileByPath(path)!; - if (!ts.sourceFileMayBeEmitted(file, state.program!)) continue; + if (!sourceFileMayBeEmitted(file, state.program!)) continue; const fileId = toFileId(path), pendingEmit = state.affectedFilesPendingEmit.get(path)!; (affectedFilesPendingEmit ||= []).push( pendingEmit === fullEmitForOptions ? @@ -1015,7 +1031,7 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa let changeFileSet: ProgramBuildInfoFileId[] | undefined; if (state.changedFilesSet.size) { - for (const path of ts.arrayFrom(state.changedFilesSet.keys()).sort(ts.compareStringsCaseSensitive)) { + for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { (changeFileSet ||= []).push(toFileId(path)); } } @@ -1033,17 +1049,17 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa emitSignatures, latestChangedDtsFile, }; - return ts.createBuildInfo(program, bundle); + return createBuildInfo(program, bundle); function relativeToBuildInfoEnsuringAbsolutePath(path: string) { - return relativeToBuildInfo(ts.getNormalizedAbsolutePath(path, currentDirectory)); + return relativeToBuildInfo(getNormalizedAbsolutePath(path, currentDirectory)); } function relativeToBuildInfo(path: string) { - return ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName)); + return ensurePathIsNonModuleName(getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName)); } - function toFileId(path: ts.Path): ProgramBuildInfoFileId { + function toFileId(path: Path): ProgramBuildInfoFileId { let fileId = fileNameToFileId.get(path); if (fileId === undefined) { fileNames.push(relativeToBuildInfo(path)); @@ -1052,13 +1068,13 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa return fileId; } - function toFileIdListId(set: ts.ReadonlySet): ProgramBuildInfoFileIdListId { - const fileIds = ts.arrayFrom(set.keys(), toFileId).sort(ts.compareValues); + function toFileIdListId(set: ReadonlySet): ProgramBuildInfoFileIdListId { + const fileIds = arrayFrom(set.keys(), toFileId).sort(compareValues); const key = fileIds.join(); let fileIdListId = fileNamesToFileIdListId?.get(key); if (fileIdListId === undefined) { (fileIdsList ||= []).push(fileIds); - (fileNamesToFileIdListId ||= new ts.Map()).set(key, fileIdListId = fileIdsList.length as ProgramBuildInfoFileIdListId); + (fileNamesToFileIdListId ||= new Map()).set(key, fileIdListId = fileIdsList.length as ProgramBuildInfoFileIdListId); } return fileIdListId; } @@ -1066,15 +1082,15 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa /** * @param optionKey key of CommandLineOption to use to determine if the option should be serialized in tsbuildinfo */ - function convertToProgramBuildInfoCompilerOptions(options: ts.CompilerOptions) { - let result: ts.CompilerOptions | undefined; - const { optionsNameMap } = ts.getOptionsNameMap(); - for (const name of ts.getOwnKeys(options).sort(ts.compareStringsCaseSensitive)) { + function convertToProgramBuildInfoCompilerOptions(options: CompilerOptions) { + let result: CompilerOptions | undefined; + const { optionsNameMap } = getOptionsNameMap(); + for (const name of getOwnKeys(options).sort(compareStringsCaseSensitive)) { const optionInfo = optionsNameMap.get(name.toLowerCase()); if (optionInfo?.affectsBuildInfo) { (result ||= {})[name] = convertToReusableCompilerOptionValue( optionInfo, - options[name] as ts.CompilerOptionsValue, + options[name] as CompilerOptionsValue, relativeToBuildInfoEnsuringAbsolutePath ); } @@ -1083,7 +1099,7 @@ function getBuildInfo(state: BuilderProgramState, getCanonicalFileName: ts.GetCa } } -function convertToReusableCompilerOptionValue(option: ts.CommandLineOption | undefined, value: ts.CompilerOptionsValue, relativeToBuildInfo: (path: string) => string) { +function convertToReusableCompilerOptionValue(option: CommandLineOption | undefined, value: CompilerOptionsValue, relativeToBuildInfo: (path: string) => string) { if (option) { if (option.type === "list") { const values = value as readonly (string | number)[]; @@ -1098,8 +1114,8 @@ function convertToReusableCompilerOptionValue(option: ts.CommandLineOption | und return value; } -function convertToReusableDiagnostics(diagnostics: readonly ts.Diagnostic[], relativeToBuildInfo: (path: string) => string): readonly ReusableDiagnostic[] { - ts.Debug.assert(!!diagnostics.length); +function convertToReusableDiagnostics(diagnostics: readonly Diagnostic[], relativeToBuildInfo: (path: string) => string): readonly ReusableDiagnostic[] { + Debug.assert(!!diagnostics.length); return diagnostics.map(diagnostic => { const result: ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation(diagnostic, relativeToBuildInfo); result.reportsUnnecessary = diagnostic.reportsUnnecessary; @@ -1116,7 +1132,7 @@ function convertToReusableDiagnostics(diagnostics: readonly ts.Diagnostic[], rel }); } -function convertToReusableDiagnosticRelatedInformation(diagnostic: ts.DiagnosticRelatedInformation, relativeToBuildInfo: (path: string) => string): ReusableDiagnosticRelatedInformation { +function convertToReusableDiagnosticRelatedInformation(diagnostic: DiagnosticRelatedInformation, relativeToBuildInfo: (path: string) => string): ReusableDiagnosticRelatedInformation { const { file } = diagnostic; return { ...diagnostic, @@ -1132,68 +1148,68 @@ export enum BuilderProgramKind { /** @internal */ export interface BuilderCreationParameters { - newProgram: ts.Program; - host: ts.BuilderProgramHost; - oldProgram: ts.BuilderProgram | undefined; - configFileParsingDiagnostics: readonly ts.Diagnostic[]; + newProgram: Program; + host: BuilderProgramHost; + oldProgram: BuilderProgram | undefined; + configFileParsingDiagnostics: readonly Diagnostic[]; } /** @internal */ -export function getBuilderCreationParameters(newProgramOrRootNames: ts.Program | readonly string[] | undefined, hostOrOptions: ts.BuilderProgramHost | ts.CompilerOptions | undefined, oldProgramOrHost?: ts.BuilderProgram | ts.CompilerHost, configFileParsingDiagnosticsOrOldProgram?: readonly ts.Diagnostic[] | ts.BuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]): BuilderCreationParameters { - let host: ts.BuilderProgramHost; - let newProgram: ts.Program; - let oldProgram: ts.BuilderProgram; +export function getBuilderCreationParameters(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: BuilderProgram | CompilerHost, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderCreationParameters { + let host: BuilderProgramHost; + let newProgram: Program; + let oldProgram: BuilderProgram; if (newProgramOrRootNames === undefined) { - ts.Debug.assert(hostOrOptions === undefined); - host = oldProgramOrHost as ts.CompilerHost; - oldProgram = configFileParsingDiagnosticsOrOldProgram as ts.BuilderProgram; - ts.Debug.assert(!!oldProgram); + Debug.assert(hostOrOptions === undefined); + host = oldProgramOrHost as CompilerHost; + oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; + Debug.assert(!!oldProgram); newProgram = oldProgram.getProgram(); } - else if (ts.isArray(newProgramOrRootNames)) { - oldProgram = configFileParsingDiagnosticsOrOldProgram as ts.BuilderProgram; - newProgram = ts.createProgram({ + else if (isArray(newProgramOrRootNames)) { + oldProgram = configFileParsingDiagnosticsOrOldProgram as BuilderProgram; + newProgram = createProgram({ rootNames: newProgramOrRootNames, - options: hostOrOptions as ts.CompilerOptions, - host: oldProgramOrHost as ts.CompilerHost, + options: hostOrOptions as CompilerOptions, + host: oldProgramOrHost as CompilerHost, oldProgram: oldProgram && oldProgram.getProgramOrUndefined(), configFileParsingDiagnostics, projectReferences }); - host = oldProgramOrHost as ts.CompilerHost; + host = oldProgramOrHost as CompilerHost; } else { newProgram = newProgramOrRootNames; - host = hostOrOptions as ts.BuilderProgramHost; - oldProgram = oldProgramOrHost as ts.BuilderProgram; - configFileParsingDiagnostics = configFileParsingDiagnosticsOrOldProgram as readonly ts.Diagnostic[]; + host = hostOrOptions as BuilderProgramHost; + oldProgram = oldProgramOrHost as BuilderProgram; + configFileParsingDiagnostics = configFileParsingDiagnosticsOrOldProgram as readonly Diagnostic[]; } - return { host, newProgram, oldProgram, configFileParsingDiagnostics: configFileParsingDiagnostics || ts.emptyArray }; + return { host, newProgram, oldProgram, configFileParsingDiagnostics: configFileParsingDiagnostics || emptyArray }; } -function getTextHandlingSourceMapForSignature(text: string, data: ts.WriteFileCallbackData | undefined) { +function getTextHandlingSourceMapForSignature(text: string, data: WriteFileCallbackData | undefined) { return data?.sourceMapUrlPos !== undefined ? text.substring(0, data.sourceMapUrlPos) : text; } /** @internal */ export function computeSignatureWithDiagnostics( - sourceFile: ts.SourceFile, + sourceFile: SourceFile, text: string, - computeHash: ts.BuilderState.ComputeHash | undefined, - getCanonicalFileName: ts.GetCanonicalFileName, - data: ts.WriteFileCallbackData | undefined + computeHash: BuilderState.ComputeHash | undefined, + getCanonicalFileName: GetCanonicalFileName, + data: WriteFileCallbackData | undefined ) { text = getTextHandlingSourceMapForSignature(text, data); let sourceFileDirectory: string | undefined; if (data?.diagnostics?.length) { text += data.diagnostics.map(diagnostic => - `${locationInfo(diagnostic)}${ts.DiagnosticCategory[diagnostic.category]}${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText)}` + `${locationInfo(diagnostic)}${DiagnosticCategory[diagnostic.category]}${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText)}` ).join("\n"); } - return (computeHash ?? ts.generateDjb2Hash)(text); + return (computeHash ?? generateDjb2Hash)(text); - function flattenDiagnosticMessageText(diagnostic: string | ts.DiagnosticMessageChain | undefined): string { - return ts.isString(diagnostic) ? + function flattenDiagnosticMessageText(diagnostic: string | DiagnosticMessageChain | undefined): string { + return isString(diagnostic) ? diagnostic : diagnostic === undefined ? "" : @@ -1202,22 +1218,22 @@ export function computeSignatureWithDiagnostics( diagnostic.messageText + diagnostic.next.map(flattenDiagnosticMessageText).join("\n"); } - function locationInfo(diagnostic: ts.DiagnosticWithLocation) { + function locationInfo(diagnostic: DiagnosticWithLocation) { if (diagnostic.file.resolvedPath === sourceFile.resolvedPath) return `(${diagnostic.start},${diagnostic.length})`; - if (sourceFileDirectory === undefined) sourceFileDirectory = ts.getDirectoryPath(sourceFile.resolvedPath); - return `${ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(sourceFileDirectory, diagnostic.file.resolvedPath, getCanonicalFileName))}(${diagnostic.start},${diagnostic.length})`; + if (sourceFileDirectory === undefined) sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath); + return `${ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceFileDirectory, diagnostic.file.resolvedPath, getCanonicalFileName))}(${diagnostic.start},${diagnostic.length})`; } } /** @internal */ -export function computeSignature(text: string, computeHash: ts.BuilderState.ComputeHash | undefined, data?: ts.WriteFileCallbackData) { - return (computeHash ?? ts.generateDjb2Hash)(getTextHandlingSourceMapForSignature(text, data)); +export function computeSignature(text: string, computeHash: BuilderState.ComputeHash | undefined, data?: WriteFileCallbackData) { + return (computeHash ?? generateDjb2Hash)(getTextHandlingSourceMapForSignature(text, data)); } /** @internal */ -export function createBuilderProgram(kind: BuilderProgramKind.SemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): ts.SemanticDiagnosticsBuilderProgram; +export function createBuilderProgram(kind: BuilderProgramKind.SemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): SemanticDiagnosticsBuilderProgram; /** @internal */ -export function createBuilderProgram(kind: BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): ts.EmitAndSemanticDiagnosticsBuilderProgram; +export function createBuilderProgram(kind: BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, builderCreationParameters: BuilderCreationParameters): EmitAndSemanticDiagnosticsBuilderProgram; /** @internal */ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, host, oldProgram, configFileParsingDiagnostics }: BuilderCreationParameters) { // Return same program if underlying program doesnt change @@ -1231,11 +1247,11 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos /** * Create the canonical file name for identity */ - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); /** * Computing hash to for signature verification */ - const computeHash = ts.maybeBind(host, host.createHash); + const computeHash = maybeBind(host, host.createHash); const state = createBuilderProgramState(newProgram, getCanonicalFileName, oldState, host.disableUseFileVersionAsSignature); newProgram.getBuildInfo = bundle => getBuildInfo(state, getCanonicalFileName, bundle); @@ -1250,32 +1266,32 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos builderProgram.saveEmitState = () => backupBuilderProgramEmitState(state); builderProgram.restoreEmitState = (saved) => restoreBuilderProgramEmitState(state, saved); builderProgram.hasChangedEmitSignature = () => !!state.hasChangedEmitSignature; - builderProgram.getAllDependencies = sourceFile => ts.BuilderState.getAllDependencies(state, ts.Debug.checkDefined(state.program), sourceFile); + builderProgram.getAllDependencies = sourceFile => BuilderState.getAllDependencies(state, Debug.checkDefined(state.program), sourceFile); builderProgram.getSemanticDiagnostics = getSemanticDiagnostics; builderProgram.emit = emit; builderProgram.releaseProgram = () => releaseCache(state); if (kind === BuilderProgramKind.SemanticDiagnosticsBuilderProgram) { - (builderProgram as ts.SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; + (builderProgram as SemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; } else if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { - (builderProgram as ts.EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; - (builderProgram as ts.EmitAndSemanticDiagnosticsBuilderProgram).emitNextAffectedFile = emitNextAffectedFile; + (builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile; + (builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).emitNextAffectedFile = emitNextAffectedFile; builderProgram.emitBuildInfo = emitBuildInfo; } else { - ts.notImplemented(); + notImplemented(); } return builderProgram; - function emitBuildInfo(writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken): ts.EmitResult { + function emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult { if (state.buildInfoEmitPending) { - const result = ts.Debug.checkDefined(state.program).emitBuildInfo(writeFile || ts.maybeBind(host, host.writeFile), cancellationToken); + const result = Debug.checkDefined(state.program).emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken); state.buildInfoEmitPending = false; return result; } - return ts.emitSkippedWithNoDiagnostics; + return emitSkippedWithNoDiagnostics; } /** @@ -1283,19 +1299,19 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - function emitNextAffectedFile(writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: ts.CustomTransformers): ts.AffectedFileResult { + function emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult { let affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host); const programEmitKind = getBuilderFileEmit(state.compilerOptions); let emitKind: BuilderFileEmit = emitOnlyDtsFiles ? programEmitKind & BuilderFileEmit.AllDts : programEmitKind; if (!affected) { - if (!ts.outFile(state.compilerOptions)) { + if (!outFile(state.compilerOptions)) { const pendingAffectedFile = getNextAffectedFilePendingEmit(state, emitOnlyDtsFiles); if (!pendingAffectedFile) { // Emit buildinfo if pending if (!state.buildInfoEmitPending) return undefined; const affected = state.program!; - const result = affected.emitBuildInfo(writeFile || ts.maybeBind(host, host.writeFile), cancellationToken); + const result = affected.emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken); state.buildInfoEmitPending = false; return { result, affected }; } @@ -1312,9 +1328,9 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos } } // Determine if we can do partial emit - let emitOnly: ts.EmitOnly | undefined; - if (emitKind & BuilderFileEmit.AllJs) emitOnly = ts.EmitOnly.Js; - if (emitKind & BuilderFileEmit.AllDts) emitOnly = emitOnly === undefined ? ts.EmitOnly.Dts : undefined; + let emitOnly: EmitOnly | undefined; + if (emitKind & BuilderFileEmit.AllJs) emitOnly = EmitOnly.Js; + if (emitKind & BuilderFileEmit.AllDts) emitOnly = emitOnly === undefined ? EmitOnly.Dts : undefined; if (affected === state.program) { // Set up programEmit before calling emit so that its set in buildInfo state.programEmitPending = state.changedFilesSet.size ? @@ -1325,7 +1341,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos } // Actual emit const result = state.program!.emit( - affected === state.program ? undefined : affected as ts.SourceFile, + affected === state.program ? undefined : affected as SourceFile, getWriteFileCallback(writeFile, customTransformers), cancellationToken, emitOnly, @@ -1333,17 +1349,17 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos ); if (affected !== state.program) { // update affected files - const affectedSourceFile = affected as ts.SourceFile; + const affectedSourceFile = affected as SourceFile; state.seenAffectedFiles!.add(affectedSourceFile.resolvedPath); if (state.affectedFilesIndex !== undefined) state.affectedFilesIndex++; // Change in changeSet/affectedFilesPendingEmit, buildInfo needs to be emitted state.buildInfoEmitPending = true; // Update the pendingEmit for the file const existing = state.seenEmittedFiles?.get(affectedSourceFile.resolvedPath) || BuilderFileEmit.None; - (state.seenEmittedFiles ??= new ts.Map()).set(affectedSourceFile.resolvedPath, emitKind | existing); + (state.seenEmittedFiles ??= new Map()).set(affectedSourceFile.resolvedPath, emitKind | existing); const existingPending = state.affectedFilesPendingEmit?.get(affectedSourceFile.resolvedPath) || programEmitKind; const pendingKind = getPendingEmitKind(existingPending, emitKind | existing); - if (pendingKind) (state.affectedFilesPendingEmit ??= new ts.Map()).set(affectedSourceFile.resolvedPath, pendingKind); + if (pendingKind) (state.affectedFilesPendingEmit ??= new Map()).set(affectedSourceFile.resolvedPath, pendingKind); else state.affectedFilesPendingEmit?.delete(affectedSourceFile.resolvedPath); } else { @@ -1353,12 +1369,12 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos return { result, affected }; } - function getWriteFileCallback(writeFile: ts.WriteFileCallback | undefined, customTransformers: ts.CustomTransformers | undefined): ts.WriteFileCallback | undefined { - if (!ts.getEmitDeclarations(state.compilerOptions)) return writeFile || ts.maybeBind(host, host.writeFile); + function getWriteFileCallback(writeFile: WriteFileCallback | undefined, customTransformers: CustomTransformers | undefined): WriteFileCallback | undefined { + if (!getEmitDeclarations(state.compilerOptions)) return writeFile || maybeBind(host, host.writeFile); return (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => { - if (ts.isDeclarationFileName(fileName)) { - if (!ts.outFile(state.compilerOptions)) { - ts.Debug.assert(sourceFiles?.length === 1); + if (isDeclarationFileName(fileName)) { + if (!outFile(state.compilerOptions)) { + Debug.assert(sourceFiles?.length === 1); let emitSignature; if (!customTransformers) { const file = sourceFiles[0]; @@ -1374,12 +1390,12 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos // With d.ts diagnostics they are also part of the signature so emitSignature will be different from it since its just hash of d.ts if (!data?.diagnostics?.length) emitSignature = signature; if (signature !== file.version) { // Update it - if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ??= new ts.Set()).add(file.resolvedPath); - if (state.exportedModulesMap) ts.BuilderState.updateExportedModules(state, file, file.exportedModulesFromDeclarationEmit); + if (host.storeFilesChangingSignatureDuringEmit) (state.filesChangingSignature ??= new Set()).add(file.resolvedPath); + if (state.exportedModulesMap) BuilderState.updateExportedModules(state, file, file.exportedModulesFromDeclarationEmit); if (state.affectedFiles) { // Keep old signature so we know what to undo if cancellation happens const existing = state.oldSignatures?.get(file.resolvedPath); - if (existing === undefined) (state.oldSignatures ??= new ts.Map()).set(file.resolvedPath, info.signature || false); + if (existing === undefined) (state.oldSignatures ??= new Map()).set(file.resolvedPath, info.signature || false); info.signature = signature; } else { @@ -1398,7 +1414,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos const filePath = sourceFiles[0].resolvedPath; emitSignature = handleNewSignature(state.emitSignatures?.get(filePath), emitSignature); if (!emitSignature) return; - (state.emitSignatures ??= new ts.Map()).set(filePath, emitSignature); + (state.emitSignatures ??= new Map()).set(filePath, emitSignature); } } else if (state.compilerOptions.composite) { @@ -1416,7 +1432,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * returning undefined means that, we dont need to emit this d.ts file since its contents didnt change */ function handleNewSignature(oldSignatureFormat: EmitSignature | undefined, newSignature: string | undefined) { - const oldSignature = !oldSignatureFormat || ts.isString(oldSignatureFormat) ? oldSignatureFormat : oldSignatureFormat[0]; + const oldSignature = !oldSignatureFormat || isString(oldSignatureFormat) ? oldSignatureFormat : oldSignatureFormat[0]; newSignature ??= computeSignature(text, computeHash, data); // Dont write dts files if they didn't change if (newSignature === oldSignature) { @@ -1447,32 +1463,32 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - function emit(targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: ts.CustomTransformers): ts.EmitResult { + function emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); } - const result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + const result = handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); if (result) return result; // Emit only affected files if using builder for emit if (!targetSourceFile) { if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { // Emit and report any errors we ran into. - let sourceMaps: ts.SourceMapEmitResult[] = []; + let sourceMaps: SourceMapEmitResult[] = []; let emitSkipped = false; - let diagnostics: ts.Diagnostic[] | undefined; + let diagnostics: Diagnostic[] | undefined; let emittedFiles: string[] = []; - let affectedEmitResult: ts.AffectedFileResult; + let affectedEmitResult: AffectedFileResult; while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); + diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } return { emitSkipped, - diagnostics: diagnostics || ts.emptyArray, + diagnostics: diagnostics || emptyArray, emittedFiles, sourceMaps }; @@ -1482,7 +1498,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos clearAffectedFilesPendingEmit(state, emitOnlyDtsFiles); } } - return ts.Debug.checkDefined(state.program).emit( + return Debug.checkDefined(state.program).emit( targetSourceFile, getWriteFileCallback(writeFile, customTransformers), cancellationToken, @@ -1495,14 +1511,14 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * Return the semantic diagnostics for the next affected file or undefined if iteration is complete * If provided ignoreSourceFile would be called before getting the diagnostics and would ignore the sourceFile if the returned value was true */ - function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: ts.CancellationToken, ignoreSourceFile?: (sourceFile: ts.SourceFile) => boolean): ts.AffectedFileResult { + function getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult { while (true) { const affected = getNextAffectedFile(state, cancellationToken, computeHash, getCanonicalFileName, host); let result; if (!affected) return undefined; // Done else if (affected !== state.program) { // Get diagnostics for the affected file if its not ignored - const affectedSourceFile = affected as ts.SourceFile; + const affectedSourceFile = affected as SourceFile; if (!ignoreSourceFile || !ignoreSourceFile(affectedSourceFile)) { result = getSemanticDiagnosticsOfFile(state, affectedSourceFile, cancellationToken); } @@ -1530,13 +1546,13 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics */ - function getSemanticDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { + function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { assertSourceFileOkWithoutNextAffectedCall(state, sourceFile); - const compilerOptions = ts.Debug.checkDefined(state.program).getCompilerOptions(); - if (ts.outFile(compilerOptions)) { - ts.Debug.assert(!state.semanticDiagnosticsPerFile); + const compilerOptions = Debug.checkDefined(state.program).getCompilerOptions(); + if (outFile(compilerOptions)) { + Debug.assert(!state.semanticDiagnosticsPerFile); // We dont need to cache the diagnostics just return them from program - return ts.Debug.checkDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken); + return Debug.checkDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken); } if (sourceFile) { @@ -1549,57 +1565,57 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos while (getSemanticDiagnosticsOfNextAffectedFile(cancellationToken)) { } - let diagnostics: ts.Diagnostic[] | undefined; - for (const sourceFile of ts.Debug.checkDefined(state.program).getSourceFiles()) { - diagnostics = ts.addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken)); + let diagnostics: Diagnostic[] | undefined; + for (const sourceFile of Debug.checkDefined(state.program).getSourceFiles()) { + diagnostics = addRange(diagnostics, getSemanticDiagnosticsOfFile(state, sourceFile, cancellationToken)); } - return diagnostics || ts.emptyArray; + return diagnostics || emptyArray; } } -function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilePendingEmit: ts.Path, kind: BuilderFileEmit) { +function addToAffectedFilesPendingEmit(state: BuilderProgramState, affectedFilePendingEmit: Path, kind: BuilderFileEmit) { const existingKind = state.affectedFilesPendingEmit?.get(affectedFilePendingEmit) || BuilderFileEmit.None; - (state.affectedFilesPendingEmit ??= new ts.Map()).set(affectedFilePendingEmit, existingKind | kind); + (state.affectedFilesPendingEmit ??= new Map()).set(affectedFilePendingEmit, existingKind | kind); } /** @internal */ -export function toBuilderStateFileInfoForMultiEmit(fileInfo: ProgramMultiFileEmitBuildInfoFileInfo): ts.BuilderState.FileInfo { - return ts.isString(fileInfo) ? +export function toBuilderStateFileInfoForMultiEmit(fileInfo: ProgramMultiFileEmitBuildInfoFileInfo): BuilderState.FileInfo { + return isString(fileInfo) ? { version: fileInfo, signature: fileInfo, affectsGlobalScope: undefined, impliedFormat: undefined } : - ts.isString(fileInfo.signature) ? - fileInfo as ts.BuilderState.FileInfo : + isString(fileInfo.signature) ? + fileInfo as BuilderState.FileInfo : { version: fileInfo.version, signature: fileInfo.signature === false ? undefined : fileInfo.version, affectsGlobalScope: fileInfo.affectsGlobalScope, impliedFormat: fileInfo.impliedFormat }; } /** @internal */ export function toBuilderFileEmit(value: ProgramBuilderInfoFilePendingEmit, fullEmitForOptions: BuilderFileEmit): BuilderFileEmit{ - return ts.isNumber(value) ? fullEmitForOptions : value[1] || BuilderFileEmit.Dts; + return isNumber(value) ? fullEmitForOptions : value[1] || BuilderFileEmit.Dts; } /** @internal */ -export function toProgramEmitPending(value: ProgramBuildInfoBundlePendingEmit, options: ts.CompilerOptions | undefined): BuilderFileEmit | undefined { +export function toProgramEmitPending(value: ProgramBuildInfoBundlePendingEmit, options: CompilerOptions | undefined): BuilderFileEmit | undefined { return !value ? getBuilderFileEmit(options || {}) : value; } /** @internal */ -export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInfo, buildInfoPath: string, host: ts.ReadBuildProgramHost): ts.EmitAndSemanticDiagnosticsBuilderProgram { +export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram { const program = buildInfo.program!; - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); let state: ReusableBuilderProgramState; const filePaths = program.fileNames?.map(toPath); - let filePathsSetList: ts.Set[] | undefined; + let filePathsSetList: Set[] | undefined; const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) : undefined; if (isProgramBundleEmitBuildInfo(program)) { - const fileInfos = new ts.Map(); + const fileInfos = new Map(); program.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1 as ProgramBuildInfoFileId); - fileInfos.set(path, ts.isString(fileInfo) ? { version: fileInfo, signature: undefined, affectsGlobalScope: undefined, impliedFormat: undefined } : fileInfo); + fileInfos.set(path, isString(fileInfo) ? { version: fileInfo, signature: undefined, affectsGlobalScope: undefined, impliedFormat: undefined } : fileInfo); }); state = { fileInfos, - compilerOptions: program.options ? ts.convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, + compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, latestChangedDtsFile, outSignature: program.outSignature, programEmitPending: program.pendingEmit === undefined ? undefined : toProgramEmitPending(program.pendingEmit, program.options), @@ -1607,9 +1623,9 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf }; } else { - filePathsSetList = program.fileIdsList?.map(fileIds => new ts.Set(fileIds.map(toFilePath))); - const fileInfos = new ts.Map(); - const emitSignatures = program.options?.composite && !ts.outFile(program.options) ? new ts.Map() : undefined; + filePathsSetList = program.fileIdsList?.map(fileIds => new Set(fileIds.map(toFilePath))); + const fileInfos = new Map(); + const emitSignatures = program.options?.composite && !outFile(program.options) ? new Map() : undefined; program.fileInfos.forEach((fileInfo, index) => { const path = toFilePath(index + 1 as ProgramBuildInfoFileId); const stateFileInfo = toBuilderStateFileInfoForMultiEmit(fileInfo); @@ -1617,10 +1633,10 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf if (emitSignatures && stateFileInfo.signature) emitSignatures.set(path, stateFileInfo.signature); }); program.emitSignatures?.forEach(value => { - if (ts.isNumber(value)) emitSignatures!.delete(toFilePath(value)); + if (isNumber(value)) emitSignatures!.delete(toFilePath(value)); else { const key = toFilePath(value[0]); - emitSignatures!.set(key, !ts.isString(value[1]) && !value[1].length ? + emitSignatures!.set(key, !isString(value[1]) && !value[1].length ? // File signature is emit signature but differs in map [emitSignatures!.get(key)! as string] : value[1] @@ -1630,13 +1646,13 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf const fullEmitForOptions = program.affectedFilesPendingEmit ? getBuilderFileEmit(program.options || {}) : undefined; state = { fileInfos, - compilerOptions: program.options ? ts.convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, + compilerOptions: program.options ? convertToOptionsWithAbsolutePaths(program.options, toAbsolutePath) : {}, referencedMap: toManyToManyPathMap(program.referencedMap), exportedModulesMap: toManyToManyPathMap(program.exportedModulesMap), - semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && ts.arrayToMap(program.semanticDiagnosticsPerFile, value => toFilePath(ts.isNumber(value) ? value : value[0]), value => ts.isNumber(value) ? ts.emptyArray : value[1]), + semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toFilePath(isNumber(value) ? value : value[0]), value => isNumber(value) ? emptyArray : value[1]), hasReusableDiagnostic: true, - affectedFilesPendingEmit: program.affectedFilesPendingEmit && ts.arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(ts.isNumber(value) ? value : value[0]), value => toBuilderFileEmit(value, fullEmitForOptions!)), - changedFilesSet: new ts.Set(ts.map(program.changeFileSet, toFilePath)), + affectedFilesPendingEmit: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toFilePath(isNumber(value) ? value : value[0]), value => toBuilderFileEmit(value, fullEmitForOptions!)), + changedFilesSet: new Set(map(program.changeFileSet, toFilePath)), latestChangedDtsFile, emitSignatures: emitSignatures?.size ? emitSignatures : undefined, }; @@ -1644,28 +1660,28 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf return { getState: () => state, - saveEmitState: ts.noop as ts.BuilderProgram["saveEmitState"], - restoreEmitState: ts.noop, - getProgram: ts.notImplemented, - getProgramOrUndefined: ts.returnUndefined, - releaseProgram: ts.noop, + saveEmitState: noop as BuilderProgram["saveEmitState"], + restoreEmitState: noop, + getProgram: notImplemented, + getProgramOrUndefined: returnUndefined, + releaseProgram: noop, getCompilerOptions: () => state.compilerOptions, - getSourceFile: ts.notImplemented, - getSourceFiles: ts.notImplemented, - getOptionsDiagnostics: ts.notImplemented, - getGlobalDiagnostics: ts.notImplemented, - getConfigFileParsingDiagnostics: ts.notImplemented, - getSyntacticDiagnostics: ts.notImplemented, - getDeclarationDiagnostics: ts.notImplemented, - getSemanticDiagnostics: ts.notImplemented, - emit: ts.notImplemented, - getAllDependencies: ts.notImplemented, - getCurrentDirectory: ts.notImplemented, - emitNextAffectedFile: ts.notImplemented, - getSemanticDiagnosticsOfNextAffectedFile: ts.notImplemented, - emitBuildInfo: ts.notImplemented, - close: ts.noop, - hasChangedEmitSignature: ts.returnFalse, + getSourceFile: notImplemented, + getSourceFiles: notImplemented, + getOptionsDiagnostics: notImplemented, + getGlobalDiagnostics: notImplemented, + getConfigFileParsingDiagnostics: notImplemented, + getSyntacticDiagnostics: notImplemented, + getDeclarationDiagnostics: notImplemented, + getSemanticDiagnostics: notImplemented, + emit: notImplemented, + getAllDependencies: notImplemented, + getCurrentDirectory: notImplemented, + emitNextAffectedFile: notImplemented, + getSemanticDiagnosticsOfNextAffectedFile: notImplemented, + emitBuildInfo: notImplemented, + close: noop, + hasChangedEmitSignature: returnFalse, }; function toPath(path: string) { @@ -1673,7 +1689,7 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf } function toAbsolutePath(path: string) { - return ts.getNormalizedAbsolutePath(path, buildInfoDirectory); + return getNormalizedAbsolutePath(path, buildInfoDirectory); } function toFilePath(fileId: ProgramBuildInfoFileId) { @@ -1684,12 +1700,12 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf return filePathsSetList![fileIdsListId - 1]; } - function toManyToManyPathMap(referenceMap: ProgramBuildInfoReferencedMap | undefined): ts.BuilderState.ManyToManyPathMap | undefined { + function toManyToManyPathMap(referenceMap: ProgramBuildInfoReferencedMap | undefined): BuilderState.ManyToManyPathMap | undefined { if (!referenceMap) { return undefined; } - const map = ts.BuilderState.createManyToManyPathMap(); + const map = BuilderState.createManyToManyPathMap(); referenceMap.forEach(([fileId, fileIdListId]) => map.set(toFilePath(fileId), toFilePathsSet(fileIdListId)) ); @@ -1701,25 +1717,25 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: ts.BuildInf export function getBuildInfoFileVersionMap( program: ProgramBuildInfo, buildInfoPath: string, - host: Pick -): ts.ESMap { - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); - const fileInfos = new ts.Map(); + host: Pick +): ESMap { + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const fileInfos = new Map(); program.fileInfos.forEach((fileInfo, index) => { - const path = ts.toPath(program.fileNames[index], buildInfoDirectory, getCanonicalFileName); - const version = ts.isString(fileInfo) ? fileInfo : fileInfo.version; + const path = toPath(program.fileNames[index], buildInfoDirectory, getCanonicalFileName); + const version = isString(fileInfo) ? fileInfo : fileInfo.version; fileInfos.set(path, version); }); return fileInfos; } /** @internal */ -export function createRedirectedBuilderProgram(getState: () => { program?: ts.Program | undefined; compilerOptions: ts.CompilerOptions; }, configFileParsingDiagnostics: readonly ts.Diagnostic[]): ts.BuilderProgram { +export function createRedirectedBuilderProgram(getState: () => { program?: Program | undefined; compilerOptions: CompilerOptions; }, configFileParsingDiagnostics: readonly Diagnostic[]): BuilderProgram { return { - getState: ts.notImplemented, - saveEmitState: ts.noop as ts.BuilderProgram["saveEmitState"], - restoreEmitState: ts.noop, + getState: notImplemented, + saveEmitState: noop as BuilderProgram["saveEmitState"], + restoreEmitState: noop, getProgram, getProgramOrUndefined: () => getState().program, releaseProgram: () => getState().program = undefined, @@ -1734,12 +1750,12 @@ export function createRedirectedBuilderProgram(getState: () => { program?: ts.Pr getSemanticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSemanticDiagnostics(sourceFile, cancellationToken), emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers), emitBuildInfo: (writeFile, cancellationToken) => getProgram().emitBuildInfo(writeFile, cancellationToken), - getAllDependencies: ts.notImplemented, + getAllDependencies: notImplemented, getCurrentDirectory: () => getProgram().getCurrentDirectory(), - close: ts.noop, + close: noop, }; function getProgram() { - return ts.Debug.checkDefined(getState().program); + return Debug.checkDefined(getState().program); } } diff --git a/src/compiler/builderPublic.ts b/src/compiler/builderPublic.ts index fa87d96f333d8..605d82018a3fd 100644 --- a/src/compiler/builderPublic.ts +++ b/src/compiler/builderPublic.ts @@ -1,6 +1,11 @@ -import * as ts from "./_namespaces/ts"; +import { + BuilderProgramKind, CancellationToken, CompilerHost, CompilerOptions, createBuilderProgram, + createRedirectedBuilderProgram, CustomTransformers, Diagnostic, DiagnosticWithLocation, EmitResult, + getBuilderCreationParameters, Program, ProjectReference, ReusableBuilderProgramState, SavedBuildProgramEmitState, + SourceFile, WriteFileCallback, +} from "./_namespaces/ts"; -export type AffectedFileResult = { result: T; affected: ts.SourceFile | ts.Program; } | undefined; +export type AffectedFileResult = { result: T; affected: SourceFile | Program; } | undefined; export interface BuilderProgramHost { /** @@ -15,7 +20,7 @@ export interface BuilderProgramHost { * When emit or emitNextAffectedFile are called without writeFile, * this callback if present would be used to write files */ - writeFile?: ts.WriteFileCallback; + writeFile?: WriteFileCallback; /** * disable using source file version as signature for testing */ @@ -38,22 +43,22 @@ export interface BuilderProgramHost { */ export interface BuilderProgram { /*@internal*/ - getState(): ts.ReusableBuilderProgramState; + getState(): ReusableBuilderProgramState; /*@internal*/ - saveEmitState(): ts.SavedBuildProgramEmitState; + saveEmitState(): SavedBuildProgramEmitState; /*@internal*/ - restoreEmitState(saved: ts.SavedBuildProgramEmitState): void; + restoreEmitState(saved: SavedBuildProgramEmitState): void; /*@internal*/ hasChangedEmitSignature?(): boolean; /** * Returns current program */ - getProgram(): ts.Program; + getProgram(): Program; /** * Returns current program that could be undefined if the program was released */ /*@internal*/ - getProgramOrUndefined(): ts.Program | undefined; + getProgramOrUndefined(): Program | undefined; /** * Releases reference to the program, making all the other operations that need program to fail. */ @@ -62,39 +67,39 @@ export interface BuilderProgram { /** * Get compiler options of the program */ - getCompilerOptions(): ts.CompilerOptions; + getCompilerOptions(): CompilerOptions; /** * Get the source file in the program with file name */ - getSourceFile(fileName: string): ts.SourceFile | undefined; + getSourceFile(fileName: string): SourceFile | undefined; /** * Get a list of files in the program */ - getSourceFiles(): readonly ts.SourceFile[]; + getSourceFiles(): readonly SourceFile[]; /** * Get the diagnostics for compiler options */ - getOptionsDiagnostics(cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; + getOptionsDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; /** * Get the diagnostics that dont belong to any file */ - getGlobalDiagnostics(cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; + getGlobalDiagnostics(cancellationToken?: CancellationToken): readonly Diagnostic[]; /** * Get the diagnostics from config file parsing */ - getConfigFileParsingDiagnostics(): readonly ts.Diagnostic[]; + getConfigFileParsingDiagnostics(): readonly Diagnostic[]; /** * Get the syntax diagnostics, for all source files if source file is not supplied */ - getSyntacticDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; + getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; /** * Get the declaration diagnostics, for all source files if source file is not supplied */ - getDeclarationDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.DiagnosticWithLocation[]; + getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[]; /** * Get all the dependencies of the file */ - getAllDependencies(sourceFile: ts.SourceFile): readonly string[]; + getAllDependencies(sourceFile: SourceFile): readonly string[]; /** * Gets the semantic diagnostics from the program corresponding to this state of file (if provided) or whole program @@ -104,7 +109,7 @@ export interface BuilderProgram { * In case of SemanticDiagnosticsBuilderProgram if the source file is not provided, * it will iterate through all the affected files, to ensure that cache stays valid and yet provide a way to get all semantic diagnostics */ - getSemanticDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; + getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; /** * Emits the JavaScript and declaration files. * When targetSource file is specified, emits the files corresponding to that source file, @@ -116,9 +121,9 @@ export interface BuilderProgram { * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emit(targetSourceFile?: ts.SourceFile, writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: ts.CustomTransformers): ts.EmitResult; + emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult; /*@internal*/ - emitBuildInfo(writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken): ts.EmitResult; + emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult; /** * Get the current directory of the program */ @@ -135,7 +140,7 @@ export interface SemanticDiagnosticsBuilderProgram extends BuilderProgram { * Gets the semantic diagnostics from the program for the next affected file and caches it * Returns undefined if the iteration is complete */ - getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: ts.CancellationToken, ignoreSourceFile?: (sourceFile: ts.SourceFile) => boolean): AffectedFileResult; + getSemanticDiagnosticsOfNextAffectedFile(cancellationToken?: CancellationToken, ignoreSourceFile?: (sourceFile: SourceFile) => boolean): AffectedFileResult; } /** @@ -148,34 +153,34 @@ export interface EmitAndSemanticDiagnosticsBuilderProgram extends SemanticDiagno * The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host * in that order would be used to write the files */ - emitNextAffectedFile(writeFile?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: ts.CustomTransformers): AffectedFileResult; + emitNextAffectedFile(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): AffectedFileResult; } /** * Create the builder to manage semantic diagnostics and cache them */ -export function createSemanticDiagnosticsBuilderProgram(newProgram: ts.Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[]): SemanticDiagnosticsBuilderProgram; -export function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: ts.CompilerOptions | undefined, host?: ts.CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]): SemanticDiagnosticsBuilderProgram; -export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: ts.Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | ts.CompilerOptions | undefined, oldProgramOrHost?: ts.CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly ts.Diagnostic[] | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]) { - return ts.createBuilderProgram(ts.BuilderProgramKind.SemanticDiagnosticsBuilderProgram, ts.getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); +export function createSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): SemanticDiagnosticsBuilderProgram; +export function createSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): SemanticDiagnosticsBuilderProgram; +export function createSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | SemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) { + return createBuilderProgram(BuilderProgramKind.SemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); } /** * Create the builder that can handle the changes in program and iterate through changed files * to emit the those files and manage semantic diagnostics cache as well */ -export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: ts.Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram; -export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: ts.CompilerOptions | undefined, host?: ts.CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram; -export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: ts.Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | ts.CompilerOptions | undefined, oldProgramOrHost?: ts.CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly ts.Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]) { - return ts.createBuilderProgram(ts.BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, ts.getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); +export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgram: Program, host: BuilderProgramHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): EmitAndSemanticDiagnosticsBuilderProgram; +export function createEmitAndSemanticDiagnosticsBuilderProgram(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): EmitAndSemanticDiagnosticsBuilderProgram; +export function createEmitAndSemanticDiagnosticsBuilderProgram(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | EmitAndSemanticDiagnosticsBuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]) { + return createBuilderProgram(BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram, getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences)); } /** * Creates a builder thats just abstraction over program and can be used with watch */ -export function createAbstractBuilder(newProgram: ts.Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[]): BuilderProgram; -export function createAbstractBuilder(rootNames: readonly string[] | undefined, options: ts.CompilerOptions | undefined, host?: ts.CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]): BuilderProgram; -export function createAbstractBuilder(newProgramOrRootNames: ts.Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | ts.CompilerOptions | undefined, oldProgramOrHost?: ts.CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly ts.Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly ts.Diagnostic[], projectReferences?: readonly ts.ProjectReference[]): BuilderProgram { - const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = ts.getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences); - return ts.createRedirectedBuilderProgram(() => ({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }), newConfigFileParsingDiagnostics); +export function createAbstractBuilder(newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): BuilderProgram; +export function createAbstractBuilder(rootNames: readonly string[] | undefined, options: CompilerOptions | undefined, host?: CompilerHost, oldProgram?: BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram; +export function createAbstractBuilder(newProgramOrRootNames: Program | readonly string[] | undefined, hostOrOptions: BuilderProgramHost | CompilerOptions | undefined, oldProgramOrHost?: CompilerHost | BuilderProgram, configFileParsingDiagnosticsOrOldProgram?: readonly Diagnostic[] | BuilderProgram, configFileParsingDiagnostics?: readonly Diagnostic[], projectReferences?: readonly ProjectReference[]): BuilderProgram { + const { newProgram, configFileParsingDiagnostics: newConfigFileParsingDiagnostics } = getBuilderCreationParameters(newProgramOrRootNames, hostOrOptions, oldProgramOrHost, configFileParsingDiagnosticsOrOldProgram, configFileParsingDiagnostics, projectReferences); + return createRedirectedBuilderProgram(() => ({ program: newProgram, compilerOptions: newProgram.getCompilerOptions() }), newConfigFileParsingDiagnostics); } diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 31ea38d87beb0..6257d8a311b07 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -1,9 +1,16 @@ -import * as ts from "./_namespaces/ts"; +import { + arrayFrom, CancellationToken, computeSignatureWithDiagnostics, CustomTransformers, Debug, EmitOutput, emptyArray, + ESMap, ExportedModulesFromDeclarationEmit, GetCanonicalFileName, getDirectoryPath, getSourceFileOfNode, + isDeclarationFileName, isExternalOrCommonJsModule, isGlobalScopeAugmentation, isJsonSourceFile, + isModuleWithStringLiteralName, isStringLiteral, Iterator, Map, mapDefined, mapDefinedIterator, ModuleDeclaration, + ModuleKind, outFile, OutputFile, Path, Program, ReadonlySet, Set, some, SourceFile, StringLiteralLike, Symbol, + toPath, TypeChecker, +} from "./_namespaces/ts"; /** @internal */ -export function getFileEmitOutput(program: ts.Program, sourceFile: ts.SourceFile, emitOnlyDtsFiles: boolean, - cancellationToken?: ts.CancellationToken, customTransformers?: ts.CustomTransformers, forceDtsEmit?: boolean): ts.EmitOutput { - const outputFiles: ts.OutputFile[] = []; +export function getFileEmitOutput(program: Program, sourceFile: SourceFile, emitOnlyDtsFiles: boolean, + cancellationToken?: CancellationToken, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitOutput { + const outputFiles: OutputFile[] = []; const { emitSkipped, diagnostics } = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers, forceDtsEmit); return { outputFiles, emitSkipped, diagnostics }; @@ -16,7 +23,7 @@ export interface BuilderState { /** * Information of the file eg. its version, signature etc */ - fileInfos: ts.ESMap; + fileInfos: ESMap; /** * Contains the map of ReferencedSet=Referenced files of the file if module emit is enabled * Otherwise undefined @@ -41,19 +48,19 @@ export interface BuilderState { * That means hence forth these files are assumed to have * no change in their signature for this version of the program */ - hasCalledUpdateShapeSignature?: ts.Set; + hasCalledUpdateShapeSignature?: Set; /** * Stores signatures before before the update till affected file is commited */ - oldSignatures?: ts.ESMap; + oldSignatures?: ESMap; /** * Stores exportedModulesMap before the update till affected file is commited */ - oldExportedModulesMap?: ts.ESMap | false>; + oldExportedModulesMap?: ESMap | false>; /** * Cache of all files excluding default library file for the current program */ - allFilesExcludingDefaultLibraryFile?: readonly ts.SourceFile[]; + allFilesExcludingDefaultLibraryFile?: readonly SourceFile[]; /** * Cache of all the file names */ @@ -68,29 +75,29 @@ export namespace BuilderState { readonly version: string; signature: string | undefined; affectsGlobalScope: true | undefined; - impliedFormat: ts.SourceFile["impliedNodeFormat"]; + impliedFormat: SourceFile["impliedNodeFormat"]; } export interface ReadonlyManyToManyPathMap { - getKeys(v: ts.Path): ts.ReadonlySet | undefined; - getValues(k: ts.Path): ts.ReadonlySet | undefined; - keys(): ts.Iterator; + getKeys(v: Path): ReadonlySet | undefined; + getValues(k: Path): ReadonlySet | undefined; + keys(): Iterator; } export interface ManyToManyPathMap extends ReadonlyManyToManyPathMap { - deleteKey(k: ts.Path): boolean; - set(k: ts.Path, v: ts.ReadonlySet): void; + deleteKey(k: Path): boolean; + set(k: Path, v: ReadonlySet): void; } export function createManyToManyPathMap(): ManyToManyPathMap { - function create(forward: ts.ESMap>, reverse: ts.ESMap>, deleted: ts.Set | undefined): ManyToManyPathMap { + function create(forward: ESMap>, reverse: ESMap>, deleted: Set | undefined): ManyToManyPathMap { const map: ManyToManyPathMap = { getKeys: v => reverse.get(v), getValues: k => forward.get(k), keys: () => forward.keys(), deleteKey: k => { - (deleted ||= new ts.Set()).add(k); + (deleted ||= new Set()).add(k); const set = forward.get(k); if (!set) { @@ -126,19 +133,19 @@ export namespace BuilderState { return map; } - return create(new ts.Map>(), new ts.Map>(), /*deleted*/ undefined); + return create(new Map>(), new Map>(), /*deleted*/ undefined); } - function addToMultimap(map: ts.ESMap>, k: K, v: V): void { + function addToMultimap(map: ESMap>, k: K, v: V): void { let set = map.get(k); if (!set) { - set = new ts.Set(); + set = new Set(); map.set(k, set); } set.add(v); } - function deleteFromMultimap(map: ts.ESMap>, k: K, v: V): boolean { + function deleteFromMultimap(map: ESMap>, k: K, v: V): boolean { const set = map.get(k); if (set?.delete(v)) { @@ -156,14 +163,14 @@ export namespace BuilderState { */ export type ComputeHash = ((data: string) => string) | undefined; - function getReferencedFilesFromImportedModuleSymbol(symbol: ts.Symbol): ts.Path[] { - return ts.mapDefined(symbol.declarations, declaration => ts.getSourceFileOfNode(declaration)?.resolvedPath); + function getReferencedFilesFromImportedModuleSymbol(symbol: Symbol): Path[] { + return mapDefined(symbol.declarations, declaration => getSourceFileOfNode(declaration)?.resolvedPath); } /** * Get the module source file and all augmenting files from the import name node from file */ - function getReferencedFilesFromImportLiteral(checker: ts.TypeChecker, importName: ts.StringLiteralLike): ts.Path[] | undefined { + function getReferencedFilesFromImportLiteral(checker: TypeChecker, importName: StringLiteralLike): Path[] | undefined { const symbol = checker.getSymbolAtLocation(importName); return symbol && getReferencedFilesFromImportedModuleSymbol(symbol); } @@ -171,28 +178,28 @@ export namespace BuilderState { /** * Gets the path to reference file from file name, it could be resolvedPath if present otherwise path */ - function getReferencedFileFromFileName(program: ts.Program, fileName: string, sourceFileDirectory: ts.Path, getCanonicalFileName: ts.GetCanonicalFileName): ts.Path { - return ts.toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName); + function getReferencedFileFromFileName(program: Program, fileName: string, sourceFileDirectory: Path, getCanonicalFileName: GetCanonicalFileName): Path { + return toPath(program.getProjectReferenceRedirect(fileName) || fileName, sourceFileDirectory, getCanonicalFileName); } /** * Gets the referenced files for a file from the program with values for the keys as referenced file's path to be true */ - function getReferencedFiles(program: ts.Program, sourceFile: ts.SourceFile, getCanonicalFileName: ts.GetCanonicalFileName): ts.Set | undefined { - let referencedFiles: ts.Set | undefined; + function getReferencedFiles(program: Program, sourceFile: SourceFile, getCanonicalFileName: GetCanonicalFileName): Set | undefined { + let referencedFiles: Set | undefined; // We need to use a set here since the code can contain the same import twice, // but that will only be one dependency. // To avoid invernal conversion, the key of the referencedFiles map must be of type Path if (sourceFile.imports && sourceFile.imports.length > 0) { - const checker: ts.TypeChecker = program.getTypeChecker(); + const checker: TypeChecker = program.getTypeChecker(); for (const importName of sourceFile.imports) { const declarationSourceFilePaths = getReferencedFilesFromImportLiteral(checker, importName); declarationSourceFilePaths?.forEach(addReferencedFile); } } - const sourceFileDirectory = ts.getDirectoryPath(sourceFile.resolvedPath); + const sourceFileDirectory = getDirectoryPath(sourceFile.resolvedPath); // Handle triple slash references if (sourceFile.referencedFiles && sourceFile.referencedFiles.length > 0) { for (const referencedFile of sourceFile.referencedFiles) { @@ -218,7 +225,7 @@ export namespace BuilderState { if (sourceFile.moduleAugmentations.length) { const checker = program.getTypeChecker(); for (const moduleName of sourceFile.moduleAugmentations) { - if (!ts.isStringLiteral(moduleName)) continue; + if (!isStringLiteral(moduleName)) continue; const symbol = checker.getSymbolAtLocation(moduleName); if (!symbol) continue; @@ -236,13 +243,13 @@ export namespace BuilderState { return referencedFiles; - function addReferenceFromAmbientModule(symbol: ts.Symbol) { + function addReferenceFromAmbientModule(symbol: Symbol) { if (!symbol.declarations) { return; } // Add any file other than our own as reference for (const declaration of symbol.declarations) { - const declarationSourceFile = ts.getSourceFileOfNode(declaration); + const declarationSourceFile = getSourceFileOfNode(declaration); if (declarationSourceFile && declarationSourceFile !== sourceFile) { addReferencedFile(declarationSourceFile.resolvedPath); @@ -250,8 +257,8 @@ export namespace BuilderState { } } - function addReferencedFile(referencedPath: ts.Path) { - (referencedFiles || (referencedFiles = new ts.Set())).add(referencedPath); + function addReferencedFile(referencedPath: Path) { + (referencedFiles || (referencedFiles = new Set())).add(referencedPath); } } @@ -265,11 +272,11 @@ export namespace BuilderState { /** * Creates the state of file references and signature for the new program from oldState if it is safe */ - export function create(newProgram: ts.Program, getCanonicalFileName: ts.GetCanonicalFileName, oldState?: Readonly, disableUseFileVersionAsSignature?: boolean): BuilderState { - const fileInfos = new ts.Map(); + export function create(newProgram: Program, getCanonicalFileName: GetCanonicalFileName, oldState?: Readonly, disableUseFileVersionAsSignature?: boolean): BuilderState { + const fileInfos = new Map(); const options = newProgram.getCompilerOptions(); - const isOutFile = ts.outFile(options); - const referencedMap = options.module !== ts.ModuleKind.None && !isOutFile ? + const isOutFile = outFile(options); + const referencedMap = options.module !== ModuleKind.None && !isOutFile ? createManyToManyPathMap() : undefined; const exportedModulesMap = referencedMap ? createManyToManyPathMap() : undefined; const useOldState = canReuseOldState(referencedMap, oldState); @@ -279,7 +286,7 @@ export namespace BuilderState { // Create the reference map, and set the file infos for (const sourceFile of newProgram.getSourceFiles()) { - const version = ts.Debug.checkDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set"); + const version = Debug.checkDefined(sourceFile.version, "Program intended to be used with Builder should have source files with versions set"); const oldUncommittedSignature = useOldState ? oldState!.oldSignatures?.get(sourceFile.resolvedPath) : undefined; const signature = oldUncommittedSignature === undefined ? useOldState ? oldState!.fileInfos.get(sourceFile.resolvedPath)?.signature : undefined : @@ -330,12 +337,12 @@ export namespace BuilderState { */ export function getFilesAffectedBy( state: BuilderState, - programOfThisState: ts.Program, - path: ts.Path, - cancellationToken: ts.CancellationToken | undefined, + programOfThisState: Program, + path: Path, + cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - ): readonly ts.SourceFile[] { + getCanonicalFileName: GetCanonicalFileName, + ): readonly SourceFile[] { const result = getFilesAffectedByWithOldState( state, programOfThisState, @@ -351,15 +358,15 @@ export namespace BuilderState { export function getFilesAffectedByWithOldState( state: BuilderState, - programOfThisState: ts.Program, - path: ts.Path, - cancellationToken: ts.CancellationToken | undefined, + programOfThisState: Program, + path: Path, + cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, - ): readonly ts.SourceFile[] { + getCanonicalFileName: GetCanonicalFileName, + ): readonly SourceFile[] { const sourceFile = programOfThisState.getSourceFileByPath(path); if (!sourceFile) { - return ts.emptyArray; + return emptyArray; } if (!updateShapeSignature(state, programOfThisState, sourceFile, cancellationToken, computeHash, getCanonicalFileName)) { @@ -369,9 +376,9 @@ export namespace BuilderState { return (state.referencedMap ? getFilesAffectedByUpdatedShapeWhenModuleEmit : getFilesAffectedByUpdatedShapeWhenNonModuleEmit)(state, programOfThisState, sourceFile, cancellationToken, computeHash, getCanonicalFileName); } - export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: ts.Path) { + export function updateSignatureOfFile(state: BuilderState, signature: string | undefined, path: Path) { state.fileInfos.get(path)!.signature = signature; - (state.hasCalledUpdateShapeSignature ||= new ts.Set()).add(path); + (state.hasCalledUpdateShapeSignature ||= new Set()).add(path); } /** @@ -379,11 +386,11 @@ export namespace BuilderState { */ export function updateShapeSignature( state: BuilderState, - programOfThisState: ts.Program, - sourceFile: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, + programOfThisState: Program, + sourceFile: SourceFile, + cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, + getCanonicalFileName: GetCanonicalFileName, useFileVersionAsSignature = state.useFileVersionAsSignature ) { // If we have cached the result for this file, that means hence forth we should assume file shape is uptodate @@ -396,8 +403,8 @@ export namespace BuilderState { programOfThisState.emit( sourceFile, (fileName, text, _writeByteOrderMark, _onError, sourceFiles, data) => { - ts.Debug.assert(ts.isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`); - latestSignature = ts.computeSignatureWithDiagnostics( + Debug.assert(isDeclarationFileName(fileName), `File extension for signature expected to be dts: Got:: ${fileName}`); + latestSignature = computeSignatureWithDiagnostics( sourceFile, text, computeHash, @@ -418,7 +425,7 @@ export namespace BuilderState { if (latestSignature === undefined) { latestSignature = sourceFile.version; if (state.exportedModulesMap && latestSignature !== prevSignature) { - (state.oldExportedModulesMap ||= new ts.Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); + (state.oldExportedModulesMap ||= new Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); // All the references in this file are exported const references = state.referencedMap ? state.referencedMap.getValues(sourceFile.resolvedPath) : undefined; if (references) { @@ -429,8 +436,8 @@ export namespace BuilderState { } } } - (state.oldSignatures ||= new ts.Map()).set(sourceFile.resolvedPath, prevSignature || false); - (state.hasCalledUpdateShapeSignature ||= new ts.Set()).add(sourceFile.resolvedPath); + (state.oldSignatures ||= new Map()).set(sourceFile.resolvedPath, prevSignature || false); + (state.hasCalledUpdateShapeSignature ||= new Set()).add(sourceFile.resolvedPath); info.signature = latestSignature; return latestSignature !== prevSignature; } @@ -438,15 +445,15 @@ export namespace BuilderState { /** * Coverts the declaration emit result into exported modules map */ - export function updateExportedModules(state: BuilderState, sourceFile: ts.SourceFile, exportedModulesFromDeclarationEmit: ts.ExportedModulesFromDeclarationEmit | undefined) { + export function updateExportedModules(state: BuilderState, sourceFile: SourceFile, exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined) { if (!state.exportedModulesMap) return; - (state.oldExportedModulesMap ||= new ts.Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); + (state.oldExportedModulesMap ||= new Map()).set(sourceFile.resolvedPath, state.exportedModulesMap.getValues(sourceFile.resolvedPath) || false); if (!exportedModulesFromDeclarationEmit) { state.exportedModulesMap.deleteKey(sourceFile.resolvedPath); return; } - let exportedModules: ts.Set | undefined; + let exportedModules: Set | undefined; exportedModulesFromDeclarationEmit.forEach(symbol => addExportedModule(getReferencedFilesFromImportedModuleSymbol(symbol))); if (exportedModules) { state.exportedModulesMap.set(sourceFile.resolvedPath, exportedModules); @@ -455,10 +462,10 @@ export namespace BuilderState { state.exportedModulesMap.deleteKey(sourceFile.resolvedPath); } - function addExportedModule(exportedModulePaths: ts.Path[] | undefined) { + function addExportedModule(exportedModulePaths: Path[] | undefined) { if (exportedModulePaths?.length) { if (!exportedModules) { - exportedModules = new ts.Set(); + exportedModules = new Set(); } exportedModulePaths.forEach(path => exportedModules!.add(path)); } @@ -468,10 +475,10 @@ export namespace BuilderState { /** * Get all the dependencies of the sourceFile */ - export function getAllDependencies(state: BuilderState, programOfThisState: ts.Program, sourceFile: ts.SourceFile): readonly string[] { + export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): readonly string[] { const compilerOptions = programOfThisState.getCompilerOptions(); // With --out or --outFile all outputs go into single file, all files depend on each other - if (ts.outFile(compilerOptions)) { + if (outFile(compilerOptions)) { return getAllFileNames(state, programOfThisState); } @@ -481,7 +488,7 @@ export namespace BuilderState { } // Get the references, traversing deep from the referenceMap - const seenMap = new ts.Set(); + const seenMap = new Set(); const queue = [sourceFile.resolvedPath]; while (queue.length) { const path = queue.pop()!; @@ -497,16 +504,16 @@ export namespace BuilderState { } } - return ts.arrayFrom(ts.mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); + return arrayFrom(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); } /** * Gets the names of all files from the program */ - function getAllFileNames(state: BuilderState, programOfThisState: ts.Program): readonly string[] { + function getAllFileNames(state: BuilderState, programOfThisState: Program): readonly string[] { if (!state.allFileNames) { const sourceFiles = programOfThisState.getSourceFiles(); - state.allFileNames = sourceFiles === ts.emptyArray ? ts.emptyArray : sourceFiles.map(file => file.fileName); + state.allFileNames = sourceFiles === emptyArray ? emptyArray : sourceFiles.map(file => file.fileName); } return state.allFileNames; } @@ -514,9 +521,9 @@ export namespace BuilderState { /** * Gets the files referenced by the the file path */ - export function getReferencedByPaths(state: Readonly, referencedFilePath: ts.Path) { + export function getReferencedByPaths(state: Readonly, referencedFilePath: Path) { const keys = state.referencedMap!.getKeys(referencedFilePath); - return keys ? ts.arrayFrom(keys.keys()) : []; + return keys ? arrayFrom(keys.keys()) : []; } /** @@ -525,9 +532,9 @@ export namespace BuilderState { * there are no point to rebuild all script files if these special files have changed. However, if any statement * in the file is not ambient external module, we treat it as a regular script file. */ - function containsOnlyAmbientModules(sourceFile: ts.SourceFile) { + function containsOnlyAmbientModules(sourceFile: SourceFile) { for (const statement of sourceFile.statements) { - if (!ts.isModuleWithStringLiteralName(statement)) { + if (!isModuleWithStringLiteralName(statement)) { return false; } } @@ -538,38 +545,38 @@ export namespace BuilderState { * Return true if file contains anything that augments to global scope we need to build them as if * they are global files as well as module */ - function containsGlobalScopeAugmentation(sourceFile: ts.SourceFile) { - return ts.some(sourceFile.moduleAugmentations, augmentation => ts.isGlobalScopeAugmentation(augmentation.parent as ts.ModuleDeclaration)); + function containsGlobalScopeAugmentation(sourceFile: SourceFile) { + return some(sourceFile.moduleAugmentations, augmentation => isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)); } /** * Return true if the file will invalidate all files because it affectes global scope */ - function isFileAffectingGlobalScope(sourceFile: ts.SourceFile) { + function isFileAffectingGlobalScope(sourceFile: SourceFile) { return containsGlobalScopeAugmentation(sourceFile) || - !ts.isExternalOrCommonJsModule(sourceFile) && !ts.isJsonSourceFile(sourceFile) && !containsOnlyAmbientModules(sourceFile); + !isExternalOrCommonJsModule(sourceFile) && !isJsonSourceFile(sourceFile) && !containsOnlyAmbientModules(sourceFile); } /** * Gets all files of the program excluding the default library file */ - export function getAllFilesExcludingDefaultLibraryFile(state: BuilderState, programOfThisState: ts.Program, firstSourceFile: ts.SourceFile | undefined): readonly ts.SourceFile[] { + export function getAllFilesExcludingDefaultLibraryFile(state: BuilderState, programOfThisState: Program, firstSourceFile: SourceFile | undefined): readonly SourceFile[] { // Use cached result if (state.allFilesExcludingDefaultLibraryFile) { return state.allFilesExcludingDefaultLibraryFile; } - let result: ts.SourceFile[] | undefined; + let result: SourceFile[] | undefined; if (firstSourceFile) addSourceFile(firstSourceFile); for (const sourceFile of programOfThisState.getSourceFiles()) { if (sourceFile !== firstSourceFile) { addSourceFile(sourceFile); } } - state.allFilesExcludingDefaultLibraryFile = result || ts.emptyArray; + state.allFilesExcludingDefaultLibraryFile = result || emptyArray; return state.allFilesExcludingDefaultLibraryFile; - function addSourceFile(sourceFile: ts.SourceFile) { + function addSourceFile(sourceFile: SourceFile) { if (!programOfThisState.isSourceFileDefaultLibrary(sourceFile)) { (result || (result = [])).push(sourceFile); } @@ -579,11 +586,11 @@ export namespace BuilderState { /** * When program emits non modular code, gets the files affected by the sourceFile whose shape has changed */ - function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state: BuilderState, programOfThisState: ts.Program, sourceFileWithUpdatedShape: ts.SourceFile) { + function getFilesAffectedByUpdatedShapeWhenNonModuleEmit(state: BuilderState, programOfThisState: Program, sourceFileWithUpdatedShape: SourceFile) { const compilerOptions = programOfThisState.getCompilerOptions(); // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project, // so returning the file itself is good enough. - if (compilerOptions && ts.outFile(compilerOptions)) { + if (compilerOptions && outFile(compilerOptions)) { return [sourceFileWithUpdatedShape]; } return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); @@ -594,25 +601,25 @@ export namespace BuilderState { */ function getFilesAffectedByUpdatedShapeWhenModuleEmit( state: BuilderState, - programOfThisState: ts.Program, - sourceFileWithUpdatedShape: ts.SourceFile, - cancellationToken: ts.CancellationToken | undefined, + programOfThisState: Program, + sourceFileWithUpdatedShape: SourceFile, + cancellationToken: CancellationToken | undefined, computeHash: ComputeHash, - getCanonicalFileName: ts.GetCanonicalFileName, + getCanonicalFileName: GetCanonicalFileName, ) { if (isFileAffectingGlobalScope(sourceFileWithUpdatedShape)) { return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape); } const compilerOptions = programOfThisState.getCompilerOptions(); - if (compilerOptions && (compilerOptions.isolatedModules || ts.outFile(compilerOptions))) { + if (compilerOptions && (compilerOptions.isolatedModules || outFile(compilerOptions))) { return [sourceFileWithUpdatedShape]; } // Now we need to if each file in the referencedBy list has a shape change as well. // Because if so, its own referencedBy files need to be saved as well to make the // emitting result consistent with files on disk. - const seenFileNamesMap = new ts.Map(); + const seenFileNamesMap = new Map(); // Start with the paths this file was referenced by seenFileNamesMap.set(sourceFileWithUpdatedShape.resolvedPath, sourceFileWithUpdatedShape); @@ -629,6 +636,6 @@ export namespace BuilderState { } // Return array of values that needs emit - return ts.arrayFrom(ts.mapDefinedIterator(seenFileNamesMap.values(), value => value)); + return arrayFrom(mapDefinedIterator(seenFileNamesMap.values(), value => value)); } } diff --git a/src/compiler/builderStatePublic.ts b/src/compiler/builderStatePublic.ts index b662d8c851891..49fd891fa1c94 100644 --- a/src/compiler/builderStatePublic.ts +++ b/src/compiler/builderStatePublic.ts @@ -1,14 +1,14 @@ -import * as ts from "./_namespaces/ts"; +import { Diagnostic, WriteFileCallbackData } from "./_namespaces/ts"; export interface EmitOutput { outputFiles: OutputFile[]; emitSkipped: boolean; - /* @internal */ diagnostics: readonly ts.Diagnostic[]; + /* @internal */ diagnostics: readonly Diagnostic[]; } export interface OutputFile { name: string; writeByteOrderMark: boolean; text: string; - /* @internal */ data?: ts.WriteFileCallbackData; + /* @internal */ data?: WriteFileCallbackData; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2d9f31d24a542..790081808d742 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1,7 +1,205 @@ import * as ts from "./_namespaces/ts"; +import { + __String, AccessExpression, AccessFlags, AccessorDeclaration, addRange, addRelatedInfo, addSyntheticLeadingComment, + AllAccessorDeclarations, and, AnonymousType, AnyImportOrReExport, AnyImportSyntax, append, appendIfUnique, + ArrayBindingPattern, arrayFrom, arrayIsHomogeneous, ArrayLiteralExpression, arrayOf, arraysEqual, arrayToMultiMap, + ArrayTypeNode, ArrowFunction, AssertionExpression, AssignmentDeclarationKind, AssignmentKind, AssignmentPattern, + AwaitExpression, BaseType, BigIntLiteral, BigIntLiteralType, BinaryExpression, BinaryOperatorToken, binarySearch, + BindableObjectDefinePropertyCall, BindingElement, BindingElementGrandparent, BindingName, BindingPattern, + bindSourceFile, Block, BreakOrContinueStatement, CallChain, CallExpression, CallLikeExpression, + CallSignatureDeclaration, CancellationToken, canHaveDecorators, canHaveExportModifier, canHaveIllegalDecorators, + canHaveIllegalModifiers, canHaveModifiers, cartesianProduct, CaseBlock, CaseClause, CaseOrDefaultClause, cast, + chainDiagnosticMessages, CharacterCodes, CheckFlags, ClassDeclaration, ClassElement, ClassExpression, + ClassLikeDeclaration, ClassStaticBlockDeclaration, clear, combinePaths, compareDiagnostics, comparePaths, + compareValues, Comparison, CompilerOptions, ComputedPropertyName, concatenate, concatenateDiagnosticMessageChains, + ConditionalExpression, ConditionalRoot, ConditionalType, ConditionalTypeNode, ConstructorDeclaration, + ConstructorTypeNode, ConstructSignatureDeclaration, contains, containsParseError, ContextFlags, copyEntries, + countWhere, createBinaryExpressionTrampoline, createCompilerDiagnostic, createDiagnosticCollection, + createDiagnosticForFileFromMessageChain, createDiagnosticForNode, createDiagnosticForNodeArray, + createDiagnosticForNodeFromMessageChain, createDiagnosticMessageChainFromDiagnostic, createEmptyExports, + createFileDiagnostic, createGetCanonicalFileName, createGetSymbolWalker, createPrinter, + createPropertyNameNodeForIdentifierOrLiteral, createScanner, createSymbolTable, createTextWriter, + createUnderscoreEscapedMultiMap, Debug, Declaration, DeclarationName, declarationNameToString, DeclarationStatement, + DeclarationWithTypeParameterChildren, DeclarationWithTypeParameters, Decorator, deduplicate, DefaultClause, + defaultMaximumTruncationLength, DeferredTypeReference, DeleteExpression, Diagnostic, DiagnosticCategory, + DiagnosticMessage, DiagnosticMessageChain, DiagnosticRelatedInformation, Diagnostics, DiagnosticWithLocation, + DoStatement, DynamicNamedDeclaration, ElementAccessChain, ElementAccessExpression, ElementFlags, EmitFlags, + EmitHint, EmitResolver, EmitTextWriter, emptyArray, endsWith, EntityName, EntityNameExpression, + EntityNameOrEntityNameExpression, entityNameToString, EnumDeclaration, EnumMember, equateValues, + escapeLeadingUnderscores, escapeString, ESMap, every, EvolvingArrayType, ExclamationToken, ExportAssignment, + exportAssignmentIsAlias, ExportDeclaration, ExportSpecifier, Expression, expressionResultIsUnused, + ExpressionStatement, ExpressionWithTypeArguments, Extension, ExternalEmitHelpers, externalHelpersModuleNameText, + factory, fileExtensionIs, fileExtensionIsOneOf, filter, find, findAncestor, findBestPatternMatch, findIndex, + findLast, findLastIndex, findUseStrictPrologue, first, firstDefined, firstOrUndefined, flatMap, flatten, + FlowArrayMutation, FlowAssignment, FlowCall, FlowCondition, FlowFlags, FlowLabel, FlowNode, FlowReduceLabel, + FlowStart, FlowSwitchClause, FlowType, forEach, forEachChild, forEachChildRecursively, + forEachEnclosingBlockScopeContainer, forEachEntry, forEachImportClauseDeclaration, forEachKey, + forEachReturnStatement, forEachYieldExpression, ForInOrOfStatement, ForInStatement, formatMessage, ForOfStatement, + ForStatement, FreshableIntrinsicType, FreshableType, FreshObjectLiteralType, FunctionDeclaration, + FunctionExpression, FunctionFlags, FunctionLikeDeclaration, FunctionTypeNode, GenericType, GetAccessorDeclaration, + getAliasDeclarationFromName, getAllAccessorDeclarations, getAllowSyntheticDefaultImports, getAncestor, + getAssignedExpandoInitializer, getAssignmentDeclarationKind, getAssignmentDeclarationPropertyAccessKind, + getAssignmentTargetKind, getCheckFlags, getClassExtendsHeritageElement, getClassLikeDeclarationOfSymbol, + getCombinedLocalAndExportSymbolFlags, getCombinedModifierFlags, getCombinedNodeFlags, getContainingClass, + getContainingFunction, getContainingFunctionOrClassStaticBlock, getDeclarationModifierFlagsFromSymbol, + getDeclarationOfKind, getDeclarationsOfKind, getDeclaredExpandoInitializer, getDirectoryPath, + getEffectiveBaseTypeNode, getEffectiveConstraintOfTypeParameter, getEffectiveContainerForJSDocTemplateTag, + getEffectiveImplementsTypeNodes, getEffectiveInitializer, getEffectiveJSDocHost, getEffectiveModifierFlags, + getEffectiveReturnTypeNode, getEffectiveSetAccessorTypeAnnotationNode, getEffectiveTypeAnnotationNode, + getEffectiveTypeParameterDeclarations, getElementOrPropertyAccessName, getEmitDeclarations, getEmitModuleKind, + getEmitModuleResolutionKind, getEmitScriptTarget, getEnclosingBlockScopeContainer, getEntityNameFromTypeNode, + getEntries, getErrorSpanForNode, getEscapedTextOfIdentifierOrLiteral, getESModuleInterop, getExpandoInitializer, + getExportAssignmentExpression, getExternalModuleImportEqualsDeclarationExpression, getExternalModuleName, + getExternalModuleRequireArgument, getFirstConstructorWithBody, getFirstIdentifier, getFunctionFlags, + getHostSignatureFromJSDoc, getImmediatelyInvokedFunctionExpression, getInitializerOfBinaryExpression, + getInterfaceBaseTypeNodes, getInvokedExpression, getJSDocClassTag, getJSDocDeprecatedTag, getJSDocEnumTag, + getJSDocHost, getJSDocParameterTags, getJSDocRoot, getJSDocTags, getJSDocThisTag, getJSDocType, + getJSDocTypeAssertionType, getJSDocTypeParameterDeclarations, getJSDocTypeTag, getJSXImplicitImportBase, + getJSXRuntimeImport, getJSXTransformEnabled, getLeftmostAccessExpression, getLineAndCharacterOfPosition, + getLocalSymbolForExportDefault, getMembersOfDeclaration, getModeForUsageLocation, getModifiers, + getModuleInstanceState, getNameFromIndexInfo, getNameOfDeclaration, getNameOfExpando, getNamespaceDeclarationNode, + getNewTargetContainer, getNonAugmentationDeclaration, getNormalizedAbsolutePath, getObjectFlags, getOriginalNode, + getOrUpdate, getOwnKeys, getParameterSymbolFromJSDoc, getParseTreeNode, getPropertyAssignmentAliasLikeExpression, + getPropertyNameForPropertyNameNode, getResolutionDiagnostic, getResolutionModeOverrideForClause, + getResolvedExternalModuleName, getResolvedModule, getRestParameterElementType, getRootDeclaration, + getScriptTargetFeatures, getSelectedEffectiveModifierFlags, getSemanticJsxChildren, getSetAccessorValueParameter, + getSingleVariableOfVariableStatement, getSourceFileOfModule, getSourceFileOfNode, getSpanOfTokenAtPosition, + getSpellingSuggestion, getStrictOptionValue, getSuperContainer, getSymbolNameForPrivateIdentifier, + getTextOfIdentifierOrLiteral, getTextOfJSDocComment, getTextOfNode, getTextOfPropertyName, getThisContainer, + getThisParameter, getTrailingSemicolonDeferringWriter, getTypeParameterFromJsDoc, getTypesPackageName, + getUseDefineForClassFields, group, hasAbstractModifier, hasAccessorModifier, hasAmbientModifier, + hasContextSensitiveParameters, hasDecorators, HasDecorators, hasDynamicName, hasEffectiveModifier, + hasEffectiveModifiers, hasEffectiveReadonlyModifier, HasExpressionInitializer, hasExtension, HasIllegalDecorators, + HasIllegalModifiers, hasInitializer, HasInitializer, hasJSDocNodes, hasJSDocParameterTags, hasJsonModuleEmitEnabled, + HasModifiers, hasOnlyExpressionInitializer, hasOverrideModifier, hasPossibleExternalModuleReference, + hasQuestionToken, hasRestParameter, hasScopeMarker, hasStaticModifier, hasSyntacticModifier, hasSyntacticModifiers, + HeritageClause, Identifier, IdentifierTypePredicate, idText, IfStatement, ImportCall, ImportClause, + ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, ImportsNotUsedAsValues, ImportSpecifier, + ImportTypeAssertionContainer, ImportTypeNode, IncompleteType, IndexedAccessType, IndexedAccessTypeNode, IndexInfo, + IndexKind, indexOfNode, IndexSignatureDeclaration, IndexType, indicesOf, InferenceContext, InferenceFlags, + InferenceInfo, InferencePriority, InferTypeNode, InstantiableType, InstantiationExpressionType, + InterfaceDeclaration, InterfaceType, InterfaceTypeWithDeclaredMembers, InternalSymbolName, IntersectionType, + IntersectionTypeNode, IntrinsicType, introducesArgumentsExoticObject, isAccessExpression, isAccessor, + isAliasableExpression, isAmbientModule, isArray, isArrayBindingPattern, isArrayLiteralExpression, isArrowFunction, + isAssertionExpression, isAssignmentDeclaration, isAssignmentExpression, isAssignmentOperator, isAssignmentPattern, + isAssignmentTarget, isAsyncFunction, isAutoAccessorPropertyDeclaration, isBinaryExpression, + isBindableObjectDefinePropertyCall, isBindableStaticElementAccessExpression, isBindableStaticNameExpression, + isBindingElement, isBindingPattern, isBlock, isBlockOrCatchScoped, isBlockScopedContainerTopLevel, isCallChain, + isCallExpression, isCallLikeExpression, isCallOrNewExpression, isCallSignatureDeclaration, isCatchClause, + isCatchClauseVariableDeclarationOrBindingElement, isCheckJsEnabledForFile, isChildOfNodeWithKind, + isClassDeclaration, isClassElement, isClassExpression, isClassLike, isClassStaticBlockDeclaration, isCommaSequence, + isCommonJsExportedExpression, isCommonJsExportPropertyAssignment, isComputedNonLiteralName, isComputedPropertyName, + isConstructorDeclaration, isConstructorTypeNode, isConstTypeReference, isDeclaration, isDeclarationName, + isDeclarationReadonly, isDecorator, isDefaultedExpandoInitializer, isDeleteTarget, isDottedName, isDynamicName, + isEffectiveExternalModule, isElementAccessExpression, isEntityName, isEntityNameExpression, isEnumConst, + isEnumDeclaration, isEnumMember, isExclusivelyTypeOnlyImportOrExport, isExportAssignment, isExportDeclaration, + isExportsIdentifier, isExportSpecifier, isExpression, isExpressionNode, isExpressionOfOptionalChainRoot, + isExpressionStatement, isExpressionWithTypeArguments, isExpressionWithTypeArgumentsInClassExtendsClause, + isExternalModule, isExternalModuleAugmentation, isExternalModuleImportEqualsDeclaration, isExternalModuleIndicator, + isExternalModuleNameRelative, isExternalModuleReference, isExternalOrCommonJsModule, isForInOrOfStatement, + isForInStatement, isForOfStatement, isForStatement, isFunctionDeclaration, isFunctionExpression, + isFunctionExpressionOrArrowFunction, isFunctionLike, isFunctionLikeDeclaration, + isFunctionLikeOrClassStaticBlockDeclaration, isFunctionOrModuleBlock, isFunctionTypeNode, isGeneratedIdentifier, + isGetAccessor, isGetAccessorDeclaration, isGetOrSetAccessorDeclaration, isGlobalScopeAugmentation, isHeritageClause, + isIdentifier, isIdentifierStart, isIdentifierText, isIdentifierTypePredicate, isIdentifierTypeReference, + isIfStatement, isImportCall, isImportClause, isImportDeclaration, isImportEqualsDeclaration, isImportKeyword, + isImportOrExportSpecifier, isImportSpecifier, isImportTypeNode, isIndexedAccessTypeNode, isInExpressionContext, + isInfinityOrNaNString, isInJSDoc, isInJSFile, isInJsonFile, isInterfaceDeclaration, + isInternalModuleImportEqualsDeclaration, isInTopLevelContext, isIntrinsicJsxName, isIterationStatement, + isJSDocAllType, isJSDocAugmentsTag, isJSDocCallbackTag, isJSDocConstructSignature, isJSDocFunctionType, + isJSDocIndexSignature, isJSDocLinkLike, isJSDocMemberName, isJSDocNameReference, isJSDocNode, + isJSDocNonNullableType, isJSDocNullableType, isJSDocOptionalType, isJSDocParameterTag, isJSDocPropertyLikeTag, + isJSDocReturnTag, isJSDocSignature, isJSDocTemplateTag, isJSDocTypeAlias, isJSDocTypeAssertion, isJSDocTypedefTag, + isJSDocTypeExpression, isJSDocTypeLiteral, isJSDocTypeTag, isJSDocUnknownType, isJSDocVariadicType, + isJsonSourceFile, isJsxAttribute, isJsxAttributeLike, isJsxAttributes, isJsxElement, isJsxOpeningElement, + isJsxOpeningFragment, isJsxOpeningLikeElement, isJsxSelfClosingElement, isJsxSpreadAttribute, isJSXTagName, + isKnownSymbol, isLateVisibilityPaintedStatement, isLeftHandSideExpression, isLet, isLineBreak, + isLiteralComputedPropertyDeclarationName, isLiteralExpressionOfObject, isLiteralImportTypeNode, isLiteralTypeNode, + isMetaProperty, isMethodDeclaration, isMethodSignature, isModifier, isModuleBlock, isModuleDeclaration, + isModuleExportsAccessExpression, isModuleIdentifier, isModuleOrEnumDeclaration, isModuleWithStringLiteralName, + isNamedDeclaration, isNamedExports, isNamedTupleMember, isNamespaceExport, isNamespaceExportDeclaration, + isNamespaceReexportDeclaration, isNewExpression, isNightly, isNodeDescendantOf, isNullishCoalesce, isNumericLiteral, + isNumericLiteralName, isObjectBindingPattern, isObjectLiteralElementLike, isObjectLiteralExpression, + isObjectLiteralMethod, isObjectLiteralOrClassExpressionMethodOrAccessor, isOmittedExpression, isOptionalChain, + isOptionalChainRoot, isOptionalTypeNode, isOutermostOptionalChain, isParameter, isParameterDeclaration, + isParameterOrCatchClauseVariable, isParameterPropertyDeclaration, isParenthesizedExpression, + isParenthesizedTypeNode, isPartOfTypeNode, isPartOfTypeQuery, isPlainJsFile, isPrefixUnaryExpression, + isPrivateIdentifier, isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression, + isPropertyAccessEntityNameExpression, isPropertyAccessExpression, isPropertyAccessOrQualifiedNameOrImportTypeNode, + isPropertyAssignment, isPropertyDeclaration, isPropertyName, isPropertyNameLiteral, isPropertySignature, + isPrototypeAccess, isPrototypePropertyAssignment, isPushOrUnshiftIdentifier, isQualifiedName, isRequireCall, + isRestParameter, isRestTypeNode, isRightSideOfQualifiedNameOrPropertyAccess, + isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName, isSameEntityName, isSetAccessor, + isShorthandAmbientModuleSymbol, isShorthandPropertyAssignment, isSingleOrDoubleQuote, isSourceFile, isSourceFileJS, + isSpreadAssignment, isSpreadElement, isStatement, isStatementWithLocals, isStatic, isString, + isStringANonContextualKeyword, isStringLiteral, isStringLiteralLike, isStringOrNumericLiteralLike, isSuperCall, + isSuperProperty, isTaggedTemplateExpression, isTemplateSpan, isThisContainerOrFunctionBlock, isThisIdentifier, + isThisInitializedDeclaration, isThisInitializedObjectBindingExpression, isThisInTypeQuery, isThisProperty, + isThisTypeParameter, isTransientSymbol, isTupleTypeNode, isTypeAlias, isTypeAliasDeclaration, isTypeDeclaration, + isTypeLiteralNode, isTypeNode, isTypeNodeKind, isTypeOfExpression, isTypeOnlyImportOrExportDeclaration, + isTypeOperatorNode, isTypeParameterDeclaration, isTypePredicateNode, isTypeQueryNode, isTypeReferenceNode, + isTypeReferenceType, isUMDExportSymbol, isValidESSymbolDeclaration, isValidTypeOnlyAliasUseSite, + isValueSignatureDeclaration, isVarConst, isVariableDeclaration, + isVariableDeclarationInitializedToBareOrAccessedRequire, isVariableDeclarationInVariableStatement, + isVariableDeclarationList, isVariableLike, isVariableLikeOrAccessor, isVariableStatement, isWriteAccess, + isWriteOnlyAccess, IterableOrIteratorType, IterationTypes, JSDoc, JSDocAugmentsTag, JSDocCallbackTag, JSDocComment, + JSDocContainer, JSDocEnumTag, JSDocFunctionType, JSDocImplementsTag, JSDocLink, JSDocLinkCode, JSDocLinkPlain, + JSDocMemberName, JSDocNullableType, JSDocOptionalType, JSDocParameterTag, JSDocPrivateTag, JSDocPropertyLikeTag, + JSDocPropertyTag, JSDocProtectedTag, JSDocPublicTag, JSDocSignature, JSDocTemplateTag, JSDocTypedefTag, + JSDocTypeExpression, JSDocTypeReferencingNode, JSDocTypeTag, JSDocVariadicType, JsxAttribute, JsxAttributeLike, + JsxAttributes, JsxChild, JsxClosingElement, JsxElement, JsxEmit, JsxExpression, JsxFlags, JsxFragment, + JsxOpeningElement, JsxOpeningFragment, JsxOpeningLikeElement, JsxReferenceKind, JsxSelfClosingElement, + JsxSpreadAttribute, JsxTagNameExpression, KeywordTypeNode, LabeledStatement, last, lastOrUndefined, + LateBoundBinaryExpressionDeclaration, LateBoundDeclaration, LateBoundName, LateVisibilityPaintedStatement, + LeftHandSideExpression, length, LiteralExpression, LiteralType, LiteralTypeNode, mangleScopedPackageName, map, Map, + mapDefined, MappedSymbol, MappedType, MappedTypeNode, MatchingKeys, maybeBind, MemberName, MemberOverrideStatus, + memoize, MetaProperty, MethodDeclaration, MethodSignature, minAndMax, MinusToken, Modifier, ModifierFlags, + modifiersToFlags, modifierToFlag, ModuleBlock, ModuleDeclaration, ModuleInstanceState, ModuleKind, + ModuleResolutionKind, moduleSpecifiers, NamedDeclaration, NamedExports, NamedImportsOrExports, NamedTupleMember, + NamespaceDeclaration, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, needsScopeMarker, NewExpression, + Node, NodeArray, NodeBuilderFlags, nodeCanBeDecorated, NodeCheckFlags, NodeFlags, nodeHasName, nodeIsDecorated, + nodeIsMissing, nodeIsPresent, nodeIsSynthesized, NodeLinks, nodeStartsNewLexicalEnvironment, NodeWithTypeArguments, + NonNullChain, NonNullExpression, not, noTruncationMaximumTruncationLength, nullTransformationContext, + NumberLiteralType, NumericLiteral, objectAllocator, ObjectBindingPattern, ObjectFlags, ObjectFlagsType, + ObjectLiteralElementLike, ObjectLiteralExpression, ObjectType, OptionalChain, OptionalTypeNode, or, + orderedRemoveItemAt, OuterExpressionKinds, outFile, ParameterDeclaration, parameterIsThisKeyword, + ParameterPropertyDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, parseIsolatedEntityName, + parseNodeFactory, parsePseudoBigInt, Path, pathIsRelative, PatternAmbientModule, PlusToken, PostfixUnaryExpression, + PrefixUnaryExpression, PrivateIdentifier, Program, PromiseOrAwaitableType, PropertyAccessChain, + PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertyName, + PropertySignature, PseudoBigInt, pseudoBigIntToString, pushIfUnique, QualifiedName, QuestionToken, rangeEquals, + rangeOfNode, rangeOfTypeParameters, ReadonlyESMap, ReadonlyKeyword, reduceLeft, RelationComparisonResult, + relativeComplement, removeExtension, removePrefix, replaceElement, resolutionExtensionIsTSOrJson, + ResolvedModuleFull, ResolvedType, resolveTripleslashReference, resolvingEmptyArray, RestTypeNode, ReturnStatement, + ReverseMappedSymbol, ReverseMappedType, sameMap, SatisfiesExpression, ScriptKind, ScriptTarget, Set, + SetAccessorDeclaration, setCommentRange, setEmitFlags, setNodeFlags, setOriginalNode, setParent, + setSyntheticLeadingComments, setTextRange, setTextRangePosEnd, setValueDeclaration, ShorthandPropertyAssignment, + shouldPreserveConstEnums, Signature, SignatureDeclaration, SignatureFlags, SignatureKind, singleElementArray, + skipOuterExpressions, skipParentheses, skipTrivia, skipTypeChecking, some, SourceFile, SpreadAssignment, + SpreadElement, startsWith, Statement, stringContains, StringLiteral, StringLiteralLike, StringLiteralType, + StringMappingType, stripQuotes, StructuredType, SubstitutionType, sum, SuperCall, SwitchStatement, Symbol, + SymbolAccessibility, SymbolAccessibilityResult, SymbolFlags, SymbolFormatFlags, SymbolId, SymbolLinks, symbolName, + SymbolTable, SymbolTracker, SymbolVisibilityResult, SyntaxKind, SyntheticDefaultModuleType, SyntheticExpression, + TaggedTemplateExpression, TemplateExpression, TemplateLiteralType, TemplateLiteralTypeNode, Ternary, + textRangeContainsPositionInclusive, TextSpan, textSpanContainsPosition, textSpanEnd, ThisExpression, ThisTypeNode, + ThrowStatement, TokenFlags, tokenToString, tracing, TracingNode, TransientSymbol, tryAddToSet, tryCast, + tryExtractTSExtension, tryGetClassImplementingOrExtendingExpressionWithTypeArguments, tryGetExtensionFromPath, + tryGetModuleSpecifierFromDeclaration, tryGetPropertyAccessOrIdentifierToString, TryStatement, TupleType, + TupleTypeNode, TupleTypeReference, Type, TypeAliasDeclaration, TypeAssertion, TypeChecker, TypeCheckerHost, + TypeComparer, TypeElement, TypeFlags, TypeFormatFlags, TypeId, TypeLiteralNode, TypeMapKind, TypeMapper, TypeNode, + TypeNodeSyntaxKind, TypeOfExpression, TypeOnlyAliasDeclaration, TypeOnlyCompatibleAliasDeclaration, + TypeOperatorNode, TypeParameter, TypeParameterDeclaration, TypePredicate, TypePredicateKind, TypePredicateNode, + TypeQueryNode, TypeReference, TypeReferenceNode, TypeReferenceSerializationKind, TypeReferenceType, TypeVariable, + UnaryExpression, UnderscoreEscapedMap, unescapeLeadingUnderscores, UnionOrIntersectionType, + UnionOrIntersectionTypeNode, UnionReduction, UnionType, UnionTypeNode, UniqueESSymbolType, + usingSingleLineStringWriter, VariableDeclaration, VariableDeclarationList, VariableLikeDeclaration, + VariableStatement, VarianceFlags, visitEachChild, visitNode, visitNodes, Visitor, VisitResult, VoidExpression, + walkUpBindingElementsAndPatterns, walkUpParenthesizedExpressions, walkUpParenthesizedTypes, + walkUpParenthesizedTypesAndGetParentAndChild, WhileStatement, WideningContext, WithStatement, YieldExpression, +} from "./_namespaces/ts"; const ambientModuleSymbolRegex = /^".+"$/; -const anon = "(anonymous)" as ts.__String & string; +const anon = "(anonymous)" as __String & string; let nextSymbolId = 1; let nextNodeId = 1; @@ -44,14 +242,14 @@ interface IterationTypesResolver { iterableCacheKey: "iterationTypesOfAsyncIterable" | "iterationTypesOfIterable"; iteratorCacheKey: "iterationTypesOfAsyncIterator" | "iterationTypesOfIterator"; iteratorSymbolName: "asyncIterator" | "iterator"; - getGlobalIteratorType: (reportErrors: boolean) => ts.GenericType; - getGlobalIterableType: (reportErrors: boolean) => ts.GenericType; - getGlobalIterableIteratorType: (reportErrors: boolean) => ts.GenericType; - getGlobalGeneratorType: (reportErrors: boolean) => ts.GenericType; - resolveIterationType: (type: ts.Type, errorNode: ts.Node | undefined) => ts.Type | undefined; - mustHaveANextMethodDiagnostic: ts.DiagnosticMessage; - mustBeAMethodDiagnostic: ts.DiagnosticMessage; - mustHaveAValueDiagnostic: ts.DiagnosticMessage; + getGlobalIteratorType: (reportErrors: boolean) => GenericType; + getGlobalIterableType: (reportErrors: boolean) => GenericType; + getGlobalIterableIteratorType: (reportErrors: boolean) => GenericType; + getGlobalGeneratorType: (reportErrors: boolean) => GenericType; + resolveIterationType: (type: Type, errorNode: Node | undefined) => Type | undefined; + mustHaveANextMethodDiagnostic: DiagnosticMessage; + mustBeAMethodDiagnostic: DiagnosticMessage; + mustHaveAValueDiagnostic: DiagnosticMessage; } const enum WideningKind { @@ -145,7 +343,7 @@ export const enum TypeFacts { AndFactsMask = All & ~OrFactsMask, } -const typeofNEFacts: ts.ReadonlyESMap = new ts.Map(ts.getEntries({ +const typeofNEFacts: ReadonlyESMap = new Map(getEntries({ string: TypeFacts.TypeofNEString, number: TypeFacts.TypeofNENumber, bigint: TypeFacts.TypeofNEBigInt, @@ -156,7 +354,7 @@ const typeofNEFacts: ts.ReadonlyESMap = new ts.Map(ts.getEntr function: TypeFacts.TypeofNEFunction })); -type TypeSystemEntity = ts.Node | ts.Symbol | ts.Type | ts.Signature; +type TypeSystemEntity = Node | Symbol | Type | Signature; const enum TypeSystemPropertyName { Type, @@ -231,9 +429,9 @@ const enum UnusedKind { } /** @param containingNode Node to check for parse error */ -type AddUnusedDiagnostic = (containingNode: ts.Node, type: UnusedKind, diagnostic: ts.DiagnosticWithLocation) => void; +type AddUnusedDiagnostic = (containingNode: Node, type: UnusedKind, diagnostic: DiagnosticWithLocation) => void; -const isNotOverloadAndNotAccessor = ts.and(isNotOverload, isNotAccessor); +const isNotOverloadAndNotAccessor = and(isNotOverload, isNotAccessor); const enum DeclarationMeaning { GetAccessor = 1, @@ -265,22 +463,22 @@ const enum IntrinsicTypeKind { Uncapitalize } -const intrinsicTypeKinds: ts.ReadonlyESMap = new ts.Map(ts.getEntries({ +const intrinsicTypeKinds: ReadonlyESMap = new Map(getEntries({ Uppercase: IntrinsicTypeKind.Uppercase, Lowercase: IntrinsicTypeKind.Lowercase, Capitalize: IntrinsicTypeKind.Capitalize, Uncapitalize: IntrinsicTypeKind.Uncapitalize })); -function SymbolLinks(this: ts.SymbolLinks) { +function SymbolLinks(this: SymbolLinks) { } -function NodeLinks(this: ts.NodeLinks) { +function NodeLinks(this: NodeLinks) { this.flags = 0; } /** @internal */ -export function getNodeId(node: ts.Node): number { +export function getNodeId(node: Node): number { if (!node.id) { node.id = nextNodeId; nextNodeId++; @@ -289,7 +487,7 @@ export function getNodeId(node: ts.Node): number { } /** @internal */ -export function getSymbolId(symbol: ts.Symbol): ts.SymbolId { +export function getSymbolId(symbol: Symbol): SymbolId { if (!symbol.id) { symbol.id = nextSymbolId; nextSymbolId++; @@ -299,25 +497,25 @@ export function getSymbolId(symbol: ts.Symbol): ts.SymbolId { } /** @internal */ -export function isInstantiatedModule(node: ts.ModuleDeclaration, preserveConstEnums: boolean) { - const moduleState = ts.getModuleInstanceState(node); - return moduleState === ts.ModuleInstanceState.Instantiated || - (preserveConstEnums && moduleState === ts.ModuleInstanceState.ConstEnumOnly); +export function isInstantiatedModule(node: ModuleDeclaration, preserveConstEnums: boolean) { + const moduleState = getModuleInstanceState(node); + return moduleState === ModuleInstanceState.Instantiated || + (preserveConstEnums && moduleState === ModuleInstanceState.ConstEnumOnly); } /** @internal */ -export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { - const getPackagesMap = ts.memoize(() => { +export function createTypeChecker(host: TypeCheckerHost): TypeChecker { + const getPackagesMap = memoize(() => { // A package name maps to true when we detect it has .d.ts files. // This is useful as an approximation of whether a package bundles its own types. // Note: we only look at files already found by module resolution, // so there may be files we did not consider. - const map = new ts.Map(); + const map = new Map(); host.getSourceFiles().forEach(sf => { if (!sf.resolvedModules) return; sf.resolvedModules.forEach(r => { - if (r && r.packageId) map.set(r.packageId.name, r.extension === ts.Extension.Dts || !!map.get(r.packageId.name)); + if (r && r.packageId) map.set(r.packageId.name, r.extension === Extension.Dts || !!map.get(r.packageId.name)); }); }); return map; @@ -338,13 +536,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Currently we only support setting the cancellation token when getting diagnostics. This // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if // they no longer need the information (for example, if the user started editing again). - let cancellationToken: ts.CancellationToken | undefined; - let requestedExternalEmitHelpers: ts.ExternalEmitHelpers; - let externalHelpersModule: ts.Symbol; + let cancellationToken: CancellationToken | undefined; + let requestedExternalEmitHelpers: ExternalEmitHelpers; + let externalHelpersModule: Symbol; - const Symbol = ts.objectAllocator.getSymbolConstructor(); - const Type = ts.objectAllocator.getTypeConstructor(); - const Signature = ts.objectAllocator.getSignatureConstructor(); + const Symbol = objectAllocator.getSymbolConstructor(); + const Type = objectAllocator.getTypeConstructor(); + const Signature = objectAllocator.getSignatureConstructor(); let typeCount = 0; let symbolCount = 0; @@ -352,43 +550,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let instantiationCount = 0; let instantiationDepth = 0; let inlineLevel = 0; - let currentNode: ts.Node | undefined; - let varianceTypeParameter: ts.TypeParameter | undefined; + let currentNode: Node | undefined; + let varianceTypeParameter: TypeParameter | undefined; - const emptySymbols = ts.createSymbolTable(); - const arrayVariances = [ts.VarianceFlags.Covariant]; + const emptySymbols = createSymbolTable(); + const arrayVariances = [VarianceFlags.Covariant]; const compilerOptions = host.getCompilerOptions(); - const languageVersion = ts.getEmitScriptTarget(compilerOptions); - const moduleKind = ts.getEmitModuleKind(compilerOptions); - const useDefineForClassFields = ts.getUseDefineForClassFields(compilerOptions); - const allowSyntheticDefaultImports = ts.getAllowSyntheticDefaultImports(compilerOptions); - const strictNullChecks = ts.getStrictOptionValue(compilerOptions, "strictNullChecks"); - const strictFunctionTypes = ts.getStrictOptionValue(compilerOptions, "strictFunctionTypes"); - const strictBindCallApply = ts.getStrictOptionValue(compilerOptions, "strictBindCallApply"); - const strictPropertyInitialization = ts.getStrictOptionValue(compilerOptions, "strictPropertyInitialization"); - const noImplicitAny = ts.getStrictOptionValue(compilerOptions, "noImplicitAny"); - const noImplicitThis = ts.getStrictOptionValue(compilerOptions, "noImplicitThis"); - const useUnknownInCatchVariables = ts.getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables"); + const languageVersion = getEmitScriptTarget(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); + const useDefineForClassFields = getUseDefineForClassFields(compilerOptions); + const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); + const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); + const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); + const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply"); + const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization"); + const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); + const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); + const useUnknownInCatchVariables = getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables"); const keyofStringsOnly = !!compilerOptions.keyofStringsOnly; - const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ts.ObjectFlags.FreshLiteral; + const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral; const exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes; const checkBinaryExpression = createCheckBinaryExpression(); const emitResolver = createResolver(); const nodeBuilder = createNodeBuilder(); - const globals = ts.createSymbolTable(); - const undefinedSymbol = createSymbol(ts.SymbolFlags.Property, "undefined" as ts.__String); + const globals = createSymbolTable(); + const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String); undefinedSymbol.declarations = []; - const globalThisSymbol = createSymbol(ts.SymbolFlags.Module, "globalThis" as ts.__String, ts.CheckFlags.Readonly); + const globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly); globalThisSymbol.exports = globals; globalThisSymbol.declarations = []; globals.set(globalThisSymbol.escapedName, globalThisSymbol); - const argumentsSymbol = createSymbol(ts.SymbolFlags.Property, "arguments" as ts.__String); - const requireSymbol = createSymbol(ts.SymbolFlags.Property, "require" as ts.__String); + const argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String); + const requireSymbol = createSymbol(SymbolFlags.Property, "require" as __String); /** This will be set during calls to `getResolvedSignature` where services determines an apparent number of arguments greater than what is actually provided. */ let apparentArgumentCount: number | undefined; @@ -398,10 +596,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // for most of these, we perform the guard only on `checker` to avoid any possible // extra cost of calling `getParseTreeNode` when calling these functions from inside the // checker. - const checker: ts.TypeChecker = { - getNodeCount: () => ts.sum(host.getSourceFiles(), "nodeCount"), - getIdentifierCount: () => ts.sum(host.getSourceFiles(), "identifierCount"), - getSymbolCount: () => ts.sum(host.getSourceFiles(), "symbolCount") + symbolCount, + const checker: TypeChecker = { + getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"), + getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"), + getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount, getTypeCount: () => typeCount, getInstantiationCount: () => totalInstantiationCount, getRelationCacheSizes: () => ({ @@ -419,39 +617,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getRecursionIdentity, getUnmatchedProperties, getTypeOfSymbolAtLocation: (symbol, locationIn) => { - const location = ts.getParseTreeNode(locationIn); + const location = getParseTreeNode(locationIn); return location ? getTypeOfSymbolAtLocation(symbol, location) : errorType; }, getTypeOfSymbol, getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { - const parameter = ts.getParseTreeNode(parameterIn, ts.isParameter); - if (parameter === undefined) return ts.Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); - return getSymbolsOfParameterPropertyDeclaration(parameter, ts.escapeLeadingUnderscores(parameterName)); + const parameter = getParseTreeNode(parameterIn, isParameter); + if (parameter === undefined) return Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); + return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, getPropertiesOfType, - getPropertyOfType: (type, name) => getPropertyOfType(type, ts.escapeLeadingUnderscores(name)), - getPrivateIdentifierPropertyOfType: (leftType: ts.Type, name: string, location: ts.Node) => { - const node = ts.getParseTreeNode(location); + getPropertyOfType: (type, name) => getPropertyOfType(type, escapeLeadingUnderscores(name)), + getPrivateIdentifierPropertyOfType: (leftType: Type, name: string, location: Node) => { + const node = getParseTreeNode(location); if (!node) { return undefined; } - const propName = ts.escapeLeadingUnderscores(name); + const propName = escapeLeadingUnderscores(name); const lexicallyScopedIdentifier = lookupSymbolForPrivateIdentifierDeclaration(propName, node); return lexicallyScopedIdentifier ? getPrivateIdentifierPropertyOfType(leftType, lexicallyScopedIdentifier) : undefined; }, - getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, ts.escapeLeadingUnderscores(name)), - getIndexInfoOfType: (type, kind) => getIndexInfoOfType(type, kind === ts.IndexKind.String ? stringType : numberType), + getTypeOfPropertyOfType: (type, name) => getTypeOfPropertyOfType(type, escapeLeadingUnderscores(name)), + getIndexInfoOfType: (type, kind) => getIndexInfoOfType(type, kind === IndexKind.String ? stringType : numberType), getIndexInfosOfType, getIndexInfosOfIndexSymbol, getSignaturesOfType, - getIndexTypeOfType: (type, kind) => getIndexTypeOfType(type, kind === ts.IndexKind.String ? stringType : numberType), + getIndexTypeOfType: (type, kind) => getIndexTypeOfType(type, kind === IndexKind.String ? stringType : numberType), getIndexType: type => getIndexType(type), getBaseTypes, getBaseTypeOfLiteralType, getWidenedType, getTypeFromTypeNode: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isTypeNode); + const node = getParseTreeNode(nodeIn, isTypeNode); return node ? getTypeFromTypeNode(node) : errorType; }, getParameterType: getTypeAtPosition, @@ -474,88 +672,88 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { symbolToParameterDeclaration: nodeBuilder.symbolToParameterDeclaration, typeParameterToDeclaration: nodeBuilder.typeParameterToDeclaration, getSymbolsInScope: (locationIn, meaning) => { - const location = ts.getParseTreeNode(locationIn); + const location = getParseTreeNode(locationIn); return location ? getSymbolsInScope(location, meaning) : []; }, getSymbolAtLocation: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); // set ignoreErrors: true because any lookups invoked by the API shouldn't cause any new errors return node ? getSymbolAtLocation(node, /*ignoreErrors*/ true) : undefined; }, getIndexInfosAtLocation: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node ? getIndexInfosAtLocation(node) : undefined; }, getShorthandAssignmentValueSymbol: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node ? getShorthandAssignmentValueSymbol(node) : undefined; }, getExportSpecifierLocalTargetSymbol: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isExportSpecifier); + const node = getParseTreeNode(nodeIn, isExportSpecifier); return node ? getExportSpecifierLocalTargetSymbol(node) : undefined; }, getExportSymbolOfSymbol(symbol) { return getMergedSymbol(symbol.exportSymbol || symbol); }, getTypeAtLocation: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node ? getTypeOfNode(node) : errorType; }, getTypeOfAssignmentPattern: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isAssignmentPattern); + const node = getParseTreeNode(nodeIn, isAssignmentPattern); return node && getTypeOfAssignmentPattern(node) || errorType; }, getPropertySymbolOfDestructuringAssignment: locationIn => { - const location = ts.getParseTreeNode(locationIn, ts.isIdentifier); + const location = getParseTreeNode(locationIn, isIdentifier); return location ? getPropertySymbolOfDestructuringAssignment(location) : undefined; }, signatureToString: (signature, enclosingDeclaration, flags, kind) => { - return signatureToString(signature, ts.getParseTreeNode(enclosingDeclaration), flags, kind); + return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind); }, typeToString: (type, enclosingDeclaration, flags) => { - return typeToString(type, ts.getParseTreeNode(enclosingDeclaration), flags); + return typeToString(type, getParseTreeNode(enclosingDeclaration), flags); }, symbolToString: (symbol, enclosingDeclaration, meaning, flags) => { - return symbolToString(symbol, ts.getParseTreeNode(enclosingDeclaration), meaning, flags); + return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags); }, typePredicateToString: (predicate, enclosingDeclaration, flags) => { - return typePredicateToString(predicate, ts.getParseTreeNode(enclosingDeclaration), flags); + return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags); }, writeSignature: (signature, enclosingDeclaration, flags, kind, writer) => { - return signatureToString(signature, ts.getParseTreeNode(enclosingDeclaration), flags, kind, writer); + return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind, writer); }, writeType: (type, enclosingDeclaration, flags, writer) => { - return typeToString(type, ts.getParseTreeNode(enclosingDeclaration), flags, writer); + return typeToString(type, getParseTreeNode(enclosingDeclaration), flags, writer); }, writeSymbol: (symbol, enclosingDeclaration, meaning, flags, writer) => { - return symbolToString(symbol, ts.getParseTreeNode(enclosingDeclaration), meaning, flags, writer); + return symbolToString(symbol, getParseTreeNode(enclosingDeclaration), meaning, flags, writer); }, writeTypePredicate: (predicate, enclosingDeclaration, flags, writer) => { - return typePredicateToString(predicate, ts.getParseTreeNode(enclosingDeclaration), flags, writer); + return typePredicateToString(predicate, getParseTreeNode(enclosingDeclaration), flags, writer); }, getAugmentedPropertiesOfType, getRootSymbols, getSymbolOfExpando, - getContextualType: (nodeIn: ts.Expression, contextFlags?: ts.ContextFlags) => { - const node = ts.getParseTreeNode(nodeIn, ts.isExpression); + getContextualType: (nodeIn: Expression, contextFlags?: ContextFlags) => { + const node = getParseTreeNode(nodeIn, isExpression); if (!node) { return undefined; } - if (contextFlags! & ts.ContextFlags.Completions) { + if (contextFlags! & ContextFlags.Completions) { return runWithInferenceBlockedFromSourceNode(node, () => getContextualType(node, contextFlags)); } return getContextualType(node, contextFlags); }, getContextualTypeForObjectLiteralElement: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isObjectLiteralElementLike); + const node = getParseTreeNode(nodeIn, isObjectLiteralElementLike); return node ? getContextualTypeForObjectLiteralElement(node, /*contextFlags*/ undefined) : undefined; }, getContextualTypeForArgumentAtIndex: (nodeIn, argIndex) => { - const node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); + const node = getParseTreeNode(nodeIn, isCallLikeExpression); return node && getContextualTypeForArgumentAtIndex(node, argIndex); }, getContextualTypeForJsxAttribute: (nodeIn) => { - const node = ts.getParseTreeNode(nodeIn, ts.isJsxAttributeLike); + const node = getParseTreeNode(nodeIn, isJsxAttributeLike); return node && getContextualTypeForJsxAttribute(node, /*contextFlags*/ undefined); }, isContextSensitive, @@ -571,23 +769,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { hasEffectiveRestParameter, containsArgumentsReference, getConstantValue: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); + const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; }, isValidPropertyAccess: (nodeIn, propertyName) => { - const node = ts.getParseTreeNode(nodeIn, ts.isPropertyAccessOrQualifiedNameOrImportTypeNode); - return !!node && isValidPropertyAccess(node, ts.escapeLeadingUnderscores(propertyName)); + const node = getParseTreeNode(nodeIn, isPropertyAccessOrQualifiedNameOrImportTypeNode); + return !!node && isValidPropertyAccess(node, escapeLeadingUnderscores(propertyName)); }, isValidPropertyAccessForCompletions: (nodeIn, type, property) => { - const node = ts.getParseTreeNode(nodeIn, ts.isPropertyAccessExpression); + const node = getParseTreeNode(nodeIn, isPropertyAccessExpression); return !!node && isValidPropertyAccessForCompletions(node, type, property); }, getSignatureFromDeclaration: declarationIn => { - const declaration = ts.getParseTreeNode(declarationIn, ts.isFunctionLike); + const declaration = getParseTreeNode(declarationIn, isFunctionLike); return declaration ? getSignatureFromDeclaration(declaration) : undefined; }, isImplementationOfOverload: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isFunctionLike); + const node = getParseTreeNode(nodeIn, isFunctionLike); return node ? isImplementationOfOverload(node) : undefined; }, getImmediateAliasedSymbol, @@ -596,7 +794,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getExportsOfModule: getExportsOfModuleAsArray, getExportsAndPropertiesOfModule, forEachExportAndPropertyOfModule, - getSymbolWalker: ts.createGetSymbolWalker( + getSymbolWalker: createGetSymbolWalker( getRestTypeOfSignature, getTypePredicateOfSignature, getReturnTypeOfSignature, @@ -605,17 +803,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getTypeOfSymbol, getResolvedSymbol, getConstraintOfTypeParameter, - ts.getFirstIdentifier, + getFirstIdentifier, getTypeArguments, ), getAmbientModules, getJsxIntrinsicTagNamesAt, isOptionalParameter: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isParameter); + const node = getParseTreeNode(nodeIn, isParameter); return node ? isOptionalParameter(node) : false; }, - tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(ts.escapeLeadingUnderscores(name), symbol), - tryGetMemberInModuleExportsAndProperties: (name, symbol) => tryGetMemberInModuleExportsAndProperties(ts.escapeLeadingUnderscores(name), symbol), + tryGetMemberInModuleExports: (name, symbol) => tryGetMemberInModuleExports(escapeLeadingUnderscores(name), symbol), + tryGetMemberInModuleExportsAndProperties: (name, symbol) => tryGetMemberInModuleExportsAndProperties(escapeLeadingUnderscores(name), symbol), tryFindAmbientModule: moduleName => tryFindAmbientModule(moduleName, /*withAugmentations*/ true), tryFindAmbientModuleWithoutAugmentations: moduleName => { // we deliberately exclude augmentations @@ -661,43 +859,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getSuggestedSymbolForNonexistentProperty, getSuggestionForNonexistentProperty, getSuggestedSymbolForNonexistentJSXAttribute, - getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => getSuggestedSymbolForNonexistentSymbol(location, ts.escapeLeadingUnderscores(name), meaning), - getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, ts.escapeLeadingUnderscores(name), meaning), + getSuggestedSymbolForNonexistentSymbol: (location, name, meaning) => getSuggestedSymbolForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), + getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), getSuggestedSymbolForNonexistentModule, getSuggestionForNonexistentExport, getSuggestedSymbolForNonexistentClassMember, getBaseConstraintOfType, - getDefaultFromTypeParameter: type => type && type.flags & ts.TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as ts.TypeParameter) : undefined, + getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined, resolveName(name, location, meaning, excludeGlobals) { - return resolveName(location, ts.escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); + return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); }, - getJsxNamespace: n => ts.unescapeLeadingUnderscores(getJsxNamespace(n)), + getJsxNamespace: n => unescapeLeadingUnderscores(getJsxNamespace(n)), getJsxFragmentFactory: n => { const jsxFragmentFactory = getJsxFragmentFactoryEntity(n); - return jsxFragmentFactory && ts.unescapeLeadingUnderscores(ts.getFirstIdentifier(jsxFragmentFactory).escapedText); + return jsxFragmentFactory && unescapeLeadingUnderscores(getFirstIdentifier(jsxFragmentFactory).escapedText); }, getAccessibleSymbolChain, getTypePredicateOfSignature, resolveExternalModuleName: moduleSpecifierIn => { - const moduleSpecifier = ts.getParseTreeNode(moduleSpecifierIn, ts.isExpression); + const moduleSpecifier = getParseTreeNode(moduleSpecifierIn, isExpression); return moduleSpecifier && resolveExternalModuleName(moduleSpecifier, moduleSpecifier, /*ignoreErrors*/ true); }, resolveExternalModuleSymbol, tryGetThisTypeAt: (nodeIn, includeGlobalThis, container) => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node && tryGetThisTypeAt(node, includeGlobalThis, container); }, getTypeArgumentConstraint: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.isTypeNode); + const node = getParseTreeNode(nodeIn, isTypeNode); return node && getTypeArgumentConstraint(node); }, getSuggestionDiagnostics: (fileIn, ct) => { - const file = ts.getParseTreeNode(fileIn, ts.isSourceFile) || ts.Debug.fail("Could not determine parsed source file."); - if (ts.skipTypeChecking(file, compilerOptions, host)) { - return ts.emptyArray; + const file = getParseTreeNode(fileIn, isSourceFile) || Debug.fail("Could not determine parsed source file."); + if (skipTypeChecking(file, compilerOptions, host)) { + return emptyArray; } - let diagnostics: ts.DiagnosticWithLocation[] | undefined; + let diagnostics: DiagnosticWithLocation[] | undefined; try { // Record the cancellation token so it can be checked later on during checkSourceElement. // Do this in a finally block so we can ensure that it gets reset back to nothing after @@ -706,16 +904,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Ensure file is type checked, with _eager_ diagnostic production, so identifiers are registered as potentially unused checkSourceFileWithEagerDiagnostics(file); - ts.Debug.assert(!!(getNodeLinks(file).flags & ts.NodeCheckFlags.TypeChecked)); + Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked)); - diagnostics = ts.addRange(diagnostics, suggestionDiagnostics.getDiagnostics(file.fileName)); + diagnostics = addRange(diagnostics, suggestionDiagnostics.getDiagnostics(file.fileName)); checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (containingNode, kind, diag) => { - if (!ts.containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & ts.NodeFlags.Ambient))) { - (diagnostics || (diagnostics = [])).push({ ...diag, category: ts.DiagnosticCategory.Suggestion }); + if (!containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { + (diagnostics || (diagnostics = [])).push({ ...diag, category: DiagnosticCategory.Suggestion }); } }); - return diagnostics || ts.emptyArray; + return diagnostics || emptyArray; } finally { cancellationToken = undefined; @@ -740,8 +938,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isTypeParameterPossiblyReferenced, }; - function runWithInferenceBlockedFromSourceNode(node: ts.Node | undefined, fn: () => T): T { - const containingCall = ts.findAncestor(node, ts.isCallLikeExpression); + function runWithInferenceBlockedFromSourceNode(node: Node | undefined, fn: () => T): T { + const containingCall = findAncestor(node, isCallLikeExpression); const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature; if (containingCall) { let toMarkSkip = node!; @@ -763,8 +961,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getResolvedSignatureWorker(nodeIn: ts.CallLikeExpression, candidatesOutArray: ts.Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: ts.Node): ts.Signature | undefined { - const node = ts.getParseTreeNode(nodeIn, ts.isCallLikeExpression); + function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined { + const node = getParseTreeNode(nodeIn, isCallLikeExpression); apparentArgumentCount = argumentCount; const res = !node ? undefined : @@ -774,50 +972,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return res; } - const tupleTypes = new ts.Map(); - const unionTypes = new ts.Map(); - const intersectionTypes = new ts.Map(); - const stringLiteralTypes = new ts.Map(); - const numberLiteralTypes = new ts.Map(); - const bigIntLiteralTypes = new ts.Map(); - const enumLiteralTypes = new ts.Map(); - const indexedAccessTypes = new ts.Map(); - const templateLiteralTypes = new ts.Map(); - const stringMappingTypes = new ts.Map(); - const substitutionTypes = new ts.Map(); - const subtypeReductionCache = new ts.Map(); - const cachedTypes = new ts.Map(); - const evolvingArrayTypes: ts.EvolvingArrayType[] = []; - const undefinedProperties: ts.SymbolTable = new ts.Map(); - const markerTypes = new ts.Set(); - - const unknownSymbol = createSymbol(ts.SymbolFlags.Property, "unknown" as ts.__String); - const resolvingSymbol = createSymbol(0, ts.InternalSymbolName.Resolving); - const unresolvedSymbols = new ts.Map(); - const errorTypes = new ts.Map(); - - const anyType = createIntrinsicType(ts.TypeFlags.Any, "any"); - const autoType = createIntrinsicType(ts.TypeFlags.Any, "any", ts.ObjectFlags.NonInferrableType); - const wildcardType = createIntrinsicType(ts.TypeFlags.Any, "any"); - const errorType = createIntrinsicType(ts.TypeFlags.Any, "error"); - const unresolvedType = createIntrinsicType(ts.TypeFlags.Any, "unresolved"); - const nonInferrableAnyType = createIntrinsicType(ts.TypeFlags.Any, "any", ts.ObjectFlags.ContainsWideningType); - const intrinsicMarkerType = createIntrinsicType(ts.TypeFlags.Any, "intrinsic"); - const unknownType = createIntrinsicType(ts.TypeFlags.Unknown, "unknown"); - const nonNullUnknownType = createIntrinsicType(ts.TypeFlags.Unknown, "unknown"); - const undefinedType = createIntrinsicType(ts.TypeFlags.Undefined, "undefined"); - const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(ts.TypeFlags.Undefined, "undefined", ts.ObjectFlags.ContainsWideningType); - const optionalType = createIntrinsicType(ts.TypeFlags.Undefined, "undefined"); - const missingType = exactOptionalPropertyTypes ? createIntrinsicType(ts.TypeFlags.Undefined, "undefined") : undefinedType; - const nullType = createIntrinsicType(ts.TypeFlags.Null, "null"); - const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(ts.TypeFlags.Null, "null", ts.ObjectFlags.ContainsWideningType); - const stringType = createIntrinsicType(ts.TypeFlags.String, "string"); - const numberType = createIntrinsicType(ts.TypeFlags.Number, "number"); - const bigintType = createIntrinsicType(ts.TypeFlags.BigInt, "bigint"); - const falseType = createIntrinsicType(ts.TypeFlags.BooleanLiteral, "false") as ts.FreshableIntrinsicType; - const regularFalseType = createIntrinsicType(ts.TypeFlags.BooleanLiteral, "false") as ts.FreshableIntrinsicType; - const trueType = createIntrinsicType(ts.TypeFlags.BooleanLiteral, "true") as ts.FreshableIntrinsicType; - const regularTrueType = createIntrinsicType(ts.TypeFlags.BooleanLiteral, "true") as ts.FreshableIntrinsicType; + const tupleTypes = new Map(); + const unionTypes = new Map(); + const intersectionTypes = new Map(); + const stringLiteralTypes = new Map(); + const numberLiteralTypes = new Map(); + const bigIntLiteralTypes = new Map(); + const enumLiteralTypes = new Map(); + const indexedAccessTypes = new Map(); + const templateLiteralTypes = new Map(); + const stringMappingTypes = new Map(); + const substitutionTypes = new Map(); + const subtypeReductionCache = new Map(); + const cachedTypes = new Map(); + const evolvingArrayTypes: EvolvingArrayType[] = []; + const undefinedProperties: SymbolTable = new Map(); + const markerTypes = new Set(); + + const unknownSymbol = createSymbol(SymbolFlags.Property, "unknown" as __String); + const resolvingSymbol = createSymbol(0, InternalSymbolName.Resolving); + const unresolvedSymbols = new Map(); + const errorTypes = new Map(); + + const anyType = createIntrinsicType(TypeFlags.Any, "any"); + const autoType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.NonInferrableType); + const wildcardType = createIntrinsicType(TypeFlags.Any, "any"); + const errorType = createIntrinsicType(TypeFlags.Any, "error"); + const unresolvedType = createIntrinsicType(TypeFlags.Any, "unresolved"); + const nonInferrableAnyType = createIntrinsicType(TypeFlags.Any, "any", ObjectFlags.ContainsWideningType); + const intrinsicMarkerType = createIntrinsicType(TypeFlags.Any, "intrinsic"); + const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); + const nonNullUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); + const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined"); + const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); + const optionalType = createIntrinsicType(TypeFlags.Undefined, "undefined"); + const missingType = exactOptionalPropertyTypes ? createIntrinsicType(TypeFlags.Undefined, "undefined") : undefinedType; + const nullType = createIntrinsicType(TypeFlags.Null, "null"); + const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); + const stringType = createIntrinsicType(TypeFlags.String, "string"); + const numberType = createIntrinsicType(TypeFlags.Number, "number"); + const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint"); + const falseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType; + const regularFalseType = createIntrinsicType(TypeFlags.BooleanLiteral, "false") as FreshableIntrinsicType; + const trueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType; + const regularTrueType = createIntrinsicType(TypeFlags.BooleanLiteral, "true") as FreshableIntrinsicType; trueType.regularType = regularTrueType; trueType.freshType = trueType; regularTrueType.regularType = regularTrueType; @@ -827,24 +1025,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { regularFalseType.regularType = regularFalseType; regularFalseType.freshType = falseType; const booleanType = getUnionType([regularFalseType, regularTrueType]); - const esSymbolType = createIntrinsicType(ts.TypeFlags.ESSymbol, "symbol"); - const voidType = createIntrinsicType(ts.TypeFlags.Void, "void"); - const neverType = createIntrinsicType(ts.TypeFlags.Never, "never"); - const silentNeverType = createIntrinsicType(ts.TypeFlags.Never, "never", ts.ObjectFlags.NonInferrableType); - const implicitNeverType = createIntrinsicType(ts.TypeFlags.Never, "never"); - const unreachableNeverType = createIntrinsicType(ts.TypeFlags.Never, "never"); - const nonPrimitiveType = createIntrinsicType(ts.TypeFlags.NonPrimitive, "object"); + const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol"); + const voidType = createIntrinsicType(TypeFlags.Void, "void"); + const neverType = createIntrinsicType(TypeFlags.Never, "never"); + const silentNeverType = createIntrinsicType(TypeFlags.Never, "never", ObjectFlags.NonInferrableType); + const implicitNeverType = createIntrinsicType(TypeFlags.Never, "never"); + const unreachableNeverType = createIntrinsicType(TypeFlags.Never, "never"); + const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object"); const stringOrNumberType = getUnionType([stringType, numberType]); const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]); const keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType; const numberOrBigIntType = getUnionType([numberType, bigintType]); - const templateConstraintType = getUnionType([stringType, numberType, booleanType, bigintType, nullType, undefinedType]) as ts.UnionType; + const templateConstraintType = getUnionType([stringType, numberType, booleanType, bigintType, nullType, undefinedType]) as UnionType; const numericStringType = getTemplateLiteralType(["", ""], [numberType]); // The `${number}` type - const restrictiveMapper: ts.TypeMapper = makeFunctionTypeMapper(t => t.flags & ts.TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t as ts.TypeParameter) : t, () => "(restrictive mapper)"); - const permissiveMapper: ts.TypeMapper = makeFunctionTypeMapper(t => t.flags & ts.TypeFlags.TypeParameter ? wildcardType : t, () => "(permissive mapper)"); - const uniqueLiteralType = createIntrinsicType(ts.TypeFlags.Never, "never"); // `uniqueLiteralType` is a special `never` flagged by union reduction to behave as a literal - const uniqueLiteralMapper: ts.TypeMapper = makeFunctionTypeMapper(t => t.flags & ts.TypeFlags.TypeParameter ? uniqueLiteralType : t, () => "(unique literal mapper)"); // replace all type parameters with the unique literal type (disregarding constraints) + const restrictiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(t as TypeParameter) : t, () => "(restrictive mapper)"); + const permissiveMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? wildcardType : t, () => "(permissive mapper)"); + const uniqueLiteralType = createIntrinsicType(TypeFlags.Never, "never"); // `uniqueLiteralType` is a special `never` flagged by union reduction to behave as a literal + const uniqueLiteralMapper: TypeMapper = makeFunctionTypeMapper(t => t.flags & TypeFlags.TypeParameter ? uniqueLiteralType : t, () => "(unique literal mapper)"); // replace all type parameters with the unique literal type (disregarding constraints) let outofbandVarianceMarkerHandler: ((onlyUnreliable: boolean) => void) | undefined; const reportUnreliableMapper = makeFunctionTypeMapper(t => { if (outofbandVarianceMarkerHandler && (t === markerSuperType || t === markerSubType || t === markerOtherType)) { @@ -859,28 +1057,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return t; }, () => "(unreliable reporter)"); - const emptyObjectType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); - const emptyJsxObjectType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); - emptyJsxObjectType.objectFlags |= ts.ObjectFlags.JsxAttributes; + const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + const emptyJsxObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + emptyJsxObjectType.objectFlags |= ObjectFlags.JsxAttributes; - const emptyTypeLiteralSymbol = createSymbol(ts.SymbolFlags.TypeLiteral, ts.InternalSymbolName.Type); - emptyTypeLiteralSymbol.members = ts.createSymbolTable(); - const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + const emptyTypeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); + emptyTypeLiteralSymbol.members = createSymbolTable(); + const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, emptyArray); - const unknownEmptyObjectType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + const unknownEmptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); const unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, unknownEmptyObjectType]) : unknownType; - const emptyGenericType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray) as ts.ObjectType as ts.GenericType; - emptyGenericType.instantiations = new ts.Map(); + const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray) as ObjectType as GenericType; + emptyGenericType.instantiations = new Map(); - const anyFunctionType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated // in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes. - anyFunctionType.objectFlags |= ts.ObjectFlags.NonInferrableType; + anyFunctionType.objectFlags |= ObjectFlags.NonInferrableType; - const noConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); - const circularConstraintType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); - const resolvingDefaultType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); + const resolvingDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); const markerSuperType = createTypeParameter(); const markerSubType = createTypeParameter(); @@ -891,20 +1089,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const markerSubTypeForCheck = createTypeParameter(); markerSubTypeForCheck.constraint = markerSuperTypeForCheck; - const noTypePredicate = createTypePredicate(ts.TypePredicateKind.Identifier, "<>", 0, anyType); + const noTypePredicate = createTypePredicate(TypePredicateKind.Identifier, "<>", 0, anyType); - const anySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, ts.SignatureFlags.None); - const unknownSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, ts.SignatureFlags.None); - const resolvingSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, ts.SignatureFlags.None); - const silentNeverSignature = createSignature(undefined, undefined, undefined, ts.emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, ts.SignatureFlags.None); + const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); + const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); + const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); + const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); const enumNumberIndexInfo = createIndexInfo(numberType, stringType, /*isReadonly*/ true); - const iterationTypesCache = new ts.Map(); // cache for common IterationTypes instances - const noIterationTypes: ts.IterationTypes = { - get yieldType(): ts.Type { return ts.Debug.fail("Not supported"); }, - get returnType(): ts.Type { return ts.Debug.fail("Not supported"); }, - get nextType(): ts.Type { return ts.Debug.fail("Not supported"); }, + const iterationTypesCache = new Map(); // cache for common IterationTypes instances + const noIterationTypes: IterationTypes = { + get yieldType(): Type { return Debug.fail("Not supported"); }, + get returnType(): Type { return Debug.fail("Not supported"); }, + get nextType(): Type { return Debug.fail("Not supported"); }, }; const anyIterationTypes = createIterationTypes(anyType, anyType, anyType); @@ -920,9 +1118,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getGlobalIterableIteratorType: getGlobalAsyncIterableIteratorType, getGlobalGeneratorType: getGlobalAsyncGeneratorType, resolveIterationType: getAwaitedType, - mustHaveANextMethodDiagnostic: ts.Diagnostics.An_async_iterator_must_have_a_next_method, - mustBeAMethodDiagnostic: ts.Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method, - mustHaveAValueDiagnostic: ts.Diagnostics.The_type_returned_by_the_0_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property, + mustHaveANextMethodDiagnostic: Diagnostics.An_async_iterator_must_have_a_next_method, + mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_async_iterator_must_be_a_method, + mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_async_iterator_must_be_a_promise_for_a_type_with_a_value_property, }; const syncIterationTypesResolver: IterationTypesResolver = { @@ -934,93 +1132,93 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getGlobalIterableIteratorType, getGlobalGeneratorType, resolveIterationType: (type, _errorNode) => type, - mustHaveANextMethodDiagnostic: ts.Diagnostics.An_iterator_must_have_a_next_method, - mustBeAMethodDiagnostic: ts.Diagnostics.The_0_property_of_an_iterator_must_be_a_method, - mustHaveAValueDiagnostic: ts.Diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property, + mustHaveANextMethodDiagnostic: Diagnostics.An_iterator_must_have_a_next_method, + mustBeAMethodDiagnostic: Diagnostics.The_0_property_of_an_iterator_must_be_a_method, + mustHaveAValueDiagnostic: Diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property, }; interface DuplicateInfoForSymbol { - readonly firstFileLocations: ts.Declaration[]; - readonly secondFileLocations: ts.Declaration[]; + readonly firstFileLocations: Declaration[]; + readonly secondFileLocations: Declaration[]; readonly isBlockScoped: boolean; } interface DuplicateInfoForFiles { - readonly firstFile: ts.SourceFile; - readonly secondFile: ts.SourceFile; + readonly firstFile: SourceFile; + readonly secondFile: SourceFile; /** Key is symbol name. */ - readonly conflictingSymbols: ts.ESMap; + readonly conflictingSymbols: ESMap; } /** Key is "/path/to/a.ts|/path/to/b.ts". */ - let amalgamatedDuplicates: ts.ESMap | undefined; - const reverseMappedCache = new ts.Map(); + let amalgamatedDuplicates: ESMap | undefined; + const reverseMappedCache = new Map(); let inInferTypeForHomomorphicMappedType = false; - let ambientModulesCache: ts.Symbol[] | undefined; + let ambientModulesCache: Symbol[] | undefined; /** * List of every ambient module with a "*" wildcard. * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. * This is only used if there is no exact match. */ - let patternAmbientModules: ts.PatternAmbientModule[]; - let patternAmbientModuleAugmentations: ts.ESMap | undefined; - - let globalObjectType: ts.ObjectType; - let globalFunctionType: ts.ObjectType; - let globalCallableFunctionType: ts.ObjectType; - let globalNewableFunctionType: ts.ObjectType; - let globalArrayType: ts.GenericType; - let globalReadonlyArrayType: ts.GenericType; - let globalStringType: ts.ObjectType; - let globalNumberType: ts.ObjectType; - let globalBooleanType: ts.ObjectType; - let globalRegExpType: ts.ObjectType; - let globalThisType: ts.GenericType; - let anyArrayType: ts.Type; - let autoArrayType: ts.Type; - let anyReadonlyArrayType: ts.Type; - let deferredGlobalNonNullableTypeAlias: ts.Symbol; + let patternAmbientModules: PatternAmbientModule[]; + let patternAmbientModuleAugmentations: ESMap | undefined; + + let globalObjectType: ObjectType; + let globalFunctionType: ObjectType; + let globalCallableFunctionType: ObjectType; + let globalNewableFunctionType: ObjectType; + let globalArrayType: GenericType; + let globalReadonlyArrayType: GenericType; + let globalStringType: ObjectType; + let globalNumberType: ObjectType; + let globalBooleanType: ObjectType; + let globalRegExpType: ObjectType; + let globalThisType: GenericType; + let anyArrayType: Type; + let autoArrayType: Type; + let anyReadonlyArrayType: Type; + let deferredGlobalNonNullableTypeAlias: Symbol; // The library files are only loaded when the feature is used. // This allows users to just specify library files they want to used through --lib // and they will not get an error from not having unrelated library files - let deferredGlobalESSymbolConstructorSymbol: ts.Symbol | undefined; - let deferredGlobalESSymbolConstructorTypeSymbol: ts.Symbol | undefined; - let deferredGlobalESSymbolType: ts.ObjectType | undefined; - let deferredGlobalTypedPropertyDescriptorType: ts.GenericType; - let deferredGlobalPromiseType: ts.GenericType | undefined; - let deferredGlobalPromiseLikeType: ts.GenericType | undefined; - let deferredGlobalPromiseConstructorSymbol: ts.Symbol | undefined; - let deferredGlobalPromiseConstructorLikeType: ts.ObjectType | undefined; - let deferredGlobalIterableType: ts.GenericType | undefined; - let deferredGlobalIteratorType: ts.GenericType | undefined; - let deferredGlobalIterableIteratorType: ts.GenericType | undefined; - let deferredGlobalGeneratorType: ts.GenericType | undefined; - let deferredGlobalIteratorYieldResultType: ts.GenericType | undefined; - let deferredGlobalIteratorReturnResultType: ts.GenericType | undefined; - let deferredGlobalAsyncIterableType: ts.GenericType | undefined; - let deferredGlobalAsyncIteratorType: ts.GenericType | undefined; - let deferredGlobalAsyncIterableIteratorType: ts.GenericType | undefined; - let deferredGlobalAsyncGeneratorType: ts.GenericType | undefined; - let deferredGlobalTemplateStringsArrayType: ts.ObjectType | undefined; - let deferredGlobalImportMetaType: ts.ObjectType; - let deferredGlobalImportMetaExpressionType: ts.ObjectType; - let deferredGlobalImportCallOptionsType: ts.ObjectType | undefined; - let deferredGlobalExtractSymbol: ts.Symbol | undefined; - let deferredGlobalOmitSymbol: ts.Symbol | undefined; - let deferredGlobalAwaitedSymbol: ts.Symbol | undefined; - let deferredGlobalBigIntType: ts.ObjectType | undefined; - let deferredGlobalNaNSymbol: ts.Symbol | undefined; - let deferredGlobalRecordSymbol: ts.Symbol | undefined; - - const allPotentiallyUnusedIdentifiers = new ts.Map(); // key is file name + let deferredGlobalESSymbolConstructorSymbol: Symbol | undefined; + let deferredGlobalESSymbolConstructorTypeSymbol: Symbol | undefined; + let deferredGlobalESSymbolType: ObjectType | undefined; + let deferredGlobalTypedPropertyDescriptorType: GenericType; + let deferredGlobalPromiseType: GenericType | undefined; + let deferredGlobalPromiseLikeType: GenericType | undefined; + let deferredGlobalPromiseConstructorSymbol: Symbol | undefined; + let deferredGlobalPromiseConstructorLikeType: ObjectType | undefined; + let deferredGlobalIterableType: GenericType | undefined; + let deferredGlobalIteratorType: GenericType | undefined; + let deferredGlobalIterableIteratorType: GenericType | undefined; + let deferredGlobalGeneratorType: GenericType | undefined; + let deferredGlobalIteratorYieldResultType: GenericType | undefined; + let deferredGlobalIteratorReturnResultType: GenericType | undefined; + let deferredGlobalAsyncIterableType: GenericType | undefined; + let deferredGlobalAsyncIteratorType: GenericType | undefined; + let deferredGlobalAsyncIterableIteratorType: GenericType | undefined; + let deferredGlobalAsyncGeneratorType: GenericType | undefined; + let deferredGlobalTemplateStringsArrayType: ObjectType | undefined; + let deferredGlobalImportMetaType: ObjectType; + let deferredGlobalImportMetaExpressionType: ObjectType; + let deferredGlobalImportCallOptionsType: ObjectType | undefined; + let deferredGlobalExtractSymbol: Symbol | undefined; + let deferredGlobalOmitSymbol: Symbol | undefined; + let deferredGlobalAwaitedSymbol: Symbol | undefined; + let deferredGlobalBigIntType: ObjectType | undefined; + let deferredGlobalNaNSymbol: Symbol | undefined; + let deferredGlobalRecordSymbol: Symbol | undefined; + + const allPotentiallyUnusedIdentifiers = new Map(); // key is file name let flowLoopStart = 0; let flowLoopCount = 0; let sharedFlowCount = 0; let flowAnalysisDisabled = false; let flowInvocationCount = 0; - let lastFlowNode: ts.FlowNode | undefined; + let lastFlowNode: FlowNode | undefined; let lastFlowNodeReachable: boolean; - let flowTypeCache: ts.Type[] | undefined; + let flowTypeCache: Type[] | undefined; const emptyStringType = getStringLiteralType(""); const zeroType = getNumberLiteralType(0); @@ -1032,40 +1230,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let suggestionCount = 0; const maximumSuggestionCount = 10; - const mergedSymbols: ts.Symbol[] = []; - const symbolLinks: ts.SymbolLinks[] = []; - const nodeLinks: ts.NodeLinks[] = []; - const flowLoopCaches: ts.ESMap[] = []; - const flowLoopNodes: ts.FlowNode[] = []; + const mergedSymbols: Symbol[] = []; + const symbolLinks: SymbolLinks[] = []; + const nodeLinks: NodeLinks[] = []; + const flowLoopCaches: ESMap[] = []; + const flowLoopNodes: FlowNode[] = []; const flowLoopKeys: string[] = []; - const flowLoopTypes: ts.Type[][] = []; - const sharedFlowNodes: ts.FlowNode[] = []; - const sharedFlowTypes: ts.FlowType[] = []; + const flowLoopTypes: Type[][] = []; + const sharedFlowNodes: FlowNode[] = []; + const sharedFlowTypes: FlowType[] = []; const flowNodeReachable: (boolean | undefined)[] = []; const flowNodePostSuper: (boolean | undefined)[] = []; - const potentialThisCollisions: ts.Node[] = []; - const potentialNewTargetCollisions: ts.Node[] = []; - const potentialWeakMapSetCollisions: ts.Node[] = []; - const potentialReflectCollisions: ts.Node[] = []; - const potentialUnusedRenamedBindingElementsInTypes: ts.BindingElement[] = []; + const potentialThisCollisions: Node[] = []; + const potentialNewTargetCollisions: Node[] = []; + const potentialWeakMapSetCollisions: Node[] = []; + const potentialReflectCollisions: Node[] = []; + const potentialUnusedRenamedBindingElementsInTypes: BindingElement[] = []; const awaitedTypeStack: number[] = []; - const diagnostics = ts.createDiagnosticCollection(); - const suggestionDiagnostics = ts.createDiagnosticCollection(); + const diagnostics = createDiagnosticCollection(); + const suggestionDiagnostics = createDiagnosticCollection(); const typeofType = createTypeofType(); - let _jsxNamespace: ts.__String; - let _jsxFactoryEntity: ts.EntityName | undefined; + let _jsxNamespace: __String; + let _jsxFactoryEntity: EntityName | undefined; - const subtypeRelation = new ts.Map(); - const strictSubtypeRelation = new ts.Map(); - const assignableRelation = new ts.Map(); - const comparableRelation = new ts.Map(); - const identityRelation = new ts.Map(); - const enumRelation = new ts.Map(); + const subtypeRelation = new Map(); + const strictSubtypeRelation = new Map(); + const assignableRelation = new Map(); + const comparableRelation = new Map(); + const identityRelation = new Map(); + const enumRelation = new Map(); - const builtinGlobals = ts.createSymbolTable(); + const builtinGlobals = createSymbolTable(); builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol); // Extensions suggested for path imports when module resolution is node16 or higher. @@ -1079,7 +1277,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { [".mjs", ".mjs"], [".js", ".js"], [".cjs", ".cjs"], - [".tsx", compilerOptions.jsx === ts.JsxEmit.Preserve ? ".jsx" : ".js"], + [".tsx", compilerOptions.jsx === JsxEmit.Preserve ? ".jsx" : ".js"], [".jsx", ".jsx"], [".json", ".json"], ]; @@ -1092,32 +1290,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return key ? cachedTypes.get(key) : undefined; } - function setCachedType(key: string | undefined, type: ts.Type) { + function setCachedType(key: string | undefined, type: Type) { if (key) cachedTypes.set(key, type); return type; } - function getJsxNamespace(location: ts.Node | undefined): ts.__String { + function getJsxNamespace(location: Node | undefined): __String { if (location) { - const file = ts.getSourceFileOfNode(location); + const file = getSourceFileOfNode(location); if (file) { - if (ts.isJsxOpeningFragment(location)) { + if (isJsxOpeningFragment(location)) { if (file.localJsxFragmentNamespace) { return file.localJsxFragmentNamespace; } const jsxFragmentPragma = file.pragmas.get("jsxfrag"); if (jsxFragmentPragma) { - const chosenPragma = ts.isArray(jsxFragmentPragma) ? jsxFragmentPragma[0] : jsxFragmentPragma; - file.localJsxFragmentFactory = ts.parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion); - ts.visitNode(file.localJsxFragmentFactory, markAsSynthetic); + const chosenPragma = isArray(jsxFragmentPragma) ? jsxFragmentPragma[0] : jsxFragmentPragma; + file.localJsxFragmentFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion); + visitNode(file.localJsxFragmentFactory, markAsSynthetic); if (file.localJsxFragmentFactory) { - return file.localJsxFragmentNamespace = ts.getFirstIdentifier(file.localJsxFragmentFactory).escapedText; + return file.localJsxFragmentNamespace = getFirstIdentifier(file.localJsxFragmentFactory).escapedText; } } const entity = getJsxFragmentFactoryEntity(location); if (entity) { file.localJsxFragmentFactory = entity; - return file.localJsxFragmentNamespace = ts.getFirstIdentifier(entity).escapedText; + return file.localJsxFragmentNamespace = getFirstIdentifier(entity).escapedText; } } else { @@ -1129,55 +1327,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (!_jsxNamespace) { - _jsxNamespace = "React" as ts.__String; + _jsxNamespace = "React" as __String; if (compilerOptions.jsxFactory) { - _jsxFactoryEntity = ts.parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); - ts.visitNode(_jsxFactoryEntity, markAsSynthetic); + _jsxFactoryEntity = parseIsolatedEntityName(compilerOptions.jsxFactory, languageVersion); + visitNode(_jsxFactoryEntity, markAsSynthetic); if (_jsxFactoryEntity) { - _jsxNamespace = ts.getFirstIdentifier(_jsxFactoryEntity).escapedText; + _jsxNamespace = getFirstIdentifier(_jsxFactoryEntity).escapedText; } } else if (compilerOptions.reactNamespace) { - _jsxNamespace = ts.escapeLeadingUnderscores(compilerOptions.reactNamespace); + _jsxNamespace = escapeLeadingUnderscores(compilerOptions.reactNamespace); } } if (!_jsxFactoryEntity) { - _jsxFactoryEntity = ts.factory.createQualifiedName(ts.factory.createIdentifier(ts.unescapeLeadingUnderscores(_jsxNamespace)), "createElement"); + _jsxFactoryEntity = factory.createQualifiedName(factory.createIdentifier(unescapeLeadingUnderscores(_jsxNamespace)), "createElement"); } return _jsxNamespace; } - function getLocalJsxNamespace(file: ts.SourceFile): ts.__String | undefined { + function getLocalJsxNamespace(file: SourceFile): __String | undefined { if (file.localJsxNamespace) { return file.localJsxNamespace; } const jsxPragma = file.pragmas.get("jsx"); if (jsxPragma) { - const chosenPragma = ts.isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; - file.localJsxFactory = ts.parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion); - ts.visitNode(file.localJsxFactory, markAsSynthetic); + const chosenPragma = isArray(jsxPragma) ? jsxPragma[0] : jsxPragma; + file.localJsxFactory = parseIsolatedEntityName(chosenPragma.arguments.factory, languageVersion); + visitNode(file.localJsxFactory, markAsSynthetic); if (file.localJsxFactory) { - return file.localJsxNamespace = ts.getFirstIdentifier(file.localJsxFactory).escapedText; + return file.localJsxNamespace = getFirstIdentifier(file.localJsxFactory).escapedText; } } } - function markAsSynthetic(node: ts.Node): ts.VisitResult { - ts.setTextRangePosEnd(node, -1, -1); - return ts.visitEachChild(node, markAsSynthetic, ts.nullTransformationContext); + function markAsSynthetic(node: Node): VisitResult { + setTextRangePosEnd(node, -1, -1); + return visitEachChild(node, markAsSynthetic, nullTransformationContext); } - function getEmitResolver(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken) { + function getEmitResolver(sourceFile: SourceFile, cancellationToken: CancellationToken) { // Ensure we have all the type information in place for this file so that all the // emitter questions of this resolver will return the right information. getDiagnostics(sourceFile, cancellationToken); return emitResolver; } - function lookupOrIssueError(location: ts.Node | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): ts.Diagnostic { + function lookupOrIssueError(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic { const diagnostic = location - ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) - : ts.createCompilerDiagnostic(message, arg0, arg1, arg2, arg3); + ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) + : createCompilerDiagnostic(message, arg0, arg1, arg2, arg3); const existing = diagnostics.lookup(diagnostic); if (existing) { return existing; @@ -1188,65 +1386,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function errorSkippedOn(key: keyof ts.CompilerOptions, location: ts.Node | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): ts.Diagnostic { + function errorSkippedOn(key: keyof CompilerOptions, location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic { const diagnostic = error(location, message, arg0, arg1, arg2, arg3); diagnostic.skippedOn = key; return diagnostic; } - function createError(location: ts.Node | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): ts.Diagnostic { + function createError(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic { return location - ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) - : ts.createCompilerDiagnostic(message, arg0, arg1, arg2, arg3); + ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) + : createCompilerDiagnostic(message, arg0, arg1, arg2, arg3); } - function error(location: ts.Node | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): ts.Diagnostic { + function error(location: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): Diagnostic { const diagnostic = createError(location, message, arg0, arg1, arg2, arg3); diagnostics.add(diagnostic); return diagnostic; } - function addErrorOrSuggestion(isError: boolean, diagnostic: ts.Diagnostic) { + function addErrorOrSuggestion(isError: boolean, diagnostic: Diagnostic) { if (isError) { diagnostics.add(diagnostic); } else { - suggestionDiagnostics.add({ ...diagnostic, category: ts.DiagnosticCategory.Suggestion }); + suggestionDiagnostics.add({ ...diagnostic, category: DiagnosticCategory.Suggestion }); } } - function errorOrSuggestion(isError: boolean, location: ts.Node, message: ts.DiagnosticMessage | ts.DiagnosticMessageChain, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { + function errorOrSuggestion(isError: boolean, location: Node, message: DiagnosticMessage | DiagnosticMessageChain, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { // Pseudo-synthesized input node if (location.pos < 0 || location.end < 0) { if (!isError) { return; // Drop suggestions (we have no span to suggest on) } // Issue errors globally - const file = ts.getSourceFileOfNode(location); - addErrorOrSuggestion(isError, "message" in message ? ts.createFileDiagnostic(file, 0, 0, message, arg0, arg1, arg2, arg3) : ts.createDiagnosticForFileFromMessageChain(file, message)); // eslint-disable-line local/no-in-operator + const file = getSourceFileOfNode(location); + addErrorOrSuggestion(isError, "message" in message ? createFileDiagnostic(file, 0, 0, message, arg0, arg1, arg2, arg3) : createDiagnosticForFileFromMessageChain(file, message)); // eslint-disable-line local/no-in-operator return; } - addErrorOrSuggestion(isError, "message" in message ? ts.createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : ts.createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line local/no-in-operator + addErrorOrSuggestion(isError, "message" in message ? createDiagnosticForNode(location, message, arg0, arg1, arg2, arg3) : createDiagnosticForNodeFromMessageChain(location, message)); // eslint-disable-line local/no-in-operator } function errorAndMaybeSuggestAwait( - location: ts.Node, + location: Node, maybeMissingAwait: boolean, - message: ts.DiagnosticMessage, - arg0?: string | number | undefined, arg1?: string | number | undefined, arg2?: string | number | undefined, arg3?: string | number | undefined): ts.Diagnostic { + message: DiagnosticMessage, + arg0?: string | number | undefined, arg1?: string | number | undefined, arg2?: string | number | undefined, arg3?: string | number | undefined): Diagnostic { const diagnostic = error(location, message, arg0, arg1, arg2, arg3); if (maybeMissingAwait) { - const related = ts.createDiagnosticForNode(location, ts.Diagnostics.Did_you_forget_to_use_await); - ts.addRelatedInfo(diagnostic, related); + const related = createDiagnosticForNode(location, Diagnostics.Did_you_forget_to_use_await); + addRelatedInfo(diagnostic, related); } return diagnostic; } - function addDeprecatedSuggestionWorker(declarations: ts.Node | ts.Node[], diagnostic: ts.DiagnosticWithLocation) { - const deprecatedTag = Array.isArray(declarations) ? ts.forEach(declarations, ts.getJSDocDeprecatedTag) : ts.getJSDocDeprecatedTag(declarations); + function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) { + const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations); if (deprecatedTag) { - ts.addRelatedInfo( + addRelatedInfo( diagnostic, - ts.createDiagnosticForNode(deprecatedTag, ts.Diagnostics.The_declaration_was_marked_as_deprecated_here) + createDiagnosticForNode(deprecatedTag, Diagnostics.The_declaration_was_marked_as_deprecated_here) ); } // We call `addRelatedInfo()` before adding the diagnostic to prevent duplicates. @@ -1254,51 +1452,51 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return diagnostic; } - function isDeprecatedSymbol(symbol: ts.Symbol) { - return !!(getDeclarationNodeFlagsFromSymbol(symbol) & ts.NodeFlags.Deprecated); + function isDeprecatedSymbol(symbol: Symbol) { + return !!(getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Deprecated); } - function addDeprecatedSuggestion(location: ts.Node, declarations: ts.Node[], deprecatedEntity: string) { - const diagnostic = ts.createDiagnosticForNode(location, ts.Diagnostics._0_is_deprecated, deprecatedEntity); + function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) { + const diagnostic = createDiagnosticForNode(location, Diagnostics._0_is_deprecated, deprecatedEntity); return addDeprecatedSuggestionWorker(declarations, diagnostic); } - function addDeprecatedSuggestionWithSignature(location: ts.Node, declaration: ts.Node, deprecatedEntity: string | undefined, signatureString: string) { + function addDeprecatedSuggestionWithSignature(location: Node, declaration: Node, deprecatedEntity: string | undefined, signatureString: string) { const diagnostic = deprecatedEntity - ? ts.createDiagnosticForNode(location, ts.Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity) - : ts.createDiagnosticForNode(location, ts.Diagnostics._0_is_deprecated, signatureString); + ? createDiagnosticForNode(location, Diagnostics.The_signature_0_of_1_is_deprecated, signatureString, deprecatedEntity) + : createDiagnosticForNode(location, Diagnostics._0_is_deprecated, signatureString); return addDeprecatedSuggestionWorker(declaration, diagnostic); } - function createSymbol(flags: ts.SymbolFlags, name: ts.__String, checkFlags?: ts.CheckFlags) { + function createSymbol(flags: SymbolFlags, name: __String, checkFlags?: CheckFlags) { symbolCount++; - const symbol = (new Symbol(flags | ts.SymbolFlags.Transient, name) as ts.TransientSymbol); + const symbol = (new Symbol(flags | SymbolFlags.Transient, name) as TransientSymbol); symbol.checkFlags = checkFlags || 0; return symbol; } - function getExcludedSymbolFlags(flags: ts.SymbolFlags): ts.SymbolFlags { - let result: ts.SymbolFlags = 0; - if (flags & ts.SymbolFlags.BlockScopedVariable) result |= ts.SymbolFlags.BlockScopedVariableExcludes; - if (flags & ts.SymbolFlags.FunctionScopedVariable) result |= ts.SymbolFlags.FunctionScopedVariableExcludes; - if (flags & ts.SymbolFlags.Property) result |= ts.SymbolFlags.PropertyExcludes; - if (flags & ts.SymbolFlags.EnumMember) result |= ts.SymbolFlags.EnumMemberExcludes; - if (flags & ts.SymbolFlags.Function) result |= ts.SymbolFlags.FunctionExcludes; - if (flags & ts.SymbolFlags.Class) result |= ts.SymbolFlags.ClassExcludes; - if (flags & ts.SymbolFlags.Interface) result |= ts.SymbolFlags.InterfaceExcludes; - if (flags & ts.SymbolFlags.RegularEnum) result |= ts.SymbolFlags.RegularEnumExcludes; - if (flags & ts.SymbolFlags.ConstEnum) result |= ts.SymbolFlags.ConstEnumExcludes; - if (flags & ts.SymbolFlags.ValueModule) result |= ts.SymbolFlags.ValueModuleExcludes; - if (flags & ts.SymbolFlags.Method) result |= ts.SymbolFlags.MethodExcludes; - if (flags & ts.SymbolFlags.GetAccessor) result |= ts.SymbolFlags.GetAccessorExcludes; - if (flags & ts.SymbolFlags.SetAccessor) result |= ts.SymbolFlags.SetAccessorExcludes; - if (flags & ts.SymbolFlags.TypeParameter) result |= ts.SymbolFlags.TypeParameterExcludes; - if (flags & ts.SymbolFlags.TypeAlias) result |= ts.SymbolFlags.TypeAliasExcludes; - if (flags & ts.SymbolFlags.Alias) result |= ts.SymbolFlags.AliasExcludes; + function getExcludedSymbolFlags(flags: SymbolFlags): SymbolFlags { + let result: SymbolFlags = 0; + if (flags & SymbolFlags.BlockScopedVariable) result |= SymbolFlags.BlockScopedVariableExcludes; + if (flags & SymbolFlags.FunctionScopedVariable) result |= SymbolFlags.FunctionScopedVariableExcludes; + if (flags & SymbolFlags.Property) result |= SymbolFlags.PropertyExcludes; + if (flags & SymbolFlags.EnumMember) result |= SymbolFlags.EnumMemberExcludes; + if (flags & SymbolFlags.Function) result |= SymbolFlags.FunctionExcludes; + if (flags & SymbolFlags.Class) result |= SymbolFlags.ClassExcludes; + if (flags & SymbolFlags.Interface) result |= SymbolFlags.InterfaceExcludes; + if (flags & SymbolFlags.RegularEnum) result |= SymbolFlags.RegularEnumExcludes; + if (flags & SymbolFlags.ConstEnum) result |= SymbolFlags.ConstEnumExcludes; + if (flags & SymbolFlags.ValueModule) result |= SymbolFlags.ValueModuleExcludes; + if (flags & SymbolFlags.Method) result |= SymbolFlags.MethodExcludes; + if (flags & SymbolFlags.GetAccessor) result |= SymbolFlags.GetAccessorExcludes; + if (flags & SymbolFlags.SetAccessor) result |= SymbolFlags.SetAccessorExcludes; + if (flags & SymbolFlags.TypeParameter) result |= SymbolFlags.TypeParameterExcludes; + if (flags & SymbolFlags.TypeAlias) result |= SymbolFlags.TypeAliasExcludes; + if (flags & SymbolFlags.Alias) result |= SymbolFlags.AliasExcludes; return result; } - function recordMergedSymbol(target: ts.Symbol, source: ts.Symbol) { + function recordMergedSymbol(target: Symbol, source: Symbol) { if (!source.mergeId) { source.mergeId = nextMergeId; nextMergeId++; @@ -1306,14 +1504,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { mergedSymbols[source.mergeId] = target; } - function cloneSymbol(symbol: ts.Symbol): ts.Symbol { + function cloneSymbol(symbol: Symbol): Symbol { const result = createSymbol(symbol.flags, symbol.escapedName); result.declarations = symbol.declarations ? symbol.declarations.slice() : []; result.parent = symbol.parent; if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; - if (symbol.members) result.members = new ts.Map(symbol.members); - if (symbol.exports) result.exports = new ts.Map(symbol.exports); + if (symbol.members) result.members = new Map(symbol.members); + if (symbol.exports) result.exports = new Map(symbol.exports); recordMergedSymbol(result, symbol); return result; } @@ -1322,15 +1520,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Note: if target is transient, then it is mutable, and mergeSymbol with both mutate and return it. * If target is not transient, mergeSymbol will produce a transient clone, mutate that and return it. */ - function mergeSymbol(target: ts.Symbol, source: ts.Symbol, unidirectional = false): ts.Symbol { + function mergeSymbol(target: Symbol, source: Symbol, unidirectional = false): Symbol { if (!(target.flags & getExcludedSymbolFlags(source.flags)) || - (source.flags | target.flags) & ts.SymbolFlags.Assignment) { + (source.flags | target.flags) & SymbolFlags.Assignment) { if (source === target) { // This can happen when an export assigned namespace exports something also erroneously exported at the top level // See `declarationFileNoCrashOnExtraExportModifier` for an example return target; } - if (!(target.flags & ts.SymbolFlags.Transient)) { + if (!(target.flags & SymbolFlags.Transient)) { const resolvedTarget = resolveSymbol(target); if (resolvedTarget === unknownSymbol) { return source; @@ -1338,58 +1536,58 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { target = cloneSymbol(resolvedTarget); } // Javascript static-property-assignment declarations always merge, even though they are also values - if (source.flags & ts.SymbolFlags.ValueModule && target.flags & ts.SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { + if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { // reset flag when merging instantiated module into value module that has only const enums target.constEnumOnlyModule = false; } target.flags |= source.flags; if (source.valueDeclaration) { - ts.setValueDeclaration(target, source.valueDeclaration); + setValueDeclaration(target, source.valueDeclaration); } - ts.addRange(target.declarations, source.declarations); + addRange(target.declarations, source.declarations); if (source.members) { - if (!target.members) target.members = ts.createSymbolTable(); + if (!target.members) target.members = createSymbolTable(); mergeSymbolTable(target.members, source.members, unidirectional); } if (source.exports) { - if (!target.exports) target.exports = ts.createSymbolTable(); + if (!target.exports) target.exports = createSymbolTable(); mergeSymbolTable(target.exports, source.exports, unidirectional); } if (!unidirectional) { recordMergedSymbol(target, source); } } - else if (target.flags & ts.SymbolFlags.NamespaceModule) { + else if (target.flags & SymbolFlags.NamespaceModule) { // Do not report an error when merging `var globalThis` with the built-in `globalThis`, // as we will already report a "Declaration name conflicts..." error, and this error // won't make much sense. if (target !== globalThisSymbol) { error( - source.declarations && ts.getNameOfDeclaration(source.declarations[0]), - ts.Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, + source.declarations && getNameOfDeclaration(source.declarations[0]), + Diagnostics.Cannot_augment_module_0_with_value_exports_because_it_resolves_to_a_non_module_entity, symbolToString(target)); } } else { // error - const isEitherEnum = !!(target.flags & ts.SymbolFlags.Enum || source.flags & ts.SymbolFlags.Enum); - const isEitherBlockScoped = !!(target.flags & ts.SymbolFlags.BlockScopedVariable || source.flags & ts.SymbolFlags.BlockScopedVariable); - const message = isEitherEnum ? ts.Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations - : isEitherBlockScoped ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 - : ts.Diagnostics.Duplicate_identifier_0; - const sourceSymbolFile = source.declarations && ts.getSourceFileOfNode(source.declarations[0]); - const targetSymbolFile = target.declarations && ts.getSourceFileOfNode(target.declarations[0]); - - const isSourcePlainJs = ts.isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); - const isTargetPlainJs = ts.isPlainJsFile(targetSymbolFile, compilerOptions.checkJs); + const isEitherEnum = !!(target.flags & SymbolFlags.Enum || source.flags & SymbolFlags.Enum); + const isEitherBlockScoped = !!(target.flags & SymbolFlags.BlockScopedVariable || source.flags & SymbolFlags.BlockScopedVariable); + const message = isEitherEnum ? Diagnostics.Enum_declarations_can_only_merge_with_namespace_or_other_enum_declarations + : isEitherBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 + : Diagnostics.Duplicate_identifier_0; + const sourceSymbolFile = source.declarations && getSourceFileOfNode(source.declarations[0]); + const targetSymbolFile = target.declarations && getSourceFileOfNode(target.declarations[0]); + + const isSourcePlainJs = isPlainJsFile(sourceSymbolFile, compilerOptions.checkJs); + const isTargetPlainJs = isPlainJsFile(targetSymbolFile, compilerOptions.checkJs); const symbolName = symbolToString(source); // Collect top-level duplicate identifier errors into one mapping, so we can then merge their diagnostics if there are a bunch if (sourceSymbolFile && targetSymbolFile && amalgamatedDuplicates && !isEitherEnum && sourceSymbolFile !== targetSymbolFile) { - const firstFile = ts.comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === ts.Comparison.LessThan ? sourceSymbolFile : targetSymbolFile; + const firstFile = comparePaths(sourceSymbolFile.path, targetSymbolFile.path) === Comparison.LessThan ? sourceSymbolFile : targetSymbolFile; const secondFile = firstFile === sourceSymbolFile ? targetSymbolFile : sourceSymbolFile; - const filesDuplicates = ts.getOrUpdate(amalgamatedDuplicates, `${firstFile.path}|${secondFile.path}`, () => - ({ firstFile, secondFile, conflictingSymbols: new ts.Map() } as DuplicateInfoForFiles)); - const conflictingSymbolInfo = ts.getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () => + const filesDuplicates = getOrUpdate(amalgamatedDuplicates, `${firstFile.path}|${secondFile.path}`, () => + ({ firstFile, secondFile, conflictingSymbols: new Map() } as DuplicateInfoForFiles)); + const conflictingSymbolInfo = getOrUpdate(filesDuplicates.conflictingSymbols, symbolName, () => ({ isBlockScoped: isEitherBlockScoped, firstFileLocations: [], secondFileLocations: [] } as DuplicateInfoForSymbol)); if (!isSourcePlainJs) addDuplicateLocations(conflictingSymbolInfo.firstFileLocations, source); if (!isTargetPlainJs) addDuplicateLocations(conflictingSymbolInfo.secondFileLocations, target); @@ -1401,69 +1599,69 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return target; - function addDuplicateLocations(locs: ts.Declaration[], symbol: ts.Symbol): void { + function addDuplicateLocations(locs: Declaration[], symbol: Symbol): void { if (symbol.declarations) { for (const decl of symbol.declarations) { - ts.pushIfUnique(locs, decl); + pushIfUnique(locs, decl); } } } } - function addDuplicateDeclarationErrorsForSymbols(target: ts.Symbol, message: ts.DiagnosticMessage, symbolName: string, source: ts.Symbol) { - ts.forEach(target.declarations, node => { + function addDuplicateDeclarationErrorsForSymbols(target: Symbol, message: DiagnosticMessage, symbolName: string, source: Symbol) { + forEach(target.declarations, node => { addDuplicateDeclarationError(node, message, symbolName, source.declarations); }); } - function addDuplicateDeclarationError(node: ts.Declaration, message: ts.DiagnosticMessage, symbolName: string, relatedNodes: readonly ts.Declaration[] | undefined) { - const errorNode = (ts.getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? ts.getNameOfExpando(node) : ts.getNameOfDeclaration(node)) || node; + function addDuplicateDeclarationError(node: Declaration, message: DiagnosticMessage, symbolName: string, relatedNodes: readonly Declaration[] | undefined) { + const errorNode = (getExpandoInitializer(node, /*isPrototypeAssignment*/ false) ? getNameOfExpando(node) : getNameOfDeclaration(node)) || node; const err = lookupOrIssueError(errorNode, message, symbolName); - for (const relatedNode of relatedNodes || ts.emptyArray) { - const adjustedNode = (ts.getExpandoInitializer(relatedNode, /*isPrototypeAssignment*/ false) ? ts.getNameOfExpando(relatedNode) : ts.getNameOfDeclaration(relatedNode)) || relatedNode; + for (const relatedNode of relatedNodes || emptyArray) { + const adjustedNode = (getExpandoInitializer(relatedNode, /*isPrototypeAssignment*/ false) ? getNameOfExpando(relatedNode) : getNameOfDeclaration(relatedNode)) || relatedNode; if (adjustedNode === errorNode) continue; err.relatedInformation = err.relatedInformation || []; - const leadingMessage = ts.createDiagnosticForNode(adjustedNode, ts.Diagnostics._0_was_also_declared_here, symbolName); - const followOnMessage = ts.createDiagnosticForNode(adjustedNode, ts.Diagnostics.and_here); - if (ts.length(err.relatedInformation) >= 5 || ts.some(err.relatedInformation, r => ts.compareDiagnostics(r, followOnMessage) === ts.Comparison.EqualTo || ts.compareDiagnostics(r, leadingMessage) === ts.Comparison.EqualTo)) continue; - ts.addRelatedInfo(err, !ts.length(err.relatedInformation) ? leadingMessage : followOnMessage); + const leadingMessage = createDiagnosticForNode(adjustedNode, Diagnostics._0_was_also_declared_here, symbolName); + const followOnMessage = createDiagnosticForNode(adjustedNode, Diagnostics.and_here); + if (length(err.relatedInformation) >= 5 || some(err.relatedInformation, r => compareDiagnostics(r, followOnMessage) === Comparison.EqualTo || compareDiagnostics(r, leadingMessage) === Comparison.EqualTo)) continue; + addRelatedInfo(err, !length(err.relatedInformation) ? leadingMessage : followOnMessage); } } - function combineSymbolTables(first: ts.SymbolTable | undefined, second: ts.SymbolTable | undefined): ts.SymbolTable | undefined { + function combineSymbolTables(first: SymbolTable | undefined, second: SymbolTable | undefined): SymbolTable | undefined { if (!first?.size) return second; if (!second?.size) return first; - const combined = ts.createSymbolTable(); + const combined = createSymbolTable(); mergeSymbolTable(combined, first); mergeSymbolTable(combined, second); return combined; } - function mergeSymbolTable(target: ts.SymbolTable, source: ts.SymbolTable, unidirectional = false) { + function mergeSymbolTable(target: SymbolTable, source: SymbolTable, unidirectional = false) { source.forEach((sourceSymbol, id) => { const targetSymbol = target.get(id); target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol)); }); } - function mergeModuleAugmentation(moduleName: ts.StringLiteral | ts.Identifier): void { - const moduleAugmentation = moduleName.parent as ts.ModuleDeclaration; + function mergeModuleAugmentation(moduleName: StringLiteral | Identifier): void { + const moduleAugmentation = moduleName.parent as ModuleDeclaration; if (moduleAugmentation.symbol.declarations?.[0] !== moduleAugmentation) { // this is a combined symbol for multiple augmentations within the same file. // its symbol already has accumulated information for all declarations // so we need to add it just once - do the work only for first declaration - ts.Debug.assert(moduleAugmentation.symbol.declarations!.length > 1); + Debug.assert(moduleAugmentation.symbol.declarations!.length > 1); return; } - if (ts.isGlobalScopeAugmentation(moduleAugmentation)) { + if (isGlobalScopeAugmentation(moduleAugmentation)) { mergeSymbolTable(globals, moduleAugmentation.symbol.exports!); } else { // find a module that about to be augmented // do not validate names of augmentations that are defined in ambient context - const moduleNotFoundError = !(moduleName.parent.parent.flags & ts.NodeFlags.Ambient) - ? ts.Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found + const moduleNotFoundError = !(moduleName.parent.parent.flags & NodeFlags.Ambient) + ? Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found : undefined; let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, moduleNotFoundError, /*isForAugmentation*/ true); if (!mainModule) { @@ -1471,25 +1669,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // obtain item referenced by 'export=' mainModule = resolveExternalModuleSymbol(mainModule); - if (mainModule.flags & ts.SymbolFlags.Namespace) { + if (mainModule.flags & SymbolFlags.Namespace) { // If we're merging an augmentation to a pattern ambient module, we want to // perform the merge unidirectionally from the augmentation ('a.foo') to // the pattern ('*.foo'), so that 'getMergedSymbol()' on a.foo gives you // all the exports both from the pattern and from the augmentation, but // 'getMergedSymbol()' on *.foo only gives you exports from *.foo. - if (ts.some(patternAmbientModules, module => mainModule === module.symbol)) { + if (some(patternAmbientModules, module => mainModule === module.symbol)) { const merged = mergeSymbol(moduleAugmentation.symbol, mainModule, /*unidirectional*/ true); if (!patternAmbientModuleAugmentations) { - patternAmbientModuleAugmentations = new ts.Map(); + patternAmbientModuleAugmentations = new Map(); } // moduleName will be a StringLiteral since this is not `declare global`. - patternAmbientModuleAugmentations.set((moduleName as ts.StringLiteral).text, merged); + patternAmbientModuleAugmentations.set((moduleName as StringLiteral).text, merged); } else { - if (mainModule.exports?.get(ts.InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) { + if (mainModule.exports?.get(InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) { // We may need to merge the module augmentation's exports into the target symbols of the resolved exports const resolvedExports = getResolvedMembersOrExportsOfSymbol(mainModule, MembersOrExportsResolutionKind.resolvedExports); - for (const [key, value] of ts.arrayFrom(moduleAugmentation.symbol.exports.entries())) { + for (const [key, value] of arrayFrom(moduleAugmentation.symbol.exports.entries())) { if (resolvedExports.has(key) && !mainModule.exports.has(key)) { mergeSymbol(resolvedExports.get(key)!, value); } @@ -1500,52 +1698,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { // moduleName will be a StringLiteral since this is not `declare global`. - error(moduleName, ts.Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, (moduleName as ts.StringLiteral).text); + error(moduleName, Diagnostics.Cannot_augment_module_0_because_it_resolves_to_a_non_module_entity, (moduleName as StringLiteral).text); } } } - function addToSymbolTable(target: ts.SymbolTable, source: ts.SymbolTable, message: ts.DiagnosticMessage) { + function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) { source.forEach((sourceSymbol, id) => { const targetSymbol = target.get(id); if (targetSymbol) { // Error on redeclarations - ts.forEach(targetSymbol.declarations, addDeclarationDiagnostic(ts.unescapeLeadingUnderscores(id), message)); + forEach(targetSymbol.declarations, addDeclarationDiagnostic(unescapeLeadingUnderscores(id), message)); } else { target.set(id, sourceSymbol); } }); - function addDeclarationDiagnostic(id: string, message: ts.DiagnosticMessage) { - return (declaration: ts.Declaration) => diagnostics.add(ts.createDiagnosticForNode(declaration, message, id)); + function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) { + return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id)); } } - function getSymbolLinks(symbol: ts.Symbol): ts.SymbolLinks { - if (symbol.flags & ts.SymbolFlags.Transient) return symbol as ts.TransientSymbol; + function getSymbolLinks(symbol: Symbol): SymbolLinks { + if (symbol.flags & SymbolFlags.Transient) return symbol as TransientSymbol; const id = getSymbolId(symbol); return symbolLinks[id] || (symbolLinks[id] = new (SymbolLinks as any)()); } - function getNodeLinks(node: ts.Node): ts.NodeLinks { + function getNodeLinks(node: Node): NodeLinks { const nodeId = getNodeId(node); return nodeLinks[nodeId] || (nodeLinks[nodeId] = new (NodeLinks as any)()); } - function isGlobalSourceFile(node: ts.Node) { - return node.kind === ts.SyntaxKind.SourceFile && !ts.isExternalOrCommonJsModule(node as ts.SourceFile); + function isGlobalSourceFile(node: Node) { + return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node as SourceFile); } - function getSymbol(symbols: ts.SymbolTable, name: ts.__String, meaning: ts.SymbolFlags): ts.Symbol | undefined { + function getSymbol(symbols: SymbolTable, name: __String, meaning: SymbolFlags): Symbol | undefined { if (meaning) { const symbol = getMergedSymbol(symbols.get(name)); if (symbol) { - ts.Debug.assert((ts.getCheckFlags(symbol) & ts.CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); + Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); if (symbol.flags & meaning) { return symbol; } - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { const targetFlags = getAllSymbolFlags(symbol); // `targetFlags` will be `SymbolFlags.All` if an error occurred in alias resolution; this avoids cascading errors if (targetFlags & meaning) { @@ -1563,29 +1761,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ts.ParameterDeclaration, parameterName: ts.__String): [ts.Symbol, ts.Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; - const parameterSymbol = getSymbol(constructorDeclaration.locals!, parameterName, ts.SymbolFlags.Value); - const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, ts.SymbolFlags.Value); + const parameterSymbol = getSymbol(constructorDeclaration.locals!, parameterName, SymbolFlags.Value); + const propertySymbol = getSymbol(getMembersOfSymbol(classDeclaration.symbol), parameterName, SymbolFlags.Value); if (parameterSymbol && propertySymbol) { return [parameterSymbol, propertySymbol]; } - return ts.Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); + return Debug.fail("There should exist two symbols, one as property declaration and one as parameter declaration"); } - function isBlockScopedNameDeclaredBeforeUse(declaration: ts.Declaration, usage: ts.Node): boolean { - const declarationFile = ts.getSourceFileOfNode(declaration); - const useFile = ts.getSourceFileOfNode(usage); - const declContainer = ts.getEnclosingBlockScopeContainer(declaration); + function isBlockScopedNameDeclaredBeforeUse(declaration: Declaration, usage: Node): boolean { + const declarationFile = getSourceFileOfNode(declaration); + const useFile = getSourceFileOfNode(usage); + const declContainer = getEnclosingBlockScopeContainer(declaration); if (declarationFile !== useFile) { if ((moduleKind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) || - (!ts.outFile(compilerOptions)) || + (!outFile(compilerOptions)) || isInTypeQuery(usage) || - declaration.flags & ts.NodeFlags.Ambient) { + declaration.flags & NodeFlags.Ambient) { // nodes are in different files and order cannot be determined return true; } @@ -1598,34 +1796,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return sourceFiles.indexOf(declarationFile) <= sourceFiles.indexOf(useFile); } - if (declaration.pos <= usage.pos && !(ts.isPropertyDeclaration(declaration) && ts.isThisProperty(usage.parent) && !declaration.initializer && !declaration.exclamationToken)) { + if (declaration.pos <= usage.pos && !(isPropertyDeclaration(declaration) && isThisProperty(usage.parent) && !declaration.initializer && !declaration.exclamationToken)) { // declaration is before usage - if (declaration.kind === ts.SyntaxKind.BindingElement) { + if (declaration.kind === SyntaxKind.BindingElement) { // still might be illegal if declaration and usage are both binding elements (eg var [a = b, b = b] = [1, 2]) - const errorBindingElement = ts.getAncestor(usage, ts.SyntaxKind.BindingElement) as ts.BindingElement; + const errorBindingElement = getAncestor(usage, SyntaxKind.BindingElement) as BindingElement; if (errorBindingElement) { - return ts.findAncestor(errorBindingElement, ts.isBindingElement) !== ts.findAncestor(declaration, ts.isBindingElement) || + return findAncestor(errorBindingElement, isBindingElement) !== findAncestor(declaration, isBindingElement) || declaration.pos < errorBindingElement.pos; } // or it might be illegal if usage happens before parent variable is declared (eg var [a] = a) - return isBlockScopedNameDeclaredBeforeUse(ts.getAncestor(declaration, ts.SyntaxKind.VariableDeclaration) as ts.Declaration, usage); + return isBlockScopedNameDeclaredBeforeUse(getAncestor(declaration, SyntaxKind.VariableDeclaration) as Declaration, usage); } - else if (declaration.kind === ts.SyntaxKind.VariableDeclaration) { + else if (declaration.kind === SyntaxKind.VariableDeclaration) { // still might be illegal if usage is in the initializer of the variable declaration (eg var a = a) - return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration as ts.VariableDeclaration, usage); + return !isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration as VariableDeclaration, usage); } - else if (ts.isClassDeclaration(declaration)) { + else if (isClassDeclaration(declaration)) { // still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} }) - return !ts.findAncestor(usage, n => ts.isComputedPropertyName(n) && n.parent.parent === declaration); + return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration); } - else if (ts.isPropertyDeclaration(declaration)) { + else if (isPropertyDeclaration(declaration)) { // still might be illegal if a self-referencing property initializer (eg private x = this.x) return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ false); } - else if (ts.isParameterPropertyDeclaration(declaration, declaration.parent)) { + else if (isParameterPropertyDeclaration(declaration, declaration.parent)) { // foo = this.bar is illegal in esnext+useDefineForClassFields when bar is a parameter property - return !(ts.getEmitScriptTarget(compilerOptions) === ts.ScriptTarget.ESNext && useDefineForClassFields - && ts.getContainingClass(declaration) === ts.getContainingClass(usage) + return !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields + && getContainingClass(declaration) === getContainingClass(usage) && isUsedInFunctionOrInstanceProperty(usage, declaration)); } return true; @@ -1642,22 +1840,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // or if usage is in a type context: // 1. inside a type query (typeof in type position) // 2. inside a jsdoc comment - if (usage.parent.kind === ts.SyntaxKind.ExportSpecifier || (usage.parent.kind === ts.SyntaxKind.ExportAssignment && (usage.parent as ts.ExportAssignment).isExportEquals)) { + if (usage.parent.kind === SyntaxKind.ExportSpecifier || (usage.parent.kind === SyntaxKind.ExportAssignment && (usage.parent as ExportAssignment).isExportEquals)) { // export specifiers do not use the variable, they only make it available for use return true; } // When resolving symbols for exports, the `usage` location passed in can be the export site directly - if (usage.kind === ts.SyntaxKind.ExportAssignment && (usage as ts.ExportAssignment).isExportEquals) { + if (usage.kind === SyntaxKind.ExportAssignment && (usage as ExportAssignment).isExportEquals) { return true; } - if (!!(usage.flags & ts.NodeFlags.JSDoc) || isInTypeQuery(usage) || usageInTypeDeclaration()) { + if (!!(usage.flags & NodeFlags.JSDoc) || isInTypeQuery(usage) || usageInTypeDeclaration()) { return true; } if (isUsedInFunctionOrInstanceProperty(usage, declaration)) { - if (ts.getEmitScriptTarget(compilerOptions) === ts.ScriptTarget.ESNext && useDefineForClassFields - && ts.getContainingClass(declaration) - && (ts.isPropertyDeclaration(declaration) || ts.isParameterPropertyDeclaration(declaration, declaration.parent))) { + if (getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields + && getContainingClass(declaration) + && (isPropertyDeclaration(declaration) || isParameterPropertyDeclaration(declaration, declaration.parent))) { return !isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage, /*stopAtAnyPropertyDeclaration*/ true); } else { @@ -1667,14 +1865,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; function usageInTypeDeclaration() { - return !!ts.findAncestor(usage, node => ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)); + return !!findAncestor(usage, node => isInterfaceDeclaration(node) || isTypeAliasDeclaration(node)); } - function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: ts.VariableDeclaration, usage: ts.Node): boolean { + function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { switch (declaration.parent.parent.kind) { - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForOfStatement: + case SyntaxKind.VariableStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForOfStatement: // variable statement/for/for-of statement case, // use site should not be inside variable declaration (initializer of declaration or binding element) if (isSameScopeDescendentOf(usage, declaration, declContainer)) { @@ -1685,34 +1883,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // ForIn/ForOf case - use site should not be used in expression part const grandparent = declaration.parent.parent; - return ts.isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, declContainer); + return isForInOrOfStatement(grandparent) && isSameScopeDescendentOf(usage, grandparent.expression, declContainer); } - function isUsedInFunctionOrInstanceProperty(usage: ts.Node, declaration: ts.Node): boolean { - return !!ts.findAncestor(usage, current => { + function isUsedInFunctionOrInstanceProperty(usage: Node, declaration: Node): boolean { + return !!findAncestor(usage, current => { if (current === declContainer) { return "quit"; } - if (ts.isFunctionLike(current)) { + if (isFunctionLike(current)) { return true; } - if (ts.isClassStaticBlockDeclaration(current)) { + if (isClassStaticBlockDeclaration(current)) { return declaration.pos < usage.pos; } - const propertyDeclaration = ts.tryCast(current.parent, ts.isPropertyDeclaration); + const propertyDeclaration = tryCast(current.parent, isPropertyDeclaration); if (propertyDeclaration) { const initializerOfProperty = propertyDeclaration.initializer === current; if (initializerOfProperty) { - if (ts.isStatic(current.parent)) { - if (declaration.kind === ts.SyntaxKind.MethodDeclaration) { + if (isStatic(current.parent)) { + if (declaration.kind === SyntaxKind.MethodDeclaration) { return true; } - if (ts.isPropertyDeclaration(declaration) && ts.getContainingClass(usage) === ts.getContainingClass(declaration)) { + if (isPropertyDeclaration(declaration) && getContainingClass(usage) === getContainingClass(declaration)) { const propName = declaration.name; - if (ts.isIdentifier(propName) || ts.isPrivateIdentifier(propName)) { + if (isIdentifier(propName) || isPrivateIdentifier(propName)) { const type = getTypeOfSymbol(getSymbolOfNode(declaration)); - const staticBlocks = ts.filter(declaration.parent.members, ts.isClassStaticBlockDeclaration); + const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); if (isPropertyInitializedInStaticBlocks(propName, type, staticBlocks, declaration.parent.pos, current.pos)) { return true; } @@ -1720,8 +1918,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else { - const isDeclarationInstanceProperty = declaration.kind === ts.SyntaxKind.PropertyDeclaration && !ts.isStatic(declaration); - if (!isDeclarationInstanceProperty || ts.getContainingClass(usage) !== ts.getContainingClass(declaration)) { + const isDeclarationInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !isStatic(declaration); + if (!isDeclarationInstanceProperty || getContainingClass(usage) !== getContainingClass(declaration)) { return true; } } @@ -1732,7 +1930,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** stopAtAnyPropertyDeclaration is used for detecting ES-standard class field use-before-def errors */ - function isPropertyImmediatelyReferencedWithinDeclaration(declaration: ts.PropertyDeclaration | ts.ParameterPropertyDeclaration, usage: ts.Node, stopAtAnyPropertyDeclaration: boolean) { + function isPropertyImmediatelyReferencedWithinDeclaration(declaration: PropertyDeclaration | ParameterPropertyDeclaration, usage: Node, stopAtAnyPropertyDeclaration: boolean) { // always legal if usage is after declaration if (usage.end > declaration.end) { return false; @@ -1740,25 +1938,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // still might be legal if usage is deferred (e.g. x: any = () => this.x) // otherwise illegal if immediately referenced within the declaration (e.g. x: any = this.x) - const ancestorChangingReferenceScope = ts.findAncestor(usage, (node: ts.Node) => { + const ancestorChangingReferenceScope = findAncestor(usage, (node: Node) => { if (node === declaration) { return "quit"; } switch (node.kind) { - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ArrowFunction: return true; - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyDeclaration: // even when stopping at any property declaration, they need to come from the same class return stopAtAnyPropertyDeclaration && - (ts.isPropertyDeclaration(declaration) && node.parent === declaration.parent - || ts.isParameterPropertyDeclaration(declaration, declaration.parent) && node.parent === declaration.parent.parent) + (isPropertyDeclaration(declaration) && node.parent === declaration.parent + || isParameterPropertyDeclaration(declaration, declaration.parent) && node.parent === declaration.parent.parent) ? "quit": true; - case ts.SyntaxKind.Block: + case SyntaxKind.Block: switch (node.parent.kind) { - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.SetAccessor: return true; default: return false; @@ -1772,10 +1970,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function useOuterVariableScopeInParameter(result: ts.Symbol, location: ts.Node, lastLocation: ts.Node) { - const target = ts.getEmitScriptTarget(compilerOptions); - const functionLocation = location as ts.FunctionLikeDeclaration; - if (ts.isParameter(lastLocation) + function useOuterVariableScopeInParameter(result: Symbol, location: Node, lastLocation: Node) { + const target = getEmitScriptTarget(compilerOptions); + const functionLocation = location as FunctionLikeDeclaration; + if (isParameter(lastLocation) && functionLocation.body && result.valueDeclaration && result.valueDeclaration.pos >= functionLocation.body.pos @@ -1785,57 +1983,57 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // - optional chaining pre-es2020 // - nullish coalesce pre-es2020 // - spread assignment in binding pattern pre-es2017 - if (target >= ts.ScriptTarget.ES2015) { + if (target >= ScriptTarget.ES2015) { const links = getNodeLinks(functionLocation); if (links.declarationRequiresScopeChange === undefined) { - links.declarationRequiresScopeChange = ts.forEach(functionLocation.parameters, requiresScopeChange) || false; + links.declarationRequiresScopeChange = forEach(functionLocation.parameters, requiresScopeChange) || false; } return !links.declarationRequiresScopeChange; } } return false; - function requiresScopeChange(node: ts.ParameterDeclaration): boolean { + function requiresScopeChange(node: ParameterDeclaration): boolean { return requiresScopeChangeWorker(node.name) || !!node.initializer && requiresScopeChangeWorker(node.initializer); } - function requiresScopeChangeWorker(node: ts.Node): boolean { + function requiresScopeChangeWorker(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.Constructor: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: // do not descend into these return false; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.PropertyAssignment: - return requiresScopeChangeWorker((node as ts.MethodDeclaration | ts.AccessorDeclaration | ts.PropertyAssignment).name); - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyAssignment: + return requiresScopeChangeWorker((node as MethodDeclaration | AccessorDeclaration | PropertyAssignment).name); + case SyntaxKind.PropertyDeclaration: // static properties in classes introduce temporary variables - if (ts.hasStaticModifier(node)) { - return target < ts.ScriptTarget.ESNext || !useDefineForClassFields; + if (hasStaticModifier(node)) { + return target < ScriptTarget.ESNext || !useDefineForClassFields; } - return requiresScopeChangeWorker((node as ts.PropertyDeclaration).name); + return requiresScopeChangeWorker((node as PropertyDeclaration).name); default: // null coalesce and optional chain pre-es2020 produce temporary variables - if (ts.isNullishCoalesce(node) || ts.isOptionalChain(node)) { - return target < ts.ScriptTarget.ES2020; + if (isNullishCoalesce(node) || isOptionalChain(node)) { + return target < ScriptTarget.ES2020; } - if (ts.isBindingElement(node) && node.dotDotDotToken && ts.isObjectBindingPattern(node.parent)) { - return target < ts.ScriptTarget.ES2017; + if (isBindingElement(node) && node.dotDotDotToken && isObjectBindingPattern(node.parent)) { + return target < ScriptTarget.ES2017; } - if (ts.isTypeNode(node)) return false; - return ts.forEachChild(node, requiresScopeChangeWorker) || false; + if (isTypeNode(node)) return false; + return forEachChild(node, requiresScopeChangeWorker) || false; } } } - function isConstAssertion(location: ts.Node) { - return (ts.isAssertionExpression(location) && ts.isConstTypeReference(location.type)) - || (ts.isJSDocTypeTag(location) && ts.isConstTypeReference(location.typeExpression)); + function isConstAssertion(location: Node) { + return (isAssertionExpression(location) && isConstTypeReference(location.type)) + || (isJSDocTypeTag(location) && isConstTypeReference(location.typeExpression)); } /** @@ -1847,36 +2045,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param isUse If true, this will count towards --noUnusedLocals / --noUnusedParameters. */ function resolveName( - location: ts.Node | undefined, - name: ts.__String, - meaning: ts.SymbolFlags, - nameNotFoundMessage: ts.DiagnosticMessage | undefined, - nameArg: ts.__String | ts.Identifier | undefined, + location: Node | undefined, + name: __String, + meaning: SymbolFlags, + nameNotFoundMessage: DiagnosticMessage | undefined, + nameArg: __String | Identifier | undefined, isUse: boolean, excludeGlobals = false, - getSpellingSuggestions = true): ts.Symbol | undefined { + getSpellingSuggestions = true): Symbol | undefined { return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, isUse, excludeGlobals, getSpellingSuggestions, getSymbol); } function resolveNameHelper( - location: ts.Node | undefined, - name: ts.__String, - meaning: ts.SymbolFlags, - nameNotFoundMessage: ts.DiagnosticMessage | undefined, - nameArg: ts.__String | ts.Identifier | undefined, + location: Node | undefined, + name: __String, + meaning: SymbolFlags, + nameNotFoundMessage: DiagnosticMessage | undefined, + nameArg: __String | Identifier | undefined, isUse: boolean, excludeGlobals: boolean, getSpellingSuggestions: boolean, - lookup: typeof getSymbol): ts.Symbol | undefined { + lookup: typeof getSymbol): Symbol | undefined { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location - let result: ts.Symbol | undefined; - let lastLocation: ts.Node | undefined; - let lastSelfReferenceLocation: ts.Node | undefined; - let propertyWithInvalidInitializer: ts.PropertyDeclaration | undefined; - let associatedDeclarationForContainingInitializerOrBindingName: ts.ParameterDeclaration | ts.BindingElement | undefined; + let result: Symbol | undefined; + let lastLocation: Node | undefined; + let lastSelfReferenceLocation: Node | undefined; + let propertyWithInvalidInitializer: PropertyDeclaration | undefined; + let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined; let withinDeferredContext = false; const errorLocation = location; - let grandparent: ts.Node; + let grandparent: Node; let isInExternalModule = false; loop: while (location) { @@ -1889,47 +2087,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (location.locals && !isGlobalSourceFile(location)) { if (result = lookup(location.locals, name, meaning)) { let useResult = true; - if (ts.isFunctionLike(location) && lastLocation && lastLocation !== (location as ts.FunctionLikeDeclaration).body) { + if (isFunctionLike(location) && lastLocation && lastLocation !== (location as FunctionLikeDeclaration).body) { // symbol lookup restrictions for function-like declarations // - Type parameters of a function are in scope in the entire function declaration, including the parameter // list and return type. However, local types are only in scope in the function body. // - parameters are only in the scope of function body // This restriction does not apply to JSDoc comment types because they are parented // at a higher level than type parameters would normally be - if (meaning & result.flags & ts.SymbolFlags.Type && lastLocation.kind !== ts.SyntaxKind.JSDoc) { - useResult = result.flags & ts.SymbolFlags.TypeParameter + if (meaning & result.flags & SymbolFlags.Type && lastLocation.kind !== SyntaxKind.JSDoc) { + useResult = result.flags & SymbolFlags.TypeParameter // type parameters are visible in parameter list, return type and type parameter list - ? lastLocation === (location as ts.FunctionLikeDeclaration).type || - lastLocation.kind === ts.SyntaxKind.Parameter || - lastLocation.kind === ts.SyntaxKind.JSDocParameterTag || - lastLocation.kind === ts.SyntaxKind.JSDocReturnTag || - lastLocation.kind === ts.SyntaxKind.TypeParameter + ? lastLocation === (location as FunctionLikeDeclaration).type || + lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.JSDocParameterTag || + lastLocation.kind === SyntaxKind.JSDocReturnTag || + lastLocation.kind === SyntaxKind.TypeParameter // local types not visible outside the function body : false; } - if (meaning & result.flags & ts.SymbolFlags.Variable) { + if (meaning & result.flags & SymbolFlags.Variable) { // expression inside parameter will lookup as normal variable scope when targeting es2015+ if (useOuterVariableScopeInParameter(result, location, lastLocation)) { useResult = false; } - else if (result.flags & ts.SymbolFlags.FunctionScopedVariable) { + else if (result.flags & SymbolFlags.FunctionScopedVariable) { // parameters are visible only inside function body, parameter list and return type // technically for parameter list case here we might mix parameters and variables declared in function, // however it is detected separately when checking initializers of parameters // to make sure that they reference no variables declared after them. useResult = - lastLocation.kind === ts.SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.Parameter || ( - lastLocation === (location as ts.FunctionLikeDeclaration).type && - !!ts.findAncestor(result.valueDeclaration, ts.isParameter) + lastLocation === (location as FunctionLikeDeclaration).type && + !!findAncestor(result.valueDeclaration, isParameter) ); } } } - else if (location.kind === ts.SyntaxKind.ConditionalType) { + else if (location.kind === SyntaxKind.ConditionalType) { // A type parameter declared using 'infer T' in a conditional type is visible only in // the true branch of the conditional type. - useResult = lastLocation === (location as ts.ConditionalTypeNode).trueType; + useResult = lastLocation === (location as ConditionalTypeNode).trueType; } if (useResult) { @@ -1942,18 +2140,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation); switch (location.kind) { - case ts.SyntaxKind.SourceFile: - if (!ts.isExternalOrCommonJsModule(location as ts.SourceFile)) break; + case SyntaxKind.SourceFile: + if (!isExternalOrCommonJsModule(location as SourceFile)) break; isInExternalModule = true; // falls through - case ts.SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfNode(location as ts.SourceFile | ts.ModuleDeclaration)?.exports || emptySymbols; - if (location.kind === ts.SyntaxKind.SourceFile || (ts.isModuleDeclaration(location) && location.flags & ts.NodeFlags.Ambient && !ts.isGlobalScopeAugmentation(location))) { + case SyntaxKind.ModuleDeclaration: + const moduleExports = getSymbolOfNode(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols; + if (location.kind === SyntaxKind.SourceFile || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient && !isGlobalScopeAugmentation(location))) { // It's an external module. First see if the module has an export default and if the local // name of that export default matches. - if (result = moduleExports.get(ts.InternalSymbolName.Default)) { - const localSymbol = ts.getLocalSymbolForExportDefault(result); + if (result = moduleExports.get(InternalSymbolName.Default)) { + const localSymbol = getLocalSymbolForExportDefault(result); if (localSymbol && (result.flags & meaning) && localSymbol.escapedName === name) { break loop; } @@ -1973,15 +2171,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // which is not the desired behavior. const moduleExport = moduleExports.get(name); if (moduleExport && - moduleExport.flags === ts.SymbolFlags.Alias && - (ts.getDeclarationOfKind(moduleExport, ts.SyntaxKind.ExportSpecifier) || ts.getDeclarationOfKind(moduleExport, ts.SyntaxKind.NamespaceExport))) { + moduleExport.flags === SymbolFlags.Alias && + (getDeclarationOfKind(moduleExport, SyntaxKind.ExportSpecifier) || getDeclarationOfKind(moduleExport, SyntaxKind.NamespaceExport))) { break; } } // ES6 exports are also visible locally (except for 'default'), but commonjs exports are not (except typedefs) - if (name !== ts.InternalSymbolName.Default && (result = lookup(moduleExports, name, meaning & ts.SymbolFlags.ModuleMember))) { - if (ts.isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations?.some(ts.isJSDocTypeAlias)) { + if (name !== InternalSymbolName.Default && (result = lookup(moduleExports, name, meaning & SymbolFlags.ModuleMember))) { + if (isSourceFile(location) && location.commonJsModuleIndicator && !result.declarations?.some(isJSDocTypeAlias)) { result = undefined; } else { @@ -1989,67 +2187,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } break; - case ts.SyntaxKind.EnumDeclaration: - if (result = lookup(getSymbolOfNode(location)?.exports || emptySymbols, name, meaning & ts.SymbolFlags.EnumMember)) { + case SyntaxKind.EnumDeclaration: + if (result = lookup(getSymbolOfNode(location)?.exports || emptySymbols, name, meaning & SymbolFlags.EnumMember)) { break loop; } break; - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyDeclaration: // TypeScript 1.0 spec (April 2014): 8.4.1 // Initializer expressions for instance member variables are evaluated in the scope // of the class constructor body but are not permitted to reference parameters or // local variables of the constructor. This effectively means that entities from outer scopes // by the same name as a constructor parameter or local variable are inaccessible // in initializer expressions for instance member variables. - if (!ts.isStatic(location)) { - const ctor = findConstructorDeclaration(location.parent as ts.ClassLikeDeclaration); + if (!isStatic(location)) { + const ctor = findConstructorDeclaration(location.parent as ClassLikeDeclaration); if (ctor && ctor.locals) { - if (lookup(ctor.locals, name, meaning & ts.SymbolFlags.Value)) { + if (lookup(ctor.locals, name, meaning & SymbolFlags.Value)) { // Remember the property node, it will be used later to report appropriate error - ts.Debug.assertNode(location, ts.isPropertyDeclaration); + Debug.assertNode(location, isPropertyDeclaration); propertyWithInvalidInitializer = location; } } } break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would // trigger resolving late-bound names, which we may already be in the process of doing while we're here! - if (result = lookup(getSymbolOfNode(location as ts.ClassLikeDeclaration | ts.InterfaceDeclaration).members || emptySymbols, name, meaning & ts.SymbolFlags.Type)) { + if (result = lookup(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; break; } - if (lastLocation && ts.isStatic(lastLocation)) { + if (lastLocation && isStatic(lastLocation)) { // TypeScript 1.0 spec (April 2014): 3.4.1 // The scope of a type parameter extends over the entire declaration with which the type // parameter list is associated, with the exception of static member declarations in classes. if (nameNotFoundMessage) { - error(errorLocation, ts.Diagnostics.Static_members_cannot_reference_class_type_parameters); + error(errorLocation, Diagnostics.Static_members_cannot_reference_class_type_parameters); } return undefined; } break loop; } - if (location.kind === ts.SyntaxKind.ClassExpression && meaning & ts.SymbolFlags.Class) { - const className = (location as ts.ClassExpression).name; + if (location.kind === SyntaxKind.ClassExpression && meaning & SymbolFlags.Class) { + const className = (location as ClassExpression).name; if (className && name === className.escapedText) { result = location.symbol; break loop; } } break; - case ts.SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.ExpressionWithTypeArguments: // The type parameters of a class are not in scope in the base class expression. - if (lastLocation === (location as ts.ExpressionWithTypeArguments).expression && (location.parent as ts.HeritageClause).token === ts.SyntaxKind.ExtendsKeyword) { + if (lastLocation === (location as ExpressionWithTypeArguments).expression && (location.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword) { const container = location.parent.parent; - if (ts.isClassLike(container) && (result = lookup(getSymbolOfNode(container).members!, name, meaning & ts.SymbolFlags.Type))) { + if (isClassLike(container) && (result = lookup(getSymbolOfNode(container).members!, name, meaning & SymbolFlags.Type))) { if (nameNotFoundMessage) { - error(errorLocation, ts.Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); + error(errorLocation, Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); } return undefined; } @@ -2063,50 +2261,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // [foo()]() { } // <-- Reference to T from class's own computed property // } // - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.ComputedPropertyName: grandparent = location.parent.parent; - if (ts.isClassLike(grandparent) || grandparent.kind === ts.SyntaxKind.InterfaceDeclaration) { + if (isClassLike(grandparent) || grandparent.kind === SyntaxKind.InterfaceDeclaration) { // A reference to this grandparent's type parameters would be an error - if (result = lookup(getSymbolOfNode(grandparent as ts.ClassLikeDeclaration | ts.InterfaceDeclaration).members!, name, meaning & ts.SymbolFlags.Type)) { + if (result = lookup(getSymbolOfNode(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) { if (nameNotFoundMessage) { - error(errorLocation, ts.Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); + error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); } return undefined; } } break; - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ArrowFunction: // when targeting ES6 or higher there is no 'arguments' in an arrow function // for lower compile targets the resolved symbol is used to emit an error - if (ts.getEmitScriptTarget(compilerOptions) >= ts.ScriptTarget.ES2015) { + if (getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015) { break; } // falls through - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionDeclaration: - if (meaning & ts.SymbolFlags.Variable && name === "arguments") { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionDeclaration: + if (meaning & SymbolFlags.Variable && name === "arguments") { result = argumentsSymbol; break loop; } break; - case ts.SyntaxKind.FunctionExpression: - if (meaning & ts.SymbolFlags.Variable && name === "arguments") { + case SyntaxKind.FunctionExpression: + if (meaning & SymbolFlags.Variable && name === "arguments") { result = argumentsSymbol; break loop; } - if (meaning & ts.SymbolFlags.Function) { - const functionName = (location as ts.FunctionExpression).name; + if (meaning & SymbolFlags.Function) { + const functionName = (location as FunctionExpression).name; if (functionName && name === functionName.escapedText) { result = location.symbol; break loop; } } break; - case ts.SyntaxKind.Decorator: + case SyntaxKind.Decorator: // Decorators are resolved at the class declaration. Resolving at the parameter // or member would result in looking up locals in the method. // @@ -2115,7 +2313,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter. // } // - if (location.parent && location.parent.kind === ts.SyntaxKind.Parameter) { + if (location.parent && location.parent.kind === SyntaxKind.Parameter) { location = location.parent; } // @@ -2131,42 +2329,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // declare function y(x: T): any; // @param(1 as T) // <-- T should resolve to the type alias outside of class C // class C {} - if (location.parent && (ts.isClassElement(location.parent) || location.parent.kind === ts.SyntaxKind.ClassDeclaration)) { + if (location.parent && (isClassElement(location.parent) || location.parent.kind === SyntaxKind.ClassDeclaration)) { location = location.parent; } break; - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: // js type aliases do not resolve names from their host, so skip past it - const root = ts.getJSDocRoot(location); + const root = getJSDocRoot(location); if (root) { location = root.parent; } break; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: if (lastLocation && ( - lastLocation === (location as ts.ParameterDeclaration).initializer || - lastLocation === (location as ts.ParameterDeclaration).name && ts.isBindingPattern(lastLocation))) { + lastLocation === (location as ParameterDeclaration).initializer || + lastLocation === (location as ParameterDeclaration).name && isBindingPattern(lastLocation))) { if (!associatedDeclarationForContainingInitializerOrBindingName) { - associatedDeclarationForContainingInitializerOrBindingName = location as ts.ParameterDeclaration; + associatedDeclarationForContainingInitializerOrBindingName = location as ParameterDeclaration; } } break; - case ts.SyntaxKind.BindingElement: + case SyntaxKind.BindingElement: if (lastLocation && ( - lastLocation === (location as ts.BindingElement).initializer || - lastLocation === (location as ts.BindingElement).name && ts.isBindingPattern(lastLocation))) { - if (ts.isParameterDeclaration(location as ts.BindingElement) && !associatedDeclarationForContainingInitializerOrBindingName) { - associatedDeclarationForContainingInitializerOrBindingName = location as ts.BindingElement; + lastLocation === (location as BindingElement).initializer || + lastLocation === (location as BindingElement).name && isBindingPattern(lastLocation))) { + if (isParameterDeclaration(location as BindingElement) && !associatedDeclarationForContainingInitializerOrBindingName) { + associatedDeclarationForContainingInitializerOrBindingName = location as BindingElement; } } break; - case ts.SyntaxKind.InferType: - if (meaning & ts.SymbolFlags.TypeParameter) { - const parameterName = (location as ts.InferTypeNode).typeParameter.name; + case SyntaxKind.InferType: + if (meaning & SymbolFlags.TypeParameter) { + const parameterName = (location as InferTypeNode).typeParameter.name; if (parameterName && name === parameterName.escapedText) { - result = (location as ts.InferTypeNode).typeParameter.symbol; + result = (location as InferTypeNode).typeParameter.symbol; break loop; } } @@ -2176,8 +2374,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { lastSelfReferenceLocation = location; } lastLocation = location; - location = ts.isJSDocTemplateTag(location) ? ts.getEffectiveContainerForJSDocTemplateTag(location) || location.parent : - ts.isJSDocParameterTag(location) || ts.isJSDocReturnTag(location) ? ts.getHostSignatureFromJSDoc(location) || location.parent : + location = isJSDocTemplateTag(location) ? getEffectiveContainerForJSDocTemplateTag(location) || location.parent : + isJSDocParameterTag(location) || isJSDocReturnTag(location) ? getHostSignatureFromJSDoc(location) || location.parent : location.parent; } @@ -2190,8 +2388,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!result) { if (lastLocation) { - ts.Debug.assert(lastLocation.kind === ts.SyntaxKind.SourceFile); - if ((lastLocation as ts.SourceFile).commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) { + Debug.assert(lastLocation.kind === SyntaxKind.SourceFile); + if ((lastLocation as SourceFile).commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) { return lastLocation.symbol; } } @@ -2201,8 +2399,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (!result) { - if (originalLocation && ts.isInJSFile(originalLocation) && originalLocation.parent) { - if (ts.isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) { + if (originalLocation && isInJSFile(originalLocation) && originalLocation.parent) { + if (isRequireCall(originalLocation.parent, /*checkArgumentIsStringLiteralLike*/ false)) { return requireSymbol; } } @@ -2212,15 +2410,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // 1. When result is undefined, after checking for a missing "this." // 2. When result is defined function checkAndReportErrorForInvalidInitializer() { - if (propertyWithInvalidInitializer && !(useDefineForClassFields && ts.getEmitScriptTarget(compilerOptions) >= ts.ScriptTarget.ES2022)) { + if (propertyWithInvalidInitializer && !(useDefineForClassFields && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022)) { // We have a match, but the reference occurred within a property initializer and the identifier also binds // to a local variable in the constructor where the code will be emitted. Note that this is actually allowed // with ESNext+useDefineForClassFields because the scope semantics are different. error(errorLocation, - errorLocation && propertyWithInvalidInitializer.type && ts.textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos) - ? ts.Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor - : ts.Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, - ts.declarationNameToString(propertyWithInvalidInitializer.name), diagnosticName(nameArg!)); + errorLocation && propertyWithInvalidInitializer.type && textRangeContainsPositionInclusive(propertyWithInvalidInitializer.type, errorLocation.pos) + ? Diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor + : Diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, + declarationNameToString(propertyWithInvalidInitializer.name), diagnosticName(nameArg!)); return true; } return false; @@ -2238,7 +2436,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingTypeAsValue(errorLocation, name, meaning) && !checkAndReportErrorForUsingValueAsType(errorLocation, name, meaning)) { - let suggestion: ts.Symbol | undefined; + let suggestion: Symbol | undefined; let suggestedLib: string | undefined; // Report missing lib first if (nameArg) { @@ -2250,22 +2448,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // then spelling suggestions if (!suggestedLib && getSpellingSuggestions && suggestionCount < maximumSuggestionCount) { suggestion = getSuggestedSymbolForNonexistentSymbol(originalLocation, name, meaning); - const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration && ts.isAmbientModule(suggestion.valueDeclaration) && ts.isGlobalScopeAugmentation(suggestion.valueDeclaration); + const isGlobalScopeAugmentationDeclaration = suggestion?.valueDeclaration && isAmbientModule(suggestion.valueDeclaration) && isGlobalScopeAugmentation(suggestion.valueDeclaration); if (isGlobalScopeAugmentationDeclaration) { suggestion = undefined; } if (suggestion) { const suggestionName = symbolToString(suggestion); const isUncheckedJS = isUncheckedJSSuggestion(originalLocation, suggestion, /*excludeClasses*/ false); - const message = meaning === ts.SymbolFlags.Namespace || nameArg && typeof nameArg !== "string" && ts.nodeIsSynthesized(nameArg) ? ts.Diagnostics.Cannot_find_namespace_0_Did_you_mean_1 - : isUncheckedJS ? ts.Diagnostics.Could_not_find_name_0_Did_you_mean_1 - : ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1; + const message = meaning === SymbolFlags.Namespace || nameArg && typeof nameArg !== "string" && nodeIsSynthesized(nameArg) ? Diagnostics.Cannot_find_namespace_0_Did_you_mean_1 + : isUncheckedJS ? Diagnostics.Could_not_find_name_0_Did_you_mean_1 + : Diagnostics.Cannot_find_name_0_Did_you_mean_1; const diagnostic = createError(errorLocation, message, diagnosticName(nameArg!), suggestionName); addErrorOrSuggestion(!isUncheckedJS, diagnostic); if (suggestion.valueDeclaration) { - ts.addRelatedInfo( + addRelatedInfo( diagnostic, - ts.createDiagnosticForNode(suggestion.valueDeclaration, ts.Diagnostics._0_is_declared_here, suggestionName) + createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName) ); } } @@ -2299,42 +2497,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // try to resolve name in /*1*/ which is used in variable position, // we want to check for block-scoped if (errorLocation && - (meaning & ts.SymbolFlags.BlockScopedVariable || - ((meaning & ts.SymbolFlags.Class || meaning & ts.SymbolFlags.Enum) && (meaning & ts.SymbolFlags.Value) === ts.SymbolFlags.Value))) { + (meaning & SymbolFlags.BlockScopedVariable || + ((meaning & SymbolFlags.Class || meaning & SymbolFlags.Enum) && (meaning & SymbolFlags.Value) === SymbolFlags.Value))) { const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result!); - if (exportOrLocalSymbol.flags & ts.SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & ts.SymbolFlags.Class || exportOrLocalSymbol.flags & ts.SymbolFlags.Enum) { + if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class || exportOrLocalSymbol.flags & SymbolFlags.Enum) { checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation); } } // If we're in an external module, we can't reference value symbols created from UMD export declarations - if (result && isInExternalModule && (meaning & ts.SymbolFlags.Value) === ts.SymbolFlags.Value && !(originalLocation!.flags & ts.NodeFlags.JSDoc)) { + if (result && isInExternalModule && (meaning & SymbolFlags.Value) === SymbolFlags.Value && !(originalLocation!.flags & NodeFlags.JSDoc)) { const merged = getMergedSymbol(result); - if (ts.length(merged.declarations) && ts.every(merged.declarations, d => ts.isNamespaceExportDeclaration(d) || ts.isSourceFile(d) && !!d.symbol.globalExports)) { - errorOrSuggestion(!compilerOptions.allowUmdGlobalAccess, errorLocation!, ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, ts.unescapeLeadingUnderscores(name)); + if (length(merged.declarations) && every(merged.declarations, d => isNamespaceExportDeclaration(d) || isSourceFile(d) && !!d.symbol.globalExports)) { + errorOrSuggestion(!compilerOptions.allowUmdGlobalAccess, errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name)); } } // If we're in a parameter initializer or binding name, we can't reference the values of the parameter whose initializer we're within or parameters to the right - if (result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext && (meaning & ts.SymbolFlags.Value) === ts.SymbolFlags.Value) { + if (result && associatedDeclarationForContainingInitializerOrBindingName && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) { const candidate = getMergedSymbol(getLateBoundSymbol(result)); - const root = (ts.getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ts.ParameterDeclaration); + const root = (getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ParameterDeclaration); // A parameter initializer or binding pattern initializer within a parameter cannot refer to itself if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializerOrBindingName)) { - error(errorLocation, ts.Diagnostics.Parameter_0_cannot_reference_itself, ts.declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name)); + error(errorLocation, Diagnostics.Parameter_0_cannot_reference_itself, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name)); } // And it cannot refer to any declarations which come after it else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializerOrBindingName.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) { - error(errorLocation, ts.Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, ts.declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), ts.declarationNameToString(errorLocation as ts.Identifier)); + error(errorLocation, Diagnostics.Parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name), declarationNameToString(errorLocation as Identifier)); } } - if (result && errorLocation && meaning & ts.SymbolFlags.Value && result.flags & ts.SymbolFlags.Alias && !(result.flags & ts.SymbolFlags.Value) && !ts.isValidTypeOnlyAliasUseSite(errorLocation)) { - const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, ts.SymbolFlags.Value); + if (result && errorLocation && meaning & SymbolFlags.Value && result.flags & SymbolFlags.Alias && !(result.flags & SymbolFlags.Value) && !isValidTypeOnlyAliasUseSite(errorLocation)) { + const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(result, SymbolFlags.Value); if (typeOnlyDeclaration) { - const message = typeOnlyDeclaration.kind === ts.SyntaxKind.ExportSpecifier - ? ts.Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type - : ts.Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type; - const unescapedName = ts.unescapeLeadingUnderscores(name); + const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier + ? Diagnostics._0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type + : Diagnostics._0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type; + const unescapedName = unescapeLeadingUnderscores(name); addTypeOnlyDeclarationRelatedInfo( error(errorLocation, message, unescapedName), typeOnlyDeclaration, @@ -2346,59 +2544,59 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function addTypeOnlyDeclarationRelatedInfo(diagnostic: ts.Diagnostic, typeOnlyDeclaration: ts.TypeOnlyCompatibleAliasDeclaration | undefined, unescapedName: string) { + function addTypeOnlyDeclarationRelatedInfo(diagnostic: Diagnostic, typeOnlyDeclaration: TypeOnlyCompatibleAliasDeclaration | undefined, unescapedName: string) { if (!typeOnlyDeclaration) return diagnostic; - return ts.addRelatedInfo( + return addRelatedInfo( diagnostic, - ts.createDiagnosticForNode( + createDiagnosticForNode( typeOnlyDeclaration, - typeOnlyDeclaration.kind === ts.SyntaxKind.ExportSpecifier ? ts.Diagnostics._0_was_exported_here : ts.Diagnostics._0_was_imported_here, + typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier ? Diagnostics._0_was_exported_here : Diagnostics._0_was_imported_here, unescapedName)); } - function getIsDeferredContext(location: ts.Node, lastLocation: ts.Node | undefined): boolean { - if (location.kind !== ts.SyntaxKind.ArrowFunction && location.kind !== ts.SyntaxKind.FunctionExpression) { + function getIsDeferredContext(location: Node, lastLocation: Node | undefined): boolean { + if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) { // initializers in instance property declaration of class like entities are executed in constructor and thus deferred - return ts.isTypeQueryNode(location) || (( - ts.isFunctionLikeDeclaration(location) || - (location.kind === ts.SyntaxKind.PropertyDeclaration && !ts.isStatic(location)) - ) && (!lastLocation || lastLocation !== (location as ts.SignatureDeclaration | ts.PropertyDeclaration).name)); // A name is evaluated within the enclosing scope - so it shouldn't count as deferred + return isTypeQueryNode(location) || (( + isFunctionLikeDeclaration(location) || + (location.kind === SyntaxKind.PropertyDeclaration && !isStatic(location)) + ) && (!lastLocation || lastLocation !== (location as SignatureDeclaration | PropertyDeclaration).name)); // A name is evaluated within the enclosing scope - so it shouldn't count as deferred } - if (lastLocation && lastLocation === (location as ts.FunctionExpression | ts.ArrowFunction).name) { + if (lastLocation && lastLocation === (location as FunctionExpression | ArrowFunction).name) { return false; } // generator functions and async functions are not inlined in control flow when immediately invoked - if ((location as ts.FunctionExpression | ts.ArrowFunction).asteriskToken || ts.hasSyntacticModifier(location, ts.ModifierFlags.Async)) { + if ((location as FunctionExpression | ArrowFunction).asteriskToken || hasSyntacticModifier(location, ModifierFlags.Async)) { return true; } - return !ts.getImmediatelyInvokedFunctionExpression(location); + return !getImmediatelyInvokedFunctionExpression(location); } - function isSelfReferenceLocation(node: ts.Node): boolean { + function isSelfReferenceLocation(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ModuleDeclaration: // For `namespace N { N; }` + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ModuleDeclaration: // For `namespace N { N; }` return true; default: return false; } } - function diagnosticName(nameArg: ts.__String | ts.Identifier | ts.PrivateIdentifier) { - return ts.isString(nameArg) ? ts.unescapeLeadingUnderscores(nameArg as ts.__String) : ts.declarationNameToString(nameArg as ts.Identifier); + function diagnosticName(nameArg: __String | Identifier | PrivateIdentifier) { + return isString(nameArg) ? unescapeLeadingUnderscores(nameArg as __String) : declarationNameToString(nameArg as Identifier); } - function isTypeParameterSymbolDeclaredInContainer(symbol: ts.Symbol, container: ts.Node) { + function isTypeParameterSymbolDeclaredInContainer(symbol: Symbol, container: Node) { if (symbol.declarations) { for (const decl of symbol.declarations) { - if (decl.kind === ts.SyntaxKind.TypeParameter) { - const parent = ts.isJSDocTemplateTag(decl.parent) ? ts.getJSDocHost(decl.parent) : decl.parent; + if (decl.kind === SyntaxKind.TypeParameter) { + const parent = isJSDocTemplateTag(decl.parent) ? getJSDocHost(decl.parent) : decl.parent; if (parent === container) { - return !(ts.isJSDocTemplateTag(decl.parent) && ts.find((decl.parent.parent as ts.JSDoc).tags, ts.isJSDocTypeAlias)); + return !(isJSDocTemplateTag(decl.parent) && find((decl.parent.parent as JSDoc).tags, isJSDocTypeAlias)); } } } @@ -2407,15 +2605,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkAndReportErrorForMissingPrefix(errorLocation: ts.Node, name: ts.__String, nameArg: ts.__String | ts.Identifier): boolean { - if (!ts.isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) { + function checkAndReportErrorForMissingPrefix(errorLocation: Node, name: __String, nameArg: __String | Identifier): boolean { + if (!isIdentifier(errorLocation) || errorLocation.escapedText !== name || isTypeReferenceIdentifier(errorLocation) || isInTypeQuery(errorLocation)) { return false; } - const container = ts.getThisContainer(errorLocation, /*includeArrowFunctions*/ false); + const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ false); let location = container; while (location) { - if (ts.isClassLike(location.parent)) { + if (isClassLike(location.parent)) { const classSymbol = getSymbolOfNode(location.parent); if (!classSymbol) { break; @@ -2424,16 +2622,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Check to see if a static member exists. const constructorType = getTypeOfSymbol(classSymbol); if (getPropertyOfType(constructorType, name)) { - error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, diagnosticName(nameArg), symbolToString(classSymbol)); return true; } // No static member is present. // Check if we're in an instance method and look for a relevant instance member. - if (location === container && !ts.isStatic(location)) { - const instanceType = (getDeclaredTypeOfSymbol(classSymbol) as ts.InterfaceType).thisType!; // TODO: GH#18217 + if (location === container && !isStatic(location)) { + const instanceType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType!; // TODO: GH#18217 if (getPropertyOfType(instanceType, name)) { - error(errorLocation, ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); + error(errorLocation, Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, diagnosticName(nameArg)); return true; } } @@ -2445,10 +2643,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } - function checkAndReportErrorForExtendingInterface(errorLocation: ts.Node): boolean { + function checkAndReportErrorForExtendingInterface(errorLocation: Node): boolean { const expression = getEntityNameForExtendingInterface(errorLocation); - if (expression && resolveEntityName(expression, ts.SymbolFlags.Interface, /*ignoreErrors*/ true)) { - error(errorLocation, ts.Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, ts.getTextOfNode(expression)); + if (expression && resolveEntityName(expression, SymbolFlags.Interface, /*ignoreErrors*/ true)) { + error(errorLocation, Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements, getTextOfNode(expression)); return true; } return false; @@ -2457,14 +2655,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Climbs up parents to an ExpressionWithTypeArguments, and returns its expression, * but returns undefined if that expression is not an EntityNameExpression. */ - function getEntityNameForExtendingInterface(node: ts.Node): ts.EntityNameExpression | undefined { + function getEntityNameForExtendingInterface(node: Node): EntityNameExpression | undefined { switch (node.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: return node.parent ? getEntityNameForExtendingInterface(node.parent) : undefined; - case ts.SyntaxKind.ExpressionWithTypeArguments: - if (ts.isEntityNameExpression((node as ts.ExpressionWithTypeArguments).expression)) { - return (node as ts.ExpressionWithTypeArguments).expression as ts.EntityNameExpression; + case SyntaxKind.ExpressionWithTypeArguments: + if (isEntityNameExpression((node as ExpressionWithTypeArguments).expression)) { + return (node as ExpressionWithTypeArguments).expression as EntityNameExpression; } // falls through default: @@ -2472,27 +2670,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: ts.Node, name: ts.__String, meaning: ts.SymbolFlags): boolean { - const namespaceMeaning = ts.SymbolFlags.Namespace | (ts.isInJSFile(errorLocation) ? ts.SymbolFlags.Value : 0); + function checkAndReportErrorForUsingTypeAsNamespace(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(errorLocation) ? SymbolFlags.Value : 0); if (meaning === namespaceMeaning) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ts.SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~namespaceMeaning, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); const parent = errorLocation.parent; if (symbol) { - if (ts.isQualifiedName(parent)) { - ts.Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace"); + if (isQualifiedName(parent)) { + Debug.assert(parent.left === errorLocation, "Should only be resolving left side of qualified name as a namespace"); const propName = parent.right.escapedText; const propType = getPropertyOfType(getDeclaredTypeOfSymbol(symbol), propName); if (propType) { error( parent, - ts.Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, - ts.unescapeLeadingUnderscores(name), - ts.unescapeLeadingUnderscores(propName), + Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, + unescapeLeadingUnderscores(name), + unescapeLeadingUnderscores(propName), ); return true; } } - error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, ts.unescapeLeadingUnderscores(name)); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, unescapeLeadingUnderscores(name)); return true; } } @@ -2500,52 +2698,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkAndReportErrorForUsingValueAsType(errorLocation: ts.Node, name: ts.__String, meaning: ts.SymbolFlags): boolean { - if (meaning & (ts.SymbolFlags.Type & ~ts.SymbolFlags.Namespace)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ~ts.SymbolFlags.Type & ts.SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); - if (symbol && !(symbol.flags & ts.SymbolFlags.Namespace)) { - error(errorLocation, ts.Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, ts.unescapeLeadingUnderscores(name)); + function checkAndReportErrorForUsingValueAsType(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Type & ~SymbolFlags.Namespace)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, ~SymbolFlags.Type & SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + if (symbol && !(symbol.flags & SymbolFlags.Namespace)) { + error(errorLocation, Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, unescapeLeadingUnderscores(name)); return true; } } return false; } - function isPrimitiveTypeName(name: ts.__String) { + function isPrimitiveTypeName(name: __String) { return name === "any" || name === "string" || name === "number" || name === "boolean" || name === "never" || name === "unknown"; } - function checkAndReportErrorForExportingPrimitiveType(errorLocation: ts.Node, name: ts.__String): boolean { - if (isPrimitiveTypeName(name) && errorLocation.parent.kind === ts.SyntaxKind.ExportSpecifier) { - error(errorLocation, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name as string); + function checkAndReportErrorForExportingPrimitiveType(errorLocation: Node, name: __String): boolean { + if (isPrimitiveTypeName(name) && errorLocation.parent.kind === SyntaxKind.ExportSpecifier) { + error(errorLocation, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name as string); return true; } return false; } - function checkAndReportErrorForUsingTypeAsValue(errorLocation: ts.Node, name: ts.__String, meaning: ts.SymbolFlags): boolean { - if (meaning & ts.SymbolFlags.Value) { + function checkAndReportErrorForUsingTypeAsValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & SymbolFlags.Value) { if (isPrimitiveTypeName(name)) { if (isExtendedByInterface(errorLocation)) { - error(errorLocation, ts.Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, ts.unescapeLeadingUnderscores(name)); + error(errorLocation, Diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_an_interface_can_only_extend_named_types_and_classes, unescapeLeadingUnderscores(name)); } else { - error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, ts.unescapeLeadingUnderscores(name)); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, unescapeLeadingUnderscores(name)); } return true; } - const symbol = resolveSymbol(resolveName(errorLocation, name, ts.SymbolFlags.Type & ~ts.SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); const allFlags = symbol && getAllSymbolFlags(symbol); - if (symbol && allFlags !== undefined && !(allFlags & ts.SymbolFlags.Value)) { - const rawName = ts.unescapeLeadingUnderscores(name); + if (symbol && allFlags !== undefined && !(allFlags & SymbolFlags.Value)) { + const rawName = unescapeLeadingUnderscores(name); if (isES2015OrLaterConstructorName(name)) { - error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName); } else if (maybeMappedType(errorLocation, symbol)) { - error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, rawName, rawName === "K" ? "P" : "K"); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, rawName, rawName === "K" ? "P" : "K"); } else { - error(errorLocation, ts.Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, rawName); + error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, rawName); } return true; } @@ -2553,28 +2751,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isExtendedByInterface(node: ts.Node): boolean { + function isExtendedByInterface(node: Node): boolean { const grandparent = node.parent.parent; const parentOfGrandparent = grandparent.parent; if(grandparent && parentOfGrandparent){ - const isExtending = ts.isHeritageClause(grandparent) && grandparent.token === ts.SyntaxKind.ExtendsKeyword; - const isInterface = ts.isInterfaceDeclaration(parentOfGrandparent); + const isExtending = isHeritageClause(grandparent) && grandparent.token === SyntaxKind.ExtendsKeyword; + const isInterface = isInterfaceDeclaration(parentOfGrandparent); return isExtending && isInterface; } return false; } - function maybeMappedType(node: ts.Node, symbol: ts.Symbol) { - const container = ts.findAncestor(node.parent, n => - ts.isComputedPropertyName(n) || ts.isPropertySignature(n) ? false : ts.isTypeLiteralNode(n) || "quit") as ts.TypeLiteralNode | undefined; + function maybeMappedType(node: Node, symbol: Symbol) { + const container = findAncestor(node.parent, n => + isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined; if (container && container.members.length === 1) { const type = getDeclaredTypeOfSymbol(symbol); - return !!(type.flags & ts.TypeFlags.Union) && allTypesAssignableToKind(type, ts.TypeFlags.StringOrNumberLiteral, /*strict*/ true); + return !!(type.flags & TypeFlags.Union) && allTypesAssignableToKind(type, TypeFlags.StringOrNumberLiteral, /*strict*/ true); } return false; } - function isES2015OrLaterConstructorName(n: ts.__String) { + function isES2015OrLaterConstructorName(n: __String) { switch (n) { case "Promise": case "Symbol": @@ -2587,61 +2785,61 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation: ts.Node, name: ts.__String, meaning: ts.SymbolFlags): boolean { - if (meaning & (ts.SymbolFlags.Value & ~ts.SymbolFlags.Type)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ts.SymbolFlags.NamespaceModule, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + function checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation: Node, name: __String, meaning: SymbolFlags): boolean { + if (meaning & (SymbolFlags.Value & ~SymbolFlags.Type)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.NamespaceModule, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { error( errorLocation, - ts.Diagnostics.Cannot_use_namespace_0_as_a_value, - ts.unescapeLeadingUnderscores(name)); + Diagnostics.Cannot_use_namespace_0_as_a_value, + unescapeLeadingUnderscores(name)); return true; } } - else if (meaning & (ts.SymbolFlags.Type & ~ts.SymbolFlags.Value)) { - const symbol = resolveSymbol(resolveName(errorLocation, name, ts.SymbolFlags.Module, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); + else if (meaning & (SymbolFlags.Type & ~SymbolFlags.Value)) { + const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Module, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false)); if (symbol) { - error(errorLocation, ts.Diagnostics.Cannot_use_namespace_0_as_a_type, ts.unescapeLeadingUnderscores(name)); + error(errorLocation, Diagnostics.Cannot_use_namespace_0_as_a_type, unescapeLeadingUnderscores(name)); return true; } } return false; } - function checkResolvedBlockScopedVariable(result: ts.Symbol, errorLocation: ts.Node): void { - ts.Debug.assert(!!(result.flags & ts.SymbolFlags.BlockScopedVariable || result.flags & ts.SymbolFlags.Class || result.flags & ts.SymbolFlags.Enum)); - if (result.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.FunctionScopedVariable | ts.SymbolFlags.Assignment) && result.flags & ts.SymbolFlags.Class) { + function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void { + Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class || result.flags & SymbolFlags.Enum)); + if (result.flags & (SymbolFlags.Function | SymbolFlags.FunctionScopedVariable | SymbolFlags.Assignment) && result.flags & SymbolFlags.Class) { // constructor functions aren't block scoped return; } // Block-scoped variables cannot be used before their definition const declaration = result.declarations?.find( - d => ts.isBlockOrCatchScoped(d) || ts.isClassLike(d) || (d.kind === ts.SyntaxKind.EnumDeclaration)); + d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration)); - if (declaration === undefined) return ts.Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration"); + if (declaration === undefined) return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration"); - if (!(declaration.flags & ts.NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { + if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) { let diagnosticMessage; - const declarationName = ts.declarationNameToString(ts.getNameOfDeclaration(declaration)); - if (result.flags & ts.SymbolFlags.BlockScopedVariable) { - diagnosticMessage = error(errorLocation, ts.Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName); + const declarationName = declarationNameToString(getNameOfDeclaration(declaration)); + if (result.flags & SymbolFlags.BlockScopedVariable) { + diagnosticMessage = error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationName); } - else if (result.flags & ts.SymbolFlags.Class) { - diagnosticMessage = error(errorLocation, ts.Diagnostics.Class_0_used_before_its_declaration, declarationName); + else if (result.flags & SymbolFlags.Class) { + diagnosticMessage = error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationName); } - else if (result.flags & ts.SymbolFlags.RegularEnum) { - diagnosticMessage = error(errorLocation, ts.Diagnostics.Enum_0_used_before_its_declaration, declarationName); + else if (result.flags & SymbolFlags.RegularEnum) { + diagnosticMessage = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName); } else { - ts.Debug.assert(!!(result.flags & ts.SymbolFlags.ConstEnum)); - if (ts.shouldPreserveConstEnums(compilerOptions)) { - diagnosticMessage = error(errorLocation, ts.Diagnostics.Enum_0_used_before_its_declaration, declarationName); + Debug.assert(!!(result.flags & SymbolFlags.ConstEnum)); + if (shouldPreserveConstEnums(compilerOptions)) { + diagnosticMessage = error(errorLocation, Diagnostics.Enum_0_used_before_its_declaration, declarationName); } } if (diagnosticMessage) { - ts.addRelatedInfo(diagnosticMessage, - ts.createDiagnosticForNode(declaration, ts.Diagnostics._0_is_declared_here, declarationName) + addRelatedInfo(diagnosticMessage, + createDiagnosticForNode(declaration, Diagnostics._0_is_declared_here, declarationName) ); } } @@ -2652,28 +2850,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * If current node is an IIFE, continue walking up. * Return false if 'stopAt' node is reached or isFunctionLike(current) === true. */ - function isSameScopeDescendentOf(initial: ts.Node, parent: ts.Node | undefined, stopAt: ts.Node): boolean { - return !!parent && !!ts.findAncestor(initial, n => n === parent - || (n === stopAt || ts.isFunctionLike(n) && (!ts.getImmediatelyInvokedFunctionExpression(n) || ts.isAsyncFunction(n)) ? "quit" : false)); + function isSameScopeDescendentOf(initial: Node, parent: Node | undefined, stopAt: Node): boolean { + return !!parent && !!findAncestor(initial, n => n === parent + || (n === stopAt || isFunctionLike(n) && (!getImmediatelyInvokedFunctionExpression(n) || isAsyncFunction(n)) ? "quit" : false)); } - function getAnyImportSyntax(node: ts.Node): ts.AnyImportSyntax | undefined { + function getAnyImportSyntax(node: Node): AnyImportSyntax | undefined { switch (node.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: - return node as ts.ImportEqualsDeclaration; - case ts.SyntaxKind.ImportClause: - return (node as ts.ImportClause).parent; - case ts.SyntaxKind.NamespaceImport: - return (node as ts.NamespaceImport).parent.parent; - case ts.SyntaxKind.ImportSpecifier: - return (node as ts.ImportSpecifier).parent.parent.parent; + case SyntaxKind.ImportEqualsDeclaration: + return node as ImportEqualsDeclaration; + case SyntaxKind.ImportClause: + return (node as ImportClause).parent; + case SyntaxKind.NamespaceImport: + return (node as NamespaceImport).parent.parent; + case SyntaxKind.ImportSpecifier: + return (node as ImportSpecifier).parent.parent.parent; default: return undefined; } } - function getDeclarationOfAliasSymbol(symbol: ts.Symbol): ts.Declaration | undefined { - return symbol.declarations && ts.findLast(symbol.declarations, isAliasSymbolDeclaration); + function getDeclarationOfAliasSymbol(symbol: Symbol): Declaration | undefined { + return symbol.declarations && findLast(symbol.declarations, isAliasSymbolDeclaration); } /** @@ -2691,43 +2889,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * {name: } * const { x } = require ... */ - function isAliasSymbolDeclaration(node: ts.Node): boolean { - return node.kind === ts.SyntaxKind.ImportEqualsDeclaration - || node.kind === ts.SyntaxKind.NamespaceExportDeclaration - || node.kind === ts.SyntaxKind.ImportClause && !!(node as ts.ImportClause).name - || node.kind === ts.SyntaxKind.NamespaceImport - || node.kind === ts.SyntaxKind.NamespaceExport - || node.kind === ts.SyntaxKind.ImportSpecifier - || node.kind === ts.SyntaxKind.ExportSpecifier - || node.kind === ts.SyntaxKind.ExportAssignment && ts.exportAssignmentIsAlias(node as ts.ExportAssignment) - || ts.isBinaryExpression(node) && ts.getAssignmentDeclarationKind(node) === ts.AssignmentDeclarationKind.ModuleExports && ts.exportAssignmentIsAlias(node) - || ts.isAccessExpression(node) - && ts.isBinaryExpression(node.parent) + function isAliasSymbolDeclaration(node: Node): boolean { + return node.kind === SyntaxKind.ImportEqualsDeclaration + || node.kind === SyntaxKind.NamespaceExportDeclaration + || node.kind === SyntaxKind.ImportClause && !!(node as ImportClause).name + || node.kind === SyntaxKind.NamespaceImport + || node.kind === SyntaxKind.NamespaceExport + || node.kind === SyntaxKind.ImportSpecifier + || node.kind === SyntaxKind.ExportSpecifier + || node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(node as ExportAssignment) + || isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.ModuleExports && exportAssignmentIsAlias(node) + || isAccessExpression(node) + && isBinaryExpression(node.parent) && node.parent.left === node - && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken + && node.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAliasableOrJsExpression(node.parent.right) - || node.kind === ts.SyntaxKind.ShorthandPropertyAssignment - || node.kind === ts.SyntaxKind.PropertyAssignment && isAliasableOrJsExpression((node as ts.PropertyAssignment).initializer) - || node.kind === ts.SyntaxKind.VariableDeclaration && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(node) - || node.kind === ts.SyntaxKind.BindingElement && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent); + || node.kind === SyntaxKind.ShorthandPropertyAssignment + || node.kind === SyntaxKind.PropertyAssignment && isAliasableOrJsExpression((node as PropertyAssignment).initializer) + || node.kind === SyntaxKind.VariableDeclaration && isVariableDeclarationInitializedToBareOrAccessedRequire(node) + || node.kind === SyntaxKind.BindingElement && isVariableDeclarationInitializedToBareOrAccessedRequire(node.parent.parent); } - function isAliasableOrJsExpression(e: ts.Expression) { - return ts.isAliasableExpression(e) || ts.isFunctionExpression(e) && isJSConstructor(e); + function isAliasableOrJsExpression(e: Expression) { + return isAliasableExpression(e) || isFunctionExpression(e) && isJSConstructor(e); } - function getTargetOfImportEqualsDeclaration(node: ts.ImportEqualsDeclaration | ts.VariableDeclaration, dontResolveAlias: boolean): ts.Symbol | undefined { + function getTargetOfImportEqualsDeclaration(node: ImportEqualsDeclaration | VariableDeclaration, dontResolveAlias: boolean): Symbol | undefined { const commonJSPropertyAccess = getCommonJSPropertyAccess(node); if (commonJSPropertyAccess) { - const name = (ts.getLeftmostAccessExpression(commonJSPropertyAccess.expression) as ts.CallExpression).arguments[0] as ts.StringLiteral; - return ts.isIdentifier(commonJSPropertyAccess.name) + const name = (getLeftmostAccessExpression(commonJSPropertyAccess.expression) as CallExpression).arguments[0] as StringLiteral; + return isIdentifier(commonJSPropertyAccess.name) ? resolveSymbol(getPropertyOfType(resolveExternalModuleTypeByLiteral(name), commonJSPropertyAccess.name.escapedText)) : undefined; } - if (ts.isVariableDeclaration(node) || node.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + if (isVariableDeclaration(node) || node.moduleReference.kind === SyntaxKind.ExternalModuleReference) { const immediate = resolveExternalModuleName( node, - ts.getExternalModuleRequireArgument(node) || ts.getExternalModuleImportEqualsDeclarationExpression(node)); + getExternalModuleRequireArgument(node) || getExternalModuleImportEqualsDeclarationExpression(node)); const resolved = resolveExternalModuleSymbol(immediate); markSymbolOfAliasDeclarationIfTypeOnly(node, immediate, resolved, /*overwriteEmpty*/ false); return resolved; @@ -2737,52 +2935,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolved; } - function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ts.ImportEqualsDeclaration, resolved: ts.Symbol | undefined) { + function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) { if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfNode(node))!; - const isExport = typeOnlyDeclaration.kind === ts.SyntaxKind.ExportSpecifier; + const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier; const message = isExport - ? ts.Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type - : ts.Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type; + ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type + : Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_imported_using_import_type; const relatedMessage = isExport - ? ts.Diagnostics._0_was_exported_here - : ts.Diagnostics._0_was_imported_here; + ? Diagnostics._0_was_exported_here + : Diagnostics._0_was_imported_here; - const name = ts.unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); - ts.addRelatedInfo(error(node.moduleReference, message), ts.createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)); + const name = unescapeLeadingUnderscores(typeOnlyDeclaration.name.escapedText); + addRelatedInfo(error(node.moduleReference, message), createDiagnosticForNode(typeOnlyDeclaration, relatedMessage, name)); } } - function resolveExportByName(moduleSymbol: ts.Symbol, name: ts.__String, sourceNode: ts.TypeOnlyCompatibleAliasDeclaration | undefined, dontResolveAlias: boolean) { - const exportValue = moduleSymbol.exports!.get(ts.InternalSymbolName.ExportEquals); + function resolveExportByName(moduleSymbol: Symbol, name: __String, sourceNode: TypeOnlyCompatibleAliasDeclaration | undefined, dontResolveAlias: boolean) { + const exportValue = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); const exportSymbol = exportValue ? getPropertyOfType(getTypeOfSymbol(exportValue), name) : moduleSymbol.exports!.get(name); const resolved = resolveSymbol(exportSymbol, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(sourceNode, exportSymbol, resolved, /*overwriteEmpty*/ false); return resolved; } - function isSyntacticDefault(node: ts.Node) { - return ((ts.isExportAssignment(node) && !node.isExportEquals) || ts.hasSyntacticModifier(node, ts.ModifierFlags.Default) || ts.isExportSpecifier(node)); + function isSyntacticDefault(node: Node) { + return ((isExportAssignment(node) && !node.isExportEquals) || hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node)); } - function getUsageModeForExpression(usage: ts.Expression) { - return ts.isStringLiteralLike(usage) ? ts.getModeForUsageLocation(ts.getSourceFileOfNode(usage), usage) : undefined; + function getUsageModeForExpression(usage: Expression) { + return isStringLiteralLike(usage) ? getModeForUsageLocation(getSourceFileOfNode(usage), usage) : undefined; } - function isESMFormatImportImportingCommonjsFormatFile(usageMode: ts.SourceFile["impliedNodeFormat"], targetMode: ts.SourceFile["impliedNodeFormat"]) { - return usageMode === ts.ModuleKind.ESNext && targetMode === ts.ModuleKind.CommonJS; + function isESMFormatImportImportingCommonjsFormatFile(usageMode: SourceFile["impliedNodeFormat"], targetMode: SourceFile["impliedNodeFormat"]) { + return usageMode === ModuleKind.ESNext && targetMode === ModuleKind.CommonJS; } - function isOnlyImportedAsDefault(usage: ts.Expression) { + function isOnlyImportedAsDefault(usage: Expression) { const usageMode = getUsageModeForExpression(usage); - return usageMode === ts.ModuleKind.ESNext && ts.endsWith((usage as ts.StringLiteralLike).text, ts.Extension.Json); + return usageMode === ModuleKind.ESNext && endsWith((usage as StringLiteralLike).text, Extension.Json); } - function canHaveSyntheticDefault(file: ts.SourceFile | undefined, moduleSymbol: ts.Symbol, dontResolveAlias: boolean, usage: ts.Expression) { + function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean, usage: Expression) { const usageMode = file && getUsageModeForExpression(usage); if (file && usageMode !== undefined) { const result = isESMFormatImportImportingCommonjsFormatFile(usageMode, file.impliedNodeFormat); - if (usageMode === ts.ModuleKind.ESNext || result) { + if (usageMode === ModuleKind.ESNext || result) { return result; } // fallthrough on cjs usages so we imply defaults for interop'd imports, too @@ -2793,13 +2991,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Declaration files (and ambient modules) if (!file || file.isDeclarationFile) { // Definitely cannot have a synthetic default if they have a syntactic default member specified - const defaultExportSymbol = resolveExportByName(moduleSymbol, ts.InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration - if (defaultExportSymbol && ts.some(defaultExportSymbol.declarations, isSyntacticDefault)) { + const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, /*sourceNode*/ undefined, /*dontResolveAlias*/ true); // Dont resolve alias because we want the immediately exported symbol's declaration + if (defaultExportSymbol && some(defaultExportSymbol.declarations, isSyntacticDefault)) { return false; } // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member // So we check a bit more, - if (resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias)) { + if (resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias)) { // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code), // it definitely is a module and does not have a synthetic default return false; @@ -2810,30 +3008,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } // TypeScript files never have a synthetic default (as they are always emitted with an __esModule marker) _unless_ they contain an export= statement - if (!ts.isSourceFileJS(file)) { + if (!isSourceFileJS(file)) { return hasExportAssignmentSymbol(moduleSymbol); } // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker - return typeof file.externalModuleIndicator !== "object" && !resolveExportByName(moduleSymbol, ts.escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); + return typeof file.externalModuleIndicator !== "object" && !resolveExportByName(moduleSymbol, escapeLeadingUnderscores("__esModule"), /*sourceNode*/ undefined, dontResolveAlias); } - function getTargetOfImportClause(node: ts.ImportClause, dontResolveAlias: boolean): ts.Symbol | undefined { + function getTargetOfImportClause(node: ImportClause, dontResolveAlias: boolean): Symbol | undefined { const moduleSymbol = resolveExternalModuleName(node, node.parent.moduleSpecifier); if (moduleSymbol) { return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias); } } - function getTargetofModuleDefault(moduleSymbol: ts.Symbol, node: ts.ImportClause | ts.ImportOrExportSpecifier, dontResolveAlias: boolean) { - let exportDefaultSymbol: ts.Symbol | undefined; - if (ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + function getTargetofModuleDefault(moduleSymbol: Symbol, node: ImportClause | ImportOrExportSpecifier, dontResolveAlias: boolean) { + let exportDefaultSymbol: Symbol | undefined; + if (isShorthandAmbientModuleSymbol(moduleSymbol)) { exportDefaultSymbol = moduleSymbol; } else { - exportDefaultSymbol = resolveExportByName(moduleSymbol, ts.InternalSymbolName.Default, node, dontResolveAlias); + exportDefaultSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, node, dontResolveAlias); } - const file = moduleSymbol.declarations?.find(ts.isSourceFile); + const file = moduleSymbol.declarations?.find(isSourceFile); const specifier = getModuleSpecifierForImportOrExport(node); if (!specifier) { return exportDefaultSymbol; @@ -2842,24 +3040,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const hasSyntheticDefault = canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, specifier); if (!exportDefaultSymbol && !hasSyntheticDefault && !hasDefaultOnly) { if (hasExportAssignmentSymbol(moduleSymbol)) { - const compilerOptionName = moduleKind >= ts.ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; - const exportEqualsSymbol = moduleSymbol.exports!.get(ts.InternalSymbolName.ExportEquals); + const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; + const exportEqualsSymbol = moduleSymbol.exports!.get(InternalSymbolName.ExportEquals); const exportAssignment = exportEqualsSymbol!.valueDeclaration; - const err = error(node.name, ts.Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName); + const err = error(node.name, Diagnostics.Module_0_can_only_be_default_imported_using_the_1_flag, symbolToString(moduleSymbol), compilerOptionName); if (exportAssignment) { - ts.addRelatedInfo(err, ts.createDiagnosticForNode( + addRelatedInfo(err, createDiagnosticForNode( exportAssignment, - ts.Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, + Diagnostics.This_module_is_declared_with_export_and_can_only_be_used_with_a_default_import_when_using_the_0_flag, compilerOptionName )); } } - else if (ts.isImportClause(node)) { + else if (isImportClause(node)) { reportNonDefaultExport(moduleSymbol, node); } else { - errorNoModuleMemberSymbol(moduleSymbol, moduleSymbol, node, ts.isImportOrExportSpecifier(node) && node.propertyName || node.name); + errorNoModuleMemberSymbol(moduleSymbol, moduleSymbol, node, isImportOrExportSpecifier(node) && node.propertyName || node.name); } } else if (hasSyntheticDefault || hasDefaultOnly) { @@ -2872,42 +3070,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return exportDefaultSymbol; } - function getModuleSpecifierForImportOrExport(node: ts.ImportEqualsDeclaration | ts.ImportClause | ts.NamespaceImport | ts.ImportOrExportSpecifier): ts.Expression | undefined { + function getModuleSpecifierForImportOrExport(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportOrExportSpecifier): Expression | undefined { switch (node.kind) { - case ts.SyntaxKind.ImportClause: return node.parent.moduleSpecifier; - case ts.SyntaxKind.ImportEqualsDeclaration: return ts.isExternalModuleReference(node.moduleReference) ? node.moduleReference.expression : undefined; - case ts.SyntaxKind.NamespaceImport: return node.parent.parent.moduleSpecifier; - case ts.SyntaxKind.ImportSpecifier: return node.parent.parent.parent.moduleSpecifier; - case ts.SyntaxKind.ExportSpecifier: return node.parent.parent.moduleSpecifier; - default: return ts.Debug.assertNever(node); + case SyntaxKind.ImportClause: return node.parent.moduleSpecifier; + case SyntaxKind.ImportEqualsDeclaration: return isExternalModuleReference(node.moduleReference) ? node.moduleReference.expression : undefined; + case SyntaxKind.NamespaceImport: return node.parent.parent.moduleSpecifier; + case SyntaxKind.ImportSpecifier: return node.parent.parent.parent.moduleSpecifier; + case SyntaxKind.ExportSpecifier: return node.parent.parent.moduleSpecifier; + default: return Debug.assertNever(node); } } - function reportNonDefaultExport(moduleSymbol: ts.Symbol, node: ts.ImportClause) { + function reportNonDefaultExport(moduleSymbol: Symbol, node: ImportClause) { if (moduleSymbol.exports?.has(node.symbol.escapedName)) { error( node.name, - ts.Diagnostics.Module_0_has_no_default_export_Did_you_mean_to_use_import_1_from_0_instead, + Diagnostics.Module_0_has_no_default_export_Did_you_mean_to_use_import_1_from_0_instead, symbolToString(moduleSymbol), symbolToString(node.symbol), ); } else { - const diagnostic = error(node.name, ts.Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); - const exportStar = moduleSymbol.exports?.get(ts.InternalSymbolName.ExportStar); + const diagnostic = error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol)); + const exportStar = moduleSymbol.exports?.get(InternalSymbolName.ExportStar); if (exportStar) { const defaultExport = exportStar.declarations?.find(decl => !!( - ts.isExportDeclaration(decl) && decl.moduleSpecifier && - resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has(ts.InternalSymbolName.Default) + isExportDeclaration(decl) && decl.moduleSpecifier && + resolveExternalModuleName(decl, decl.moduleSpecifier)?.exports?.has(InternalSymbolName.Default) )); if (defaultExport) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(defaultExport, ts.Diagnostics.export_Asterisk_does_not_re_export_a_default)); + addRelatedInfo(diagnostic, createDiagnosticForNode(defaultExport, Diagnostics.export_Asterisk_does_not_re_export_a_default)); } } } } - function getTargetOfNamespaceImport(node: ts.NamespaceImport, dontResolveAlias: boolean): ts.Symbol | undefined { + function getTargetOfNamespaceImport(node: NamespaceImport, dontResolveAlias: boolean): Symbol | undefined { const moduleSpecifier = node.parent.parent.moduleSpecifier; const immediate = resolveExternalModuleName(node, moduleSpecifier); const resolved = resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false); @@ -2915,7 +3113,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolved; } - function getTargetOfNamespaceExport(node: ts.NamespaceExport, dontResolveAlias: boolean): ts.Symbol | undefined { + function getTargetOfNamespaceExport(node: NamespaceExport, dontResolveAlias: boolean): Symbol | undefined { const moduleSpecifier = node.parent.moduleSpecifier; const immediate = moduleSpecifier && resolveExternalModuleName(node, moduleSpecifier); const resolved = moduleSpecifier && resolveESModuleSymbol(immediate, moduleSpecifier, dontResolveAlias, /*suppressUsageError*/ false); @@ -2941,24 +3139,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // // An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point' // property with the type/namespace side interface 'Point'. - function combineValueAndTypeSymbols(valueSymbol: ts.Symbol, typeSymbol: ts.Symbol): ts.Symbol { + function combineValueAndTypeSymbols(valueSymbol: Symbol, typeSymbol: Symbol): Symbol { if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) { return unknownSymbol; } - if (valueSymbol.flags & (ts.SymbolFlags.Type | ts.SymbolFlags.Namespace)) { + if (valueSymbol.flags & (SymbolFlags.Type | SymbolFlags.Namespace)) { return valueSymbol; } const result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); - result.declarations = ts.deduplicate(ts.concatenate(valueSymbol.declarations, typeSymbol.declarations), ts.equateValues); + result.declarations = deduplicate(concatenate(valueSymbol.declarations, typeSymbol.declarations), equateValues); result.parent = valueSymbol.parent || typeSymbol.parent; if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration; - if (typeSymbol.members) result.members = new ts.Map(typeSymbol.members); - if (valueSymbol.exports) result.exports = new ts.Map(valueSymbol.exports); + if (typeSymbol.members) result.members = new Map(typeSymbol.members); + if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports); return result; } - function getExportOfModule(symbol: ts.Symbol, name: ts.Identifier, specifier: ts.Declaration, dontResolveAlias: boolean): ts.Symbol | undefined { - if (symbol.flags & ts.SymbolFlags.Module) { + function getExportOfModule(symbol: Symbol, name: Identifier, specifier: Declaration, dontResolveAlias: boolean): Symbol | undefined { + if (symbol.flags & SymbolFlags.Module) { const exportSymbol = getExportsOfSymbol(symbol).get(name.escapedText); const resolved = resolveSymbol(exportSymbol, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(specifier, exportSymbol, resolved, /*overwriteEmpty*/ false); @@ -2966,33 +3164,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getPropertyOfVariable(symbol: ts.Symbol, name: ts.__String): ts.Symbol | undefined { - if (symbol.flags & ts.SymbolFlags.Variable) { - const typeAnnotation = (symbol.valueDeclaration as ts.VariableDeclaration).type; + function getPropertyOfVariable(symbol: Symbol, name: __String): Symbol | undefined { + if (symbol.flags & SymbolFlags.Variable) { + const typeAnnotation = (symbol.valueDeclaration as VariableDeclaration).type; if (typeAnnotation) { return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); } } } - function getExternalModuleMember(node: ts.ImportDeclaration | ts.ExportDeclaration | ts.VariableDeclaration, specifier: ts.ImportOrExportSpecifier | ts.BindingElement | ts.PropertyAccessExpression, dontResolveAlias = false): ts.Symbol | undefined { - const moduleSpecifier = ts.getExternalModuleRequireArgument(node) || (node as ts.ImportDeclaration | ts.ExportDeclaration).moduleSpecifier!; + function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration | VariableDeclaration, specifier: ImportOrExportSpecifier | BindingElement | PropertyAccessExpression, dontResolveAlias = false): Symbol | undefined { + const moduleSpecifier = getExternalModuleRequireArgument(node) || (node as ImportDeclaration | ExportDeclaration).moduleSpecifier!; const moduleSymbol = resolveExternalModuleName(node, moduleSpecifier)!; // TODO: GH#18217 - const name = !ts.isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name; - if (!ts.isIdentifier(name)) { + const name = !isPropertyAccessExpression(specifier) && specifier.propertyName || specifier.name; + if (!isIdentifier(name)) { return undefined; } - const suppressInteropError = name.escapedText === ts.InternalSymbolName.Default && !!(compilerOptions.allowSyntheticDefaultImports || ts.getESModuleInterop(compilerOptions)); + const suppressInteropError = name.escapedText === InternalSymbolName.Default && !!(compilerOptions.allowSyntheticDefaultImports || getESModuleInterop(compilerOptions)); const targetSymbol = resolveESModuleSymbol(moduleSymbol, moduleSpecifier, /*dontResolveAlias*/ false, suppressInteropError); if (targetSymbol) { if (name.escapedText) { - if (ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + if (isShorthandAmbientModuleSymbol(moduleSymbol)) { return moduleSymbol; } - let symbolFromVariable: ts.Symbol | undefined; + let symbolFromVariable: Symbol | undefined; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(ts.InternalSymbolName.ExportEquals)) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText, /*skipObjectFunctionPropertyAugment*/ true); } else { @@ -3002,8 +3200,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { symbolFromVariable = resolveSymbol(symbolFromVariable, dontResolveAlias); let symbolFromModule = getExportOfModule(targetSymbol, name, specifier, dontResolveAlias); - if (symbolFromModule === undefined && name.escapedText === ts.InternalSymbolName.Default) { - const file = moduleSymbol.declarations?.find(ts.isSourceFile); + if (symbolFromModule === undefined && name.escapedText === InternalSymbolName.Default) { + const file = moduleSymbol.declarations?.find(isSourceFile); if (isOnlyImportedAsDefault(moduleSpecifier) || canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier)) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } @@ -3020,24 +3218,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function errorNoModuleMemberSymbol(moduleSymbol: ts.Symbol, targetSymbol: ts.Symbol, node: ts.Node, name: ts.Identifier) { + function errorNoModuleMemberSymbol(moduleSymbol: Symbol, targetSymbol: Symbol, node: Node, name: Identifier) { const moduleName = getFullyQualifiedName(moduleSymbol, node); - const declarationName = ts.declarationNameToString(name); + const declarationName = declarationNameToString(name); const suggestion = getSuggestedSymbolForNonexistentModule(name, targetSymbol); if (suggestion !== undefined) { const suggestionName = symbolToString(suggestion); - const diagnostic = error(name, ts.Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName); + const diagnostic = error(name, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, moduleName, declarationName, suggestionName); if (suggestion.valueDeclaration) { - ts.addRelatedInfo(diagnostic, - ts.createDiagnosticForNode(suggestion.valueDeclaration, ts.Diagnostics._0_is_declared_here, suggestionName) + addRelatedInfo(diagnostic, + createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestionName) ); } } else { - if (moduleSymbol.exports?.has(ts.InternalSymbolName.Default)) { + if (moduleSymbol.exports?.has(InternalSymbolName.Default)) { error( name, - ts.Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_to_use_import_1_from_0_instead, + Diagnostics.Module_0_has_no_exported_member_1_Did_you_mean_to_use_import_1_from_0_instead, moduleName, declarationName ); @@ -3048,84 +3246,84 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function reportNonExportedMember(node: ts.Node, name: ts.Identifier, declarationName: string, moduleSymbol: ts.Symbol, moduleName: string): void { + function reportNonExportedMember(node: Node, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void { const localSymbol = moduleSymbol.valueDeclaration?.locals?.get(name.escapedText); const exports = moduleSymbol.exports; if (localSymbol) { - const exportedEqualsSymbol = exports?.get(ts.InternalSymbolName.ExportEquals); + const exportedEqualsSymbol = exports?.get(InternalSymbolName.ExportEquals); if (exportedEqualsSymbol) { getSymbolIfSameReference(exportedEqualsSymbol, localSymbol) ? reportInvalidImportEqualsExportMember(node, name, declarationName, moduleName) : - error(name, ts.Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); + error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); } else { - const exportedSymbol = exports ? ts.find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol)) : undefined; - const diagnostic = exportedSymbol ? error(name, ts.Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol)) : - error(name, ts.Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName); + const exportedSymbol = exports ? find(symbolsToArray(exports), symbol => !!getSymbolIfSameReference(symbol, localSymbol)) : undefined; + const diagnostic = exportedSymbol ? error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_exported_as_2, moduleName, declarationName, symbolToString(exportedSymbol)) : + error(name, Diagnostics.Module_0_declares_1_locally_but_it_is_not_exported, moduleName, declarationName); if (localSymbol.declarations) { - ts.addRelatedInfo(diagnostic, - ...ts.map(localSymbol.declarations, (decl, index) => - ts.createDiagnosticForNode(decl, index === 0 ? ts.Diagnostics._0_is_declared_here : ts.Diagnostics.and_here, declarationName))); + addRelatedInfo(diagnostic, + ...map(localSymbol.declarations, (decl, index) => + createDiagnosticForNode(decl, index === 0 ? Diagnostics._0_is_declared_here : Diagnostics.and_here, declarationName))); } } } else { - error(name, ts.Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); + error(name, Diagnostics.Module_0_has_no_exported_member_1, moduleName, declarationName); } } - function reportInvalidImportEqualsExportMember(node: ts.Node, name: ts.Identifier, declarationName: string, moduleName: string) { - if (moduleKind >= ts.ModuleKind.ES2015) { - const message = ts.getESModuleInterop(compilerOptions) ? ts.Diagnostics._0_can_only_be_imported_by_using_a_default_import : - ts.Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + function reportInvalidImportEqualsExportMember(node: Node, name: Identifier, declarationName: string, moduleName: string) { + if (moduleKind >= ModuleKind.ES2015) { + const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_default_import : + Diagnostics._0_can_only_be_imported_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName); } else { - if (ts.isInJSFile(node)) { - const message = ts.getESModuleInterop(compilerOptions) ? ts.Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import : - ts.Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + if (isInJSFile(node)) { + const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_using_a_default_import : + Diagnostics._0_can_only_be_imported_by_using_a_require_call_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName); } else { - const message = ts.getESModuleInterop(compilerOptions) ? ts.Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import : - ts.Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; + const message = getESModuleInterop(compilerOptions) ? Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_a_default_import : + Diagnostics._0_can_only_be_imported_by_using_import_1_require_2_or_by_turning_on_the_esModuleInterop_flag_and_using_a_default_import; error(name, message, declarationName, declarationName, moduleName); } } } - function getTargetOfImportSpecifier(node: ts.ImportSpecifier | ts.BindingElement, dontResolveAlias: boolean): ts.Symbol | undefined { - if (ts.isImportSpecifier(node) && ts.idText(node.propertyName || node.name) === ts.InternalSymbolName.Default) { + function getTargetOfImportSpecifier(node: ImportSpecifier | BindingElement, dontResolveAlias: boolean): Symbol | undefined { + if (isImportSpecifier(node) && idText(node.propertyName || node.name) === InternalSymbolName.Default) { const specifier = getModuleSpecifierForImportOrExport(node); const moduleSymbol = specifier && resolveExternalModuleName(node, specifier); if (moduleSymbol) { return getTargetofModuleDefault(moduleSymbol, node, dontResolveAlias); } } - const root = ts.isBindingElement(node) ? ts.getRootDeclaration(node) as ts.VariableDeclaration : node.parent.parent.parent; + const root = isBindingElement(node) ? getRootDeclaration(node) as VariableDeclaration : node.parent.parent.parent; const commonJSPropertyAccess = getCommonJSPropertyAccess(root); const resolved = getExternalModuleMember(root, commonJSPropertyAccess || node, dontResolveAlias); const name = node.propertyName || node.name; - if (commonJSPropertyAccess && resolved && ts.isIdentifier(name)) { + if (commonJSPropertyAccess && resolved && isIdentifier(name)) { return resolveSymbol(getPropertyOfType(getTypeOfSymbol(resolved), name.escapedText), dontResolveAlias); } markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); return resolved; } - function getCommonJSPropertyAccess(node: ts.Node) { - if (ts.isVariableDeclaration(node) && node.initializer && ts.isPropertyAccessExpression(node.initializer)) { + function getCommonJSPropertyAccess(node: Node) { + if (isVariableDeclaration(node) && node.initializer && isPropertyAccessExpression(node.initializer)) { return node.initializer; } } - function getTargetOfNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration, dontResolveAlias: boolean): ts.Symbol { + function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol { const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); return resolved; } - function getTargetOfExportSpecifier(node: ts.ExportSpecifier, meaning: ts.SymbolFlags, dontResolveAlias?: boolean) { - if (ts.idText(node.propertyName || node.name) === ts.InternalSymbolName.Default) { + function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) { + if (idText(node.propertyName || node.name) === InternalSymbolName.Default) { const specifier = getModuleSpecifierForImportOrExport(node); const moduleSymbol = specifier && resolveExternalModuleName(node, specifier); if (moduleSymbol) { @@ -3139,21 +3337,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolved; } - function getTargetOfExportAssignment(node: ts.ExportAssignment | ts.BinaryExpression, dontResolveAlias: boolean): ts.Symbol | undefined { - const expression = ts.isExportAssignment(node) ? node.expression : node.right; + function getTargetOfExportAssignment(node: ExportAssignment | BinaryExpression, dontResolveAlias: boolean): Symbol | undefined { + const expression = isExportAssignment(node) ? node.expression : node.right; const resolved = getTargetOfAliasLikeExpression(expression, dontResolveAlias); markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); return resolved; } - function getTargetOfAliasLikeExpression(expression: ts.Expression, dontResolveAlias: boolean) { - if (ts.isClassExpression(expression)) { + function getTargetOfAliasLikeExpression(expression: Expression, dontResolveAlias: boolean) { + if (isClassExpression(expression)) { return checkExpressionCached(expression).symbol; } - if (!ts.isEntityName(expression) && !ts.isEntityNameExpression(expression)) { + if (!isEntityName(expression) && !isEntityNameExpression(expression)) { return undefined; } - const aliasLike = resolveEntityName(expression, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias); + const aliasLike = resolveEntityName(expression, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontResolveAlias); if (aliasLike) { return aliasLike; } @@ -3161,44 +3359,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getNodeLinks(expression).resolvedSymbol; } - function getTargetOfAccessExpression(node: ts.AccessExpression, dontRecursivelyResolve: boolean): ts.Symbol | undefined { - if (!(ts.isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken)) { + function getTargetOfAccessExpression(node: AccessExpression, dontRecursivelyResolve: boolean): Symbol | undefined { + if (!(isBinaryExpression(node.parent) && node.parent.left === node && node.parent.operatorToken.kind === SyntaxKind.EqualsToken)) { return undefined; } return getTargetOfAliasLikeExpression(node.parent.right, dontRecursivelyResolve); } - function getTargetOfAliasDeclaration(node: ts.Declaration, dontRecursivelyResolve = false): ts.Symbol | undefined { + function getTargetOfAliasDeclaration(node: Declaration, dontRecursivelyResolve = false): Symbol | undefined { switch (node.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.VariableDeclaration: - return getTargetOfImportEqualsDeclaration(node as ts.ImportEqualsDeclaration | ts.VariableDeclaration, dontRecursivelyResolve); - case ts.SyntaxKind.ImportClause: - return getTargetOfImportClause(node as ts.ImportClause, dontRecursivelyResolve); - case ts.SyntaxKind.NamespaceImport: - return getTargetOfNamespaceImport(node as ts.NamespaceImport, dontRecursivelyResolve); - case ts.SyntaxKind.NamespaceExport: - return getTargetOfNamespaceExport(node as ts.NamespaceExport, dontRecursivelyResolve); - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.BindingElement: - return getTargetOfImportSpecifier(node as ts.ImportSpecifier | ts.BindingElement, dontRecursivelyResolve); - case ts.SyntaxKind.ExportSpecifier: - return getTargetOfExportSpecifier(node as ts.ExportSpecifier, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, dontRecursivelyResolve); - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.BinaryExpression: - return getTargetOfExportAssignment((node as ts.ExportAssignment | ts.BinaryExpression), dontRecursivelyResolve); - case ts.SyntaxKind.NamespaceExportDeclaration: - return getTargetOfNamespaceExportDeclaration(node as ts.NamespaceExportDeclaration, dontRecursivelyResolve); - case ts.SyntaxKind.ShorthandPropertyAssignment: - return resolveEntityName((node as ts.ShorthandPropertyAssignment).name, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, /*ignoreErrors*/ true, dontRecursivelyResolve); - case ts.SyntaxKind.PropertyAssignment: - return getTargetOfAliasLikeExpression((node as ts.PropertyAssignment).initializer, dontRecursivelyResolve); - case ts.SyntaxKind.ElementAccessExpression: - case ts.SyntaxKind.PropertyAccessExpression: - return getTargetOfAccessExpression(node as ts.AccessExpression, dontRecursivelyResolve); + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.VariableDeclaration: + return getTargetOfImportEqualsDeclaration(node as ImportEqualsDeclaration | VariableDeclaration, dontRecursivelyResolve); + case SyntaxKind.ImportClause: + return getTargetOfImportClause(node as ImportClause, dontRecursivelyResolve); + case SyntaxKind.NamespaceImport: + return getTargetOfNamespaceImport(node as NamespaceImport, dontRecursivelyResolve); + case SyntaxKind.NamespaceExport: + return getTargetOfNamespaceExport(node as NamespaceExport, dontRecursivelyResolve); + case SyntaxKind.ImportSpecifier: + case SyntaxKind.BindingElement: + return getTargetOfImportSpecifier(node as ImportSpecifier | BindingElement, dontRecursivelyResolve); + case SyntaxKind.ExportSpecifier: + return getTargetOfExportSpecifier(node as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, dontRecursivelyResolve); + case SyntaxKind.ExportAssignment: + case SyntaxKind.BinaryExpression: + return getTargetOfExportAssignment((node as ExportAssignment | BinaryExpression), dontRecursivelyResolve); + case SyntaxKind.NamespaceExportDeclaration: + return getTargetOfNamespaceExportDeclaration(node as NamespaceExportDeclaration, dontRecursivelyResolve); + case SyntaxKind.ShorthandPropertyAssignment: + return resolveEntityName((node as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ true, dontRecursivelyResolve); + case SyntaxKind.PropertyAssignment: + return getTargetOfAliasLikeExpression((node as PropertyAssignment).initializer, dontRecursivelyResolve); + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + return getTargetOfAccessExpression(node as AccessExpression, dontRecursivelyResolve); default: - return ts.Debug.fail(); + return Debug.fail(); } } @@ -3206,30 +3404,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Indicates that a symbol is an alias that does not merge with a local declaration. * OR Is a JSContainer which may merge an alias with a local declaration */ - function isNonLocalAlias(symbol: ts.Symbol | undefined, excludes = ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace): symbol is ts.Symbol { + function isNonLocalAlias(symbol: Symbol | undefined, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace): symbol is Symbol { if (!symbol) return false; - return (symbol.flags & (ts.SymbolFlags.Alias | excludes)) === ts.SymbolFlags.Alias || !!(symbol.flags & ts.SymbolFlags.Alias && symbol.flags & ts.SymbolFlags.Assignment); + return (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias || !!(symbol.flags & SymbolFlags.Alias && symbol.flags & SymbolFlags.Assignment); } - function resolveSymbol(symbol: ts.Symbol, dontResolveAlias?: boolean): ts.Symbol; - function resolveSymbol(symbol: ts.Symbol | undefined, dontResolveAlias?: boolean): ts.Symbol | undefined; - function resolveSymbol(symbol: ts.Symbol | undefined, dontResolveAlias?: boolean): ts.Symbol | undefined { + function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol; + function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; + function resolveSymbol(symbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined { return !dontResolveAlias && isNonLocalAlias(symbol) ? resolveAlias(symbol) : symbol; } - function resolveAlias(symbol: ts.Symbol): ts.Symbol { - ts.Debug.assert((symbol.flags & ts.SymbolFlags.Alias) !== 0, "Should only get Alias here."); + function resolveAlias(symbol: Symbol): Symbol { + Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here."); const links = getSymbolLinks(symbol); if (!links.aliasTarget) { links.aliasTarget = resolvingSymbol; const node = getDeclarationOfAliasSymbol(symbol); - if (!node) return ts.Debug.fail(); + if (!node) return Debug.fail(); const target = getTargetOfAliasDeclaration(node); if (links.aliasTarget === resolvingSymbol) { links.aliasTarget = target || unknownSymbol; } else { - error(node, ts.Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol)); + error(node, Diagnostics.Circular_definition_of_import_alias_0, symbolToString(symbol)); } } else if (links.aliasTarget === resolvingSymbol) { @@ -3238,7 +3436,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.aliasTarget; } - function tryResolveAlias(symbol: ts.Symbol): ts.Symbol | undefined { + function tryResolveAlias(symbol: Symbol): Symbol | undefined { const links = getSymbolLinks(symbol); if (links.aliasTarget !== resolvingSymbol) { return resolveAlias(symbol); @@ -3267,13 +3465,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @returns SymbolFlags.All if `symbol` is an alias that ultimately resolves to `unknown`; * combined flags of all alias targets otherwise. */ - function getAllSymbolFlags(symbol: ts.Symbol): ts.SymbolFlags { + function getAllSymbolFlags(symbol: Symbol): SymbolFlags { let flags = symbol.flags; let seenSymbols; - while (symbol.flags & ts.SymbolFlags.Alias) { + while (symbol.flags & SymbolFlags.Alias) { const target = resolveAlias(symbol); if (target === unknownSymbol) { - return ts.SymbolFlags.All; + return SymbolFlags.All; } // Optimizations - try to avoid creating or adding to @@ -3281,12 +3479,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (target === symbol || seenSymbols?.has(target)) { break; } - if (target.flags & ts.SymbolFlags.Alias) { + if (target.flags & SymbolFlags.Alias) { if (seenSymbols) { seenSymbols.add(target); } else { - seenSymbols = new ts.Set([symbol, target]); + seenSymbols = new Set([symbol, target]); } } flags |= target.flags; @@ -3316,17 +3514,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * must still be checked for a type-only marker, overwriting the previous negative result if found. */ function markSymbolOfAliasDeclarationIfTypeOnly( - aliasDeclaration: ts.Declaration | undefined, - immediateTarget: ts.Symbol | undefined, - finalTarget: ts.Symbol | undefined, + aliasDeclaration: Declaration | undefined, + immediateTarget: Symbol | undefined, + finalTarget: Symbol | undefined, overwriteEmpty: boolean, ): boolean { - if (!aliasDeclaration || ts.isPropertyAccessExpression(aliasDeclaration)) return false; + if (!aliasDeclaration || isPropertyAccessExpression(aliasDeclaration)) return false; // If the declaration itself is type-only, mark it and return. // No need to check what it resolves to. const sourceSymbol = getSymbolOfNode(aliasDeclaration); - if (ts.isTypeOnlyImportOrExportDeclaration(aliasDeclaration)) { + if (isTypeOnlyImportOrExportDeclaration(aliasDeclaration)) { const links = getSymbolLinks(sourceSymbol); links.typeOnlyDeclaration = aliasDeclaration; return true; @@ -3337,18 +3535,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { || markSymbolOfAliasDeclarationIfTypeOnlyWorker(links, finalTarget, overwriteEmpty); } - function markSymbolOfAliasDeclarationIfTypeOnlyWorker(aliasDeclarationLinks: ts.SymbolLinks, target: ts.Symbol | undefined, overwriteEmpty: boolean): boolean { + function markSymbolOfAliasDeclarationIfTypeOnlyWorker(aliasDeclarationLinks: SymbolLinks, target: Symbol | undefined, overwriteEmpty: boolean): boolean { if (target && (aliasDeclarationLinks.typeOnlyDeclaration === undefined || overwriteEmpty && aliasDeclarationLinks.typeOnlyDeclaration === false)) { - const exportSymbol = target.exports?.get(ts.InternalSymbolName.ExportEquals) ?? target; - const typeOnly = exportSymbol.declarations && ts.find(exportSymbol.declarations, ts.isTypeOnlyImportOrExportDeclaration); + const exportSymbol = target.exports?.get(InternalSymbolName.ExportEquals) ?? target; + const typeOnly = exportSymbol.declarations && find(exportSymbol.declarations, isTypeOnlyImportOrExportDeclaration); aliasDeclarationLinks.typeOnlyDeclaration = typeOnly ?? getSymbolLinks(exportSymbol).typeOnlyDeclaration ?? false; } return !!aliasDeclarationLinks.typeOnlyDeclaration; } /** Indicates that a symbol directly or indirectly resolves to a type-only import or export. */ - function getTypeOnlyAliasDeclaration(symbol: ts.Symbol, include?: ts.SymbolFlags): ts.TypeOnlyAliasDeclaration | undefined { - if (!(symbol.flags & ts.SymbolFlags.Alias)) { + function getTypeOnlyAliasDeclaration(symbol: Symbol, include?: SymbolFlags): TypeOnlyAliasDeclaration | undefined { + if (!(symbol.flags & SymbolFlags.Alias)) { return undefined; } const links = getSymbolLinks(symbol); @@ -3361,12 +3559,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function markExportAsReferenced(node: ts.ImportEqualsDeclaration | ts.ExportSpecifier) { + function markExportAsReferenced(node: ImportEqualsDeclaration | ExportSpecifier) { const symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || - ((getAllSymbolFlags(target) & ts.SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol, ts.SymbolFlags.Value)); + ((getAllSymbolFlags(target) & SymbolFlags.Value) && !isConstEnumOrConstEnumOnlyModule(target) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)); if (markAlias) { markAliasSymbolAsReferenced(symbol); @@ -3377,19 +3575,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When an alias symbol is referenced, we need to mark the entity it references as referenced and in turn repeat that until // we reach a non-alias or an exported entity (which is always considered referenced). We do this by checking the target of // the alias as an expression (which recursively takes us back here if the target references another alias). - function markAliasSymbolAsReferenced(symbol: ts.Symbol) { + function markAliasSymbolAsReferenced(symbol: Symbol) { const links = getSymbolLinks(symbol); if (!links.referenced) { links.referenced = true; const node = getDeclarationOfAliasSymbol(symbol); - if (!node) return ts.Debug.fail(); + if (!node) return Debug.fail(); // We defer checking of the reference of an `import =` until the import itself is referenced, // This way a chain of imports can be elided if ultimately the final input is only used in a type // position. - if (ts.isInternalModuleImportEqualsDeclaration(node)) { - if (getAllSymbolFlags(resolveSymbol(symbol)) & ts.SymbolFlags.Value) { + if (isInternalModuleImportEqualsDeclaration(node)) { + if (getAllSymbolFlags(resolveSymbol(symbol)) & SymbolFlags.Value) { // import foo = - checkExpressionCached(node.moduleReference as ts.Expression); + checkExpressionCached(node.moduleReference as Expression); } } } @@ -3397,7 +3595,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Aliases that resolve to const enums are not marked as referenced because they are not emitted, // but their usage in value positions must be tracked to determine if the import can be type-only. - function markConstEnumAliasAsReferenced(symbol: ts.Symbol) { + function markConstEnumAliasAsReferenced(symbol: Symbol) { const links = getSymbolLinks(symbol); if (!links.constEnumReferenced) { links.constEnumReferenced = true; @@ -3405,46 +3603,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // This function is only for imports with entity names - function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: ts.EntityName, dontResolveAlias?: boolean): ts.Symbol | undefined { + function getSymbolOfPartOfRightHandSideOfImportEquals(entityName: EntityName, dontResolveAlias?: boolean): Symbol | undefined { // There are three things we might try to look for. In the following examples, // the search term is enclosed in |...|: // // import a = |b|; // Namespace // import a = |b.c|; // Value, type, namespace // import a = |b.c|.d; // Namespace - if (entityName.kind === ts.SyntaxKind.Identifier && ts.isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { - entityName = entityName.parent as ts.QualifiedName; + if (entityName.kind === SyntaxKind.Identifier && isRightSideOfQualifiedNameOrPropertyAccess(entityName)) { + entityName = entityName.parent as QualifiedName; } // Check for case 1 and 3 in the above example - if (entityName.kind === ts.SyntaxKind.Identifier || entityName.parent.kind === ts.SyntaxKind.QualifiedName) { - return resolveEntityName(entityName, ts.SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); + if (entityName.kind === SyntaxKind.Identifier || entityName.parent.kind === SyntaxKind.QualifiedName) { + return resolveEntityName(entityName, SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); } else { // Case 2 in above example // entityName.kind could be a QualifiedName or a Missing identifier - ts.Debug.assert(entityName.parent.kind === ts.SyntaxKind.ImportEqualsDeclaration); - return resolveEntityName(entityName, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); + Debug.assert(entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration); + return resolveEntityName(entityName, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, /*ignoreErrors*/ false, dontResolveAlias); } } - function getFullyQualifiedName(symbol: ts.Symbol, containingLocation?: ts.Node): string { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, ts.SymbolFormatFlags.DoNotIncludeSymbolChain | ts.SymbolFormatFlags.AllowAnyNodeKind); + function getFullyQualifiedName(symbol: Symbol, containingLocation?: Node): string { + return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind); } - function getContainingQualifiedNameNode(node: ts.QualifiedName) { - while (ts.isQualifiedName(node.parent)) { + function getContainingQualifiedNameNode(node: QualifiedName) { + while (isQualifiedName(node.parent)) { node = node.parent; } return node; } - function tryGetQualifiedNameAsValue(node: ts.QualifiedName) { - let left: ts.Identifier | ts.QualifiedName = ts.getFirstIdentifier(node); - let symbol = resolveName(left, left.escapedText, ts.SymbolFlags.Value, undefined, left, /*isUse*/ true); + function tryGetQualifiedNameAsValue(node: QualifiedName) { + let left: Identifier | QualifiedName = getFirstIdentifier(node); + let symbol = resolveName(left, left.escapedText, SymbolFlags.Value, undefined, left, /*isUse*/ true); if (!symbol) { return undefined; } - while (ts.isQualifiedName(left.parent)) { + while (isQualifiedName(left.parent)) { const type = getTypeOfSymbol(symbol); symbol = getPropertyOfType(type, left.parent.right.escapedText); if (!symbol) { @@ -3458,26 +3656,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Resolves a qualified name and any involved aliases. */ - function resolveEntityName(name: ts.EntityNameOrEntityNameExpression, meaning: ts.SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: ts.Node): ts.Symbol | undefined { - if (ts.nodeIsMissing(name)) { + function resolveEntityName(name: EntityNameOrEntityNameExpression, meaning: SymbolFlags, ignoreErrors?: boolean, dontResolveAlias?: boolean, location?: Node): Symbol | undefined { + if (nodeIsMissing(name)) { return undefined; } - const namespaceMeaning = ts.SymbolFlags.Namespace | (ts.isInJSFile(name) ? meaning & ts.SymbolFlags.Value : 0); - let symbol: ts.Symbol | undefined; - if (name.kind === ts.SyntaxKind.Identifier) { - const message = meaning === namespaceMeaning || ts.nodeIsSynthesized(name) ? ts.Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(ts.getFirstIdentifier(name)); - const symbolFromJSPrototype = ts.isInJSFile(name) && !ts.nodeIsSynthesized(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined; + const namespaceMeaning = SymbolFlags.Namespace | (isInJSFile(name) ? meaning & SymbolFlags.Value : 0); + let symbol: Symbol | undefined; + if (name.kind === SyntaxKind.Identifier) { + const message = meaning === namespaceMeaning || nodeIsSynthesized(name) ? Diagnostics.Cannot_find_namespace_0 : getCannotFindNameDiagnosticForName(getFirstIdentifier(name)); + const symbolFromJSPrototype = isInJSFile(name) && !nodeIsSynthesized(name) ? resolveEntityNameFromAssignmentDeclaration(name, meaning) : undefined; symbol = getMergedSymbol(resolveName(location || name, name.escapedText, meaning, ignoreErrors || symbolFromJSPrototype ? undefined : message, name, /*isUse*/ true, false)); if (!symbol) { return getMergedSymbol(symbolFromJSPrototype); } } - else if (name.kind === ts.SyntaxKind.QualifiedName || name.kind === ts.SyntaxKind.PropertyAccessExpression) { - const left = name.kind === ts.SyntaxKind.QualifiedName ? name.left : name.expression; - const right = name.kind === ts.SyntaxKind.QualifiedName ? name.right : name.name; + else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) { + const left = name.kind === SyntaxKind.QualifiedName ? name.left : name.expression; + const right = name.kind === SyntaxKind.QualifiedName ? name.right : name.name; let namespace = resolveEntityName(left, namespaceMeaning, ignoreErrors, /*dontResolveAlias*/ false, location); - if (!namespace || ts.nodeIsMissing(right)) { + if (!namespace || nodeIsMissing(right)) { return undefined; } else if (namespace === unknownSymbol) { @@ -3485,12 +3683,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if ( namespace.valueDeclaration && - ts.isInJSFile(namespace.valueDeclaration) && - ts.isVariableDeclaration(namespace.valueDeclaration) && + isInJSFile(namespace.valueDeclaration) && + isVariableDeclaration(namespace.valueDeclaration) && namespace.valueDeclaration.initializer && isCommonJsRequire(namespace.valueDeclaration.initializer) ) { - const moduleName = (namespace.valueDeclaration.initializer as ts.CallExpression).arguments[0] as ts.StringLiteral; + const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral; const moduleSym = resolveExternalModuleName(moduleName, moduleName); if (moduleSym) { const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); @@ -3503,52 +3701,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!symbol) { if (!ignoreErrors) { const namespaceName = getFullyQualifiedName(namespace); - const declarationName = ts.declarationNameToString(right); + const declarationName = declarationNameToString(right); const suggestionForNonexistentModule = getSuggestedSymbolForNonexistentModule(right, namespace); if (suggestionForNonexistentModule) { - error(right, ts.Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, namespaceName, declarationName, symbolToString(suggestionForNonexistentModule)); + error(right, Diagnostics._0_has_no_exported_member_named_1_Did_you_mean_2, namespaceName, declarationName, symbolToString(suggestionForNonexistentModule)); return undefined; } - const containingQualifiedName = ts.isQualifiedName(name) && getContainingQualifiedNameNode(name); + const containingQualifiedName = isQualifiedName(name) && getContainingQualifiedNameNode(name); const canSuggestTypeof = globalObjectType // <-- can't pull on types if global types aren't initialized yet - && (meaning & ts.SymbolFlags.Type) + && (meaning & SymbolFlags.Type) && containingQualifiedName - && !ts.isTypeOfExpression(containingQualifiedName.parent) + && !isTypeOfExpression(containingQualifiedName.parent) && tryGetQualifiedNameAsValue(containingQualifiedName); if (canSuggestTypeof) { error( containingQualifiedName, - ts.Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, - ts.entityNameToString(containingQualifiedName) + Diagnostics._0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, + entityNameToString(containingQualifiedName) ); return undefined; } - if (meaning & ts.SymbolFlags.Namespace && ts.isQualifiedName(name.parent)) { - const exportedTypeSymbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, ts.SymbolFlags.Type)); + if (meaning & SymbolFlags.Namespace && isQualifiedName(name.parent)) { + const exportedTypeSymbol = getMergedSymbol(getSymbol(getExportsOfSymbol(namespace), right.escapedText, SymbolFlags.Type)); if (exportedTypeSymbol) { error( name.parent.right, - ts.Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, + Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, symbolToString(exportedTypeSymbol), - ts.unescapeLeadingUnderscores(name.parent.right.escapedText) + unescapeLeadingUnderscores(name.parent.right.escapedText) ); return undefined; } } - error(right, ts.Diagnostics.Namespace_0_has_no_exported_member_1, namespaceName, declarationName); + error(right, Diagnostics.Namespace_0_has_no_exported_member_1, namespaceName, declarationName); } return undefined; } } else { - throw ts.Debug.assertNever(name, "Unknown entity name kind."); + throw Debug.assertNever(name, "Unknown entity name kind."); } - ts.Debug.assert((ts.getCheckFlags(symbol) & ts.CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); - if (!ts.nodeIsSynthesized(name) && ts.isEntityName(name) && (symbol.flags & ts.SymbolFlags.Alias || name.parent.kind === ts.SyntaxKind.ExportAssignment)) { - markSymbolOfAliasDeclarationIfTypeOnly(ts.getAliasDeclarationFromName(name), symbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ true); + Debug.assert((getCheckFlags(symbol) & CheckFlags.Instantiated) === 0, "Should never get an instantiated symbol here."); + if (!nodeIsSynthesized(name) && isEntityName(name) && (symbol.flags & SymbolFlags.Alias || name.parent.kind === SyntaxKind.ExportAssignment)) { + markSymbolOfAliasDeclarationIfTypeOnly(getAliasDeclarationFromName(name), symbol, /*finalTarget*/ undefined, /*overwriteEmpty*/ true); } return (symbol.flags & meaning) || dontResolveAlias ? symbol : resolveAlias(symbol); } @@ -3559,7 +3757,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * name resolution won't work either. * 2. For property assignments like `{ x: function f () { } }`, try to resolve names in the scope of `f` too. */ - function resolveEntityNameFromAssignmentDeclaration(name: ts.Identifier, meaning: ts.SymbolFlags) { + function resolveEntityNameFromAssignmentDeclaration(name: Identifier, meaning: SymbolFlags) { if (isJSDocTypeReference(name.parent)) { const secondaryLocation = getAssignmentDeclarationLocation(name.parent); if (secondaryLocation) { @@ -3568,49 +3766,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getAssignmentDeclarationLocation(node: ts.TypeReferenceNode): ts.Node | undefined { - const typeAlias = ts.findAncestor(node, node => !(ts.isJSDocNode(node) || node.flags & ts.NodeFlags.JSDoc) ? "quit" : ts.isJSDocTypeAlias(node)); + function getAssignmentDeclarationLocation(node: TypeReferenceNode): Node | undefined { + const typeAlias = findAncestor(node, node => !(isJSDocNode(node) || node.flags & NodeFlags.JSDoc) ? "quit" : isJSDocTypeAlias(node)); if (typeAlias) { return; } - const host = ts.getJSDocHost(node); - if (host && ts.isExpressionStatement(host) && ts.isPrototypePropertyAssignment(host.expression)) { + const host = getJSDocHost(node); + if (host && isExpressionStatement(host) && isPrototypePropertyAssignment(host.expression)) { // /** @param {K} p */ X.prototype.m = function () { } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.expression.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } - if (host && ts.isFunctionExpression(host) && ts.isPrototypePropertyAssignment(host.parent) && ts.isExpressionStatement(host.parent.parent)) { + if (host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) && isExpressionStatement(host.parent.parent)) { // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.parent.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } - if (host && (ts.isObjectLiteralMethod(host) || ts.isPropertyAssignment(host)) && - ts.isBinaryExpression(host.parent.parent) && - ts.getAssignmentDeclarationKind(host.parent.parent) === ts.AssignmentDeclarationKind.Prototype) { + if (host && (isObjectLiteralMethod(host) || isPropertyAssignment(host)) && + isBinaryExpression(host.parent.parent) && + getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype) { // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration const symbol = getSymbolOfNode(host.parent.parent.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } - const sig = ts.getEffectiveJSDocHost(node); - if (sig && ts.isFunctionLike(sig)) { + const sig = getEffectiveJSDocHost(node); + if (sig && isFunctionLike(sig)) { const symbol = getSymbolOfNode(sig); return symbol && symbol.valueDeclaration; } } - function getDeclarationOfJSPrototypeContainer(symbol: ts.Symbol) { + function getDeclarationOfJSPrototypeContainer(symbol: Symbol) { const decl = symbol.parent!.valueDeclaration; if (!decl) { return undefined; } - const initializer = ts.isAssignmentDeclaration(decl) ? ts.getAssignedExpandoInitializer(decl) : - ts.hasOnlyExpressionInitializer(decl) ? ts.getDeclaredExpandoInitializer(decl) : + const initializer = isAssignmentDeclaration(decl) ? getAssignedExpandoInitializer(decl) : + hasOnlyExpressionInitializer(decl) ? getDeclaredExpandoInitializer(decl) : undefined; return initializer || decl; } @@ -3621,12 +3819,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Normally, declarations have an associated symbol, but when a declaration has an expando * initializer, the expando's symbol is the one that has all the members merged into it. */ - function getExpandoSymbol(symbol: ts.Symbol): ts.Symbol | undefined { + function getExpandoSymbol(symbol: Symbol): Symbol | undefined { const decl = symbol.valueDeclaration; - if (!decl || !ts.isInJSFile(decl) || symbol.flags & ts.SymbolFlags.TypeAlias || ts.getExpandoInitializer(decl, /*isPrototypeAssignment*/ false)) { + if (!decl || !isInJSFile(decl) || symbol.flags & SymbolFlags.TypeAlias || getExpandoInitializer(decl, /*isPrototypeAssignment*/ false)) { return undefined; } - const init = ts.isVariableDeclaration(decl) ? ts.getDeclaredExpandoInitializer(decl) : ts.getAssignedExpandoInitializer(decl); + const init = isVariableDeclaration(decl) ? getDeclaredExpandoInitializer(decl) : getAssignedExpandoInitializer(decl); if (init) { const initSymbol = getSymbolOfNode(init); if (initSymbol) { @@ -3635,24 +3833,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function resolveExternalModuleName(location: ts.Node, moduleReferenceExpression: ts.Expression, ignoreErrors?: boolean): ts.Symbol | undefined { - const isClassic = ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Classic; + function resolveExternalModuleName(location: Node, moduleReferenceExpression: Expression, ignoreErrors?: boolean): Symbol | undefined { + const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic; const errorMessage = isClassic? - ts.Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option - : ts.Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; + Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option + : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; return resolveExternalModuleNameWorker(location, moduleReferenceExpression, ignoreErrors ? undefined : errorMessage); } - function resolveExternalModuleNameWorker(location: ts.Node, moduleReferenceExpression: ts.Expression, moduleNotFoundError: ts.DiagnosticMessage | undefined, isForAugmentation = false): ts.Symbol | undefined { - return ts.isStringLiteralLike(moduleReferenceExpression) + function resolveExternalModuleNameWorker(location: Node, moduleReferenceExpression: Expression, moduleNotFoundError: DiagnosticMessage | undefined, isForAugmentation = false): Symbol | undefined { + return isStringLiteralLike(moduleReferenceExpression) ? resolveExternalModule(location, moduleReferenceExpression.text, moduleNotFoundError, moduleReferenceExpression, isForAugmentation) : undefined; } - function resolveExternalModule(location: ts.Node, moduleReference: string, moduleNotFoundError: ts.DiagnosticMessage | undefined, errorNode: ts.Node, isForAugmentation = false): ts.Symbol | undefined { - if (ts.startsWith(moduleReference, "@types/")) { - const diag = ts.Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1; - const withoutAtTypePrefix = ts.removePrefix(moduleReference, "@types/"); + function resolveExternalModule(location: Node, moduleReference: string, moduleNotFoundError: DiagnosticMessage | undefined, errorNode: Node, isForAugmentation = false): Symbol | undefined { + if (startsWith(moduleReference, "@types/")) { + const diag = Diagnostics.Cannot_import_type_declaration_files_Consider_importing_0_instead_of_1; + const withoutAtTypePrefix = removePrefix(moduleReference, "@types/"); error(errorNode, diag, withoutAtTypePrefix, moduleReference); } @@ -3660,20 +3858,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (ambientModule) { return ambientModule; } - const currentSourceFile = ts.getSourceFileOfNode(location); - const contextSpecifier = ts.isStringLiteralLike(location) + const currentSourceFile = getSourceFileOfNode(location); + const contextSpecifier = isStringLiteralLike(location) ? location - : ts.findAncestor(location, ts.isImportCall)?.arguments[0] || - ts.findAncestor(location, ts.isImportDeclaration)?.moduleSpecifier || - ts.findAncestor(location, ts.isExternalModuleImportEqualsDeclaration)?.moduleReference.expression || - ts.findAncestor(location, ts.isExportDeclaration)?.moduleSpecifier || - (ts.isModuleDeclaration(location) ? location : location.parent && ts.isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name || - (ts.isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; - const mode = contextSpecifier && ts.isStringLiteralLike(contextSpecifier) ? ts.getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; - const resolvedModule = ts.getResolvedModule(currentSourceFile, moduleReference, mode); - const resolutionDiagnostic = resolvedModule && ts.getResolutionDiagnostic(compilerOptions, resolvedModule); + : findAncestor(location, isImportCall)?.arguments[0] || + findAncestor(location, isImportDeclaration)?.moduleSpecifier || + findAncestor(location, isExternalModuleImportEqualsDeclaration)?.moduleReference.expression || + findAncestor(location, isExportDeclaration)?.moduleSpecifier || + (isModuleDeclaration(location) ? location : location.parent && isModuleDeclaration(location.parent) && location.parent.name === location ? location.parent : undefined)?.name || + (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; + const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; + const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode); + const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); const sourceFile = resolvedModule - && (!resolutionDiagnostic || resolutionDiagnostic === ts.Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) + && (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) && host.getSourceFile(resolvedModule.resolvedFileName); if (sourceFile) { // If there's a resolutionDiagnostic we need to report it even if a sourceFile is found. @@ -3681,59 +3879,59 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } if (sourceFile.symbol) { - if (resolvedModule.isExternalLibraryImport && !ts.resolutionExtensionIsTSOrJson(resolvedModule.extension)) { + if (resolvedModule.isExternalLibraryImport && !resolutionExtensionIsTSOrJson(resolvedModule.extension)) { errorOnImplicitAnyModule(/*isError*/ false, errorNode, resolvedModule, moduleReference); } - if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeNext) { - const isSyncImport = (currentSourceFile.impliedNodeFormat === ts.ModuleKind.CommonJS && !ts.findAncestor(location, ts.isImportCall)) || !!ts.findAncestor(location, ts.isImportEqualsDeclaration); - const overrideClauseHost = ts.findAncestor(location, l => ts.isImportTypeNode(l) || ts.isExportDeclaration(l) || ts.isImportDeclaration(l)) as ts.ImportTypeNode | ts.ImportDeclaration | ts.ExportDeclaration | undefined; - const overrideClause = overrideClauseHost && ts.isImportTypeNode(overrideClauseHost) ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause; + if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) { + const isSyncImport = (currentSourceFile.impliedNodeFormat === ModuleKind.CommonJS && !findAncestor(location, isImportCall)) || !!findAncestor(location, isImportEqualsDeclaration); + const overrideClauseHost = findAncestor(location, l => isImportTypeNode(l) || isExportDeclaration(l) || isImportDeclaration(l)) as ImportTypeNode | ImportDeclaration | ExportDeclaration | undefined; + const overrideClause = overrideClauseHost && isImportTypeNode(overrideClauseHost) ? overrideClauseHost.assertions?.assertClause : overrideClauseHost?.assertClause; // An override clause will take effect for type-only imports and import types, and allows importing the types across formats, regardless of // normal mode restrictions - if (isSyncImport && sourceFile.impliedNodeFormat === ts.ModuleKind.ESNext && !ts.getResolutionModeOverrideForClause(overrideClause)) { - if (ts.findAncestor(location, ts.isImportEqualsDeclaration)) { + if (isSyncImport && sourceFile.impliedNodeFormat === ModuleKind.ESNext && !getResolutionModeOverrideForClause(overrideClause)) { + if (findAncestor(location, isImportEqualsDeclaration)) { // ImportEquals in a ESM file resolving to another ESM file - error(errorNode, ts.Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference); + error(errorNode, Diagnostics.Module_0_cannot_be_imported_using_this_construct_The_specifier_only_resolves_to_an_ES_module_which_cannot_be_imported_with_require_Use_an_ECMAScript_import_instead, moduleReference); } else { // CJS file resolving to an ESM file let diagnosticDetails; - const ext = ts.tryGetExtensionFromPath(currentSourceFile.fileName); - if (ext === ts.Extension.Ts || ext === ts.Extension.Js || ext === ts.Extension.Tsx || ext === ts.Extension.Jsx) { + const ext = tryGetExtensionFromPath(currentSourceFile.fileName); + if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) { const scope = currentSourceFile.packageJsonScope; - const targetExt = ext === ts.Extension.Ts ? ts.Extension.Mts : ext === ts.Extension.Js ? ts.Extension.Mjs : undefined; + const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined; if (scope && !scope.contents.packageJsonContent.type) { if (targetExt) { - diagnosticDetails = ts.chainDiagnosticMessages( + diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_add_the_field_type_Colon_module_to_1, targetExt, - ts.combinePaths(scope.packageDirectory, "package.json")); + combinePaths(scope.packageDirectory, "package.json")); } else { - diagnosticDetails = ts.chainDiagnosticMessages( + diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, - ts.combinePaths(scope.packageDirectory, "package.json")); + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_add_the_field_type_Colon_module_to_0, + combinePaths(scope.packageDirectory, "package.json")); } } else { if (targetExt) { - diagnosticDetails = ts.chainDiagnosticMessages( + diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_change_its_file_extension_to_0_or_create_a_local_package_json_file_with_type_Colon_module, targetExt); } else { - diagnosticDetails = ts.chainDiagnosticMessages( + diagnosticDetails = chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module); + Diagnostics.To_convert_this_file_to_an_ECMAScript_module_create_a_local_package_json_file_with_type_Colon_module); } } } - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, ts.chainDiagnosticMessages( + diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chainDiagnosticMessages( diagnosticDetails, - ts.Diagnostics.The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead, + Diagnostics.The_current_file_is_a_CommonJS_module_whose_imports_will_produce_require_calls_however_the_referenced_file_is_an_ECMAScript_module_and_cannot_be_imported_with_require_Consider_writing_a_dynamic_import_0_call_instead, moduleReference))); } } @@ -3743,13 +3941,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (moduleNotFoundError) { // report errors only if it was requested - error(errorNode, ts.Diagnostics.File_0_is_not_a_module, sourceFile.fileName); + error(errorNode, Diagnostics.File_0_is_not_a_module, sourceFile.fileName); } return undefined; } if (patternAmbientModules) { - const pattern = ts.findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleReference); + const pattern = findBestPatternMatch(patternAmbientModules, _ => _.pattern, moduleReference); if (pattern) { // If the module reference matched a pattern ambient module ('*.foo') but there's also a // module augmentation by the specific name requested ('a.foo'), we store the merged symbol @@ -3764,9 +3962,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // May be an untyped module. If so, ignore resolutionDiagnostic. - if (resolvedModule && !ts.resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { + if (resolvedModule && !resolutionExtensionIsTSOrJson(resolvedModule.extension) && resolutionDiagnostic === undefined || resolutionDiagnostic === Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type) { if (isForAugmentation) { - const diag = ts.Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; + const diag = Diagnostics.Invalid_module_name_in_augmentation_Module_0_resolves_to_an_untyped_module_at_1_which_cannot_be_augmented; error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName); } else { @@ -3781,7 +3979,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (resolvedModule) { const redirect = host.getProjectReferenceRedirect(resolvedModule.resolvedFileName); if (redirect) { - error(errorNode, ts.Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, resolvedModule.resolvedFileName); + error(errorNode, Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, resolvedModule.resolvedFileName); return undefined; } } @@ -3790,40 +3988,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { error(errorNode, resolutionDiagnostic, moduleReference, resolvedModule.resolvedFileName); } else { - const tsExtension = ts.tryExtractTSExtension(moduleReference); - const isExtensionlessRelativePathImport = ts.pathIsRelative(moduleReference) && !ts.hasExtension(moduleReference); - const moduleResolutionKind = ts.getEmitModuleResolutionKind(compilerOptions); - const resolutionIsNode16OrNext = moduleResolutionKind === ts.ModuleResolutionKind.Node16 || - moduleResolutionKind === ts.ModuleResolutionKind.NodeNext; + const tsExtension = tryExtractTSExtension(moduleReference); + const isExtensionlessRelativePathImport = pathIsRelative(moduleReference) && !hasExtension(moduleReference); + const moduleResolutionKind = getEmitModuleResolutionKind(compilerOptions); + const resolutionIsNode16OrNext = moduleResolutionKind === ModuleResolutionKind.Node16 || + moduleResolutionKind === ModuleResolutionKind.NodeNext; if (tsExtension) { - const diag = ts.Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; - const importSourceWithoutExtension = ts.removeExtension(moduleReference, tsExtension); + const diag = Diagnostics.An_import_path_cannot_end_with_a_0_extension_Consider_importing_1_instead; + const importSourceWithoutExtension = removeExtension(moduleReference, tsExtension); let replacedImportSource = importSourceWithoutExtension; /** * Direct users to import source with .js extension if outputting an ES module. * @see https://github.com/microsoft/TypeScript/issues/42151 */ - if (moduleKind >= ts.ModuleKind.ES2015) { - replacedImportSource += tsExtension === ts.Extension.Mts ? ".mjs" : tsExtension === ts.Extension.Cts ? ".cjs" : ".js"; + if (moduleKind >= ModuleKind.ES2015) { + replacedImportSource += tsExtension === Extension.Mts ? ".mjs" : tsExtension === Extension.Cts ? ".cjs" : ".js"; } error(errorNode, diag, tsExtension, replacedImportSource); } else if (!compilerOptions.resolveJsonModule && - ts.fileExtensionIs(moduleReference, ts.Extension.Json) && - ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Classic && - ts.hasJsonModuleEmitEnabled(compilerOptions)) { - error(errorNode, ts.Diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference); + fileExtensionIs(moduleReference, Extension.Json) && + getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic && + hasJsonModuleEmitEnabled(compilerOptions)) { + error(errorNode, Diagnostics.Cannot_find_module_0_Consider_using_resolveJsonModule_to_import_module_with_json_extension, moduleReference); } - else if (mode === ts.ModuleKind.ESNext && resolutionIsNode16OrNext && isExtensionlessRelativePathImport) { - const absoluteRef = ts.getNormalizedAbsolutePath(moduleReference, ts.getDirectoryPath(currentSourceFile.path)); + else if (mode === ModuleKind.ESNext && resolutionIsNode16OrNext && isExtensionlessRelativePathImport) { + const absoluteRef = getNormalizedAbsolutePath(moduleReference, getDirectoryPath(currentSourceFile.path)); const suggestedExt = suggestedExtensions.find(([actualExt, _importExt]) => host.fileExists(absoluteRef + actualExt))?.[1]; if (suggestedExt) { error(errorNode, - ts.Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, + Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Did_you_mean_0, moduleReference + suggestedExt); } else { - error(errorNode, ts.Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path); + error(errorNode, Diagnostics.Relative_import_paths_need_explicit_file_extensions_in_EcmaScript_imports_when_moduleResolution_is_node16_or_nodenext_Consider_adding_an_extension_to_the_import_path); } } else { @@ -3834,64 +4032,64 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function errorOnImplicitAnyModule(isError: boolean, errorNode: ts.Node, { packageId, resolvedFileName }: ts.ResolvedModuleFull, moduleReference: string): void { - const errorInfo = !ts.isExternalModuleNameRelative(moduleReference) && packageId + function errorOnImplicitAnyModule(isError: boolean, errorNode: Node, { packageId, resolvedFileName }: ResolvedModuleFull, moduleReference: string): void { + const errorInfo = !isExternalModuleNameRelative(moduleReference) && packageId ? typesPackageExists(packageId.name) - ? ts.chainDiagnosticMessages( + ? chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1, - packageId.name, ts.mangleScopedPackageName(packageId.name)) + Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1, + packageId.name, mangleScopedPackageName(packageId.name)) : packageBundlesTypes(packageId.name) - ? ts.chainDiagnosticMessages( + ? chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1, + Diagnostics.If_the_0_package_actually_exposes_this_module_try_adding_a_new_declaration_d_ts_file_containing_declare_module_1, packageId.name, moduleReference) - : ts.chainDiagnosticMessages( + : chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, + Diagnostics.Try_npm_i_save_dev_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, moduleReference, - ts.mangleScopedPackageName(packageId.name)) + mangleScopedPackageName(packageId.name)) : undefined; - errorOrSuggestion(isError, errorNode, ts.chainDiagnosticMessages( + errorOrSuggestion(isError, errorNode, chainDiagnosticMessages( errorInfo, - ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, + Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type, moduleReference, resolvedFileName)); } function typesPackageExists(packageName: string): boolean { - return getPackagesMap().has(ts.getTypesPackageName(packageName)); + return getPackagesMap().has(getTypesPackageName(packageName)); } function packageBundlesTypes(packageName: string): boolean { return !!getPackagesMap().get(packageName); } - function resolveExternalModuleSymbol(moduleSymbol: ts.Symbol, dontResolveAlias?: boolean): ts.Symbol; - function resolveExternalModuleSymbol(moduleSymbol: ts.Symbol | undefined, dontResolveAlias?: boolean): ts.Symbol | undefined; - function resolveExternalModuleSymbol(moduleSymbol: ts.Symbol, dontResolveAlias?: boolean): ts.Symbol | undefined { + function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol; + function resolveExternalModuleSymbol(moduleSymbol: Symbol | undefined, dontResolveAlias?: boolean): Symbol | undefined; + function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol | undefined { if (moduleSymbol?.exports) { - const exportEquals = resolveSymbol(moduleSymbol.exports.get(ts.InternalSymbolName.ExportEquals), dontResolveAlias); + const exportEquals = resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias); const exported = getCommonJsExportEquals(getMergedSymbol(exportEquals), getMergedSymbol(moduleSymbol)); return getMergedSymbol(exported) || moduleSymbol; } return undefined; } - function getCommonJsExportEquals(exported: ts.Symbol | undefined, moduleSymbol: ts.Symbol): ts.Symbol | undefined { - if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 || exported.flags & ts.SymbolFlags.Alias) { + function getCommonJsExportEquals(exported: Symbol | undefined, moduleSymbol: Symbol): Symbol | undefined { + if (!exported || exported === unknownSymbol || exported === moduleSymbol || moduleSymbol.exports!.size === 1 || exported.flags & SymbolFlags.Alias) { return exported; } const links = getSymbolLinks(exported); if (links.cjsExportMerged) { return links.cjsExportMerged; } - const merged = exported.flags & ts.SymbolFlags.Transient ? exported : cloneSymbol(exported); - merged.flags = merged.flags | ts.SymbolFlags.ValueModule; + const merged = exported.flags & SymbolFlags.Transient ? exported : cloneSymbol(exported); + merged.flags = merged.flags | SymbolFlags.ValueModule; if (merged.exports === undefined) { - merged.exports = ts.createSymbolTable(); + merged.exports = createSymbolTable(); } moduleSymbol.exports!.forEach((s, name) => { - if (name === ts.InternalSymbolName.ExportEquals) return; + if (name === InternalSymbolName.ExportEquals) return; merged.exports!.set(name, merged.exports!.has(name) ? mergeSymbol(merged.exports!.get(name)!, s) : s); }); getSymbolLinks(merged).cjsExportMerged = merged; @@ -3901,42 +4099,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' // references a symbol that is at least declared as a module or a variable. The target of the 'export =' may // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). - function resolveESModuleSymbol(moduleSymbol: ts.Symbol | undefined, referencingLocation: ts.Node, dontResolveAlias: boolean, suppressInteropError: boolean): ts.Symbol | undefined { + function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean, suppressInteropError: boolean): Symbol | undefined { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { - if (!suppressInteropError && !(symbol.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Variable)) && !ts.getDeclarationOfKind(symbol, ts.SyntaxKind.SourceFile)) { - const compilerOptionName = moduleKind >= ts.ModuleKind.ES2015 + if (!suppressInteropError && !(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile)) { + const compilerOptionName = moduleKind >= ModuleKind.ES2015 ? "allowSyntheticDefaultImports" : "esModuleInterop"; - error(referencingLocation, ts.Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName); + error(referencingLocation, Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName); return symbol; } const referenceParent = referencingLocation.parent; if ( - (ts.isImportDeclaration(referenceParent) && ts.getNamespaceDeclarationNode(referenceParent)) || - ts.isImportCall(referenceParent) + (isImportDeclaration(referenceParent) && getNamespaceDeclarationNode(referenceParent)) || + isImportCall(referenceParent) ) { - const reference = ts.isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier; + const reference = isImportCall(referenceParent) ? referenceParent.arguments[0] : referenceParent.moduleSpecifier; const type = getTypeOfSymbol(symbol); const defaultOnlyType = getTypeWithSyntheticDefaultOnly(type, symbol, moduleSymbol!, reference); if (defaultOnlyType) { return cloneTypeAsModuleType(symbol, defaultOnlyType, referenceParent); } - const targetFile = moduleSymbol?.declarations?.find(ts.isSourceFile); + const targetFile = moduleSymbol?.declarations?.find(isSourceFile); const isEsmCjsRef = targetFile && isESMFormatImportImportingCommonjsFormatFile(getUsageModeForExpression(reference), targetFile.impliedNodeFormat); - if (ts.getESModuleInterop(compilerOptions) || isEsmCjsRef) { - let sigs = getSignaturesOfStructuredType(type, ts.SignatureKind.Call); + if (getESModuleInterop(compilerOptions) || isEsmCjsRef) { + let sigs = getSignaturesOfStructuredType(type, SignatureKind.Call); if (!sigs || !sigs.length) { - sigs = getSignaturesOfStructuredType(type, ts.SignatureKind.Construct); + sigs = getSignaturesOfStructuredType(type, SignatureKind.Construct); } if ( (sigs && sigs.length) || - getPropertyOfType(type, ts.InternalSymbolName.Default, /*skipObjectFunctionPropertyAugment*/ true) || + getPropertyOfType(type, InternalSymbolName.Default, /*skipObjectFunctionPropertyAugment*/ true) || isEsmCjsRef ) { const moduleType = getTypeWithSyntheticDefaultImportType(type, symbol, moduleSymbol!, reference); @@ -3951,7 +4149,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Create a new symbol which has the module's type less the call and construct signatures */ - function cloneTypeAsModuleType(symbol: ts.Symbol, moduleType: ts.Type, referenceParent: ts.ImportDeclaration | ts.ImportCall) { + function cloneTypeAsModuleType(symbol: Symbol, moduleType: Type, referenceParent: ImportDeclaration | ImportCall) { const result = createSymbol(symbol.flags, symbol.escapedName); result.declarations = symbol.declarations ? symbol.declarations.slice() : []; result.parent = symbol.parent; @@ -3959,34 +4157,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result.originatingImport = referenceParent; if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; - if (symbol.members) result.members = new ts.Map(symbol.members); - if (symbol.exports) result.exports = new ts.Map(symbol.exports); - const resolvedModuleType = resolveStructuredTypeMembers(moduleType as ts.StructuredType); // Should already be resolved from the signature checks above - result.type = createAnonymousType(result, resolvedModuleType.members, ts.emptyArray, ts.emptyArray, resolvedModuleType.indexInfos); + if (symbol.members) result.members = new Map(symbol.members); + if (symbol.exports) result.exports = new Map(symbol.exports); + const resolvedModuleType = resolveStructuredTypeMembers(moduleType as StructuredType); // Should already be resolved from the signature checks above + result.type = createAnonymousType(result, resolvedModuleType.members, emptyArray, emptyArray, resolvedModuleType.indexInfos); return result; } - function hasExportAssignmentSymbol(moduleSymbol: ts.Symbol): boolean { - return moduleSymbol.exports!.get(ts.InternalSymbolName.ExportEquals) !== undefined; + function hasExportAssignmentSymbol(moduleSymbol: Symbol): boolean { + return moduleSymbol.exports!.get(InternalSymbolName.ExportEquals) !== undefined; } - function getExportsOfModuleAsArray(moduleSymbol: ts.Symbol): ts.Symbol[] { + function getExportsOfModuleAsArray(moduleSymbol: Symbol): Symbol[] { return symbolsToArray(getExportsOfModule(moduleSymbol)); } - function getExportsAndPropertiesOfModule(moduleSymbol: ts.Symbol): ts.Symbol[] { + function getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[] { const exports = getExportsOfModuleAsArray(moduleSymbol); const exportEquals = resolveExternalModuleSymbol(moduleSymbol); if (exportEquals !== moduleSymbol) { const type = getTypeOfSymbol(exportEquals); if (shouldTreatPropertiesOfExternalModuleAsExports(type)) { - ts.addRange(exports, getPropertiesOfType(type)); + addRange(exports, getPropertiesOfType(type)); } } return exports; } - function forEachExportAndPropertyOfModule(moduleSymbol: ts.Symbol, cb: (symbol: ts.Symbol, key: ts.__String) => void): void { + function forEachExportAndPropertyOfModule(moduleSymbol: Symbol, cb: (symbol: Symbol, key: __String) => void): void { const exports = getExportsOfModule(moduleSymbol); exports.forEach((symbol, key) => { if (!isReservedMemberName(key)) { @@ -4004,14 +4202,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function tryGetMemberInModuleExports(memberName: ts.__String, moduleSymbol: ts.Symbol): ts.Symbol | undefined { + function tryGetMemberInModuleExports(memberName: __String, moduleSymbol: Symbol): Symbol | undefined { const symbolTable = getExportsOfModule(moduleSymbol); if (symbolTable) { return symbolTable.get(memberName); } } - function tryGetMemberInModuleExportsAndProperties(memberName: ts.__String, moduleSymbol: ts.Symbol): ts.Symbol | undefined { + function tryGetMemberInModuleExportsAndProperties(memberName: __String, moduleSymbol: Symbol): Symbol | undefined { const symbol = tryGetMemberInModuleExports(memberName, moduleSymbol); if (symbol) { return symbol; @@ -4026,47 +4224,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return shouldTreatPropertiesOfExternalModuleAsExports(type) ? getPropertyOfType(type, memberName) : undefined; } - function shouldTreatPropertiesOfExternalModuleAsExports(resolvedExternalModuleType: ts.Type) { - return !(resolvedExternalModuleType.flags & ts.TypeFlags.Primitive || - ts.getObjectFlags(resolvedExternalModuleType) & ts.ObjectFlags.Class || + function shouldTreatPropertiesOfExternalModuleAsExports(resolvedExternalModuleType: Type) { + return !(resolvedExternalModuleType.flags & TypeFlags.Primitive || + getObjectFlags(resolvedExternalModuleType) & ObjectFlags.Class || // `isArrayOrTupleLikeType` is too expensive to use in this auto-imports hot path isArrayType(resolvedExternalModuleType) || isTupleType(resolvedExternalModuleType)); } - function getExportsOfSymbol(symbol: ts.Symbol): ts.SymbolTable { - return symbol.flags & ts.SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) : - symbol.flags & ts.SymbolFlags.Module ? getExportsOfModule(symbol) : + function getExportsOfSymbol(symbol: Symbol): SymbolTable { + return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedExports) : + symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports || emptySymbols; } - function getExportsOfModule(moduleSymbol: ts.Symbol): ts.SymbolTable { + function getExportsOfModule(moduleSymbol: Symbol): SymbolTable { const links = getSymbolLinks(moduleSymbol); return links.resolvedExports || (links.resolvedExports = getExportsOfModuleWorker(moduleSymbol)); } interface ExportCollisionTracker { specifierText: string; - exportsWithDuplicate: ts.ExportDeclaration[]; + exportsWithDuplicate: ExportDeclaration[]; } - type ExportCollisionTrackerTable = ts.UnderscoreEscapedMap; + type ExportCollisionTrackerTable = UnderscoreEscapedMap; /** * Extends one symbol table with another while collecting information on name collisions for error message generation into the `lookupTable` argument * Not passing `lookupTable` and `exportNode` disables this collection, and just extends the tables */ - function extendExportSymbols(target: ts.SymbolTable, source: ts.SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ts.ExportDeclaration) { + function extendExportSymbols(target: SymbolTable, source: SymbolTable | undefined, lookupTable?: ExportCollisionTrackerTable, exportNode?: ExportDeclaration) { if (!source) return; source.forEach((sourceSymbol, id) => { - if (id === ts.InternalSymbolName.Default) return; + if (id === InternalSymbolName.Default) return; const targetSymbol = target.get(id); if (!targetSymbol) { target.set(id, sourceSymbol); if (lookupTable && exportNode) { lookupTable.set(id, { - specifierText: ts.getTextOfNode(exportNode.moduleSpecifier!) + specifierText: getTextOfNode(exportNode.moduleSpecifier!) } as ExportCollisionTracker); } } @@ -4082,8 +4280,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function getExportsOfModuleWorker(moduleSymbol: ts.Symbol): ts.SymbolTable { - const visitedSymbols: ts.Symbol[] = []; + function getExportsOfModuleWorker(moduleSymbol: Symbol): SymbolTable { + const visitedSymbols: Symbol[] = []; // A module defined by an 'export=' consists of one export that needs to be resolved moduleSymbol = resolveExternalModuleSymbol(moduleSymbol); @@ -4092,25 +4290,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. - function visit(symbol: ts.Symbol | undefined): ts.SymbolTable | undefined { - if (!(symbol && symbol.exports && ts.pushIfUnique(visitedSymbols, symbol))) { + function visit(symbol: Symbol | undefined): SymbolTable | undefined { + if (!(symbol && symbol.exports && pushIfUnique(visitedSymbols, symbol))) { return; } - const symbols = new ts.Map(symbol.exports); + const symbols = new Map(symbol.exports); // All export * declarations are collected in an __export symbol by the binder - const exportStars = symbol.exports.get(ts.InternalSymbolName.ExportStar); + const exportStars = symbol.exports.get(InternalSymbolName.ExportStar); if (exportStars) { - const nestedSymbols = ts.createSymbolTable(); - const lookupTable: ExportCollisionTrackerTable = new ts.Map(); + const nestedSymbols = createSymbolTable(); + const lookupTable: ExportCollisionTrackerTable = new Map(); if (exportStars.declarations) { for (const node of exportStars.declarations) { - const resolvedModule = resolveExternalModuleName(node, (node as ts.ExportDeclaration).moduleSpecifier!); + const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); const exportedSymbols = visit(resolvedModule); extendExportSymbols( nestedSymbols, exportedSymbols, lookupTable, - node as ts.ExportDeclaration + node as ExportDeclaration ); } } @@ -4120,11 +4318,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } for (const node of exportsWithDuplicate) { - diagnostics.add(ts.createDiagnosticForNode( + diagnostics.add(createDiagnosticForNode( node, - ts.Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, + Diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, lookupTable.get(id)!.specifierText, - ts.unescapeLeadingUnderscores(id) + unescapeLeadingUnderscores(id) )); } }); @@ -4134,43 +4332,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getMergedSymbol(symbol: ts.Symbol): ts.Symbol; - function getMergedSymbol(symbol: ts.Symbol | undefined): ts.Symbol | undefined; - function getMergedSymbol(symbol: ts.Symbol | undefined): ts.Symbol | undefined { - let merged: ts.Symbol; + function getMergedSymbol(symbol: Symbol): Symbol; + function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined; + function getMergedSymbol(symbol: Symbol | undefined): Symbol | undefined { + let merged: Symbol; return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol; } - function getSymbolOfNode(node: ts.Declaration): ts.Symbol; - function getSymbolOfNode(node: ts.Node): ts.Symbol | undefined; - function getSymbolOfNode(node: ts.Node): ts.Symbol | undefined { + function getSymbolOfNode(node: Declaration): Symbol; + function getSymbolOfNode(node: Node): Symbol | undefined; + function getSymbolOfNode(node: Node): Symbol | undefined { return getMergedSymbol(node.symbol && getLateBoundSymbol(node.symbol)); } - function getParentOfSymbol(symbol: ts.Symbol): ts.Symbol | undefined { + function getParentOfSymbol(symbol: Symbol): Symbol | undefined { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } - function getAlternativeContainingModules(symbol: ts.Symbol, enclosingDeclaration: ts.Node): ts.Symbol[] { - const containingFile = ts.getSourceFileOfNode(enclosingDeclaration); + function getAlternativeContainingModules(symbol: Symbol, enclosingDeclaration: Node): Symbol[] { + const containingFile = getSourceFileOfNode(enclosingDeclaration); const id = getNodeId(containingFile); const links = getSymbolLinks(symbol); - let results: ts.Symbol[] | undefined; + let results: Symbol[] | undefined; if (links.extendedContainersByFile && (results = links.extendedContainersByFile.get(id))) { return results; } if (containingFile && containingFile.imports) { // Try to make an import using an import already in the enclosing file, if possible for (const importRef of containingFile.imports) { - if (ts.nodeIsSynthesized(importRef)) continue; // Synthetic names can't be resolved by `resolveExternalModuleName` - they'll cause a debug assert if they error + if (nodeIsSynthesized(importRef)) continue; // Synthetic names can't be resolved by `resolveExternalModuleName` - they'll cause a debug assert if they error const resolvedModule = resolveExternalModuleName(enclosingDeclaration, importRef, /*ignoreErrors*/ true); if (!resolvedModule) continue; const ref = getAliasForSymbolInContainer(resolvedModule, symbol); if (!ref) continue; - results = ts.append(results, resolvedModule); + results = append(results, resolvedModule); } - if (ts.length(results)) { - (links.extendedContainersByFile || (links.extendedContainersByFile = new ts.Map())).set(id, results!); + if (length(results)) { + (links.extendedContainersByFile || (links.extendedContainersByFile = new Map())).set(id, results!); return results!; } } @@ -4180,106 +4378,106 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // No results from files already being imported by this file - expand search (expensive, but not location-specific, so cached) const otherFiles = host.getSourceFiles(); for (const file of otherFiles) { - if (!ts.isExternalModule(file)) continue; + if (!isExternalModule(file)) continue; const sym = getSymbolOfNode(file); const ref = getAliasForSymbolInContainer(sym, symbol); if (!ref) continue; - results = ts.append(results, sym); + results = append(results, sym); } - return links.extendedContainers = results || ts.emptyArray; + return links.extendedContainers = results || emptyArray; } /** * Attempts to find the symbol corresponding to the container a symbol is in - usually this * is just its' `.parent`, but for locals, this value is `undefined` */ - function getContainersOfSymbol(symbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined, meaning: ts.SymbolFlags): ts.Symbol[] | undefined { + function getContainersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): Symbol[] | undefined { const container = getParentOfSymbol(symbol); // Type parameters end up in the `members` lists but are not externally visible - if (container && !(symbol.flags & ts.SymbolFlags.TypeParameter)) { - const additionalContainers = ts.mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer); + if (container && !(symbol.flags & SymbolFlags.TypeParameter)) { + const additionalContainers = mapDefined(container.declarations, fileSymbolIfFileSymbolExportEqualsContainer); const reexportContainers = enclosingDeclaration && getAlternativeContainingModules(symbol, enclosingDeclaration); const objectLiteralContainer = getVariableDeclarationOfObjectLiteral(container, meaning); if ( enclosingDeclaration && container.flags & getQualifiedLeftMeaning(meaning) && - getAccessibleSymbolChain(container, enclosingDeclaration, ts.SymbolFlags.Namespace, /*externalOnly*/ false) + getAccessibleSymbolChain(container, enclosingDeclaration, SymbolFlags.Namespace, /*externalOnly*/ false) ) { - return ts.append(ts.concatenate(ts.concatenate([container], additionalContainers), reexportContainers), objectLiteralContainer); // This order expresses a preference for the real container if it is in scope + return append(concatenate(concatenate([container], additionalContainers), reexportContainers), objectLiteralContainer); // This order expresses a preference for the real container if it is in scope } // we potentially have a symbol which is a member of the instance side of something - look for a variable in scope with the container's type // which may be acting like a namespace (eg, `Symbol` acts like a namespace when looking up `Symbol.toStringTag`) const firstVariableMatch = !(container.flags & getQualifiedLeftMeaning(meaning)) - && container.flags & ts.SymbolFlags.Type - && getDeclaredTypeOfSymbol(container).flags & ts.TypeFlags.Object - && meaning === ts.SymbolFlags.Value + && container.flags & SymbolFlags.Type + && getDeclaredTypeOfSymbol(container).flags & TypeFlags.Object + && meaning === SymbolFlags.Value ? forEachSymbolTableInScope(enclosingDeclaration, t => { - return ts.forEachEntry(t, s => { + return forEachEntry(t, s => { if (s.flags & getQualifiedLeftMeaning(meaning) && getTypeOfSymbol(s) === getDeclaredTypeOfSymbol(container)) { return s; } }); }) : undefined; let res = firstVariableMatch ? [firstVariableMatch, ...additionalContainers, container] : [...additionalContainers, container]; - res = ts.append(res, objectLiteralContainer); - res = ts.addRange(res, reexportContainers); + res = append(res, objectLiteralContainer); + res = addRange(res, reexportContainers); return res; } - const candidates = ts.mapDefined(symbol.declarations, d => { - if (!ts.isAmbientModule(d) && d.parent){ + const candidates = mapDefined(symbol.declarations, d => { + if (!isAmbientModule(d) && d.parent){ // direct children of a module if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) { return getSymbolOfNode(d.parent); } // export ='d member of an ambient module - if (ts.isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfNode(d.parent.parent)) === symbol) { + if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfNode(d.parent.parent)) === symbol) { return getSymbolOfNode(d.parent.parent); } } - if (ts.isClassExpression(d) && ts.isBinaryExpression(d.parent) && d.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && ts.isAccessExpression(d.parent.left) && ts.isEntityNameExpression(d.parent.left.expression)) { - if (ts.isModuleExportsAccessExpression(d.parent.left) || ts.isExportsIdentifier(d.parent.left.expression)) { - return getSymbolOfNode(ts.getSourceFileOfNode(d)); + if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) { + if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) { + return getSymbolOfNode(getSourceFileOfNode(d)); } checkExpressionCached(d.parent.left.expression); return getNodeLinks(d.parent.left.expression).resolvedSymbol; } }); - if (!ts.length(candidates)) { + if (!length(candidates)) { return undefined; } - return ts.mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined); + return mapDefined(candidates, candidate => getAliasForSymbolInContainer(candidate, symbol) ? candidate : undefined); - function fileSymbolIfFileSymbolExportEqualsContainer(d: ts.Declaration) { + function fileSymbolIfFileSymbolExportEqualsContainer(d: Declaration) { return container && getFileSymbolIfFileSymbolExportEqualsContainer(d, container); } } - function getVariableDeclarationOfObjectLiteral(symbol: ts.Symbol, meaning: ts.SymbolFlags) { + function getVariableDeclarationOfObjectLiteral(symbol: Symbol, meaning: SymbolFlags) { // If we're trying to reference some object literal in, eg `var a = { x: 1 }`, the symbol for the literal, `__object`, is distinct // from the symbol of the declaration it is being assigned to. Since we can use the declaration to refer to the literal, however, // we'd like to make that connection here - potentially causing us to paint the declaration's visibility, and therefore the literal. - const firstDecl: ts.Node | false = !!ts.length(symbol.declarations) && ts.first(symbol.declarations!); - if (meaning & ts.SymbolFlags.Value && firstDecl && firstDecl.parent && ts.isVariableDeclaration(firstDecl.parent)) { - if (ts.isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer || ts.isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type) { + const firstDecl: Node | false = !!length(symbol.declarations) && first(symbol.declarations!); + if (meaning & SymbolFlags.Value && firstDecl && firstDecl.parent && isVariableDeclaration(firstDecl.parent)) { + if (isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer || isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type) { return getSymbolOfNode(firstDecl.parent); } } } - function getFileSymbolIfFileSymbolExportEqualsContainer(d: ts.Declaration, container: ts.Symbol) { + function getFileSymbolIfFileSymbolExportEqualsContainer(d: Declaration, container: Symbol) { const fileSymbol = getExternalModuleContainer(d); - const exported = fileSymbol && fileSymbol.exports && fileSymbol.exports.get(ts.InternalSymbolName.ExportEquals); + const exported = fileSymbol && fileSymbol.exports && fileSymbol.exports.get(InternalSymbolName.ExportEquals); return exported && getSymbolIfSameReference(exported, container) ? fileSymbol : undefined; } - function getAliasForSymbolInContainer(container: ts.Symbol, symbol: ts.Symbol) { + function getAliasForSymbolInContainer(container: Symbol, symbol: Symbol) { if (container === getParentOfSymbol(symbol)) { // fast path, `symbol` is either already the alias or isn't aliased return symbol; } // Check if container is a thing with an `export=` which points directly at `symbol`, and if so, return // the container itself as the alias for the symbol - const exportEquals = container.exports && container.exports.get(ts.InternalSymbolName.ExportEquals); + const exportEquals = container.exports && container.exports.get(InternalSymbolName.ExportEquals); if (exportEquals && getSymbolIfSameReference(exportEquals, symbol)) { return container; } @@ -4288,7 +4486,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (quick && getSymbolIfSameReference(quick, symbol)) { return quick; } - return ts.forEachEntry(exports, exported => { + return forEachEntry(exports, exported => { if (getSymbolIfSameReference(exported, symbol)) { return exported; } @@ -4298,60 +4496,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Checks if two symbols, through aliasing and/or merging, refer to the same thing */ - function getSymbolIfSameReference(s1: ts.Symbol, s2: ts.Symbol) { + function getSymbolIfSameReference(s1: Symbol, s2: Symbol) { if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { return s1; } } - function getExportSymbolOfValueSymbolIfExported(symbol: ts.Symbol): ts.Symbol; - function getExportSymbolOfValueSymbolIfExported(symbol: ts.Symbol | undefined): ts.Symbol | undefined; - function getExportSymbolOfValueSymbolIfExported(symbol: ts.Symbol | undefined): ts.Symbol | undefined { - return getMergedSymbol(symbol && (symbol.flags & ts.SymbolFlags.ExportValue) !== 0 && symbol.exportSymbol || symbol); + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol): Symbol; + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined; + function getExportSymbolOfValueSymbolIfExported(symbol: Symbol | undefined): Symbol | undefined { + return getMergedSymbol(symbol && (symbol.flags & SymbolFlags.ExportValue) !== 0 && symbol.exportSymbol || symbol); } - function symbolIsValue(symbol: ts.Symbol, includeTypeOnlyMembers?: boolean): boolean { + function symbolIsValue(symbol: Symbol, includeTypeOnlyMembers?: boolean): boolean { return !!( - symbol.flags & ts.SymbolFlags.Value || - symbol.flags & ts.SymbolFlags.Alias && getAllSymbolFlags(symbol) & ts.SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); + symbol.flags & SymbolFlags.Value || + symbol.flags & SymbolFlags.Alias && getAllSymbolFlags(symbol) & SymbolFlags.Value && (includeTypeOnlyMembers || !getTypeOnlyAliasDeclaration(symbol))); } - function findConstructorDeclaration(node: ts.ClassLikeDeclaration): ts.ConstructorDeclaration | undefined { + function findConstructorDeclaration(node: ClassLikeDeclaration): ConstructorDeclaration | undefined { const members = node.members; for (const member of members) { - if (member.kind === ts.SyntaxKind.Constructor && ts.nodeIsPresent((member as ts.ConstructorDeclaration).body)) { - return member as ts.ConstructorDeclaration; + if (member.kind === SyntaxKind.Constructor && nodeIsPresent((member as ConstructorDeclaration).body)) { + return member as ConstructorDeclaration; } } } - function createType(flags: ts.TypeFlags): ts.Type { + function createType(flags: TypeFlags): Type { const result = new Type(checker, flags); typeCount++; result.id = typeCount; - ts.tracing?.recordType(result); + tracing?.recordType(result); return result; } - function createTypeWithSymbol(flags: ts.TypeFlags, symbol: ts.Symbol): ts.Type { + function createTypeWithSymbol(flags: TypeFlags, symbol: Symbol): Type { const result = createType(flags); result.symbol = symbol; return result; } - function createOriginType(flags: ts.TypeFlags): ts.Type { + function createOriginType(flags: TypeFlags): Type { return new Type(checker, flags); } - function createIntrinsicType(kind: ts.TypeFlags, intrinsicName: string, objectFlags: ts.ObjectFlags = 0): ts.IntrinsicType { - const type = createType(kind) as ts.IntrinsicType; + function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags = 0): IntrinsicType { + const type = createType(kind) as IntrinsicType; type.intrinsicName = intrinsicName; type.objectFlags = objectFlags; return type; } - function createObjectType(objectFlags: ts.ObjectFlags, symbol?: ts.Symbol): ts.ObjectType { - const type = createTypeWithSymbol(ts.TypeFlags.Object, symbol!) as ts.ObjectType; + function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType { + const type = createTypeWithSymbol(TypeFlags.Object, symbol!) as ObjectType; type.objectFlags = objectFlags; type.members = undefined; type.properties = undefined; @@ -4362,49 +4560,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function createTypeofType() { - return getUnionType(ts.arrayFrom(typeofNEFacts.keys(), getStringLiteralType)); + return getUnionType(arrayFrom(typeofNEFacts.keys(), getStringLiteralType)); } - function createTypeParameter(symbol?: ts.Symbol) { - return createTypeWithSymbol(ts.TypeFlags.TypeParameter, symbol!) as ts.TypeParameter; + function createTypeParameter(symbol?: Symbol) { + return createTypeWithSymbol(TypeFlags.TypeParameter, symbol!) as TypeParameter; } // A reserved member name starts with two underscores, but the third character cannot be an underscore, // @, or #. A third underscore indicates an escaped form of an identifier that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES // Symbol instance and the # character indicates that the name is a PrivateIdentifier. - function isReservedMemberName(name: ts.__String) { - return (name as string).charCodeAt(0) === ts.CharacterCodes._ && - (name as string).charCodeAt(1) === ts.CharacterCodes._ && - (name as string).charCodeAt(2) !== ts.CharacterCodes._ && - (name as string).charCodeAt(2) !== ts.CharacterCodes.at && - (name as string).charCodeAt(2) !== ts.CharacterCodes.hash; + function isReservedMemberName(name: __String) { + return (name as string).charCodeAt(0) === CharacterCodes._ && + (name as string).charCodeAt(1) === CharacterCodes._ && + (name as string).charCodeAt(2) !== CharacterCodes._ && + (name as string).charCodeAt(2) !== CharacterCodes.at && + (name as string).charCodeAt(2) !== CharacterCodes.hash; } - function getNamedMembers(members: ts.SymbolTable): ts.Symbol[] { - let result: ts.Symbol[] | undefined; + function getNamedMembers(members: SymbolTable): Symbol[] { + let result: Symbol[] | undefined; members.forEach((symbol, id) => { if (isNamedMember(symbol, id)) { (result || (result = [])).push(symbol); } }); - return result || ts.emptyArray; + return result || emptyArray; } - function isNamedMember(member: ts.Symbol, escapedName: ts.__String) { + function isNamedMember(member: Symbol, escapedName: __String) { return !isReservedMemberName(escapedName) && symbolIsValue(member); } - function getNamedOrIndexSignatureMembers(members: ts.SymbolTable): ts.Symbol[] { + function getNamedOrIndexSignatureMembers(members: SymbolTable): Symbol[] { const result = getNamedMembers(members); const index = getIndexSymbolFromSymbolTable(members); - return index ? ts.concatenate(result, [index]) : result; + return index ? concatenate(result, [index]) : result; } - function setStructuredTypeMembers(type: ts.StructuredType, members: ts.SymbolTable, callSignatures: readonly ts.Signature[], constructSignatures: readonly ts.Signature[], indexInfos: readonly ts.IndexInfo[]): ts.ResolvedType { - const resolved = type as ts.ResolvedType; + function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType { + const resolved = type as ResolvedType; resolved.members = members; - resolved.properties = ts.emptyArray; + resolved.properties = emptyArray; resolved.callSignatures = callSignatures; resolved.constructSignatures = constructSignatures; resolved.indexInfos = indexInfos; @@ -4413,28 +4611,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolved; } - function createAnonymousType(symbol: ts.Symbol | undefined, members: ts.SymbolTable, callSignatures: readonly ts.Signature[], constructSignatures: readonly ts.Signature[], indexInfos: readonly ts.IndexInfo[]): ts.ResolvedType { - return setStructuredTypeMembers(createObjectType(ts.ObjectFlags.Anonymous, symbol), + function createAnonymousType(symbol: Symbol | undefined, members: SymbolTable, callSignatures: readonly Signature[], constructSignatures: readonly Signature[], indexInfos: readonly IndexInfo[]): ResolvedType { + return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol), members, callSignatures, constructSignatures, indexInfos); } - function getResolvedTypeWithoutAbstractConstructSignatures(type: ts.ResolvedType) { + function getResolvedTypeWithoutAbstractConstructSignatures(type: ResolvedType) { if (type.constructSignatures.length === 0) return type; if (type.objectTypeWithoutAbstractConstructSignatures) return type.objectTypeWithoutAbstractConstructSignatures; - const constructSignatures = ts.filter(type.constructSignatures, signature => !(signature.flags & ts.SignatureFlags.Abstract)); + const constructSignatures = filter(type.constructSignatures, signature => !(signature.flags & SignatureFlags.Abstract)); if (type.constructSignatures === constructSignatures) return type; const typeCopy = createAnonymousType( type.symbol, type.members, type.callSignatures, - ts.some(constructSignatures) ? constructSignatures : ts.emptyArray, + some(constructSignatures) ? constructSignatures : emptyArray, type.indexInfos); type.objectTypeWithoutAbstractConstructSignatures = typeCopy; typeCopy.objectTypeWithoutAbstractConstructSignatures = typeCopy; return typeCopy; } - function forEachSymbolTableInScope(enclosingDeclaration: ts.Node | undefined, callback: (symbolTable: ts.SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean, scopeNode?: ts.Node) => T): T { + function forEachSymbolTableInScope(enclosingDeclaration: Node | undefined, callback: (symbolTable: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean, scopeNode?: Node) => T): T { let result: T; for (let location = enclosingDeclaration; location; location = location.parent) { // Locals of a source file are not in scope (because they get merged into the global symbol table) @@ -4444,13 +4642,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } switch (location.kind) { - case ts.SyntaxKind.SourceFile: - if (!ts.isExternalOrCommonJsModule(location as ts.SourceFile)) { + case SyntaxKind.SourceFile: + if (!isExternalOrCommonJsModule(location as SourceFile)) { break; } // falls through - case ts.SyntaxKind.ModuleDeclaration: - const sym = getSymbolOfNode(location as ts.ModuleDeclaration); + case SyntaxKind.ModuleDeclaration: + const sym = getSymbolOfNode(location as ModuleDeclaration); // `sym` may not have exports if this module declaration is backed by the symbol for a `const` that's being rewritten // into a namespace - in such cases, it's best to just let the namespace appear empty (the const members couldn't have referred // to one another anyway) @@ -4458,9 +4656,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: // Type parameters are bound into `members` lists so they can merge across declarations // This is troublesome, since in all other respects, they behave like locals :cries: // TODO: the below is shared with similar code in `resolveName` - in fact, rephrasing all this symbol @@ -4468,11 +4666,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would // trigger resolving late-bound names, which we may already be in the process of doing while we're here! - let table: ts.UnderscoreEscapedMap | undefined; + let table: UnderscoreEscapedMap | undefined; // TODO: Should this filtered table be cached in some way? - (getSymbolOfNode(location as ts.ClassLikeDeclaration | ts.InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => { - if (memberSymbol.flags & (ts.SymbolFlags.Type & ~ts.SymbolFlags.Assignment)) { - (table || (table = ts.createSymbolTable())).set(key, memberSymbol); + (getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => { + if (memberSymbol.flags & (SymbolFlags.Type & ~SymbolFlags.Assignment)) { + (table || (table = createSymbolTable())).set(key, memberSymbol); } }); if (table && (result = callback(table, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ false, location))) { @@ -4485,17 +4683,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return callback(globals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true); } - function getQualifiedLeftMeaning(rightMeaning: ts.SymbolFlags) { + function getQualifiedLeftMeaning(rightMeaning: SymbolFlags) { // If we are looking in value space, the parent meaning is value, other wise it is namespace - return rightMeaning === ts.SymbolFlags.Value ? ts.SymbolFlags.Value : ts.SymbolFlags.Namespace; + return rightMeaning === SymbolFlags.Value ? SymbolFlags.Value : SymbolFlags.Namespace; } - function getAccessibleSymbolChain(symbol: ts.Symbol | undefined, enclosingDeclaration: ts.Node | undefined, meaning: ts.SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: ts.ESMap = new ts.Map()): ts.Symbol[] | undefined { + function getAccessibleSymbolChain(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, useOnlyExternalAliasing: boolean, visitedSymbolTablesMap: ESMap = new Map()): Symbol[] | undefined { if (!(symbol && !isPropertyOrMethodDeclarationSymbol(symbol))) { return undefined; } const links = getSymbolLinks(symbol); - const cache = (links.accessibleChainCache ||= new ts.Map()); + const cache = (links.accessibleChainCache ||= new Map()); // Go from enclosingDeclaration to the first scope we check, so the cache is keyed off the scope and thus shared more const firstRelevantLocation = forEachSymbolTableInScope(enclosingDeclaration, (_, __, ___, node) => node); const key = `${useOnlyExternalAliasing ? 0 : 1}|${firstRelevantLocation && getNodeId(firstRelevantLocation)}|${meaning}`; @@ -4515,8 +4713,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) */ - function getAccessibleSymbolChainFromSymbolTable(symbols: ts.SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean): ts.Symbol[] | undefined { - if (!ts.pushIfUnique(visitedSymbolTables!, symbols)) { + function getAccessibleSymbolChainFromSymbolTable(symbols: SymbolTable, ignoreQualification?: boolean, isLocalNameLookup?: boolean): Symbol[] | undefined { + if (!pushIfUnique(visitedSymbolTables!, symbols)) { return undefined; } @@ -4525,41 +4723,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function canQualifySymbol(symbolFromSymbolTable: ts.Symbol, meaning: ts.SymbolFlags) { + function canQualifySymbol(symbolFromSymbolTable: Symbol, meaning: SymbolFlags) { // If the symbol is equivalent and doesn't need further qualification, this symbol is accessible return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing, visitedSymbolTablesMap); } - function isAccessible(symbolFromSymbolTable: ts.Symbol, resolvedAliasSymbol?: ts.Symbol, ignoreQualification?: boolean) { + function isAccessible(symbolFromSymbolTable: Symbol, resolvedAliasSymbol?: Symbol, ignoreQualification?: boolean) { return (symbol === (resolvedAliasSymbol || symbolFromSymbolTable) || getMergedSymbol(symbol) === getMergedSymbol(resolvedAliasSymbol || symbolFromSymbolTable)) && // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) // and if symbolFromSymbolTable or alias resolution matches the symbol, // check the symbol can be qualified, it is only then this symbol is accessible - !ts.some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) && + !some(symbolFromSymbolTable.declarations, hasNonGlobalAugmentationExternalModuleSymbol) && (ignoreQualification || canQualifySymbol(getMergedSymbol(symbolFromSymbolTable), meaning)); } - function trySymbolTable(symbols: ts.SymbolTable, ignoreQualification: boolean | undefined, isLocalNameLookup: boolean | undefined): ts.Symbol[] | undefined { + function trySymbolTable(symbols: SymbolTable, ignoreQualification: boolean | undefined, isLocalNameLookup: boolean | undefined): Symbol[] | undefined { // If symbol is directly available by its name in the symbol table if (isAccessible(symbols.get(symbol!.escapedName)!, /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol!]; } // Check if symbol is any of the aliases in scope - const result = ts.forEachEntry(symbols, symbolFromSymbolTable => { - if (symbolFromSymbolTable.flags & ts.SymbolFlags.Alias - && symbolFromSymbolTable.escapedName !== ts.InternalSymbolName.ExportEquals - && symbolFromSymbolTable.escapedName !== ts.InternalSymbolName.Default - && !(ts.isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && ts.isExternalModule(ts.getSourceFileOfNode(enclosingDeclaration))) + const result = forEachEntry(symbols, symbolFromSymbolTable => { + if (symbolFromSymbolTable.flags & SymbolFlags.Alias + && symbolFromSymbolTable.escapedName !== InternalSymbolName.ExportEquals + && symbolFromSymbolTable.escapedName !== InternalSymbolName.Default + && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && isExternalModule(getSourceFileOfNode(enclosingDeclaration))) // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name - && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration)) + && (!useOnlyExternalAliasing || some(symbolFromSymbolTable.declarations, isExternalModuleImportEqualsDeclaration)) // If we're looking up a local name to reference directly, omit namespace reexports, otherwise when we're trawling through an export list to make a dotted name, we can keep it - && (isLocalNameLookup ? !ts.some(symbolFromSymbolTable.declarations, ts.isNamespaceReexportDeclaration) : true) + && (isLocalNameLookup ? !some(symbolFromSymbolTable.declarations, isNamespaceReexportDeclaration) : true) // While exports are generally considered to be in scope, export-specifier declared symbols are _not_ // See similar comment in `resolveName` for details - && (ignoreQualification || !ts.getDeclarationOfKind(symbolFromSymbolTable, ts.SyntaxKind.ExportSpecifier)) + && (ignoreQualification || !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) ) { const resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); @@ -4579,7 +4777,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result || (symbols === globals ? getCandidateListForSymbol(globalThisSymbol, globalThisSymbol, ignoreQualification) : undefined); } - function getCandidateListForSymbol(symbolFromSymbolTable: ts.Symbol, resolvedImportedSymbol: ts.Symbol, ignoreQualification: boolean | undefined) { + function getCandidateListForSymbol(symbolFromSymbolTable: Symbol, resolvedImportedSymbol: Symbol, ignoreQualification: boolean | undefined) { if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } @@ -4594,7 +4792,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function needsQualification(symbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined, meaning: ts.SymbolFlags) { + function needsQualification(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags) { let qualify = false; forEachSymbolTableInScope(enclosingDeclaration, symbolTable => { // If symbol of this name is not available in the symbol table we are ok @@ -4610,7 +4808,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Qualify if the symbol from symbol table has same meaning as expected - const shouldResolveAlias = (symbolFromSymbolTable.flags & ts.SymbolFlags.Alias && !ts.getDeclarationOfKind(symbolFromSymbolTable, ts.SyntaxKind.ExportSpecifier)); + const shouldResolveAlias = (symbolFromSymbolTable.flags & SymbolFlags.Alias && !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)); symbolFromSymbolTable = shouldResolveAlias ? resolveAlias(symbolFromSymbolTable) : symbolFromSymbolTable; const flags = shouldResolveAlias ? getAllSymbolFlags(symbolFromSymbolTable) : symbolFromSymbolTable.flags; if (flags & meaning) { @@ -4625,14 +4823,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return qualify; } - function isPropertyOrMethodDeclarationSymbol(symbol: ts.Symbol) { + function isPropertyOrMethodDeclarationSymbol(symbol: Symbol) { if (symbol.declarations && symbol.declarations.length) { for (const declaration of symbol.declarations) { switch (declaration.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: continue; default: return false; @@ -4643,25 +4841,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isTypeSymbolAccessible(typeSymbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined): boolean { - const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, ts.SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); - return access.accessibility === ts.SymbolAccessibility.Accessible; + function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean { + const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); + return access.accessibility === SymbolAccessibility.Accessible; } - function isValueSymbolAccessible(typeSymbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined): boolean { - const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, ts.SymbolFlags.Value, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); - return access.accessibility === ts.SymbolAccessibility.Accessible; + function isValueSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node | undefined): boolean { + const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, SymbolFlags.Value, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ true); + return access.accessibility === SymbolAccessibility.Accessible; } - function isSymbolAccessibleByFlags(typeSymbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined, flags: ts.SymbolFlags): boolean { + function isSymbolAccessibleByFlags(typeSymbol: Symbol, enclosingDeclaration: Node | undefined, flags: SymbolFlags): boolean { const access = isSymbolAccessibleWorker(typeSymbol, enclosingDeclaration, flags, /*shouldComputeAliasesToMakeVisible*/ false, /*allowModules*/ false); - return access.accessibility === ts.SymbolAccessibility.Accessible; + return access.accessibility === SymbolAccessibility.Accessible; } - function isAnySymbolAccessible(symbols: ts.Symbol[] | undefined, enclosingDeclaration: ts.Node | undefined, initialSymbol: ts.Symbol, meaning: ts.SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): ts.SymbolAccessibilityResult | undefined { - if (!ts.length(symbols)) return; + function isAnySymbolAccessible(symbols: Symbol[] | undefined, enclosingDeclaration: Node | undefined, initialSymbol: Symbol, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult | undefined { + if (!length(symbols)) return; - let hadAccessibleChain: ts.Symbol | undefined; + let hadAccessibleChain: Symbol | undefined; let earlyModuleBail = false; for (const symbol of symbols!) { // Symbol is accessible if it by itself is accessible @@ -4674,7 +4872,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (allowModules) { - if (ts.some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + if (some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { if (shouldComputeAliasesToMakeVisible) { earlyModuleBail = true; // Generally speaking, we want to use the aliases that already exist to refer to a module, if present @@ -4685,7 +4883,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Any meaning of a module symbol is always accessible via an `import` type return { - accessibility: ts.SymbolAccessibility.Accessible + accessibility: SymbolAccessibility.Accessible }; } } @@ -4712,15 +4910,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (earlyModuleBail) { return { - accessibility: ts.SymbolAccessibility.Accessible + accessibility: SymbolAccessibility.Accessible }; } if (hadAccessibleChain) { return { - accessibility: ts.SymbolAccessibility.NotAccessible, + accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: symbolToString(initialSymbol, enclosingDeclaration, meaning), - errorModuleName: hadAccessibleChain !== initialSymbol ? symbolToString(hadAccessibleChain, enclosingDeclaration, ts.SymbolFlags.Namespace) : undefined, + errorModuleName: hadAccessibleChain !== initialSymbol ? symbolToString(hadAccessibleChain, enclosingDeclaration, SymbolFlags.Namespace) : undefined, }; } } @@ -4733,11 +4931,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param meaning a SymbolFlags to check if such meaning of the symbol is accessible * @param shouldComputeAliasToMakeVisible a boolean value to indicate whether to return aliases to be mark visible in case the symbol is accessible */ - function isSymbolAccessible(symbol: ts.Symbol | undefined, enclosingDeclaration: ts.Node | undefined, meaning: ts.SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): ts.SymbolAccessibilityResult { + function isSymbolAccessible(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean): SymbolAccessibilityResult { return isSymbolAccessibleWorker(symbol, enclosingDeclaration, meaning, shouldComputeAliasesToMakeVisible, /*allowModules*/ true); } - function isSymbolAccessibleWorker(symbol: ts.Symbol | undefined, enclosingDeclaration: ts.Node | undefined, meaning: ts.SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): ts.SymbolAccessibilityResult { + function isSymbolAccessibleWorker(symbol: Symbol | undefined, enclosingDeclaration: Node | undefined, meaning: SymbolFlags, shouldComputeAliasesToMakeVisible: boolean, allowModules: boolean): SymbolAccessibilityResult { if (symbol && enclosingDeclaration) { const result = isAnySymbolAccessible([symbol], enclosingDeclaration, symbol, meaning, shouldComputeAliasesToMakeVisible, allowModules); if (result) { @@ -4746,83 +4944,83 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // This could be a symbol that is not exported in the external module // or it could be a symbol from different external module that is not aliased and hence cannot be named - const symbolExternalModule = ts.forEach(symbol.declarations, getExternalModuleContainer); + const symbolExternalModule = forEach(symbol.declarations, getExternalModuleContainer); if (symbolExternalModule) { const enclosingExternalModule = getExternalModuleContainer(enclosingDeclaration); if (symbolExternalModule !== enclosingExternalModule) { // name from different external module that is not visible return { - accessibility: ts.SymbolAccessibility.CannotBeNamed, + accessibility: SymbolAccessibility.CannotBeNamed, errorSymbolName: symbolToString(symbol, enclosingDeclaration, meaning), errorModuleName: symbolToString(symbolExternalModule), - errorNode: ts.isInJSFile(enclosingDeclaration) ? enclosingDeclaration : undefined, + errorNode: isInJSFile(enclosingDeclaration) ? enclosingDeclaration : undefined, }; } } // Just a local name that is not accessible return { - accessibility: ts.SymbolAccessibility.NotAccessible, + accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: symbolToString(symbol, enclosingDeclaration, meaning), }; } - return { accessibility: ts.SymbolAccessibility.Accessible }; + return { accessibility: SymbolAccessibility.Accessible }; } - function getExternalModuleContainer(declaration: ts.Node) { - const node = ts.findAncestor(declaration, hasExternalModuleSymbol); + function getExternalModuleContainer(declaration: Node) { + const node = findAncestor(declaration, hasExternalModuleSymbol); return node && getSymbolOfNode(node); } - function hasExternalModuleSymbol(declaration: ts.Node) { - return ts.isAmbientModule(declaration) || (declaration.kind === ts.SyntaxKind.SourceFile && ts.isExternalOrCommonJsModule(declaration as ts.SourceFile)); + function hasExternalModuleSymbol(declaration: Node) { + return isAmbientModule(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); } - function hasNonGlobalAugmentationExternalModuleSymbol(declaration: ts.Node) { - return ts.isModuleWithStringLiteralName(declaration) || (declaration.kind === ts.SyntaxKind.SourceFile && ts.isExternalOrCommonJsModule(declaration as ts.SourceFile)); + function hasNonGlobalAugmentationExternalModuleSymbol(declaration: Node) { + return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile)); } - function hasVisibleDeclarations(symbol: ts.Symbol, shouldComputeAliasToMakeVisible: boolean): ts.SymbolVisibilityResult | undefined { - let aliasesToMakeVisible: ts.LateVisibilityPaintedStatement[] | undefined; - if (!ts.every(ts.filter(symbol.declarations, d => d.kind !== ts.SyntaxKind.Identifier), getIsDeclarationVisible)) { + function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined { + let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined; + if (!every(filter(symbol.declarations, d => d.kind !== SyntaxKind.Identifier), getIsDeclarationVisible)) { return undefined; } - return { accessibility: ts.SymbolAccessibility.Accessible, aliasesToMakeVisible }; + return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible }; - function getIsDeclarationVisible(declaration: ts.Declaration) { + function getIsDeclarationVisible(declaration: Declaration) { if (!isDeclarationVisible(declaration)) { // Mark the unexported alias as visible if its parent is visible // because these kind of aliases can be used to name types in declaration file const anyImportSyntax = getAnyImportSyntax(declaration); if (anyImportSyntax && - !ts.hasSyntacticModifier(anyImportSyntax, ts.ModifierFlags.Export) && // import clause without export + !hasSyntacticModifier(anyImportSyntax, ModifierFlags.Export) && // import clause without export isDeclarationVisible(anyImportSyntax.parent)) { return addVisibleAlias(declaration, anyImportSyntax); } - else if (ts.isVariableDeclaration(declaration) && ts.isVariableStatement(declaration.parent.parent) && - !ts.hasSyntacticModifier(declaration.parent.parent, ts.ModifierFlags.Export) && // unexported variable statement + else if (isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) && + !hasSyntacticModifier(declaration.parent.parent, ModifierFlags.Export) && // unexported variable statement isDeclarationVisible(declaration.parent.parent.parent)) { return addVisibleAlias(declaration, declaration.parent.parent); } - else if (ts.isLateVisibilityPaintedStatement(declaration) // unexported top-level statement - && !ts.hasSyntacticModifier(declaration, ts.ModifierFlags.Export) + else if (isLateVisibilityPaintedStatement(declaration) // unexported top-level statement + && !hasSyntacticModifier(declaration, ModifierFlags.Export) && isDeclarationVisible(declaration.parent)) { return addVisibleAlias(declaration, declaration); } - else if (ts.isBindingElement(declaration)) { - if (symbol.flags & ts.SymbolFlags.Alias && ts.isInJSFile(declaration) && declaration.parent?.parent // exported import-like top-level JS require statement - && ts.isVariableDeclaration(declaration.parent.parent) - && declaration.parent.parent.parent?.parent && ts.isVariableStatement(declaration.parent.parent.parent.parent) - && !ts.hasSyntacticModifier(declaration.parent.parent.parent.parent, ts.ModifierFlags.Export) + else if (isBindingElement(declaration)) { + if (symbol.flags & SymbolFlags.Alias && isInJSFile(declaration) && declaration.parent?.parent // exported import-like top-level JS require statement + && isVariableDeclaration(declaration.parent.parent) + && declaration.parent.parent.parent?.parent && isVariableStatement(declaration.parent.parent.parent.parent) + && !hasSyntacticModifier(declaration.parent.parent.parent.parent, ModifierFlags.Export) && declaration.parent.parent.parent.parent.parent // check if the thing containing the variable statement is visible (ie, the file) && isDeclarationVisible(declaration.parent.parent.parent.parent.parent)) { return addVisibleAlias(declaration, declaration.parent.parent.parent.parent); } - else if (symbol.flags & ts.SymbolFlags.BlockScopedVariable) { - const variableStatement = ts.findAncestor(declaration, ts.isVariableStatement)!; - if (ts.hasSyntacticModifier(variableStatement, ts.ModifierFlags.Export)) { + else if (symbol.flags & SymbolFlags.BlockScopedVariable) { + const variableStatement = findAncestor(declaration, isVariableStatement)!; + if (hasSyntacticModifier(variableStatement, ModifierFlags.Export)) { return true; } if (!isDeclarationVisible(variableStatement.parent)) { @@ -4839,124 +5037,124 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function addVisibleAlias(declaration: ts.Declaration, aliasingStatement: ts.LateVisibilityPaintedStatement) { + function addVisibleAlias(declaration: Declaration, aliasingStatement: LateVisibilityPaintedStatement) { // In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types, // we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time // since we will do the emitting later in trackSymbol. if (shouldComputeAliasToMakeVisible) { getNodeLinks(declaration).isVisible = true; - aliasesToMakeVisible = ts.appendIfUnique(aliasesToMakeVisible, aliasingStatement); + aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, aliasingStatement); } return true; } } - function isEntityNameVisible(entityName: ts.EntityNameOrEntityNameExpression, enclosingDeclaration: ts.Node): ts.SymbolVisibilityResult { + function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult { // get symbol of the first identifier of the entityName - let meaning: ts.SymbolFlags; - if (entityName.parent.kind === ts.SyntaxKind.TypeQuery || - entityName.parent.kind === ts.SyntaxKind.ExpressionWithTypeArguments && !ts.isPartOfTypeNode(entityName.parent) || - entityName.parent.kind === ts.SyntaxKind.ComputedPropertyName) { + let meaning: SymbolFlags; + if (entityName.parent.kind === SyntaxKind.TypeQuery || + entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || + entityName.parent.kind === SyntaxKind.ComputedPropertyName) { // Typeof value - meaning = ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue; + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } - else if (entityName.kind === ts.SyntaxKind.QualifiedName || entityName.kind === ts.SyntaxKind.PropertyAccessExpression || - entityName.parent.kind === ts.SyntaxKind.ImportEqualsDeclaration) { + else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || + entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) { // Left identifier from type reference or TypeAlias // Entity name of the import declaration - meaning = ts.SymbolFlags.Namespace; + meaning = SymbolFlags.Namespace; } else { // Type Reference or TypeAlias entity = Identifier - meaning = ts.SymbolFlags.Type; + meaning = SymbolFlags.Type; } - const firstIdentifier = ts.getFirstIdentifier(entityName); + const firstIdentifier = getFirstIdentifier(entityName); const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); - if (symbol && symbol.flags & ts.SymbolFlags.TypeParameter && meaning & ts.SymbolFlags.Type) { - return { accessibility: ts.SymbolAccessibility.Accessible }; + if (symbol && symbol.flags & SymbolFlags.TypeParameter && meaning & SymbolFlags.Type) { + return { accessibility: SymbolAccessibility.Accessible }; } - if (!symbol && ts.isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfNode(ts.getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false)), firstIdentifier, meaning, /*computeAliases*/ false).accessibility === ts.SymbolAccessibility.Accessible) { - return { accessibility: ts.SymbolAccessibility.Accessible }; + if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfNode(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false)), firstIdentifier, meaning, /*computeAliases*/ false).accessibility === SymbolAccessibility.Accessible) { + return { accessibility: SymbolAccessibility.Accessible }; } // Verify if the symbol is accessible return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || { - accessibility: ts.SymbolAccessibility.NotAccessible, - errorSymbolName: ts.getTextOfNode(firstIdentifier), + accessibility: SymbolAccessibility.NotAccessible, + errorSymbolName: getTextOfNode(firstIdentifier), errorNode: firstIdentifier }; } - function symbolToString(symbol: ts.Symbol, enclosingDeclaration?: ts.Node, meaning?: ts.SymbolFlags, flags: ts.SymbolFormatFlags = ts.SymbolFormatFlags.AllowAnyNodeKind, writer?: ts.EmitTextWriter): string { - let nodeFlags = ts.NodeBuilderFlags.IgnoreErrors; - if (flags & ts.SymbolFormatFlags.UseOnlyExternalAliasing) { - nodeFlags |= ts.NodeBuilderFlags.UseOnlyExternalAliasing; + function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, writer?: EmitTextWriter): string { + let nodeFlags = NodeBuilderFlags.IgnoreErrors; + if (flags & SymbolFormatFlags.UseOnlyExternalAliasing) { + nodeFlags |= NodeBuilderFlags.UseOnlyExternalAliasing; } - if (flags & ts.SymbolFormatFlags.WriteTypeParametersOrArguments) { - nodeFlags |= ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName; + if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) { + nodeFlags |= NodeBuilderFlags.WriteTypeParametersInQualifiedName; } - if (flags & ts.SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope) { - nodeFlags |= ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; + if (flags & SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope) { + nodeFlags |= NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; } - if (flags & ts.SymbolFormatFlags.DoNotIncludeSymbolChain) { - nodeFlags |= ts.NodeBuilderFlags.DoNotIncludeSymbolChain; + if (flags & SymbolFormatFlags.DoNotIncludeSymbolChain) { + nodeFlags |= NodeBuilderFlags.DoNotIncludeSymbolChain; } - if (flags & ts.SymbolFormatFlags.WriteComputedProps) { - nodeFlags |= ts.NodeBuilderFlags.WriteComputedProps; + if (flags & SymbolFormatFlags.WriteComputedProps) { + nodeFlags |= NodeBuilderFlags.WriteComputedProps; } - const builder = flags & ts.SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToNode : nodeBuilder.symbolToEntityName; - return writer ? symbolToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(symbolToStringWorker); + const builder = flags & SymbolFormatFlags.AllowAnyNodeKind ? nodeBuilder.symbolToNode : nodeBuilder.symbolToEntityName; + return writer ? symbolToStringWorker(writer).getText() : usingSingleLineStringWriter(symbolToStringWorker); - function symbolToStringWorker(writer: ts.EmitTextWriter) { + function symbolToStringWorker(writer: EmitTextWriter) { const entity = builder(symbol, meaning!, enclosingDeclaration, nodeFlags)!; // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - const printer = enclosingDeclaration?.kind === ts.SyntaxKind.SourceFile ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); - const sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(ts.EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer); + const printer = enclosingDeclaration?.kind === SyntaxKind.SourceFile ? createPrinter({ removeComments: true, neverAsciiEscape: true }) : createPrinter({ removeComments: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer); return writer; } } - function signatureToString(signature: ts.Signature, enclosingDeclaration?: ts.Node, flags = ts.TypeFormatFlags.None, kind?: ts.SignatureKind, writer?: ts.EmitTextWriter): string { - return writer ? signatureToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(signatureToStringWorker); + function signatureToString(signature: Signature, enclosingDeclaration?: Node, flags = TypeFormatFlags.None, kind?: SignatureKind, writer?: EmitTextWriter): string { + return writer ? signatureToStringWorker(writer).getText() : usingSingleLineStringWriter(signatureToStringWorker); - function signatureToStringWorker(writer: ts.EmitTextWriter) { - let sigOutput: ts.SyntaxKind; - if (flags & ts.TypeFormatFlags.WriteArrowStyleSignature) { - sigOutput = kind === ts.SignatureKind.Construct ? ts.SyntaxKind.ConstructorType : ts.SyntaxKind.FunctionType; + function signatureToStringWorker(writer: EmitTextWriter) { + let sigOutput: SyntaxKind; + if (flags & TypeFormatFlags.WriteArrowStyleSignature) { + sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructorType : SyntaxKind.FunctionType; } else { - sigOutput = kind === ts.SignatureKind.Construct ? ts.SyntaxKind.ConstructSignature : ts.SyntaxKind.CallSignature; + sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature; } - const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName); - const printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); - const sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(ts.EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 + const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); + const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; } } - function typeToString(type: ts.Type, enclosingDeclaration?: ts.Node, flags: ts.TypeFormatFlags = ts.TypeFormatFlags.AllowUniqueESSymbolType | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: ts.EmitTextWriter = ts.createTextWriter("")): string { - const noTruncation = compilerOptions.noErrorTruncation || flags & ts.TypeFormatFlags.NoTruncation; - const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | ts.NodeBuilderFlags.IgnoreErrors | (noTruncation ? ts.NodeBuilderFlags.NoTruncation : 0), writer); - if (typeNode === undefined) return ts.Debug.fail("should always get typenode"); + function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: EmitTextWriter = createTextWriter("")): string { + const noTruncation = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation; + const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0), writer); + if (typeNode === undefined) return Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. const options = { removeComments: type !== unresolvedType }; - const printer = ts.createPrinter(options); - const sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(ts.EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); + const printer = createPrinter(options); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); - const maxLength = noTruncation ? ts.noTruncationMaximumTruncationLength * 2 : ts.defaultMaximumTruncationLength * 2; + const maxLength = noTruncation ? noTruncationMaximumTruncationLength * 2 : defaultMaximumTruncationLength * 2; if (maxLength && result && result.length >= maxLength) { return result.substr(0, maxLength - "...".length) + "..."; } return result; } - function getTypeNamesForErrorDisplay(left: ts.Type, right: ts.Type): [string, string] { + function getTypeNamesForErrorDisplay(left: Type, right: Type): [string, string] { let leftStr = symbolValueDeclarationIsContextSensitive(left.symbol) ? typeToString(left, left.symbol.valueDeclaration) : typeToString(left); let rightStr = symbolValueDeclarationIsContextSensitive(right.symbol) ? typeToString(right, right.symbol.valueDeclaration) : typeToString(right); if (leftStr === rightStr) { @@ -4966,73 +5164,73 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return [leftStr, rightStr]; } - function getTypeNameForErrorDisplay(type: ts.Type) { - return typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.UseFullyQualifiedType); + function getTypeNameForErrorDisplay(type: Type) { + return typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType); } - function symbolValueDeclarationIsContextSensitive(symbol: ts.Symbol): boolean { - return symbol && !!symbol.valueDeclaration && ts.isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration); + function symbolValueDeclarationIsContextSensitive(symbol: Symbol): boolean { + return symbol && !!symbol.valueDeclaration && isExpression(symbol.valueDeclaration) && !isContextSensitive(symbol.valueDeclaration); } - function toNodeBuilderFlags(flags = ts.TypeFormatFlags.None): ts.NodeBuilderFlags { - return flags & ts.TypeFormatFlags.NodeBuilderFlagsMask; + function toNodeBuilderFlags(flags = TypeFormatFlags.None): NodeBuilderFlags { + return flags & TypeFormatFlags.NodeBuilderFlagsMask; } - function isClassInstanceSide(type: ts.Type) { - return !!type.symbol && !!(type.symbol.flags & ts.SymbolFlags.Class) && (type === getDeclaredTypeOfClassOrInterface(type.symbol) || (!!(type.flags & ts.TypeFlags.Object) && !!(ts.getObjectFlags(type) & ts.ObjectFlags.IsClassInstanceClone))); + function isClassInstanceSide(type: Type) { + return !!type.symbol && !!(type.symbol.flags & SymbolFlags.Class) && (type === getDeclaredTypeOfClassOrInterface(type.symbol) || (!!(type.flags & TypeFlags.Object) && !!(getObjectFlags(type) & ObjectFlags.IsClassInstanceClone))); } function createNodeBuilder() { return { - typeToTypeNode: (type: ts.Type, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)), - indexInfoToIndexSignatureDeclaration: (indexInfo: ts.IndexInfo, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)), - signatureToSignatureDeclaration: (signature: ts.Signature, kind: ts.SignatureDeclaration["kind"], enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)), - symbolToEntityName: (symbol: ts.Symbol, meaning: ts.SymbolFlags, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)), - symbolToExpression: (symbol: ts.Symbol, meaning: ts.SymbolFlags, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + symbolToExpression: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToExpression(symbol, context, meaning)), - symbolToTypeParameterDeclarations: (symbol: ts.Symbol, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + symbolToTypeParameterDeclarations: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeParametersToTypeParameterDeclarations(symbol, context)), - symbolToParameterDeclaration: (symbol: ts.Symbol, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + symbolToParameterDeclaration: (symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToParameterDeclaration(symbol, context)), - typeParameterToDeclaration: (parameter: ts.TypeParameter, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + typeParameterToDeclaration: (parameter: TypeParameter, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeParameterToDeclaration(parameter, context)), - symbolTableToDeclarationStatements: (symbolTable: ts.SymbolTable, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker, bundled?: boolean) => + symbolTableToDeclarationStatements: (symbolTable: SymbolTable, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker, bundled?: boolean) => withContext(enclosingDeclaration, flags, tracker, context => symbolTableToDeclarationStatements(symbolTable, context, bundled)), - symbolToNode: (symbol: ts.Symbol, meaning: ts.SymbolFlags, enclosingDeclaration?: ts.Node, flags?: ts.NodeBuilderFlags, tracker?: ts.SymbolTracker) => + symbolToNode: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToNode(symbol, context, meaning)), }; - function symbolToNode(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags) { - if (context.flags & ts.NodeBuilderFlags.WriteComputedProps) { + function symbolToNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { + if (context.flags & NodeBuilderFlags.WriteComputedProps) { if (symbol.valueDeclaration) { - const name = ts.getNameOfDeclaration(symbol.valueDeclaration); - if (name && ts.isComputedPropertyName(name)) return name; + const name = getNameOfDeclaration(symbol.valueDeclaration); + if (name && isComputedPropertyName(name)) return name; } const nameType = getSymbolLinks(symbol).nameType; - if (nameType && nameType.flags & (ts.TypeFlags.EnumLiteral | ts.TypeFlags.UniqueESSymbol)) { + if (nameType && nameType.flags & (TypeFlags.EnumLiteral | TypeFlags.UniqueESSymbol)) { context.enclosingDeclaration = nameType.symbol.valueDeclaration; - return ts.factory.createComputedPropertyName(symbolToExpression(nameType.symbol, context, meaning)); + return factory.createComputedPropertyName(symbolToExpression(nameType.symbol, context, meaning)); } } return symbolToExpression(symbol, context, meaning); } - function withContext(enclosingDeclaration: ts.Node | undefined, flags: ts.NodeBuilderFlags | undefined, tracker: ts.SymbolTracker | undefined, cb: (context: NodeBuilderContext) => T): T | undefined { - ts.Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & ts.NodeFlags.Synthesized) === 0); + function withContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined, cb: (context: NodeBuilderContext) => T): T | undefined { + Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); const context: NodeBuilderContext = { enclosingDeclaration, - flags: flags || ts.NodeBuilderFlags.None, + flags: flags || NodeBuilderFlags.None, // If no full tracker is provided, fake up a dummy one with a basic limited-functionality moduleResolverHost - tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: () => false, moduleResolverHost: flags! & ts.NodeBuilderFlags.DoNotIncludeSymbolChain ? { - getCommonSourceDirectory: !!(host as ts.Program).getCommonSourceDirectory ? () => (host as ts.Program).getCommonSourceDirectory() : () => "", + tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: () => false, moduleResolverHost: flags! & NodeBuilderFlags.DoNotIncludeSymbolChain ? { + getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory ? () => (host as Program).getCommonSourceDirectory() : () => "", getCurrentDirectory: () => host.getCurrentDirectory(), - getSymlinkCache: ts.maybeBind(host, host.getSymlinkCache), + getSymlinkCache: maybeBind(host, host.getSymlinkCache), getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(), - useCaseSensitiveFileNames: ts.maybeBind(host, host.useCaseSensitiveFileNames), + useCaseSensitiveFileNames: maybeBind(host, host.useCaseSensitiveFileNames), redirectTargetsMap: host.redirectTargetsMap, getProjectReferenceRedirect: fileName => host.getProjectReferenceRedirect(fileName), isSourceOfProjectReferenceRedirect: fileName => host.isSourceOfProjectReferenceRedirect(fileName), @@ -5049,13 +5247,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker); const resultingNode = cb(context); - if (context.truncating && context.flags & ts.NodeBuilderFlags.NoTruncation) { + if (context.truncating && context.flags & NodeBuilderFlags.NoTruncation) { context.tracker?.reportTruncationError?.(); } return context.encounteredError ? undefined : resultingNode; } - function wrapSymbolTrackerToReportForContext(context: NodeBuilderContext, tracker: ts.SymbolTracker): ts.SymbolTracker { + function wrapSymbolTrackerToReportForContext(context: NodeBuilderContext, tracker: SymbolTracker): SymbolTracker { const oldTrackSymbol = tracker.trackSymbol; return { ...tracker, @@ -5088,149 +5286,149 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function checkTruncationLength(context: NodeBuilderContext): boolean { if (context.truncating) return context.truncating; - return context.truncating = context.approximateLength > ((context.flags & ts.NodeBuilderFlags.NoTruncation) ? ts.noTruncationMaximumTruncationLength : ts.defaultMaximumTruncationLength); + return context.truncating = context.approximateLength > ((context.flags & NodeBuilderFlags.NoTruncation) ? noTruncationMaximumTruncationLength : defaultMaximumTruncationLength); } - function typeToTypeNodeHelper(type: ts.Type, context: NodeBuilderContext): ts.TypeNode { + function typeToTypeNodeHelper(type: Type, context: NodeBuilderContext): TypeNode { const savedFlags = context.flags; const typeNode = typeToTypeNodeWorker(type, context); context.flags = savedFlags; return typeNode; } - function typeToTypeNodeWorker(type: ts.Type, context: NodeBuilderContext): ts.TypeNode { + function typeToTypeNodeWorker(type: Type, context: NodeBuilderContext): TypeNode { if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } - const inTypeAlias = context.flags & ts.NodeBuilderFlags.InTypeAlias; - context.flags &= ~ts.NodeBuilderFlags.InTypeAlias; + const inTypeAlias = context.flags & NodeBuilderFlags.InTypeAlias; + context.flags &= ~NodeBuilderFlags.InTypeAlias; if (!type) { - if (!(context.flags & ts.NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { + if (!(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; return undefined!; // TODO: GH#18217 } context.approximateLength += 3; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } - if (!(context.flags & ts.NodeBuilderFlags.NoTypeReduction)) { + if (!(context.flags & NodeBuilderFlags.NoTypeReduction)) { type = getReducedType(type); } - if (type.flags & ts.TypeFlags.Any) { + if (type.flags & TypeFlags.Any) { if (type.aliasSymbol) { - return ts.factory.createTypeReferenceNode(symbolToEntityNameNode(type.aliasSymbol), mapToTypeNodes(type.aliasTypeArguments, context)); + return factory.createTypeReferenceNode(symbolToEntityNameNode(type.aliasSymbol), mapToTypeNodes(type.aliasTypeArguments, context)); } if (type === unresolvedType) { - return ts.addSyntheticLeadingComment(ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), ts.SyntaxKind.MultiLineCommentTrivia, "unresolved"); + return addSyntheticLeadingComment(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), SyntaxKind.MultiLineCommentTrivia, "unresolved"); } context.approximateLength += 3; - return ts.factory.createKeywordTypeNode(type === intrinsicMarkerType ? ts.SyntaxKind.IntrinsicKeyword : ts.SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(type === intrinsicMarkerType ? SyntaxKind.IntrinsicKeyword : SyntaxKind.AnyKeyword); } - if (type.flags & ts.TypeFlags.Unknown) { - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword); + if (type.flags & TypeFlags.Unknown) { + return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); } - if (type.flags & ts.TypeFlags.String) { + if (type.flags & TypeFlags.String) { context.approximateLength += 6; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword); + return factory.createKeywordTypeNode(SyntaxKind.StringKeyword); } - if (type.flags & ts.TypeFlags.Number) { + if (type.flags & TypeFlags.Number) { context.approximateLength += 6; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword); + return factory.createKeywordTypeNode(SyntaxKind.NumberKeyword); } - if (type.flags & ts.TypeFlags.BigInt) { + if (type.flags & TypeFlags.BigInt) { context.approximateLength += 6; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BigIntKeyword); + return factory.createKeywordTypeNode(SyntaxKind.BigIntKeyword); } - if (type.flags & ts.TypeFlags.Boolean && !type.aliasSymbol) { + if (type.flags & TypeFlags.Boolean && !type.aliasSymbol) { context.approximateLength += 7; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword); + return factory.createKeywordTypeNode(SyntaxKind.BooleanKeyword); } - if (type.flags & ts.TypeFlags.EnumLike) { - if (type.symbol.flags & ts.SymbolFlags.EnumMember) { + if (type.flags & TypeFlags.EnumLike) { + if (type.symbol.flags & SymbolFlags.EnumMember) { const parentSymbol = getParentOfSymbol(type.symbol)!; - const parentName = symbolToTypeNode(parentSymbol, context, ts.SymbolFlags.Type); + const parentName = symbolToTypeNode(parentSymbol, context, SymbolFlags.Type); if (getDeclaredTypeOfSymbol(parentSymbol) === type) { return parentName; } - const memberName = ts.symbolName(type.symbol); - if (ts.isIdentifierText(memberName, ts.ScriptTarget.ES3)) { + const memberName = symbolName(type.symbol); + if (isIdentifierText(memberName, ScriptTarget.ES3)) { return appendReferenceToType( - parentName as ts.TypeReferenceNode | ts.ImportTypeNode, - ts.factory.createTypeReferenceNode(memberName, /*typeArguments*/ undefined) + parentName as TypeReferenceNode | ImportTypeNode, + factory.createTypeReferenceNode(memberName, /*typeArguments*/ undefined) ); } - if (ts.isImportTypeNode(parentName)) { + if (isImportTypeNode(parentName)) { (parentName as any).isTypeOf = true; // mutably update, node is freshly manufactured anyhow - return ts.factory.createIndexedAccessTypeNode(parentName, ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(memberName))); + return factory.createIndexedAccessTypeNode(parentName, factory.createLiteralTypeNode(factory.createStringLiteral(memberName))); } - else if (ts.isTypeReferenceNode(parentName)) { - return ts.factory.createIndexedAccessTypeNode(ts.factory.createTypeQueryNode(parentName.typeName), ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(memberName))); + else if (isTypeReferenceNode(parentName)) { + return factory.createIndexedAccessTypeNode(factory.createTypeQueryNode(parentName.typeName), factory.createLiteralTypeNode(factory.createStringLiteral(memberName))); } else { - return ts.Debug.fail("Unhandled type node kind returned from `symbolToTypeNode`."); + return Debug.fail("Unhandled type node kind returned from `symbolToTypeNode`."); } } - return symbolToTypeNode(type.symbol, context, ts.SymbolFlags.Type); + return symbolToTypeNode(type.symbol, context, SymbolFlags.Type); } - if (type.flags & ts.TypeFlags.StringLiteral) { - context.approximateLength += ((type as ts.StringLiteralType).value.length + 2); - return ts.factory.createLiteralTypeNode(ts.setEmitFlags(ts.factory.createStringLiteral((type as ts.StringLiteralType).value, !!(context.flags & ts.NodeBuilderFlags.UseSingleQuotesForStringLiteralType)), ts.EmitFlags.NoAsciiEscaping)); + if (type.flags & TypeFlags.StringLiteral) { + context.approximateLength += ((type as StringLiteralType).value.length + 2); + return factory.createLiteralTypeNode(setEmitFlags(factory.createStringLiteral((type as StringLiteralType).value, !!(context.flags & NodeBuilderFlags.UseSingleQuotesForStringLiteralType)), EmitFlags.NoAsciiEscaping)); } - if (type.flags & ts.TypeFlags.NumberLiteral) { - const value = (type as ts.NumberLiteralType).value; + if (type.flags & TypeFlags.NumberLiteral) { + const value = (type as NumberLiteralType).value; context.approximateLength += ("" + value).length; - return ts.factory.createLiteralTypeNode(value < 0 ? ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(-value)) : ts.factory.createNumericLiteral(value)); + return factory.createLiteralTypeNode(value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : factory.createNumericLiteral(value)); } - if (type.flags & ts.TypeFlags.BigIntLiteral) { - context.approximateLength += (ts.pseudoBigIntToString((type as ts.BigIntLiteralType).value).length) + 1; - return ts.factory.createLiteralTypeNode((ts.factory.createBigIntLiteral((type as ts.BigIntLiteralType).value))); + if (type.flags & TypeFlags.BigIntLiteral) { + context.approximateLength += (pseudoBigIntToString((type as BigIntLiteralType).value).length) + 1; + return factory.createLiteralTypeNode((factory.createBigIntLiteral((type as BigIntLiteralType).value))); } - if (type.flags & ts.TypeFlags.BooleanLiteral) { - context.approximateLength += (type as ts.IntrinsicType).intrinsicName.length; - return ts.factory.createLiteralTypeNode((type as ts.IntrinsicType).intrinsicName === "true" ? ts.factory.createTrue() : ts.factory.createFalse()); + if (type.flags & TypeFlags.BooleanLiteral) { + context.approximateLength += (type as IntrinsicType).intrinsicName.length; + return factory.createLiteralTypeNode((type as IntrinsicType).intrinsicName === "true" ? factory.createTrue() : factory.createFalse()); } - if (type.flags & ts.TypeFlags.UniqueESSymbol) { - if (!(context.flags & ts.NodeBuilderFlags.AllowUniqueESSymbolType)) { + if (type.flags & TypeFlags.UniqueESSymbol) { + if (!(context.flags & NodeBuilderFlags.AllowUniqueESSymbolType)) { if (isValueSymbolAccessible(type.symbol, context.enclosingDeclaration)) { context.approximateLength += 6; - return symbolToTypeNode(type.symbol, context, ts.SymbolFlags.Value); + return symbolToTypeNode(type.symbol, context, SymbolFlags.Value); } if (context.tracker.reportInaccessibleUniqueSymbolError) { context.tracker.reportInaccessibleUniqueSymbolError(); } } context.approximateLength += 13; - return ts.factory.createTypeOperatorNode(ts.SyntaxKind.UniqueKeyword, ts.factory.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword)); + return factory.createTypeOperatorNode(SyntaxKind.UniqueKeyword, factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword)); } - if (type.flags & ts.TypeFlags.Void) { + if (type.flags & TypeFlags.Void) { context.approximateLength += 4; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword); + return factory.createKeywordTypeNode(SyntaxKind.VoidKeyword); } - if (type.flags & ts.TypeFlags.Undefined) { + if (type.flags & TypeFlags.Undefined) { context.approximateLength += 9; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword); + return factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword); } - if (type.flags & ts.TypeFlags.Null) { + if (type.flags & TypeFlags.Null) { context.approximateLength += 4; - return ts.factory.createLiteralTypeNode(ts.factory.createNull()); + return factory.createLiteralTypeNode(factory.createNull()); } - if (type.flags & ts.TypeFlags.Never) { + if (type.flags & TypeFlags.Never) { context.approximateLength += 5; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword); + return factory.createKeywordTypeNode(SyntaxKind.NeverKeyword); } - if (type.flags & ts.TypeFlags.ESSymbol) { + if (type.flags & TypeFlags.ESSymbol) { context.approximateLength += 6; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword); + return factory.createKeywordTypeNode(SyntaxKind.SymbolKeyword); } - if (type.flags & ts.TypeFlags.NonPrimitive) { + if (type.flags & TypeFlags.NonPrimitive) { context.approximateLength += 6; - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword); + return factory.createKeywordTypeNode(SyntaxKind.ObjectKeyword); } - if (ts.isThisTypeParameter(type)) { - if (context.flags & ts.NodeBuilderFlags.InObjectTypeLiteral) { - if (!context.encounteredError && !(context.flags & ts.NodeBuilderFlags.AllowThisInObjectLiteral)) { + if (isThisTypeParameter(type)) { + if (context.flags & NodeBuilderFlags.InObjectTypeLiteral) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } if (context.tracker.reportInaccessibleThisError) { @@ -5238,125 +5436,125 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } context.approximateLength += 4; - return ts.factory.createThisTypeNode(); + return factory.createThisTypeNode(); } - if (!inTypeAlias && type.aliasSymbol && (context.flags & ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { + if (!inTypeAlias && type.aliasSymbol && (context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope || isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration))) { const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context); - if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & ts.SymbolFlags.Class)) return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(""), typeArgumentNodes); - if (ts.length(typeArgumentNodes) === 1 && type.aliasSymbol === globalArrayType.symbol) { - return ts.factory.createArrayTypeNode(typeArgumentNodes![0]); + if (isReservedMemberName(type.aliasSymbol.escapedName) && !(type.aliasSymbol.flags & SymbolFlags.Class)) return factory.createTypeReferenceNode(factory.createIdentifier(""), typeArgumentNodes); + if (length(typeArgumentNodes) === 1 && type.aliasSymbol === globalArrayType.symbol) { + return factory.createArrayTypeNode(typeArgumentNodes![0]); } - return symbolToTypeNode(type.aliasSymbol, context, ts.SymbolFlags.Type, typeArgumentNodes); + return symbolToTypeNode(type.aliasSymbol, context, SymbolFlags.Type, typeArgumentNodes); } - const objectFlags = ts.getObjectFlags(type); + const objectFlags = getObjectFlags(type); - if (objectFlags & ts.ObjectFlags.Reference) { - ts.Debug.assert(!!(type.flags & ts.TypeFlags.Object)); - return (type as ts.TypeReference).node ? visitAndTransformType(type, typeReferenceToTypeNode) : typeReferenceToTypeNode(type as ts.TypeReference); + if (objectFlags & ObjectFlags.Reference) { + Debug.assert(!!(type.flags & TypeFlags.Object)); + return (type as TypeReference).node ? visitAndTransformType(type, typeReferenceToTypeNode) : typeReferenceToTypeNode(type as TypeReference); } - if (type.flags & ts.TypeFlags.TypeParameter || objectFlags & ts.ObjectFlags.ClassOrInterface) { - if (type.flags & ts.TypeFlags.TypeParameter && ts.contains(context.inferTypeParameters, type)) { - context.approximateLength += (ts.symbolName(type.symbol).length + 6); - let constraintNode: ts.TypeNode | undefined; - const constraint = getConstraintOfTypeParameter(type as ts.TypeParameter); + if (type.flags & TypeFlags.TypeParameter || objectFlags & ObjectFlags.ClassOrInterface) { + if (type.flags & TypeFlags.TypeParameter && contains(context.inferTypeParameters, type)) { + context.approximateLength += (symbolName(type.symbol).length + 6); + let constraintNode: TypeNode | undefined; + const constraint = getConstraintOfTypeParameter(type as TypeParameter); if (constraint) { // If the infer type has a constraint that is not the same as the constraint // we would have normally inferred based on context, we emit the constraint // using `infer T extends ?`. We omit inferred constraints from type references // as they may be elided. - const inferredConstraint = getInferredTypeParameterConstraint(type as ts.TypeParameter, /*omitTypeReferences*/ true); + const inferredConstraint = getInferredTypeParameterConstraint(type as TypeParameter, /*omitTypeReferences*/ true); if (!(inferredConstraint && isTypeIdenticalTo(constraint, inferredConstraint))) { context.approximateLength += 9; constraintNode = constraint && typeToTypeNodeHelper(constraint, context); } } - return ts.factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as ts.TypeParameter, context, constraintNode)); + return factory.createInferTypeNode(typeParameterToDeclarationWithConstraint(type as TypeParameter, context, constraintNode)); } - if (context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams && - type.flags & ts.TypeFlags.TypeParameter && + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && + type.flags & TypeFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration)) { const name = typeParameterToName(type, context); - context.approximateLength += ts.idText(name).length; - return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(ts.idText(name)), /*typeArguments*/ undefined); + context.approximateLength += idText(name).length; + return factory.createTypeReferenceNode(factory.createIdentifier(idText(name)), /*typeArguments*/ undefined); } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. if (type.symbol) { - return symbolToTypeNode(type.symbol, context, ts.SymbolFlags.Type); + return symbolToTypeNode(type.symbol, context, SymbolFlags.Type); } const name = (type === markerSuperTypeForCheck || type === markerSubTypeForCheck) && varianceTypeParameter && varianceTypeParameter.symbol ? - (type === markerSubTypeForCheck ? "sub-" : "super-") + ts.symbolName(varianceTypeParameter.symbol) : "?"; - return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(name), /*typeArguments*/ undefined); + (type === markerSubTypeForCheck ? "sub-" : "super-") + symbolName(varianceTypeParameter.symbol) : "?"; + return factory.createTypeReferenceNode(factory.createIdentifier(name), /*typeArguments*/ undefined); } - if (type.flags & ts.TypeFlags.Union && (type as ts.UnionType).origin) { - type = (type as ts.UnionType).origin!; + if (type.flags & TypeFlags.Union && (type as UnionType).origin) { + type = (type as UnionType).origin!; } - if (type.flags & (ts.TypeFlags.Union | ts.TypeFlags.Intersection)) { - const types = type.flags & ts.TypeFlags.Union ? formatUnionTypes((type as ts.UnionType).types) : (type as ts.IntersectionType).types; - if (ts.length(types) === 1) { + if (type.flags & (TypeFlags.Union | TypeFlags.Intersection)) { + const types = type.flags & TypeFlags.Union ? formatUnionTypes((type as UnionType).types) : (type as IntersectionType).types; + if (length(types) === 1) { return typeToTypeNodeHelper(types[0], context); } const typeNodes = mapToTypeNodes(types, context, /*isBareList*/ true); if (typeNodes && typeNodes.length > 0) { - return type.flags & ts.TypeFlags.Union ? ts.factory.createUnionTypeNode(typeNodes) : ts.factory.createIntersectionTypeNode(typeNodes); + return type.flags & TypeFlags.Union ? factory.createUnionTypeNode(typeNodes) : factory.createIntersectionTypeNode(typeNodes); } else { - if (!context.encounteredError && !(context.flags & ts.NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { + if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowEmptyUnionOrIntersection)) { context.encounteredError = true; } return undefined!; // TODO: GH#18217 } } - if (objectFlags & (ts.ObjectFlags.Anonymous | ts.ObjectFlags.Mapped)) { - ts.Debug.assert(!!(type.flags & ts.TypeFlags.Object)); + if (objectFlags & (ObjectFlags.Anonymous | ObjectFlags.Mapped)) { + Debug.assert(!!(type.flags & TypeFlags.Object)); // The type is an object literal type. - return createAnonymousTypeNode(type as ts.ObjectType); + return createAnonymousTypeNode(type as ObjectType); } - if (type.flags & ts.TypeFlags.Index) { - const indexedType = (type as ts.IndexType).type; + if (type.flags & TypeFlags.Index) { + const indexedType = (type as IndexType).type; context.approximateLength += 6; const indexTypeNode = typeToTypeNodeHelper(indexedType, context); - return ts.factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, indexTypeNode); - } - if (type.flags & ts.TypeFlags.TemplateLiteral) { - const texts = (type as ts.TemplateLiteralType).texts; - const types = (type as ts.TemplateLiteralType).types; - const templateHead = ts.factory.createTemplateHead(texts[0]); - const templateSpans = ts.factory.createNodeArray( - ts.map(types, (t, i) => ts.factory.createTemplateLiteralTypeSpan( + return factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, indexTypeNode); + } + if (type.flags & TypeFlags.TemplateLiteral) { + const texts = (type as TemplateLiteralType).texts; + const types = (type as TemplateLiteralType).types; + const templateHead = factory.createTemplateHead(texts[0]); + const templateSpans = factory.createNodeArray( + map(types, (t, i) => factory.createTemplateLiteralTypeSpan( typeToTypeNodeHelper(t, context), - (i < types.length - 1 ? ts.factory.createTemplateMiddle : ts.factory.createTemplateTail)(texts[i + 1])))); + (i < types.length - 1 ? factory.createTemplateMiddle : factory.createTemplateTail)(texts[i + 1])))); context.approximateLength += 2; - return ts.factory.createTemplateLiteralType(templateHead, templateSpans); + return factory.createTemplateLiteralType(templateHead, templateSpans); } - if (type.flags & ts.TypeFlags.StringMapping) { - const typeNode = typeToTypeNodeHelper((type as ts.StringMappingType).type, context); - return symbolToTypeNode((type as ts.StringMappingType).symbol, context, ts.SymbolFlags.Type, [typeNode]); + if (type.flags & TypeFlags.StringMapping) { + const typeNode = typeToTypeNodeHelper((type as StringMappingType).type, context); + return symbolToTypeNode((type as StringMappingType).symbol, context, SymbolFlags.Type, [typeNode]); } - if (type.flags & ts.TypeFlags.IndexedAccess) { - const objectTypeNode = typeToTypeNodeHelper((type as ts.IndexedAccessType).objectType, context); - const indexTypeNode = typeToTypeNodeHelper((type as ts.IndexedAccessType).indexType, context); + if (type.flags & TypeFlags.IndexedAccess) { + const objectTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).objectType, context); + const indexTypeNode = typeToTypeNodeHelper((type as IndexedAccessType).indexType, context); context.approximateLength += 2; - return ts.factory.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); + return factory.createIndexedAccessTypeNode(objectTypeNode, indexTypeNode); } - if (type.flags & ts.TypeFlags.Conditional) { - return visitAndTransformType(type, type => conditionalTypeToTypeNode(type as ts.ConditionalType)); + if (type.flags & TypeFlags.Conditional) { + return visitAndTransformType(type, type => conditionalTypeToTypeNode(type as ConditionalType)); } - if (type.flags & ts.TypeFlags.Substitution) { - return typeToTypeNodeHelper((type as ts.SubstitutionType).baseType, context); + if (type.flags & TypeFlags.Substitution) { + return typeToTypeNodeHelper((type as SubstitutionType).baseType, context); } - return ts.Debug.fail("Should be unreachable."); + return Debug.fail("Should be unreachable."); - function conditionalTypeToTypeNode(type: ts.ConditionalType) { + function conditionalTypeToTypeNode(type: ConditionalType) { const checkTypeNode = typeToTypeNodeHelper(type.checkType, context); context.approximateLength += 15; - if (context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive && !(type.checkType.flags & ts.TypeFlags.TypeParameter)) { - const newParam = createTypeParameter(createSymbol(ts.SymbolFlags.TypeParameter, "T" as ts.__String)); + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && type.root.isDistributive && !(type.checkType.flags & TypeFlags.TypeParameter)) { + const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String)); const name = typeParameterToName(newParam, context); - const newTypeVariable = ts.factory.createTypeReferenceNode(name); + const newTypeVariable = factory.createTypeReferenceNode(name); context.approximateLength += 37; // 15 each for two added conditionals, 7 for an added infer type const newMapper = prependTypeMapping(type.root.checkType, newParam, type.mapper); const saveInferTypeParameters = context.inferTypeParameters; @@ -5377,16 +5575,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // On the other hand, // checkType extends infer T extends checkType ? T extends extendsType ? trueType : falseType : never; // may also work with `infer ... extends ...` in, but would produce declarations only compatible with the latest TS. - return ts.factory.createConditionalTypeNode( + return factory.createConditionalTypeNode( checkTypeNode, - ts.factory.createInferTypeNode(ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, ts.factory.cloneNode(newTypeVariable.typeName) as ts.Identifier)), - ts.factory.createConditionalTypeNode( - ts.factory.createTypeReferenceNode(ts.factory.cloneNode(name)), + factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable.typeName) as Identifier)), + factory.createConditionalTypeNode( + factory.createTypeReferenceNode(factory.cloneNode(name)), typeToTypeNodeHelper(type.checkType, context), - ts.factory.createConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword) + factory.createConditionalTypeNode(newTypeVariable, extendsTypeNode, trueTypeNode, falseTypeNode), + factory.createKeywordTypeNode(SyntaxKind.NeverKeyword) ), - ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword) + factory.createKeywordTypeNode(SyntaxKind.NeverKeyword) ); } const saveInferTypeParameters = context.inferTypeParameters; @@ -5395,13 +5593,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { context.inferTypeParameters = saveInferTypeParameters; const trueTypeNode = typeToTypeNodeOrCircularityElision(getTrueTypeFromConditionalType(type)); const falseTypeNode = typeToTypeNodeOrCircularityElision(getFalseTypeFromConditionalType(type)); - return ts.factory.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); + return factory.createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode); } - function typeToTypeNodeOrCircularityElision(type: ts.Type) { - if (type.flags & ts.TypeFlags.Union) { + function typeToTypeNodeOrCircularityElision(type: Type) { + if (type.flags & TypeFlags.Union) { if (context.visitedTypes?.has(getTypeId(type))) { - if (!(context.flags & ts.NodeBuilderFlags.AllowAnonymousIdentifier)) { + if (!(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { context.encounteredError = true; context.tracker?.reportCyclicStructureError?.(); } @@ -5412,26 +5610,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeToTypeNodeHelper(type, context); } - function isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type: ts.MappedType) { + function isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type: MappedType) { return isMappedTypeWithKeyofConstraintDeclaration(type) - && !(getModifiersTypeFromMappedType(type).flags & ts.TypeFlags.TypeParameter); + && !(getModifiersTypeFromMappedType(type).flags & TypeFlags.TypeParameter); } - function createMappedTypeNodeFromType(type: ts.MappedType) { - ts.Debug.assert(!!(type.flags & ts.TypeFlags.Object)); - const readonlyToken = type.declaration.readonlyToken ? ts.factory.createToken(type.declaration.readonlyToken.kind) as ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken : undefined; - const questionToken = type.declaration.questionToken ? ts.factory.createToken(type.declaration.questionToken.kind) as ts.QuestionToken | ts.PlusToken | ts.MinusToken : undefined; - let appropriateConstraintTypeNode: ts.TypeNode; - let newTypeVariable: ts.TypeReferenceNode | undefined; + function createMappedTypeNodeFromType(type: MappedType) { + Debug.assert(!!(type.flags & TypeFlags.Object)); + const readonlyToken = type.declaration.readonlyToken ? factory.createToken(type.declaration.readonlyToken.kind) as ReadonlyKeyword | PlusToken | MinusToken : undefined; + const questionToken = type.declaration.questionToken ? factory.createToken(type.declaration.questionToken.kind) as QuestionToken | PlusToken | MinusToken : undefined; + let appropriateConstraintTypeNode: TypeNode; + let newTypeVariable: TypeReferenceNode | undefined; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` - if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { - const newParam = createTypeParameter(createSymbol(ts.SymbolFlags.TypeParameter, "T" as ts.__String)); + if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + const newParam = createTypeParameter(createSymbol(SymbolFlags.TypeParameter, "T" as __String)); const name = typeParameterToName(newParam, context); - newTypeVariable = ts.factory.createTypeReferenceNode(name); + newTypeVariable = factory.createTypeReferenceNode(name); } - appropriateConstraintTypeNode = ts.factory.createTypeOperatorNode(ts.SyntaxKind.KeyOfKeyword, newTypeVariable || typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); + appropriateConstraintTypeNode = factory.createTypeOperatorNode(SyntaxKind.KeyOfKeyword, newTypeVariable || typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context)); } else { appropriateConstraintTypeNode = typeToTypeNodeHelper(getConstraintTypeFromMappedType(type), context); @@ -5439,38 +5637,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode); const nameTypeNode = type.declaration.nameType ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined; const templateTypeNode = typeToTypeNodeHelper(removeMissingType(getTemplateTypeFromMappedType(type), !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), context); - const mappedTypeNode = ts.factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode, /*members*/ undefined); + const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode, /*members*/ undefined); context.approximateLength += 10; - const result = ts.setEmitFlags(mappedTypeNode, ts.EmitFlags.SingleLine); - if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + const result = setEmitFlags(mappedTypeNode, EmitFlags.SingleLine); + if (isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type) && context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { // homomorphic mapped type with a non-homomorphic naive inlining // wrap it with a conditional like `SomeModifiersType extends infer U ? {..the mapped type...} : never` to ensure the resulting // type stays homomorphic - const originalConstraint = instantiateType(getConstraintOfTypeParameter(getTypeFromTypeNode((type.declaration.typeParameter.constraint! as ts.TypeOperatorNode).type) as ts.TypeParameter) || unknownType, type.mapper); - return ts.factory.createConditionalTypeNode( + const originalConstraint = instantiateType(getConstraintOfTypeParameter(getTypeFromTypeNode((type.declaration.typeParameter.constraint! as TypeOperatorNode).type) as TypeParameter) || unknownType, type.mapper); + return factory.createConditionalTypeNode( typeToTypeNodeHelper(getModifiersTypeFromMappedType(type), context), - ts.factory.createInferTypeNode(ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, ts.factory.cloneNode(newTypeVariable!.typeName) as ts.Identifier, originalConstraint.flags & ts.TypeFlags.Unknown ? undefined : typeToTypeNodeHelper(originalConstraint, context))), + factory.createInferTypeNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, factory.cloneNode(newTypeVariable!.typeName) as Identifier, originalConstraint.flags & TypeFlags.Unknown ? undefined : typeToTypeNodeHelper(originalConstraint, context))), result, - ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword) + factory.createKeywordTypeNode(SyntaxKind.NeverKeyword) ); } return result; } - function createAnonymousTypeNode(type: ts.ObjectType): ts.TypeNode { + function createAnonymousTypeNode(type: ObjectType): TypeNode { const typeId = type.id; const symbol = type.symbol; if (symbol) { - const isInstanceType = isClassInstanceSide(type) ? ts.SymbolFlags.Type : ts.SymbolFlags.Value; + const isInstanceType = isClassInstanceSide(type) ? SymbolFlags.Type : SymbolFlags.Value; if (isJSConstructor(symbol.valueDeclaration)) { // Instance and static types share the same symbol; only add 'typeof' for the static side. return symbolToTypeNode(symbol, context, isInstanceType); } // Always use 'typeof T' for type of class, enum, and module objects - else if (symbol.flags & ts.SymbolFlags.Class + else if (symbol.flags & SymbolFlags.Class && !getBaseTypeVariableOfClass(symbol) - && !(symbol.valueDeclaration && ts.isClassLike(symbol.valueDeclaration) && context.flags & ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && (!ts.isClassDeclaration(symbol.valueDeclaration) || isSymbolAccessible(symbol, context.enclosingDeclaration, isInstanceType, /*computeAliases*/ false).accessibility !== ts.SymbolAccessibility.Accessible)) || - symbol.flags & (ts.SymbolFlags.Enum | ts.SymbolFlags.ValueModule) || + && !(symbol.valueDeclaration && isClassLike(symbol.valueDeclaration) && context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && (!isClassDeclaration(symbol.valueDeclaration) || isSymbolAccessible(symbol, context.enclosingDeclaration, isInstanceType, /*computeAliases*/ false).accessibility !== SymbolAccessibility.Accessible)) || + symbol.flags & (SymbolFlags.Enum | SymbolFlags.ValueModule) || shouldWriteTypeOfFunctionSymbol()) { return symbolToTypeNode(symbol, context, isInstanceType); } @@ -5479,7 +5677,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const typeAlias = getTypeAliasForTypeLiteral(type); if (typeAlias) { // The specified symbol flags need to be reinterpreted as type flags - return symbolToTypeNode(typeAlias, context, ts.SymbolFlags.Type); + return symbolToTypeNode(typeAlias, context, SymbolFlags.Type); } else { return createElidedInformationPlaceholder(context); @@ -5494,40 +5692,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createTypeNodeFromObjectType(type); } function shouldWriteTypeOfFunctionSymbol() { - const isStaticMethodSymbol = !!(symbol.flags & ts.SymbolFlags.Method) && // typeof static method - ts.some(symbol.declarations, declaration => ts.isStatic(declaration)); - const isNonLocalFunctionSymbol = !!(symbol.flags & ts.SymbolFlags.Function) && + const isStaticMethodSymbol = !!(symbol.flags & SymbolFlags.Method) && // typeof static method + some(symbol.declarations, declaration => isStatic(declaration)); + const isNonLocalFunctionSymbol = !!(symbol.flags & SymbolFlags.Function) && (symbol.parent || // is exported function symbol - ts.forEach(symbol.declarations, declaration => - declaration.parent.kind === ts.SyntaxKind.SourceFile || declaration.parent.kind === ts.SyntaxKind.ModuleBlock)); + forEach(symbol.declarations, declaration => + declaration.parent.kind === SyntaxKind.SourceFile || declaration.parent.kind === SyntaxKind.ModuleBlock)); if (isStaticMethodSymbol || isNonLocalFunctionSymbol) { // typeof is allowed only for static/non local functions - return (!!(context.flags & ts.NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes?.has(typeId))) && // it is type of the symbol uses itself recursively - (!(context.flags & ts.NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed + return (!!(context.flags & NodeBuilderFlags.UseTypeOfFunction) || (context.visitedTypes?.has(typeId))) && // it is type of the symbol uses itself recursively + (!(context.flags & NodeBuilderFlags.UseStructuralFallback) || isValueSymbolAccessible(symbol, context.enclosingDeclaration)); // And the build is going to succeed without visibility error or there is no structural fallback allowed } } } - function visitAndTransformType(type: ts.Type, transform: (type: ts.Type) => T) { + function visitAndTransformType(type: Type, transform: (type: Type) => T) { const typeId = type.id; - const isConstructorObject = ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous && type.symbol && type.symbol.flags & ts.SymbolFlags.Class; - const id = ts.getObjectFlags(type) & ts.ObjectFlags.Reference && (type as ts.TypeReference).node ? "N" + getNodeId((type as ts.TypeReference).node!) : - type.flags & ts.TypeFlags.Conditional ? "N" + getNodeId((type as ts.ConditionalType).root.node) : + const isConstructorObject = getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & SymbolFlags.Class; + const id = getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).node ? "N" + getNodeId((type as TypeReference).node!) : + type.flags & TypeFlags.Conditional ? "N" + getNodeId((type as ConditionalType).root.node) : type.symbol ? (isConstructorObject ? "+" : "") + getSymbolId(type.symbol) : undefined; // Since instantiations of the same anonymous type have the same symbol, tracking symbols instead // of types allows us to catch circular references to instantiations of the same anonymous type if (!context.visitedTypes) { - context.visitedTypes = new ts.Set(); + context.visitedTypes = new Set(); } if (id && !context.symbolDepth) { - context.symbolDepth = new ts.Map(); + context.symbolDepth = new Map(); } const links = context.enclosingDeclaration && getNodeLinks(context.enclosingDeclaration); const key = `${getTypeId(type)}|${context.flags}`; if (links) { - links.serializedTypes ||= new ts.Map(); + links.serializedTypes ||= new Map(); } const cachedResult = links?.serializedTypes?.get(key); if (cachedResult) { @@ -5535,7 +5733,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { context.truncating = true; } context.approximateLength += cachedResult.addedLength; - return deepCloneOrReuseNode(cachedResult) as ts.TypeNode as T; + return deepCloneOrReuseNode(cachedResult) as TypeNode as T; } let depth: number | undefined; @@ -5555,7 +5753,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { (result as any).truncating = true; } (result as any).addedLength = addedLength; - links?.serializedTypes?.set(key, result as ts.TypeNode as ts.TypeNode & {truncating?: boolean, addedLength: number}); + links?.serializedTypes?.set(key, result as TypeNode as TypeNode & {truncating?: boolean, addedLength: number}); } context.visitedTypes.delete(typeId); if (id) { @@ -5563,54 +5761,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return result; - function deepCloneOrReuseNode(node: ts.Node): ts.Node { - if (!ts.nodeIsSynthesized(node) && ts.getParseTreeNode(node) === node) { + function deepCloneOrReuseNode(node: Node): Node { + if (!nodeIsSynthesized(node) && getParseTreeNode(node) === node) { return node; } - return ts.setTextRange(ts.factory.cloneNode(ts.visitEachChild(node, deepCloneOrReuseNode, ts.nullTransformationContext, deepCloneOrReuseNodes)), node); + return setTextRange(factory.cloneNode(visitEachChild(node, deepCloneOrReuseNode, nullTransformationContext, deepCloneOrReuseNodes)), node); } - function deepCloneOrReuseNodes(nodes: ts.NodeArray, visitor: ts.Visitor | undefined, test?: (node: ts.Node) => boolean, start?: number, count?: number): ts.NodeArray; - function deepCloneOrReuseNodes(nodes: ts.NodeArray | undefined, visitor: ts.Visitor | undefined, test?: (node: ts.Node) => boolean, start?: number, count?: number): ts.NodeArray | undefined; - function deepCloneOrReuseNodes(nodes: ts.NodeArray | undefined, visitor: ts.Visitor | undefined, test?: (node: ts.Node) => boolean, start?: number, count?: number): ts.NodeArray | undefined { + function deepCloneOrReuseNodes(nodes: NodeArray, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray; + function deepCloneOrReuseNodes(nodes: NodeArray | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined; + function deepCloneOrReuseNodes(nodes: NodeArray | undefined, visitor: Visitor | undefined, test?: (node: Node) => boolean, start?: number, count?: number): NodeArray | undefined { if (nodes && nodes.length === 0) { // Ensure we explicitly make a copy of an empty array; visitNodes will not do this unless the array has elements, // which can lead to us reusing the same empty NodeArray more than once within the same AST during type noding. - return ts.setTextRange(ts.factory.createNodeArray(/*nodes*/ undefined, nodes.hasTrailingComma), nodes); + return setTextRange(factory.createNodeArray(/*nodes*/ undefined, nodes.hasTrailingComma), nodes); } - return ts.visitNodes(nodes, visitor, test, start, count); + return visitNodes(nodes, visitor, test, start, count); } } - function createTypeNodeFromObjectType(type: ts.ObjectType): ts.TypeNode { - if (isGenericMappedType(type) || (type as ts.MappedType).containsError) { - return createMappedTypeNodeFromType(type as ts.MappedType); + function createTypeNodeFromObjectType(type: ObjectType): TypeNode { + if (isGenericMappedType(type) || (type as MappedType).containsError) { + return createMappedTypeNodeFromType(type as MappedType); } const resolved = resolveStructuredTypeMembers(type); if (!resolved.properties.length && !resolved.indexInfos.length) { if (!resolved.callSignatures.length && !resolved.constructSignatures.length) { context.approximateLength += 2; - return ts.setEmitFlags(ts.factory.createTypeLiteralNode(/*members*/ undefined), ts.EmitFlags.SingleLine); + return setEmitFlags(factory.createTypeLiteralNode(/*members*/ undefined), EmitFlags.SingleLine); } if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) { const signature = resolved.callSignatures[0]; - const signatureNode = signatureToSignatureDeclarationHelper(signature, ts.SyntaxKind.FunctionType, context) as ts.FunctionTypeNode; + const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.FunctionType, context) as FunctionTypeNode; return signatureNode; } if (resolved.constructSignatures.length === 1 && !resolved.callSignatures.length) { const signature = resolved.constructSignatures[0]; - const signatureNode = signatureToSignatureDeclarationHelper(signature, ts.SyntaxKind.ConstructorType, context) as ts.ConstructorTypeNode; + const signatureNode = signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructorType, context) as ConstructorTypeNode; return signatureNode; } } - const abstractSignatures = ts.filter(resolved.constructSignatures, signature => !!(signature.flags & ts.SignatureFlags.Abstract)); - if (ts.some(abstractSignatures)) { - const types = ts.map(abstractSignatures, getOrCreateTypeFromSignature); + const abstractSignatures = filter(resolved.constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract)); + if (some(abstractSignatures)) { + const types = map(abstractSignatures, getOrCreateTypeFromSignature); // count the number of type elements excluding abstract constructors const typeElementCount = resolved.callSignatures.length + @@ -5618,9 +5816,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { resolved.indexInfos.length + // exclude `prototype` when writing a class expression as a type literal, as per // the logic in `createTypeNodesFromResolvedType`. - (context.flags & ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral ? - ts.countWhere(resolved.properties, p => !(p.flags & ts.SymbolFlags.Prototype)) : - ts.length(resolved.properties)); + (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral ? + countWhere(resolved.properties, p => !(p.flags & SymbolFlags.Prototype)) : + length(resolved.properties)); // don't include an empty object literal if there were no other static-side // properties to write, i.e. `abstract class C { }` becomes `abstract new () => {}` // and not `(abstract new () => {}) & {}` @@ -5632,67 +5830,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const savedFlags = context.flags; - context.flags |= ts.NodeBuilderFlags.InObjectTypeLiteral; + context.flags |= NodeBuilderFlags.InObjectTypeLiteral; const members = createTypeNodesFromResolvedType(resolved); context.flags = savedFlags; - const typeLiteralNode = ts.factory.createTypeLiteralNode(members); + const typeLiteralNode = factory.createTypeLiteralNode(members); context.approximateLength += 2; - ts.setEmitFlags(typeLiteralNode, (context.flags & ts.NodeBuilderFlags.MultilineObjectLiterals) ? 0 : ts.EmitFlags.SingleLine); + setEmitFlags(typeLiteralNode, (context.flags & NodeBuilderFlags.MultilineObjectLiterals) ? 0 : EmitFlags.SingleLine); return typeLiteralNode; } - function typeReferenceToTypeNode(type: ts.TypeReference) { - let typeArguments: readonly ts.Type[] = getTypeArguments(type); + function typeReferenceToTypeNode(type: TypeReference) { + let typeArguments: readonly Type[] = getTypeArguments(type); if (type.target === globalArrayType || type.target === globalReadonlyArrayType) { - if (context.flags & ts.NodeBuilderFlags.WriteArrayAsGenericType) { + if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) { const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context); - return ts.factory.createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]); + return factory.createTypeReferenceNode(type.target === globalArrayType ? "Array" : "ReadonlyArray", [typeArgumentNode]); } const elementType = typeToTypeNodeHelper(typeArguments[0], context); - const arrayType = ts.factory.createArrayTypeNode(elementType); - return type.target === globalArrayType ? arrayType : ts.factory.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, arrayType); + const arrayType = factory.createArrayTypeNode(elementType); + return type.target === globalArrayType ? arrayType : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType); } - else if (type.target.objectFlags & ts.ObjectFlags.Tuple) { - typeArguments = ts.sameMap(typeArguments, (t, i) => removeMissingType(t, !!((type.target as ts.TupleType).elementFlags[i] & ts.ElementFlags.Optional))); + else if (type.target.objectFlags & ObjectFlags.Tuple) { + typeArguments = sameMap(typeArguments, (t, i) => removeMissingType(t, !!((type.target as TupleType).elementFlags[i] & ElementFlags.Optional))); if (typeArguments.length > 0) { const arity = getTypeReferenceArity(type); const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context); if (tupleConstituentNodes) { - if ((type.target as ts.TupleType).labeledElementDeclarations) { + if ((type.target as TupleType).labeledElementDeclarations) { for (let i = 0; i < tupleConstituentNodes.length; i++) { - const flags = (type.target as ts.TupleType).elementFlags[i]; - tupleConstituentNodes[i] = ts.factory.createNamedTupleMember( - flags & ts.ElementFlags.Variable ? ts.factory.createToken(ts.SyntaxKind.DotDotDotToken) : undefined, - ts.factory.createIdentifier(ts.unescapeLeadingUnderscores(getTupleElementLabel((type.target as ts.TupleType).labeledElementDeclarations![i]))), - flags & ts.ElementFlags.Optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, - flags & ts.ElementFlags.Rest ? ts.factory.createArrayTypeNode(tupleConstituentNodes[i]) : + const flags = (type.target as TupleType).elementFlags[i]; + tupleConstituentNodes[i] = factory.createNamedTupleMember( + flags & ElementFlags.Variable ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined, + factory.createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))), + flags & ElementFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i] ); } } else { for (let i = 0; i < Math.min(arity, tupleConstituentNodes.length); i++) { - const flags = (type.target as ts.TupleType).elementFlags[i]; + const flags = (type.target as TupleType).elementFlags[i]; tupleConstituentNodes[i] = - flags & ts.ElementFlags.Variable ? ts.factory.createRestTypeNode(flags & ts.ElementFlags.Rest ? ts.factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) : - flags & ts.ElementFlags.Optional ? ts.factory.createOptionalTypeNode(tupleConstituentNodes[i]) : + flags & ElementFlags.Variable ? factory.createRestTypeNode(flags & ElementFlags.Rest ? factory.createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]) : + flags & ElementFlags.Optional ? factory.createOptionalTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]; } } - const tupleTypeNode = ts.setEmitFlags(ts.factory.createTupleTypeNode(tupleConstituentNodes), ts.EmitFlags.SingleLine); - return (type.target as ts.TupleType).readonly ? ts.factory.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine); + return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; } } - if (context.encounteredError || (context.flags & ts.NodeBuilderFlags.AllowEmptyTuple)) { - const tupleTypeNode = ts.setEmitFlags(ts.factory.createTupleTypeNode([]), ts.EmitFlags.SingleLine); - return (type.target as ts.TupleType).readonly ? ts.factory.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; + if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) { + const tupleTypeNode = setEmitFlags(factory.createTupleTypeNode([]), EmitFlags.SingleLine); + return (type.target as TupleType).readonly ? factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode; } context.encounteredError = true; return undefined!; // TODO: GH#18217 } - else if (context.flags & ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && + else if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral && type.symbol.valueDeclaration && - ts.isClassLike(type.symbol.valueDeclaration) && + isClassLike(type.symbol.valueDeclaration) && !isValueSymbolAccessible(type.symbol, context.enclosingDeclaration) ) { return createAnonymousTypeNode(type); @@ -5700,7 +5898,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { const outerTypeParameters = type.target.outerTypeParameters; let i = 0; - let resultType: ts.TypeReferenceNode | ts.ImportTypeNode | undefined; + let resultType: TypeReferenceNode | ImportTypeNode | undefined; if (outerTypeParameters) { const length = outerTypeParameters.length; while (i < length) { @@ -5712,52 +5910,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } while (i < length && getParentSymbolOfTypeParameter(outerTypeParameters[i]) === parent); // When type parameters are their own type arguments for the whole group (i.e. we have // the default outer type arguments), we don't show the group. - if (!ts.rangeEquals(outerTypeParameters, typeArguments, start, i)) { + if (!rangeEquals(outerTypeParameters, typeArguments, start, i)) { const typeArgumentSlice = mapToTypeNodes(typeArguments.slice(start, i), context); const flags = context.flags; - context.flags |= ts.NodeBuilderFlags.ForbidIndexedAccessSymbolReferences; - const ref = symbolToTypeNode(parent, context, ts.SymbolFlags.Type, typeArgumentSlice) as ts.TypeReferenceNode | ts.ImportTypeNode; + context.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences; + const ref = symbolToTypeNode(parent, context, SymbolFlags.Type, typeArgumentSlice) as TypeReferenceNode | ImportTypeNode; context.flags = flags; - resultType = !resultType ? ref : appendReferenceToType(resultType, ref as ts.TypeReferenceNode); + resultType = !resultType ? ref : appendReferenceToType(resultType, ref as TypeReferenceNode); } } } - let typeArgumentNodes: readonly ts.TypeNode[] | undefined; + let typeArgumentNodes: readonly TypeNode[] | undefined; if (typeArguments.length > 0) { - const typeParameterCount = (type.target.typeParameters || ts.emptyArray).length; + const typeParameterCount = (type.target.typeParameters || emptyArray).length; typeArgumentNodes = mapToTypeNodes(typeArguments.slice(i, typeParameterCount), context); } const flags = context.flags; - context.flags |= ts.NodeBuilderFlags.ForbidIndexedAccessSymbolReferences; - const finalRef = symbolToTypeNode(type.symbol, context, ts.SymbolFlags.Type, typeArgumentNodes); + context.flags |= NodeBuilderFlags.ForbidIndexedAccessSymbolReferences; + const finalRef = symbolToTypeNode(type.symbol, context, SymbolFlags.Type, typeArgumentNodes); context.flags = flags; - return !resultType ? finalRef : appendReferenceToType(resultType, finalRef as ts.TypeReferenceNode); + return !resultType ? finalRef : appendReferenceToType(resultType, finalRef as TypeReferenceNode); } } - function appendReferenceToType(root: ts.TypeReferenceNode | ts.ImportTypeNode, ref: ts.TypeReferenceNode): ts.TypeReferenceNode | ts.ImportTypeNode { - if (ts.isImportTypeNode(root)) { + function appendReferenceToType(root: TypeReferenceNode | ImportTypeNode, ref: TypeReferenceNode): TypeReferenceNode | ImportTypeNode { + if (isImportTypeNode(root)) { // first shift type arguments let typeArguments = root.typeArguments; let qualifier = root.qualifier; if (qualifier) { - if (ts.isIdentifier(qualifier)) { - qualifier = ts.factory.updateIdentifier(qualifier, typeArguments); + if (isIdentifier(qualifier)) { + qualifier = factory.updateIdentifier(qualifier, typeArguments); } else { - qualifier = ts.factory.updateQualifiedName(qualifier, + qualifier = factory.updateQualifiedName(qualifier, qualifier.left, - ts.factory.updateIdentifier(qualifier.right, typeArguments)); + factory.updateIdentifier(qualifier.right, typeArguments)); } } typeArguments = ref.typeArguments; // then move qualifiers const ids = getAccessStack(ref); for (const id of ids) { - qualifier = qualifier ? ts.factory.createQualifiedName(qualifier, id) : id; + qualifier = qualifier ? factory.createQualifiedName(qualifier, id) : id; } - return ts.factory.updateImportTypeNode( + return factory.updateImportTypeNode( root, root.argument, root.assertions, @@ -5769,31 +5967,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // first shift type arguments let typeArguments = root.typeArguments; let typeName = root.typeName; - if (ts.isIdentifier(typeName)) { - typeName = ts.factory.updateIdentifier(typeName, typeArguments); + if (isIdentifier(typeName)) { + typeName = factory.updateIdentifier(typeName, typeArguments); } else { - typeName = ts.factory.updateQualifiedName(typeName, + typeName = factory.updateQualifiedName(typeName, typeName.left, - ts.factory.updateIdentifier(typeName.right, typeArguments)); + factory.updateIdentifier(typeName.right, typeArguments)); } typeArguments = ref.typeArguments; // then move qualifiers const ids = getAccessStack(ref); for (const id of ids) { - typeName = ts.factory.createQualifiedName(typeName, id); + typeName = factory.createQualifiedName(typeName, id); } - return ts.factory.updateTypeReferenceNode( + return factory.updateTypeReferenceNode( root, typeName, typeArguments); } } - function getAccessStack(ref: ts.TypeReferenceNode): ts.Identifier[] { + function getAccessStack(ref: TypeReferenceNode): Identifier[] { let state = ref.typeName; const ids = []; - while (!ts.isIdentifier(state)) { + while (!isIdentifier(state)) { ids.unshift(state.right); state = state.left; } @@ -5801,20 +5999,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return ids; } - function createTypeNodesFromResolvedType(resolvedType: ts.ResolvedType): ts.TypeElement[] | undefined { + function createTypeNodesFromResolvedType(resolvedType: ResolvedType): TypeElement[] | undefined { if (checkTruncationLength(context)) { - return [ts.factory.createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined)]; + return [factory.createPropertySignature(/*modifiers*/ undefined, "...", /*questionToken*/ undefined, /*type*/ undefined)]; } - const typeElements: ts.TypeElement[] = []; + const typeElements: TypeElement[] = []; for (const signature of resolvedType.callSignatures) { - typeElements.push(signatureToSignatureDeclarationHelper(signature, ts.SyntaxKind.CallSignature, context) as ts.CallSignatureDeclaration); + typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.CallSignature, context) as CallSignatureDeclaration); } for (const signature of resolvedType.constructSignatures) { - if (signature.flags & ts.SignatureFlags.Abstract) continue; - typeElements.push(signatureToSignatureDeclarationHelper(signature, ts.SyntaxKind.ConstructSignature, context) as ts.ConstructSignatureDeclaration); + if (signature.flags & SignatureFlags.Abstract) continue; + typeElements.push(signatureToSignatureDeclarationHelper(signature, SyntaxKind.ConstructSignature, context) as ConstructSignatureDeclaration); } for (const info of resolvedType.indexInfos) { - typeElements.push(indexInfoToIndexSignatureDeclarationHelper(info, context, resolvedType.objectFlags & ts.ObjectFlags.ReverseMapped ? createElidedInformationPlaceholder(context) : undefined)); + typeElements.push(indexInfoToIndexSignatureDeclarationHelper(info, context, resolvedType.objectFlags & ObjectFlags.ReverseMapped ? createElidedInformationPlaceholder(context) : undefined)); } const properties = resolvedType.properties; @@ -5825,16 +6023,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let i = 0; for (const propertySymbol of properties) { i++; - if (context.flags & ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { - if (propertySymbol.flags & ts.SymbolFlags.Prototype) { + if (context.flags & NodeBuilderFlags.WriteClassExpressionAsTypeLiteral) { + if (propertySymbol.flags & SymbolFlags.Prototype) { continue; } - if (ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ts.ModifierFlags.Private | ts.ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { - context.tracker.reportPrivateInBaseOfClassExpression(ts.unescapeLeadingUnderscores(propertySymbol.escapedName)); + if (getDeclarationModifierFlagsFromSymbol(propertySymbol) & (ModifierFlags.Private | ModifierFlags.Protected) && context.tracker.reportPrivateInBaseOfClassExpression) { + context.tracker.reportPrivateInBaseOfClassExpression(unescapeLeadingUnderscores(propertySymbol.escapedName)); } } if (checkTruncationLength(context) && (i + 2 < properties.length - 1)) { - typeElements.push(ts.factory.createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined)); + typeElements.push(factory.createPropertySignature(/*modifiers*/ undefined, `... ${properties.length - i} more ...`, /*questionToken*/ undefined, /*type*/ undefined)); addPropertyToElementList(properties[properties.length - 1], context, typeElements); break; } @@ -5847,42 +6045,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function createElidedInformationPlaceholder(context: NodeBuilderContext) { context.approximateLength += 3; - if (!(context.flags & ts.NodeBuilderFlags.NoTruncation)) { - return ts.factory.createTypeReferenceNode(ts.factory.createIdentifier("..."), /*typeArguments*/ undefined); + if (!(context.flags & NodeBuilderFlags.NoTruncation)) { + return factory.createTypeReferenceNode(factory.createIdentifier("..."), /*typeArguments*/ undefined); } - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } - function shouldUsePlaceholderForProperty(propertySymbol: ts.Symbol, context: NodeBuilderContext) { + function shouldUsePlaceholderForProperty(propertySymbol: Symbol, context: NodeBuilderContext) { // Use placeholders for reverse mapped types we've either already descended into, or which // are nested reverse mappings within a mapping over a non-anonymous type. The later is a restriction mostly just to // reduce the blowup in printback size from doing, eg, a deep reverse mapping over `Window`. // Since anonymous types usually come from expressions, this allows us to preserve the output // for deep mappings which likely come from expressions, while truncating those parts which // come from mappings over library functions. - return !!(ts.getCheckFlags(propertySymbol) & ts.CheckFlags.ReverseMapped) + return !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped) && ( - ts.contains(context.reverseMappedStack, propertySymbol as ts.ReverseMappedSymbol) + contains(context.reverseMappedStack, propertySymbol as ReverseMappedSymbol) || ( context.reverseMappedStack?.[0] - && !(ts.getObjectFlags(ts.last(context.reverseMappedStack).propertyType) & ts.ObjectFlags.Anonymous) + && !(getObjectFlags(last(context.reverseMappedStack).propertyType) & ObjectFlags.Anonymous) ) ); } - function addPropertyToElementList(propertySymbol: ts.Symbol, context: NodeBuilderContext, typeElements: ts.TypeElement[]) { - const propertyIsReverseMapped = !!(ts.getCheckFlags(propertySymbol) & ts.CheckFlags.ReverseMapped); + function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) { + const propertyIsReverseMapped = !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped); const propertyType = shouldUsePlaceholderForProperty(propertySymbol, context) ? anyType : getNonMissingTypeOfSymbol(propertySymbol); const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; if (context.tracker.trackSymbol && isLateBoundName(propertySymbol.escapedName)) { if (propertySymbol.declarations) { - const decl = ts.first(propertySymbol.declarations); + const decl = first(propertySymbol.declarations); if (hasLateBindableName(decl)) { - if (ts.isBinaryExpression(decl)) { - const name = ts.getNameOfDeclaration(decl); - if (name && ts.isElementAccessExpression(name) && ts.isPropertyAccessEntityNameExpression(name.argumentExpression)) { + if (isBinaryExpression(decl)) { + const name = getNameOfDeclaration(decl); + if (name && isElementAccessExpression(name) && isPropertyAccessEntityNameExpression(name.argumentExpression)) { trackComputedName(name.argumentExpression, saveEnclosingDeclaration, context); } } @@ -5898,36 +6096,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { context.enclosingDeclaration = propertySymbol.valueDeclaration || propertySymbol.declarations?.[0] || saveEnclosingDeclaration; const propertyName = getPropertyNameNodeForSymbol(propertySymbol, context); context.enclosingDeclaration = saveEnclosingDeclaration; - context.approximateLength += (ts.symbolName(propertySymbol).length + 1); - const optionalToken = propertySymbol.flags & ts.SymbolFlags.Optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined; - if (propertySymbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol)) { - const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & ts.TypeFlags.Undefined)), ts.SignatureKind.Call); + context.approximateLength += (symbolName(propertySymbol).length + 1); + const optionalToken = propertySymbol.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; + if (propertySymbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && !getPropertiesOfObjectType(propertyType).length && !isReadonlySymbol(propertySymbol)) { + const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), SignatureKind.Call); for (const signature of signatures) { - const methodDeclaration = signatureToSignatureDeclarationHelper(signature, ts.SyntaxKind.MethodSignature, context, { name: propertyName, questionToken: optionalToken }) as ts.MethodSignature; + const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context, { name: propertyName, questionToken: optionalToken }) as MethodSignature; typeElements.push(preserveCommentsOn(methodDeclaration)); } } else { - let propertyTypeNode: ts.TypeNode; + let propertyTypeNode: TypeNode; if (shouldUsePlaceholderForProperty(propertySymbol, context)) { propertyTypeNode = createElidedInformationPlaceholder(context); } else { if (propertyIsReverseMapped) { context.reverseMappedStack ||= []; - context.reverseMappedStack.push(propertySymbol as ts.ReverseMappedSymbol); + context.reverseMappedStack.push(propertySymbol as ReverseMappedSymbol); } - propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + propertyTypeNode = propertyType ? serializeTypeForDeclaration(context, propertyType, propertySymbol, saveEnclosingDeclaration) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); if (propertyIsReverseMapped) { context.reverseMappedStack!.pop(); } } - const modifiers = isReadonlySymbol(propertySymbol) ? [ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)] : undefined; + const modifiers = isReadonlySymbol(propertySymbol) ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined; if (modifiers) { context.approximateLength += 9; } - const propertySignature = ts.factory.createPropertySignature( + const propertySignature = factory.createPropertySignature( modifiers, propertyName, optionalToken, @@ -5936,45 +6134,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { typeElements.push(preserveCommentsOn(propertySignature)); } - function preserveCommentsOn(node: T) { - if (ts.some(propertySymbol.declarations, d => d.kind === ts.SyntaxKind.JSDocPropertyTag)) { - const d = propertySymbol.declarations?.find(d => d.kind === ts.SyntaxKind.JSDocPropertyTag)! as ts.JSDocPropertyTag; - const commentText = ts.getTextOfJSDocComment(d.comment); + function preserveCommentsOn(node: T) { + if (some(propertySymbol.declarations, d => d.kind === SyntaxKind.JSDocPropertyTag)) { + const d = propertySymbol.declarations?.find(d => d.kind === SyntaxKind.JSDocPropertyTag)! as JSDocPropertyTag; + const commentText = getTextOfJSDocComment(d.comment); if (commentText) { - ts.setSyntheticLeadingComments(node, [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]); + setSyntheticLeadingComments(node, [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]); } } else if (propertySymbol.valueDeclaration) { // Copy comments to node for declaration emit - ts.setCommentRange(node, propertySymbol.valueDeclaration); + setCommentRange(node, propertySymbol.valueDeclaration); } return node; } } - function mapToTypeNodes(types: readonly ts.Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): ts.TypeNode[] | undefined { - if (ts.some(types)) { + function mapToTypeNodes(types: readonly Type[] | undefined, context: NodeBuilderContext, isBareList?: boolean): TypeNode[] | undefined { + if (some(types)) { if (checkTruncationLength(context)) { if (!isBareList) { - return [ts.factory.createTypeReferenceNode("...", /*typeArguments*/ undefined)]; + return [factory.createTypeReferenceNode("...", /*typeArguments*/ undefined)]; } else if (types.length > 2) { return [ typeToTypeNodeHelper(types[0], context), - ts.factory.createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined), + factory.createTypeReferenceNode(`... ${types.length - 2} more ...`, /*typeArguments*/ undefined), typeToTypeNodeHelper(types[types.length - 1], context) ]; } } - const mayHaveNameCollisions = !(context.flags & ts.NodeBuilderFlags.UseFullyQualifiedType); + const mayHaveNameCollisions = !(context.flags & NodeBuilderFlags.UseFullyQualifiedType); /** Map from type reference identifier text to [type, index in `result` where the type node is] */ - const seenNames = mayHaveNameCollisions ? ts.createUnderscoreEscapedMultiMap<[ts.Type, number]>() : undefined; - const result: ts.TypeNode[] = []; + const seenNames = mayHaveNameCollisions ? createUnderscoreEscapedMultiMap<[Type, number]>() : undefined; + const result: TypeNode[] = []; let i = 0; for (const type of types) { i++; if (checkTruncationLength(context) && (i + 2 < types.length - 1)) { - result.push(ts.factory.createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined)); + result.push(factory.createTypeReferenceNode(`... ${types.length - i} more ...`, /*typeArguments*/ undefined)); const typeNode = typeToTypeNodeHelper(types[types.length - 1], context); if (typeNode) { result.push(typeNode); @@ -5985,7 +6183,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const typeNode = typeToTypeNodeHelper(type, context); if (typeNode) { result.push(typeNode); - if (seenNames && ts.isIdentifierTypeReference(typeNode)) { + if (seenNames && isIdentifierTypeReference(typeNode)) { seenNames.add(typeNode.typeName.escapedText, [type, result.length - 1]); } } @@ -6000,9 +6198,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // type node for each entry by that name with the // `UseFullyQualifiedType` flag enabled. const saveContextFlags = context.flags; - context.flags |= ts.NodeBuilderFlags.UseFullyQualifiedType; + context.flags |= NodeBuilderFlags.UseFullyQualifiedType; seenNames.forEach(types => { - if (!ts.arrayIsHomogeneous(types, ([a], [b]) => typesAreSameReference(a, b))) { + if (!arrayIsHomogeneous(types, ([a], [b]) => typesAreSameReference(a, b))) { for (const [type, resultIndex] of types) { result[resultIndex] = typeToTypeNodeHelper(type, context); } @@ -6015,17 +6213,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function typesAreSameReference(a: ts.Type, b: ts.Type): boolean { + function typesAreSameReference(a: Type, b: Type): boolean { return a === b || !!a.symbol && a.symbol === b.symbol || !!a.aliasSymbol && a.aliasSymbol === b.aliasSymbol; } - function indexInfoToIndexSignatureDeclarationHelper(indexInfo: ts.IndexInfo, context: NodeBuilderContext, typeNode: ts.TypeNode | undefined): ts.IndexSignatureDeclaration { - const name = ts.getNameFromIndexInfo(indexInfo) || "x"; + function indexInfoToIndexSignatureDeclarationHelper(indexInfo: IndexInfo, context: NodeBuilderContext, typeNode: TypeNode | undefined): IndexSignatureDeclaration { + const name = getNameFromIndexInfo(indexInfo) || "x"; const indexerTypeNode = typeToTypeNodeHelper(indexInfo.keyType, context); - const indexingParameter = ts.factory.createParameterDeclaration( + const indexingParameter = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name, @@ -6035,31 +6233,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!typeNode) { typeNode = typeToTypeNodeHelper(indexInfo.type || anyType, context); } - if (!indexInfo.type && !(context.flags & ts.NodeBuilderFlags.AllowEmptyIndexInfoType)) { + if (!indexInfo.type && !(context.flags & NodeBuilderFlags.AllowEmptyIndexInfoType)) { context.encounteredError = true; } context.approximateLength += (name.length + 4); - return ts.factory.createIndexSignature( - indexInfo.isReadonly ? [ts.factory.createToken(ts.SyntaxKind.ReadonlyKeyword)] : undefined, + return factory.createIndexSignature( + indexInfo.isReadonly ? [factory.createToken(SyntaxKind.ReadonlyKeyword)] : undefined, [indexingParameter], typeNode); } interface SignatureToSignatureDeclarationOptions { - modifiers?: readonly ts.Modifier[]; - name?: ts.PropertyName; - questionToken?: ts.QuestionToken; - privateSymbolVisitor?: (s: ts.Symbol) => void; + modifiers?: readonly Modifier[]; + name?: PropertyName; + questionToken?: QuestionToken; + privateSymbolVisitor?: (s: Symbol) => void; bundledImports?: boolean; } - function signatureToSignatureDeclarationHelper(signature: ts.Signature, kind: ts.SignatureDeclaration["kind"], context: NodeBuilderContext, options?: SignatureToSignatureDeclarationOptions): ts.SignatureDeclaration { - const suppressAny = context.flags & ts.NodeBuilderFlags.SuppressAnyReturnType; - if (suppressAny) context.flags &= ~ts.NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s + function signatureToSignatureDeclarationHelper(signature: Signature, kind: SignatureDeclaration["kind"], context: NodeBuilderContext, options?: SignatureToSignatureDeclarationOptions): SignatureDeclaration { + const suppressAny = context.flags & NodeBuilderFlags.SuppressAnyReturnType; + if (suppressAny) context.flags &= ~NodeBuilderFlags.SuppressAnyReturnType; // suppress only toplevel `any`s context.approximateLength += 3; // Usually a signature contributes a few more characters than this, but 3 is the minimum - let typeParameters: ts.TypeParameterDeclaration[] | undefined; - let typeArguments: ts.TypeNode[] | undefined; - if (context.flags & ts.NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { + let typeParameters: TypeParameterDeclaration[] | undefined; + let typeArguments: TypeNode[] | undefined; + if (context.flags & NodeBuilderFlags.WriteTypeArgumentsOfSignature && signature.target && signature.mapper && signature.target.typeParameters) { typeArguments = signature.target.typeParameters.map(parameter => typeToTypeNodeHelper(instantiateType(parameter, signature.mapper), context)); } else { @@ -6068,23 +6266,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const expandedParams = getExpandedParameters(signature, /*skipUnionExpanding*/ true)[0]; // If the expanded parameter list had a variadic in a non-trailing position, don't expand it - const parameters = (ts.some(expandedParams, p => p !== expandedParams[expandedParams.length - 1] && !!(ts.getCheckFlags(p) & ts.CheckFlags.RestParameter)) ? signature.parameters : expandedParams).map(parameter => symbolToParameterDeclaration(parameter, context, kind === ts.SyntaxKind.Constructor, options?.privateSymbolVisitor, options?.bundledImports)); - const thisParameter = context.flags & ts.NodeBuilderFlags.OmitThisParameter ? undefined : tryGetThisParameterDeclaration(signature, context); + const parameters = (some(expandedParams, p => p !== expandedParams[expandedParams.length - 1] && !!(getCheckFlags(p) & CheckFlags.RestParameter)) ? signature.parameters : expandedParams).map(parameter => symbolToParameterDeclaration(parameter, context, kind === SyntaxKind.Constructor, options?.privateSymbolVisitor, options?.bundledImports)); + const thisParameter = context.flags & NodeBuilderFlags.OmitThisParameter ? undefined : tryGetThisParameterDeclaration(signature, context); if (thisParameter) { parameters.unshift(thisParameter); } - let returnTypeNode: ts.TypeNode | undefined; + let returnTypeNode: TypeNode | undefined; const typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { - const assertsModifier = typePredicate.kind === ts.TypePredicateKind.AssertsThis || typePredicate.kind === ts.TypePredicateKind.AssertsIdentifier ? - ts.factory.createToken(ts.SyntaxKind.AssertsKeyword) : + const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? + factory.createToken(SyntaxKind.AssertsKeyword) : undefined; - const parameterName = typePredicate.kind === ts.TypePredicateKind.Identifier || typePredicate.kind === ts.TypePredicateKind.AssertsIdentifier ? - ts.setEmitFlags(ts.factory.createIdentifier(typePredicate.parameterName), ts.EmitFlags.NoAsciiEscaping) : - ts.factory.createThisTypeNode(); + const parameterName = typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? + setEmitFlags(factory.createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) : + factory.createThisTypeNode(); const typeNode = typePredicate.type && typeToTypeNodeHelper(typePredicate.type, context); - returnTypeNode = ts.factory.createTypePredicateNode(assertsModifier, parameterName, typeNode); + returnTypeNode = factory.createTypePredicateNode(assertsModifier, parameterName, typeNode); } else { const returnType = getReturnTypeOfSignature(signature); @@ -6092,47 +6290,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { returnTypeNode = serializeReturnTypeForSignature(context, returnType, signature, options?.privateSymbolVisitor, options?.bundledImports); } else if (!suppressAny) { - returnTypeNode = ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + returnTypeNode = factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } } let modifiers = options?.modifiers; - if ((kind === ts.SyntaxKind.ConstructorType) && signature.flags & ts.SignatureFlags.Abstract) { - const flags = ts.modifiersToFlags(modifiers); - modifiers = ts.factory.createModifiersFromModifierFlags(flags | ts.ModifierFlags.Abstract); + if ((kind === SyntaxKind.ConstructorType) && signature.flags & SignatureFlags.Abstract) { + const flags = modifiersToFlags(modifiers); + modifiers = factory.createModifiersFromModifierFlags(flags | ModifierFlags.Abstract); } const node = - kind === ts.SyntaxKind.CallSignature ? ts.factory.createCallSignature(typeParameters, parameters, returnTypeNode) : - kind === ts.SyntaxKind.ConstructSignature ? ts.factory.createConstructSignature(typeParameters, parameters, returnTypeNode) : - kind === ts.SyntaxKind.MethodSignature ? ts.factory.createMethodSignature(modifiers, options?.name ?? ts.factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) : - kind === ts.SyntaxKind.MethodDeclaration ? ts.factory.createMethodDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ?? ts.factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : - kind === ts.SyntaxKind.Constructor ? ts.factory.createConstructorDeclaration(modifiers, parameters, /*body*/ undefined) : - kind === ts.SyntaxKind.GetAccessor ? ts.factory.createGetAccessorDeclaration(modifiers, options?.name ?? ts.factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : - kind === ts.SyntaxKind.SetAccessor ? ts.factory.createSetAccessorDeclaration(modifiers, options?.name ?? ts.factory.createIdentifier(""), parameters, /*body*/ undefined) : - kind === ts.SyntaxKind.IndexSignature ? ts.factory.createIndexSignature(modifiers, parameters, returnTypeNode) : - kind === ts.SyntaxKind.JSDocFunctionType ? ts.factory.createJSDocFunctionType(parameters, returnTypeNode) : - kind === ts.SyntaxKind.FunctionType ? ts.factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(""))) : - kind === ts.SyntaxKind.ConstructorType ? ts.factory.createConstructorTypeNode(modifiers, typeParameters, parameters, returnTypeNode ?? ts.factory.createTypeReferenceNode(ts.factory.createIdentifier(""))) : - kind === ts.SyntaxKind.FunctionDeclaration ? ts.factory.createFunctionDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ? ts.cast(options.name, ts.isIdentifier) : ts.factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) : - kind === ts.SyntaxKind.FunctionExpression ? ts.factory.createFunctionExpression(modifiers, /*asteriskToken*/ undefined, options?.name ? ts.cast(options.name, ts.isIdentifier) : ts.factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, ts.factory.createBlock([])) : - kind === ts.SyntaxKind.ArrowFunction ? ts.factory.createArrowFunction(modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, ts.factory.createBlock([])) : - ts.Debug.assertNever(kind); + kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, returnTypeNode) : + kind === SyntaxKind.ConstructSignature ? factory.createConstructSignature(typeParameters, parameters, returnTypeNode) : + kind === SyntaxKind.MethodSignature ? factory.createMethodSignature(modifiers, options?.name ?? factory.createIdentifier(""), options?.questionToken, typeParameters, parameters, returnTypeNode) : + kind === SyntaxKind.MethodDeclaration ? factory.createMethodDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ?? factory.createIdentifier(""), /*questionToken*/ undefined, typeParameters, parameters, returnTypeNode, /*body*/ undefined) : + kind === SyntaxKind.Constructor ? factory.createConstructorDeclaration(modifiers, parameters, /*body*/ undefined) : + kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, returnTypeNode, /*body*/ undefined) : + kind === SyntaxKind.SetAccessor ? factory.createSetAccessorDeclaration(modifiers, options?.name ?? factory.createIdentifier(""), parameters, /*body*/ undefined) : + kind === SyntaxKind.IndexSignature ? factory.createIndexSignature(modifiers, parameters, returnTypeNode) : + kind === SyntaxKind.JSDocFunctionType ? factory.createJSDocFunctionType(parameters, returnTypeNode) : + kind === SyntaxKind.FunctionType ? factory.createFunctionTypeNode(typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) : + kind === SyntaxKind.ConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, returnTypeNode ?? factory.createTypeReferenceNode(factory.createIdentifier(""))) : + kind === SyntaxKind.FunctionDeclaration ? factory.createFunctionDeclaration(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, /*body*/ undefined) : + kind === SyntaxKind.FunctionExpression ? factory.createFunctionExpression(modifiers, /*asteriskToken*/ undefined, options?.name ? cast(options.name, isIdentifier) : factory.createIdentifier(""), typeParameters, parameters, returnTypeNode, factory.createBlock([])) : + kind === SyntaxKind.ArrowFunction ? factory.createArrowFunction(modifiers, typeParameters, parameters, returnTypeNode, /*equalsGreaterThanToken*/ undefined, factory.createBlock([])) : + Debug.assertNever(kind); if (typeArguments) { - node.typeArguments = ts.factory.createNodeArray(typeArguments); + node.typeArguments = factory.createNodeArray(typeArguments); } return node; } - function tryGetThisParameterDeclaration(signature: ts.Signature, context: NodeBuilderContext) { + function tryGetThisParameterDeclaration(signature: Signature, context: NodeBuilderContext) { if (signature.thisParameter) { return symbolToParameterDeclaration(signature.thisParameter, context); } if (signature.declaration) { - const thisTag = ts.getJSDocThisTag(signature.declaration); + const thisTag = getJSDocThisTag(signature.declaration); if (thisTag && thisTag.typeExpression) { - return ts.factory.createParameterDeclaration( + return factory.createParameterDeclaration( /* modifiers */ undefined, /* dotDotDotToken */ undefined, "this", @@ -6143,26 +6341,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function typeParameterToDeclarationWithConstraint(type: ts.TypeParameter, context: NodeBuilderContext, constraintNode: ts.TypeNode | undefined): ts.TypeParameterDeclaration { + function typeParameterToDeclarationWithConstraint(type: TypeParameter, context: NodeBuilderContext, constraintNode: TypeNode | undefined): TypeParameterDeclaration { const savedContextFlags = context.flags; - context.flags &= ~ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic - const modifiers = ts.factory.createModifiersFromModifierFlags(getVarianceModifiers(type)); + context.flags &= ~NodeBuilderFlags.WriteTypeParametersInQualifiedName; // Avoids potential infinite loop when building for a claimspace with a generic + const modifiers = factory.createModifiersFromModifierFlags(getVarianceModifiers(type)); const name = typeParameterToName(type, context); const defaultParameter = getDefaultFromTypeParameter(type); const defaultParameterNode = defaultParameter && typeToTypeNodeHelper(defaultParameter, context); context.flags = savedContextFlags; - return ts.factory.createTypeParameterDeclaration(modifiers, name, constraintNode, defaultParameterNode); + return factory.createTypeParameterDeclaration(modifiers, name, constraintNode, defaultParameterNode); } - function typeParameterToDeclaration(type: ts.TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): ts.TypeParameterDeclaration { + function typeParameterToDeclaration(type: TypeParameter, context: NodeBuilderContext, constraint = getConstraintOfTypeParameter(type)): TypeParameterDeclaration { const constraintNode = constraint && typeToTypeNodeHelper(constraint, context); return typeParameterToDeclarationWithConstraint(type, context, constraintNode); } - function symbolToParameterDeclaration(parameterSymbol: ts.Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: ts.Symbol) => void, bundledImports?: boolean): ts.ParameterDeclaration { - let parameterDeclaration: ts.ParameterDeclaration | ts.JSDocParameterTag | undefined = ts.getDeclarationOfKind(parameterSymbol, ts.SyntaxKind.Parameter); - if (!parameterDeclaration && !ts.isTransientSymbol(parameterSymbol)) { - parameterDeclaration = ts.getDeclarationOfKind(parameterSymbol, ts.SyntaxKind.JSDocParameterTag); + function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: Symbol) => void, bundledImports?: boolean): ParameterDeclaration { + let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind(parameterSymbol, SyntaxKind.Parameter); + if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) { + parameterDeclaration = getDeclarationOfKind(parameterSymbol, SyntaxKind.JSDocParameterTag); } let parameterType = getTypeOfSymbol(parameterSymbol); @@ -6171,72 +6369,72 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, privateSymbolVisitor, bundledImports); - const modifiers = !(context.flags & ts.NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && ts.canHaveModifiers(parameterDeclaration) ? ts.map(ts.getModifiers(parameterDeclaration), ts.factory.cloneNode) : undefined; - const isRest = parameterDeclaration && ts.isRestParameter(parameterDeclaration) || ts.getCheckFlags(parameterSymbol) & ts.CheckFlags.RestParameter; - const dotDotDotToken = isRest ? ts.factory.createToken(ts.SyntaxKind.DotDotDotToken) : undefined; + const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && canHaveModifiers(parameterDeclaration) ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined; + const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter; + const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined; const name = parameterDeclaration ? parameterDeclaration.name ? - parameterDeclaration.name.kind === ts.SyntaxKind.Identifier ? ts.setEmitFlags(ts.factory.cloneNode(parameterDeclaration.name), ts.EmitFlags.NoAsciiEscaping) : - parameterDeclaration.name.kind === ts.SyntaxKind.QualifiedName ? ts.setEmitFlags(ts.factory.cloneNode(parameterDeclaration.name.right), ts.EmitFlags.NoAsciiEscaping) : + parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) : + parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) : cloneBindingName(parameterDeclaration.name) : - ts.symbolName(parameterSymbol) : - ts.symbolName(parameterSymbol); - const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || ts.getCheckFlags(parameterSymbol) & ts.CheckFlags.OptionalParameter; - const questionToken = isOptional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined; - const parameterNode = ts.factory.createParameterDeclaration( + symbolName(parameterSymbol) : + symbolName(parameterSymbol); + const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter; + const questionToken = isOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined; + const parameterNode = factory.createParameterDeclaration( modifiers, dotDotDotToken, name, questionToken, parameterTypeNode, /*initializer*/ undefined); - context.approximateLength += ts.symbolName(parameterSymbol).length + 3; + context.approximateLength += symbolName(parameterSymbol).length + 3; return parameterNode; - function cloneBindingName(node: ts.BindingName): ts.BindingName { - return elideInitializerAndSetEmitFlags(node) as ts.BindingName; - function elideInitializerAndSetEmitFlags(node: ts.Node): ts.Node { - if (context.tracker.trackSymbol && ts.isComputedPropertyName(node) && isLateBindableName(node)) { + function cloneBindingName(node: BindingName): BindingName { + return elideInitializerAndSetEmitFlags(node) as BindingName; + function elideInitializerAndSetEmitFlags(node: Node): Node { + if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { trackComputedName(node.expression, context.enclosingDeclaration, context); } - let visited = ts.visitEachChild(node, elideInitializerAndSetEmitFlags, ts.nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; - if (ts.isBindingElement(visited)) { - visited = ts.factory.updateBindingElement( + let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; + if (isBindingElement(visited)) { + visited = factory.updateBindingElement( visited, visited.dotDotDotToken, visited.propertyName, visited.name, /*initializer*/ undefined); } - if (!ts.nodeIsSynthesized(visited)) { - visited = ts.factory.cloneNode(visited); + if (!nodeIsSynthesized(visited)) { + visited = factory.cloneNode(visited); } - return ts.setEmitFlags(visited, ts.EmitFlags.SingleLine | ts.EmitFlags.NoAsciiEscaping); + return setEmitFlags(visited, EmitFlags.SingleLine | EmitFlags.NoAsciiEscaping); } } } - function trackComputedName(accessExpression: ts.EntityNameOrEntityNameExpression, enclosingDeclaration: ts.Node | undefined, context: NodeBuilderContext) { + function trackComputedName(accessExpression: EntityNameOrEntityNameExpression, enclosingDeclaration: Node | undefined, context: NodeBuilderContext) { if (!context.tracker.trackSymbol) return; // get symbol of the first identifier of the entityName - const firstIdentifier = ts.getFirstIdentifier(accessExpression); - const name = resolveName(firstIdentifier, firstIdentifier.escapedText, ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + const firstIdentifier = getFirstIdentifier(accessExpression); + const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (name) { - context.tracker.trackSymbol(name, enclosingDeclaration, ts.SymbolFlags.Value); + context.tracker.trackSymbol(name, enclosingDeclaration, SymbolFlags.Value); } } - function lookupSymbolChain(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, yieldModuleSymbol?: boolean) { + function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { context.tracker.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217 return lookupSymbolChainWorker(symbol, context, meaning, yieldModuleSymbol); } - function lookupSymbolChainWorker(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, yieldModuleSymbol?: boolean) { + function lookupSymbolChainWorker(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { // Try to get qualified name if the symbol is not a type parameter and there is an enclosing declaration. - let chain: ts.Symbol[]; - const isTypeParameter = symbol.flags & ts.SymbolFlags.TypeParameter; - if (!isTypeParameter && (context.enclosingDeclaration || context.flags & ts.NodeBuilderFlags.UseFullyQualifiedType) && !(context.flags & ts.NodeBuilderFlags.DoNotIncludeSymbolChain)) { - chain = ts.Debug.checkDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); - ts.Debug.assert(chain && chain.length > 0); + let chain: Symbol[]; + const isTypeParameter = symbol.flags & SymbolFlags.TypeParameter; + if (!isTypeParameter && (context.enclosingDeclaration || context.flags & NodeBuilderFlags.UseFullyQualifiedType) && !(context.flags & NodeBuilderFlags.DoNotIncludeSymbolChain)) { + chain = Debug.checkDefined(getSymbolChain(symbol, meaning, /*endOfChain*/ true)); + Debug.assert(chain && chain.length > 0); } else { chain = [symbol]; @@ -6244,17 +6442,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return chain; /** @param endOfChain Set to false for recursive calls; non-recursive calls should always output something. */ - function getSymbolChain(symbol: ts.Symbol, meaning: ts.SymbolFlags, endOfChain: boolean): ts.Symbol[] | undefined { - let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & ts.NodeBuilderFlags.UseOnlyExternalAliasing)); + function getSymbolChain(symbol: Symbol, meaning: SymbolFlags, endOfChain: boolean): Symbol[] | undefined { + let accessibleSymbolChain = getAccessibleSymbolChain(symbol, context.enclosingDeclaration, meaning, !!(context.flags & NodeBuilderFlags.UseOnlyExternalAliasing)); let parentSpecifiers: (string | undefined)[]; if (!accessibleSymbolChain || needsQualification(accessibleSymbolChain[0], context.enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) { // Go up and add our parent. const parents = getContainersOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol, context.enclosingDeclaration, meaning); - if (ts.length(parents)) { + if (length(parents)) { parentSpecifiers = parents!.map(symbol => - ts.some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol) + some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol) ? getSpecifierForModuleSymbol(symbol, context) : undefined); const indices = parents!.map((_, i) => i); @@ -6263,8 +6461,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (const parent of sortedParents) { const parentChain = getSymbolChain(parent, getQualifiedLeftMeaning(meaning), /*endOfChain*/ false); if (parentChain) { - if (parent.exports && parent.exports.get(ts.InternalSymbolName.ExportEquals) && - getSymbolIfSameReference(parent.exports.get(ts.InternalSymbolName.ExportEquals)!, symbol)) { + if (parent.exports && parent.exports.get(InternalSymbolName.ExportEquals) && + getSymbolIfSameReference(parent.exports.get(InternalSymbolName.ExportEquals)!, symbol)) { // parentChain root _is_ symbol - symbol is a module export=, so it kinda looks like it's own parent // No need to lookup an alias for the symbol in itself accessibleSymbolChain = parentChain; @@ -6284,9 +6482,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If this is the last part of outputting the symbol, always output. The cases apply only to parent symbols. endOfChain || // If a parent symbol is an anonymous type, don't write it. - !(symbol.flags & (ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.ObjectLiteral))) { + !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral))) { // If a parent symbol is an external module, don't write it. (We prefer just `x` vs `"foo/bar".x`.) - if (!endOfChain && !yieldModuleSymbol && !!ts.forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + if (!endOfChain && !yieldModuleSymbol && !!forEach(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { return; } return [symbol]; @@ -6296,10 +6494,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const specifierA = parentSpecifiers[a]; const specifierB = parentSpecifiers[b]; if (specifierA && specifierB) { - const isBRelative = ts.pathIsRelative(specifierB); - if (ts.pathIsRelative(specifierA) === isBRelative) { + const isBRelative = pathIsRelative(specifierB); + if (pathIsRelative(specifierA) === isBRelative) { // Both relative or both non-relative, sort by number of parts - return ts.moduleSpecifiers.countPathComponents(specifierA) - ts.moduleSpecifiers.countPathComponents(specifierB); + return moduleSpecifiers.countPathComponents(specifierA) - moduleSpecifiers.countPathComponents(specifierB); } if (isBRelative) { // A is non-relative, B is relative: prefer A @@ -6313,32 +6511,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function typeParametersToTypeParameterDeclarations(symbol: ts.Symbol, context: NodeBuilderContext) { - let typeParameterNodes: ts.NodeArray | undefined; + function typeParametersToTypeParameterDeclarations(symbol: Symbol, context: NodeBuilderContext) { + let typeParameterNodes: NodeArray | undefined; const targetSymbol = getTargetSymbol(symbol); - if (targetSymbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface | ts.SymbolFlags.TypeAlias)) { - typeParameterNodes = ts.factory.createNodeArray(ts.map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); + if (targetSymbol.flags & (SymbolFlags.Class | SymbolFlags.Interface | SymbolFlags.TypeAlias)) { + typeParameterNodes = factory.createNodeArray(map(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol), tp => typeParameterToDeclaration(tp, context))); } return typeParameterNodes; } - function lookupTypeParameterNodes(chain: ts.Symbol[], index: number, context: NodeBuilderContext) { - ts.Debug.assert(chain && 0 <= index && index < chain.length); + function lookupTypeParameterNodes(chain: Symbol[], index: number, context: NodeBuilderContext) { + Debug.assert(chain && 0 <= index && index < chain.length); const symbol = chain[index]; const symbolId = getSymbolId(symbol); if (context.typeParameterSymbolList?.has(symbolId)) { return undefined; } - (context.typeParameterSymbolList || (context.typeParameterSymbolList = new ts.Set())).add(symbolId); - let typeParameterNodes: readonly ts.TypeNode[] | readonly ts.TypeParameterDeclaration[] | undefined; - if (context.flags & ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { + (context.typeParameterSymbolList || (context.typeParameterSymbolList = new Set())).add(symbolId); + let typeParameterNodes: readonly TypeNode[] | readonly TypeParameterDeclaration[] | undefined; + if (context.flags & NodeBuilderFlags.WriteTypeParametersInQualifiedName && index < (chain.length - 1)) { const parentSymbol = symbol; const nextSymbol = chain[index + 1]; - if (ts.getCheckFlags(nextSymbol) & ts.CheckFlags.Instantiated) { + if (getCheckFlags(nextSymbol) & CheckFlags.Instantiated) { const params = getTypeParametersOfClassOrInterface( - parentSymbol.flags & ts.SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol + parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol ); - typeParameterNodes = mapToTypeNodes(ts.map(params, t => getMappedType(t, (nextSymbol as ts.TransientSymbol).mapper!)), context); + typeParameterNodes = mapToTypeNodes(map(params, t => getMappedType(t, (nextSymbol as TransientSymbol).mapper!)), context); } else { typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context); @@ -6350,19 +6548,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Given A[B][C][D], finds A[B] */ - function getTopmostIndexedAccessType(top: ts.IndexedAccessTypeNode): ts.IndexedAccessTypeNode { - if (ts.isIndexedAccessTypeNode(top.objectType)) { + function getTopmostIndexedAccessType(top: IndexedAccessTypeNode): IndexedAccessTypeNode { + if (isIndexedAccessTypeNode(top.objectType)) { return getTopmostIndexedAccessType(top.objectType); } return top; } - function getSpecifierForModuleSymbol(symbol: ts.Symbol, context: NodeBuilderContext, overrideImportMode?: ts.SourceFile["impliedNodeFormat"]) { - let file = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.SourceFile); + function getSpecifierForModuleSymbol(symbol: Symbol, context: NodeBuilderContext, overrideImportMode?: SourceFile["impliedNodeFormat"]) { + let file = getDeclarationOfKind(symbol, SyntaxKind.SourceFile); if (!file) { - const equivalentFileSymbol = ts.firstDefined(symbol.declarations, d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol)); + const equivalentFileSymbol = firstDefined(symbol.declarations, d => getFileSymbolIfFileSymbolExportEqualsContainer(d, symbol)); if (equivalentFileSymbol) { - file = ts.getDeclarationOfKind(equivalentFileSymbol, ts.SyntaxKind.SourceFile); + file = getDeclarationOfKind(equivalentFileSymbol, SyntaxKind.SourceFile); } } if (file && file.moduleName !== undefined) { @@ -6371,8 +6569,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (!file) { if (context.tracker.trackReferencedAmbientModule) { - const ambientDecls = ts.filter(symbol.declarations, ts.isAmbientModule); - if (ts.length(ambientDecls)) { + const ambientDecls = filter(symbol.declarations, isAmbientModule); + if (length(ambientDecls)) { for (const decl of ambientDecls!) { context.tracker.trackReferencedAmbientModule(decl, symbol); } @@ -6387,22 +6585,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (ambientModuleSymbolRegex.test(symbol.escapedName as string)) { return (symbol.escapedName as string).substring(1, (symbol.escapedName as string).length - 1); } - return ts.getSourceFileOfNode(ts.getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full + return getSourceFileOfNode(getNonAugmentationDeclaration(symbol)!).fileName; // A resolver may not be provided for baselines and errors - in those cases we use the fileName in full } - const contextFile = ts.getSourceFileOfNode(ts.getOriginalNode(context.enclosingDeclaration)); + const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration)); const resolutionMode = overrideImportMode || contextFile?.impliedNodeFormat; const cacheKey = getSpecifierCacheKey(contextFile.path, resolutionMode); const links = getSymbolLinks(symbol); let specifier = links.specifierCache && links.specifierCache.get(cacheKey); if (!specifier) { - const isBundle = !!ts.outFile(compilerOptions); + const isBundle = !!outFile(compilerOptions); // For declaration bundles, we need to generate absolute paths relative to the common source dir for imports, // just like how the declaration emitter does for the ambient module declarations - we can easily accomplish this // using the `baseUrl` compiler option (which we would otherwise never use in declaration emit) and a non-relative // specifier preference const { moduleResolverHost } = context.tracker; const specifierCompilerOptions = isBundle ? { ...compilerOptions, baseUrl: moduleResolverHost.getCommonSourceDirectory() } : compilerOptions; - specifier = ts.first(ts.moduleSpecifiers.getModuleSpecifiers( + specifier = first(moduleSpecifiers.getModuleSpecifiers( symbol, checker, specifierCompilerOptions, @@ -6411,46 +6609,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { { importModuleSpecifierPreference: isBundle ? "non-relative" : "project-relative", importModuleSpecifierEnding: isBundle ? "minimal" - : resolutionMode === ts.ModuleKind.ESNext ? "js" + : resolutionMode === ModuleKind.ESNext ? "js" : undefined, }, { overrideImportMode } )); - links.specifierCache ??= new ts.Map(); + links.specifierCache ??= new Map(); links.specifierCache.set(cacheKey, specifier); } return specifier; - function getSpecifierCacheKey(path: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined) { + function getSpecifierCacheKey(path: string, mode: SourceFile["impliedNodeFormat"] | undefined) { return mode === undefined ? path : `${mode}|${path}`; } } - function symbolToEntityNameNode(symbol: ts.Symbol): ts.EntityName { - const identifier = ts.factory.createIdentifier(ts.unescapeLeadingUnderscores(symbol.escapedName)); - return symbol.parent ? ts.factory.createQualifiedName(symbolToEntityNameNode(symbol.parent), identifier) : identifier; + function symbolToEntityNameNode(symbol: Symbol): EntityName { + const identifier = factory.createIdentifier(unescapeLeadingUnderscores(symbol.escapedName)); + return symbol.parent ? factory.createQualifiedName(symbolToEntityNameNode(symbol.parent), identifier) : identifier; } - function symbolToTypeNode(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, overrideTypeArguments?: readonly ts.TypeNode[]): ts.TypeNode { - const chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope)); // If we're using aliases outside the current scope, dont bother with the module + function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, overrideTypeArguments?: readonly TypeNode[]): TypeNode { + const chain = lookupSymbolChain(symbol, context, meaning, !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope)); // If we're using aliases outside the current scope, dont bother with the module - const isTypeOf = meaning === ts.SymbolFlags.Value; - if (ts.some(chain[0].declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + const isTypeOf = meaning === SymbolFlags.Value; + if (some(chain[0].declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { // module is root, must use `ImportTypeNode` const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined; const typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context); - const contextFile = ts.getSourceFileOfNode(ts.getOriginalNode(context.enclosingDeclaration)); - const targetFile = ts.getSourceFileOfModule(chain[0]); + const contextFile = getSourceFileOfNode(getOriginalNode(context.enclosingDeclaration)); + const targetFile = getSourceFileOfModule(chain[0]); let specifier: string | undefined; - let assertion: ts.ImportTypeAssertionContainer | undefined; - if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeNext) { + let assertion: ImportTypeAssertionContainer | undefined; + if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) { // An `import` type directed at an esm format file is only going to resolve in esm mode - set the esm mode assertion - if (targetFile?.impliedNodeFormat === ts.ModuleKind.ESNext && targetFile.impliedNodeFormat !== contextFile?.impliedNodeFormat) { - specifier = getSpecifierForModuleSymbol(chain[0], context, ts.ModuleKind.ESNext); - assertion = ts.factory.createImportTypeAssertionContainer(ts.factory.createAssertClause(ts.factory.createNodeArray([ - ts.factory.createAssertEntry( - ts.factory.createStringLiteral("resolution-mode"), - ts.factory.createStringLiteral("import") + if (targetFile?.impliedNodeFormat === ModuleKind.ESNext && targetFile.impliedNodeFormat !== contextFile?.impliedNodeFormat) { + specifier = getSpecifierForModuleSymbol(chain[0], context, ModuleKind.ESNext); + assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([ + factory.createAssertEntry( + factory.createStringLiteral("resolution-mode"), + factory.createStringLiteral("import") ) ]))); context.tracker.reportImportTypeNodeResolutionModeOverride?.(); @@ -6459,11 +6657,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!specifier) { specifier = getSpecifierForModuleSymbol(chain[0], context); } - if (!(context.flags & ts.NodeBuilderFlags.AllowNodeModulesRelativePaths) && ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Classic && specifier.indexOf("/node_modules/") >= 0) { + if (!(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic && specifier.indexOf("/node_modules/") >= 0) { const oldSpecifier = specifier; - if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeNext) { + if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) { // We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set - const swappedMode = contextFile?.impliedNodeFormat === ts.ModuleKind.ESNext ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext; + const swappedMode = contextFile?.impliedNodeFormat === ModuleKind.ESNext ? ModuleKind.CommonJS : ModuleKind.ESNext; specifier = getSpecifierForModuleSymbol(chain[0], context, swappedMode); if (specifier.indexOf("/node_modules/") >= 0) { @@ -6471,10 +6669,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { specifier = oldSpecifier; } else { - assertion = ts.factory.createImportTypeAssertionContainer(ts.factory.createAssertClause(ts.factory.createNodeArray([ - ts.factory.createAssertEntry( - ts.factory.createStringLiteral("resolution-mode"), - ts.factory.createStringLiteral(swappedMode === ts.ModuleKind.ESNext ? "import" : "require") + assertion = factory.createImportTypeAssertionContainer(factory.createAssertClause(factory.createNodeArray([ + factory.createAssertEntry( + factory.createStringLiteral("resolution-mode"), + factory.createStringLiteral(swappedMode === ModuleKind.ESNext ? "import" : "require") ) ]))); context.tracker.reportImportTypeNodeResolutionModeOverride?.(); @@ -6490,55 +6688,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - const lit = ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(specifier)); + const lit = factory.createLiteralTypeNode(factory.createStringLiteral(specifier)); if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]); context.approximateLength += specifier.length + 10; // specifier + import("") - if (!nonRootParts || ts.isEntityName(nonRootParts)) { + if (!nonRootParts || isEntityName(nonRootParts)) { if (nonRootParts) { - const lastId = ts.isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; + const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; lastId.typeArguments = undefined; } - return ts.factory.createImportTypeNode(lit, assertion, nonRootParts as ts.EntityName, typeParameterNodes as readonly ts.TypeNode[], isTypeOf); + return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); } else { const splitNode = getTopmostIndexedAccessType(nonRootParts); - const qualifier = (splitNode.objectType as ts.TypeReferenceNode).typeName; - return ts.factory.createIndexedAccessTypeNode(ts.factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly ts.TypeNode[], isTypeOf), splitNode.indexType); + const qualifier = (splitNode.objectType as TypeReferenceNode).typeName; + return factory.createIndexedAccessTypeNode(factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType); } } const entityName = createAccessFromSymbolChain(chain, chain.length - 1, 0); - if (ts.isIndexedAccessTypeNode(entityName)) { + if (isIndexedAccessTypeNode(entityName)) { return entityName; // Indexed accesses can never be `typeof` } if (isTypeOf) { - return ts.factory.createTypeQueryNode(entityName); + return factory.createTypeQueryNode(entityName); } else { - const lastId = ts.isIdentifier(entityName) ? entityName : entityName.right; + const lastId = isIdentifier(entityName) ? entityName : entityName.right; const lastTypeArgs = lastId.typeArguments; lastId.typeArguments = undefined; - return ts.factory.createTypeReferenceNode(entityName, lastTypeArgs as ts.NodeArray); + return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray); } - function createAccessFromSymbolChain(chain: ts.Symbol[], index: number, stopper: number): ts.EntityName | ts.IndexedAccessTypeNode { + function createAccessFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName | IndexedAccessTypeNode { const typeParameterNodes = index === (chain.length - 1) ? overrideTypeArguments : lookupTypeParameterNodes(chain, index, context); const symbol = chain[index]; const parent = chain[index - 1]; let symbolName: string | undefined; if (index === 0) { - context.flags |= ts.NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; symbolName = getNameOfSymbolAsWritten(symbol, context); context.approximateLength += (symbolName ? symbolName.length : 0) + 1; - context.flags ^= ts.NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } else { if (parent && getExportsOfSymbol(parent)) { const exports = getExportsOfSymbol(parent); - ts.forEachEntry(exports, (ex, name) => { - if (getSymbolIfSameReference(ex, symbol) && !isLateBoundName(name) && name !== ts.InternalSymbolName.ExportEquals) { - symbolName = ts.unescapeLeadingUnderscores(name); + forEachEntry(exports, (ex, name) => { + if (getSymbolIfSameReference(ex, symbol) && !isLateBoundName(name) && name !== InternalSymbolName.ExportEquals) { + symbolName = unescapeLeadingUnderscores(name); return true; } }); @@ -6546,11 +6744,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (symbolName === undefined) { - const name = ts.firstDefined(symbol.declarations, ts.getNameOfDeclaration); - if (name && ts.isComputedPropertyName(name) && ts.isEntityName(name.expression)) { + const name = firstDefined(symbol.declarations, getNameOfDeclaration); + if (name && isComputedPropertyName(name) && isEntityName(name.expression)) { const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); - if (ts.isEntityName(LHS)) { - return ts.factory.createIndexedAccessTypeNode(ts.factory.createParenthesizedType(ts.factory.createTypeQueryNode(LHS)), ts.factory.createTypeQueryNode(name.expression)); + if (isEntityName(LHS)) { + return factory.createIndexedAccessTypeNode(factory.createParenthesizedType(factory.createTypeQueryNode(LHS)), factory.createTypeQueryNode(name.expression)); } return LHS; } @@ -6558,37 +6756,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } context.approximateLength += symbolName.length + 1; - if (!(context.flags & ts.NodeBuilderFlags.ForbidIndexedAccessSymbolReferences) && parent && + if (!(context.flags & NodeBuilderFlags.ForbidIndexedAccessSymbolReferences) && parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) && getSymbolIfSameReference(getMembersOfSymbol(parent).get(symbol.escapedName)!, symbol)) { // Should use an indexed access const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); - if (ts.isIndexedAccessTypeNode(LHS)) { - return ts.factory.createIndexedAccessTypeNode(LHS, ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(symbolName))); + if (isIndexedAccessTypeNode(LHS)) { + return factory.createIndexedAccessTypeNode(LHS, factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); } else { - return ts.factory.createIndexedAccessTypeNode(ts.factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly ts.TypeNode[]), ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(symbolName))); + return factory.createIndexedAccessTypeNode(factory.createTypeReferenceNode(LHS, typeParameterNodes as readonly TypeNode[]), factory.createLiteralTypeNode(factory.createStringLiteral(symbolName))); } } - const identifier = ts.setEmitFlags(ts.factory.createIdentifier(symbolName, typeParameterNodes), ts.EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; if (index > stopper) { const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); - if (!ts.isEntityName(LHS)) { - return ts.Debug.fail("Impossible construct - an export of an indexed access cannot be reachable"); + if (!isEntityName(LHS)) { + return Debug.fail("Impossible construct - an export of an indexed access cannot be reachable"); } - return ts.factory.createQualifiedName(LHS, identifier); + return factory.createQualifiedName(LHS, identifier); } return identifier; } } - function typeParameterShadowsNameInScope(escapedName: ts.__String, context: NodeBuilderContext, type: ts.TypeParameter) { - const result = resolveName(context.enclosingDeclaration, escapedName, ts.SymbolFlags.Type, /*nameNotFoundArg*/ undefined, escapedName, /*isUse*/ false); + function typeParameterShadowsNameInScope(escapedName: __String, context: NodeBuilderContext, type: TypeParameter) { + const result = resolveName(context.enclosingDeclaration, escapedName, SymbolFlags.Type, /*nameNotFoundArg*/ undefined, escapedName, /*isUse*/ false); if (result) { - if (result.flags & ts.SymbolFlags.TypeParameter && result === type.symbol) { + if (result.flags & SymbolFlags.TypeParameter && result === type.symbol) { return false; } return true; @@ -6596,156 +6794,156 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function typeParameterToName(type: ts.TypeParameter, context: NodeBuilderContext) { - if (context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams && context.typeParameterNames) { + function typeParameterToName(type: TypeParameter, context: NodeBuilderContext) { + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams && context.typeParameterNames) { const cached = context.typeParameterNames.get(getTypeId(type)); if (cached) { return cached; } } - let result = symbolToName(type.symbol, context, ts.SymbolFlags.Type, /*expectsIdentifier*/ true); - if (!(result.kind & ts.SyntaxKind.Identifier)) { - return ts.factory.createIdentifier("(Missing type parameter)"); + let result = symbolToName(type.symbol, context, SymbolFlags.Type, /*expectsIdentifier*/ true); + if (!(result.kind & SyntaxKind.Identifier)) { + return factory.createIdentifier("(Missing type parameter)"); } - if (context.flags & ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { + if (context.flags & NodeBuilderFlags.GenerateNamesForShadowedTypeParams) { const rawtext = result.escapedText as string; let i = context.typeParameterNamesByTextNextNameCount?.get(rawtext) || 0; let text = rawtext; - while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsNameInScope(text as ts.__String, context, type)) { + while (context.typeParameterNamesByText?.has(text) || typeParameterShadowsNameInScope(text as __String, context, type)) { i++; text = `${rawtext}_${i}`; } if (text !== rawtext) { - result = ts.factory.createIdentifier(text, result.typeArguments); + result = factory.createIdentifier(text, result.typeArguments); } // avoiding iterations of the above loop turns out to be worth it when `i` starts to get large, so we cache the max // `i` we've used thus far, to save work later - (context.typeParameterNamesByTextNextNameCount ||= new ts.Map()).set(rawtext, i); - (context.typeParameterNames ||= new ts.Map()).set(getTypeId(type), result); - (context.typeParameterNamesByText ||= new ts.Set()).add(rawtext); + (context.typeParameterNamesByTextNextNameCount ||= new Map()).set(rawtext, i); + (context.typeParameterNames ||= new Map()).set(getTypeId(type), result); + (context.typeParameterNamesByText ||= new Set()).add(rawtext); } return result; } - function symbolToName(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, expectsIdentifier: true): ts.Identifier; - function symbolToName(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, expectsIdentifier: false): ts.EntityName; - function symbolToName(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags, expectsIdentifier: boolean): ts.EntityName { + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: true): Identifier; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: false): EntityName; + function symbolToName(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, expectsIdentifier: boolean): EntityName { const chain = lookupSymbolChain(symbol, context, meaning); if (expectsIdentifier && chain.length !== 1 && !context.encounteredError - && !(context.flags & ts.NodeBuilderFlags.AllowQualifiedNameInPlaceOfIdentifier)) { + && !(context.flags & NodeBuilderFlags.AllowQualifiedNameInPlaceOfIdentifier)) { context.encounteredError = true; } return createEntityNameFromSymbolChain(chain, chain.length - 1); - function createEntityNameFromSymbolChain(chain: ts.Symbol[], index: number): ts.EntityName { + function createEntityNameFromSymbolChain(chain: Symbol[], index: number): EntityName { const typeParameterNodes = lookupTypeParameterNodes(chain, index, context); const symbol = chain[index]; if (index === 0) { - context.flags |= ts.NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; } const symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= ts.NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } - const identifier = ts.setEmitFlags(ts.factory.createIdentifier(symbolName, typeParameterNodes), ts.EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; - return index > 0 ? ts.factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; } } - function symbolToExpression(symbol: ts.Symbol, context: NodeBuilderContext, meaning: ts.SymbolFlags) { + function symbolToExpression(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags) { const chain = lookupSymbolChain(symbol, context, meaning); return createExpressionFromSymbolChain(chain, chain.length - 1); - function createExpressionFromSymbolChain(chain: ts.Symbol[], index: number): ts.Expression { + function createExpressionFromSymbolChain(chain: Symbol[], index: number): Expression { const typeParameterNodes = lookupTypeParameterNodes(chain, index, context); const symbol = chain[index]; if (index === 0) { - context.flags |= ts.NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; } let symbolName = getNameOfSymbolAsWritten(symbol, context); if (index === 0) { - context.flags ^= ts.NodeBuilderFlags.InInitialEntityName; + context.flags ^= NodeBuilderFlags.InInitialEntityName; } let firstChar = symbolName.charCodeAt(0); - if (ts.isSingleOrDoubleQuote(firstChar) && ts.some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { - return ts.factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context)); + if (isSingleOrDoubleQuote(firstChar) && some(symbol.declarations, hasNonGlobalAugmentationExternalModuleSymbol)) { + return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context)); } - const canUsePropertyAccess = firstChar === ts.CharacterCodes.hash ? - symbolName.length > 1 && ts.isIdentifierStart(symbolName.charCodeAt(1), languageVersion) : - ts.isIdentifierStart(firstChar, languageVersion); + const canUsePropertyAccess = firstChar === CharacterCodes.hash ? + symbolName.length > 1 && isIdentifierStart(symbolName.charCodeAt(1), languageVersion) : + isIdentifierStart(firstChar, languageVersion); if (index === 0 || canUsePropertyAccess) { - const identifier = ts.setEmitFlags(ts.factory.createIdentifier(symbolName, typeParameterNodes), ts.EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; - return index > 0 ? ts.factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; + return index > 0 ? factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; } else { - if (firstChar === ts.CharacterCodes.openBracket) { + if (firstChar === CharacterCodes.openBracket) { symbolName = symbolName.substring(1, symbolName.length - 1); firstChar = symbolName.charCodeAt(0); } - let expression: ts.Expression | undefined; - if (ts.isSingleOrDoubleQuote(firstChar) && !(symbol.flags & ts.SymbolFlags.EnumMember)) { - expression = ts.factory.createStringLiteral(ts.stripQuotes(symbolName).replace(/\\./g, s => s.substring(1)), firstChar === ts.CharacterCodes.singleQuote); + let expression: Expression | undefined; + if (isSingleOrDoubleQuote(firstChar) && !(symbol.flags & SymbolFlags.EnumMember)) { + expression = factory.createStringLiteral(stripQuotes(symbolName).replace(/\\./g, s => s.substring(1)), firstChar === CharacterCodes.singleQuote); } else if (("" + +symbolName) === symbolName) { - expression = ts.factory.createNumericLiteral(+symbolName); + expression = factory.createNumericLiteral(+symbolName); } if (!expression) { - expression = ts.setEmitFlags(ts.factory.createIdentifier(symbolName, typeParameterNodes), ts.EmitFlags.NoAsciiEscaping); + expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); expression.symbol = symbol; } - return ts.factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression); + return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression); } } } - function isStringNamed(d: ts.Declaration) { - const name = ts.getNameOfDeclaration(d); - return !!name && ts.isStringLiteral(name); + function isStringNamed(d: Declaration) { + const name = getNameOfDeclaration(d); + return !!name && isStringLiteral(name); } - function isSingleQuotedStringNamed(d: ts.Declaration) { - const name = ts.getNameOfDeclaration(d); - return !!(name && ts.isStringLiteral(name) && (name.singleQuote || !ts.nodeIsSynthesized(name) && ts.startsWith(ts.getTextOfNode(name, /*includeTrivia*/ false), "'"))); + function isSingleQuotedStringNamed(d: Declaration) { + const name = getNameOfDeclaration(d); + return !!(name && isStringLiteral(name) && (name.singleQuote || !nodeIsSynthesized(name) && startsWith(getTextOfNode(name, /*includeTrivia*/ false), "'"))); } - function getPropertyNameNodeForSymbol(symbol: ts.Symbol, context: NodeBuilderContext) { - const singleQuote = !!ts.length(symbol.declarations) && ts.every(symbol.declarations, isSingleQuotedStringNamed); + function getPropertyNameNodeForSymbol(symbol: Symbol, context: NodeBuilderContext) { + const singleQuote = !!length(symbol.declarations) && every(symbol.declarations, isSingleQuotedStringNamed); const fromNameType = getPropertyNameNodeForSymbolFromNameType(symbol, context, singleQuote); if (fromNameType) { return fromNameType; } - const rawName = ts.unescapeLeadingUnderscores(symbol.escapedName); - const stringNamed = !!ts.length(symbol.declarations) && ts.every(symbol.declarations, isStringNamed); - return ts.createPropertyNameNodeForIdentifierOrLiteral(rawName, ts.getEmitScriptTarget(compilerOptions), singleQuote, stringNamed); + const rawName = unescapeLeadingUnderscores(symbol.escapedName); + const stringNamed = !!length(symbol.declarations) && every(symbol.declarations, isStringNamed); + return createPropertyNameNodeForIdentifierOrLiteral(rawName, getEmitScriptTarget(compilerOptions), singleQuote, stringNamed); } // See getNameForSymbolFromNameType for a stringy equivalent - function getPropertyNameNodeForSymbolFromNameType(symbol: ts.Symbol, context: NodeBuilderContext, singleQuote?: boolean) { + function getPropertyNameNodeForSymbolFromNameType(symbol: Symbol, context: NodeBuilderContext, singleQuote?: boolean) { const nameType = getSymbolLinks(symbol).nameType; if (nameType) { - if (nameType.flags & ts.TypeFlags.StringOrNumberLiteral) { - const name = "" + (nameType as ts.StringLiteralType | ts.NumberLiteralType).value; - if (!ts.isIdentifierText(name, ts.getEmitScriptTarget(compilerOptions)) && !ts.isNumericLiteralName(name)) { - return ts.factory.createStringLiteral(name, !!singleQuote); + if (nameType.flags & TypeFlags.StringOrNumberLiteral) { + const name = "" + (nameType as StringLiteralType | NumberLiteralType).value; + if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) { + return factory.createStringLiteral(name, !!singleQuote); } - if (ts.isNumericLiteralName(name) && ts.startsWith(name, "-")) { - return ts.factory.createComputedPropertyName(ts.factory.createNumericLiteral(+name)); + if (isNumericLiteralName(name) && startsWith(name, "-")) { + return factory.createComputedPropertyName(factory.createNumericLiteral(+name)); } - return ts.createPropertyNameNodeForIdentifierOrLiteral(name, ts.getEmitScriptTarget(compilerOptions)); + return createPropertyNameNodeForIdentifierOrLiteral(name, getEmitScriptTarget(compilerOptions)); } - if (nameType.flags & ts.TypeFlags.UniqueESSymbol) { - return ts.factory.createComputedPropertyName(symbolToExpression((nameType as ts.UniqueESSymbolType).symbol, context, ts.SymbolFlags.Value)); + if (nameType.flags & TypeFlags.UniqueESSymbol) { + return factory.createComputedPropertyName(symbolToExpression((nameType as UniqueESSymbolType).symbol, context, SymbolFlags.Value)); } } } @@ -6765,37 +6963,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // export const x: (x: T) => T // export const y: (x: T_1) => T_1 if (initial.typeParameterNames) { - initial.typeParameterNames = new ts.Map(initial.typeParameterNames); + initial.typeParameterNames = new Map(initial.typeParameterNames); } if (initial.typeParameterNamesByText) { - initial.typeParameterNamesByText = new ts.Set(initial.typeParameterNamesByText); + initial.typeParameterNamesByText = new Set(initial.typeParameterNamesByText); } if (initial.typeParameterSymbolList) { - initial.typeParameterSymbolList = new ts.Set(initial.typeParameterSymbolList); + initial.typeParameterSymbolList = new Set(initial.typeParameterSymbolList); } initial.tracker = wrapSymbolTrackerToReportForContext(initial, initial.tracker); return initial; } - function getDeclarationWithTypeAnnotation(symbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined) { - return symbol.declarations && ts.find(symbol.declarations, s => !!ts.getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!ts.findAncestor(s, n => n === enclosingDeclaration))); + function getDeclarationWithTypeAnnotation(symbol: Symbol, enclosingDeclaration: Node | undefined) { + return symbol.declarations && find(symbol.declarations, s => !!getEffectiveTypeAnnotationNode(s) && (!enclosingDeclaration || !!findAncestor(s, n => n === enclosingDeclaration))); } - function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: ts.TypeNode, type: ts.Type) { - return !(ts.getObjectFlags(type) & ts.ObjectFlags.Reference) || !ts.isTypeReferenceNode(existing) || ts.length(existing.typeArguments) >= getMinTypeArgumentCount((type as ts.TypeReference).target.typeParameters); + function existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing: TypeNode, type: Type) { + return !(getObjectFlags(type) & ObjectFlags.Reference) || !isTypeReferenceNode(existing) || length(existing.typeArguments) >= getMinTypeArgumentCount((type as TypeReference).target.typeParameters); } /** * Unlike `typeToTypeNodeHelper`, this handles setting up the `AllowUniqueESSymbolType` flag * so a `unique symbol` is returned when appropriate for the input symbol, rather than `typeof sym` */ - function serializeTypeForDeclaration(context: NodeBuilderContext, type: ts.Type, symbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined, includePrivateSymbol?: (s: ts.Symbol) => void, bundled?: boolean) { + function serializeTypeForDeclaration(context: NodeBuilderContext, type: Type, symbol: Symbol, enclosingDeclaration: Node | undefined, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { if (!isErrorType(type) && enclosingDeclaration) { const declWithExistingAnnotation = getDeclarationWithTypeAnnotation(symbol, enclosingDeclaration); - if (declWithExistingAnnotation && !ts.isFunctionLikeDeclaration(declWithExistingAnnotation) && !ts.isGetAccessorDeclaration(declWithExistingAnnotation)) { + if (declWithExistingAnnotation && !isFunctionLikeDeclaration(declWithExistingAnnotation) && !isGetAccessorDeclaration(declWithExistingAnnotation)) { // try to reuse the existing annotation - const existing = ts.getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; + const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!; if (typeNodeIsEquivalentToType(existing, declWithExistingAnnotation, type) && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(existing, type)) { const result = serializeExistingTypeNode(context, existing, includePrivateSymbol, bundled); if (result) { @@ -6805,32 +7003,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } const oldFlags = context.flags; - if (type.flags & ts.TypeFlags.UniqueESSymbol && - type.symbol === symbol && (!context.enclosingDeclaration || ts.some(symbol.declarations, d => ts.getSourceFileOfNode(d) === ts.getSourceFileOfNode(context.enclosingDeclaration!)))) { - context.flags |= ts.NodeBuilderFlags.AllowUniqueESSymbolType; + if (type.flags & TypeFlags.UniqueESSymbol && + type.symbol === symbol && (!context.enclosingDeclaration || some(symbol.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!)))) { + context.flags |= NodeBuilderFlags.AllowUniqueESSymbolType; } const result = typeToTypeNodeHelper(type, context); context.flags = oldFlags; return result; } - function typeNodeIsEquivalentToType(typeNode: ts.TypeNode, annotatedDeclaration: ts.Declaration, type: ts.Type) { + function typeNodeIsEquivalentToType(typeNode: TypeNode, annotatedDeclaration: Declaration, type: Type) { const typeFromTypeNode = getTypeFromTypeNode(typeNode); if (typeFromTypeNode === type) { return true; } - if (ts.isParameter(annotatedDeclaration) && annotatedDeclaration.questionToken) { + if (isParameter(annotatedDeclaration) && annotatedDeclaration.questionToken) { return getTypeWithFacts(type, TypeFacts.NEUndefined) === typeFromTypeNode; } return false; } - function serializeReturnTypeForSignature(context: NodeBuilderContext, type: ts.Type, signature: ts.Signature, includePrivateSymbol?: (s: ts.Symbol) => void, bundled?: boolean) { + function serializeReturnTypeForSignature(context: NodeBuilderContext, type: Type, signature: Signature, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { if (!isErrorType(type) && context.enclosingDeclaration) { - const annotation = signature.declaration && ts.getEffectiveReturnTypeNode(signature.declaration); - if (!!ts.findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation) { + const annotation = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); + if (!!findAncestor(annotation, n => n === context.enclosingDeclaration) && annotation) { const annotated = getTypeFromTypeNode(annotation); - const thisInstantiated = annotated.flags & ts.TypeFlags.TypeParameter && (annotated as ts.TypeParameter).isThisType ? instantiateType(annotated, signature.mapper) : annotated; + const thisInstantiated = annotated.flags & TypeFlags.TypeParameter && (annotated as TypeParameter).isThisType ? instantiateType(annotated, signature.mapper) : annotated; if (thisInstantiated === type && existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(annotation, type)) { const result = serializeExistingTypeNode(context, annotation, includePrivateSymbol, bundled); if (result) { @@ -6842,154 +7040,154 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeToTypeNodeHelper(type, context); } - function trackExistingEntityName(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: ts.Symbol) => void) { + function trackExistingEntityName(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: Symbol) => void) { let introducesError = false; - const leftmost = ts.getFirstIdentifier(node); - if (ts.isInJSFile(node) && (ts.isExportsIdentifier(leftmost) || ts.isModuleExportsAccessExpression(leftmost.parent) || (ts.isQualifiedName(leftmost.parent) && ts.isModuleIdentifier(leftmost.parent.left) && ts.isExportsIdentifier(leftmost.parent.right)))) { + const leftmost = getFirstIdentifier(node); + if (isInJSFile(node) && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) && isExportsIdentifier(leftmost.parent.right)))) { introducesError = true; return { introducesError, node }; } - const sym = resolveEntityName(leftmost, ts.SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveALias*/ true); + const sym = resolveEntityName(leftmost, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveALias*/ true); if (sym) { - if (isSymbolAccessible(sym, context.enclosingDeclaration, ts.SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== ts.SymbolAccessibility.Accessible) { + if (isSymbolAccessible(sym, context.enclosingDeclaration, SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible) { introducesError = true; } else { - context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, ts.SymbolFlags.All); + context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, SymbolFlags.All); includePrivateSymbol?.(sym); } - if (ts.isIdentifier(node)) { + if (isIdentifier(node)) { const type = getDeclaredTypeOfSymbol(sym); - const name = sym.flags & ts.SymbolFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ? typeParameterToName(type, context) : ts.factory.cloneNode(node); + const name = sym.flags & SymbolFlags.TypeParameter && !isTypeSymbolAccessible(type.symbol, context.enclosingDeclaration) ? typeParameterToName(type, context) : factory.cloneNode(node); name.symbol = sym; // for quickinfo, which uses identifier symbol information - return { introducesError, node: ts.setEmitFlags(ts.setOriginalNode(name, node), ts.EmitFlags.NoAsciiEscaping) }; + return { introducesError, node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping) }; } } return { introducesError, node }; } - function serializeExistingTypeNode(context: NodeBuilderContext, existing: ts.TypeNode, includePrivateSymbol?: (s: ts.Symbol) => void, bundled?: boolean) { + function serializeExistingTypeNode(context: NodeBuilderContext, existing: TypeNode, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) { if (cancellationToken && cancellationToken.throwIfCancellationRequested) { cancellationToken.throwIfCancellationRequested(); } let hadError = false; - const file = ts.getSourceFileOfNode(existing); - const transformed = ts.visitNode(existing, visitExistingNodeTreeSymbols); + const file = getSourceFileOfNode(existing); + const transformed = visitNode(existing, visitExistingNodeTreeSymbols); if (hadError) { return undefined; } - return transformed === existing ? ts.setTextRange(ts.factory.cloneNode(existing), existing) : transformed; + return transformed === existing ? setTextRange(factory.cloneNode(existing), existing) : transformed; - function visitExistingNodeTreeSymbols(node: T): ts.Node { + function visitExistingNodeTreeSymbols(node: T): Node { // We don't _actually_ support jsdoc namepath types, emit `any` instead - if (ts.isJSDocAllType(node) || node.kind === ts.SyntaxKind.JSDocNamepathType) { - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + if (isJSDocAllType(node) || node.kind === SyntaxKind.JSDocNamepathType) { + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } - if (ts.isJSDocUnknownType(node)) { - return ts.factory.createKeywordTypeNode(ts.SyntaxKind.UnknownKeyword); + if (isJSDocUnknownType(node)) { + return factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword); } - if (ts.isJSDocNullableType(node)) { - return ts.factory.createUnionTypeNode([ts.visitNode(node.type, visitExistingNodeTreeSymbols), ts.factory.createLiteralTypeNode(ts.factory.createNull())]); + if (isJSDocNullableType(node)) { + return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createLiteralTypeNode(factory.createNull())]); } - if (ts.isJSDocOptionalType(node)) { - return ts.factory.createUnionTypeNode([ts.visitNode(node.type, visitExistingNodeTreeSymbols), ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]); + if (isJSDocOptionalType(node)) { + return factory.createUnionTypeNode([visitNode(node.type, visitExistingNodeTreeSymbols), factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); } - if (ts.isJSDocNonNullableType(node)) { - return ts.visitNode(node.type, visitExistingNodeTreeSymbols); + if (isJSDocNonNullableType(node)) { + return visitNode(node.type, visitExistingNodeTreeSymbols); } - if (ts.isJSDocVariadicType(node)) { - return ts.factory.createArrayTypeNode(ts.visitNode((node as ts.JSDocVariadicType).type, visitExistingNodeTreeSymbols)); + if (isJSDocVariadicType(node)) { + return factory.createArrayTypeNode(visitNode((node as JSDocVariadicType).type, visitExistingNodeTreeSymbols)); } - if (ts.isJSDocTypeLiteral(node)) { - return ts.factory.createTypeLiteralNode(ts.map(node.jsDocPropertyTags, t => { - const name = ts.isIdentifier(t.name) ? t.name : t.name.right; + if (isJSDocTypeLiteral(node)) { + return factory.createTypeLiteralNode(map(node.jsDocPropertyTags, t => { + const name = isIdentifier(t.name) ? t.name : t.name.right; const typeViaParent = getTypeOfPropertyOfType(getTypeFromTypeNode(node), name.escapedText); const overrideTypeNode = typeViaParent && t.typeExpression && getTypeFromTypeNode(t.typeExpression.type) !== typeViaParent ? typeToTypeNodeHelper(typeViaParent, context) : undefined; - return ts.factory.createPropertySignature( + return factory.createPropertySignature( /*modifiers*/ undefined, name, - t.isBracketed || t.typeExpression && ts.isJSDocOptionalType(t.typeExpression.type) ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, - overrideTypeNode || (t.typeExpression && ts.visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols)) || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + t.isBracketed || t.typeExpression && isJSDocOptionalType(t.typeExpression.type) ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + overrideTypeNode || (t.typeExpression && visitNode(t.typeExpression.type, visitExistingNodeTreeSymbols)) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ); })); } - if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "") { - return ts.setOriginalNode(ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), node); + if (isTypeReferenceNode(node) && isIdentifier(node.typeName) && node.typeName.escapedText === "") { + return setOriginalNode(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword), node); } - if ((ts.isExpressionWithTypeArguments(node) || ts.isTypeReferenceNode(node)) && ts.isJSDocIndexSignature(node)) { - return ts.factory.createTypeLiteralNode([ts.factory.createIndexSignature( + if ((isExpressionWithTypeArguments(node) || isTypeReferenceNode(node)) && isJSDocIndexSignature(node)) { + return factory.createTypeLiteralNode([factory.createIndexSignature( /*modifiers*/ undefined, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotdotdotToken*/ undefined, "x", /*questionToken*/ undefined, - ts.visitNode(node.typeArguments![0], visitExistingNodeTreeSymbols) + visitNode(node.typeArguments![0], visitExistingNodeTreeSymbols) )], - ts.visitNode(node.typeArguments![1], visitExistingNodeTreeSymbols) + visitNode(node.typeArguments![1], visitExistingNodeTreeSymbols) )]); } - if (ts.isJSDocFunctionType(node)) { - if (ts.isJSDocConstructSignature(node)) { - let newTypeNode: ts.TypeNode | undefined; - return ts.factory.createConstructorTypeNode( + if (isJSDocFunctionType(node)) { + if (isJSDocConstructSignature(node)) { + let newTypeNode: TypeNode | undefined; + return factory.createConstructorTypeNode( /*modifiers*/ undefined, - ts.visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), - ts.mapDefined(node.parameters, (p, i) => p.name && ts.isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : ts.factory.createParameterDeclaration( + visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), + mapDefined(node.parameters, (p, i) => p.name && isIdentifier(p.name) && p.name.escapedText === "new" ? (newTypeNode = p.type, undefined) : factory.createParameterDeclaration( /*modifiers*/ undefined, getEffectiveDotDotDotForParameter(p), getNameForJSDocFunctionParameter(p, i), p.questionToken, - ts.visitNode(p.type, visitExistingNodeTreeSymbols), + visitNode(p.type, visitExistingNodeTreeSymbols), /*initializer*/ undefined )), - ts.visitNode(newTypeNode || node.type, visitExistingNodeTreeSymbols) || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + visitNode(newTypeNode || node.type, visitExistingNodeTreeSymbols) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ); } else { - return ts.factory.createFunctionTypeNode( - ts.visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), - ts.map(node.parameters, (p, i) => ts.factory.createParameterDeclaration( + return factory.createFunctionTypeNode( + visitNodes(node.typeParameters, visitExistingNodeTreeSymbols), + map(node.parameters, (p, i) => factory.createParameterDeclaration( /*modifiers*/ undefined, getEffectiveDotDotDotForParameter(p), getNameForJSDocFunctionParameter(p, i), p.questionToken, - ts.visitNode(p.type, visitExistingNodeTreeSymbols), + visitNode(p.type, visitExistingNodeTreeSymbols), /*initializer*/ undefined )), - ts.visitNode(node.type, visitExistingNodeTreeSymbols) || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + visitNode(node.type, visitExistingNodeTreeSymbols) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ); } } - if (ts.isTypeReferenceNode(node) && ts.isInJSDoc(node) && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(node, getTypeFromTypeNode(node)) || getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(node, ts.SymbolFlags.Type, /*ignoreErrors*/ true))) { - return ts.setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); + if (isTypeReferenceNode(node) && isInJSDoc(node) && (!existingTypeNodeIsNotReferenceOrIsReferenceWithCompatibleTypeArgumentCount(node, getTypeFromTypeNode(node)) || getIntendedTypeFromJSDocTypeReference(node) || unknownSymbol === resolveTypeReferenceName(node, SymbolFlags.Type, /*ignoreErrors*/ true))) { + return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } - if (ts.isLiteralImportTypeNode(node)) { + if (isLiteralImportTypeNode(node)) { const nodeSymbol = getNodeLinks(node).resolvedSymbol; - if (ts.isInJSDoc(node) && + if (isInJSDoc(node) && nodeSymbol && ( // The import type resolved using jsdoc fallback logic - (!node.isTypeOf && !(nodeSymbol.flags & ts.SymbolFlags.Type)) || + (!node.isTypeOf && !(nodeSymbol.flags & SymbolFlags.Type)) || // The import type had type arguments autofilled by js fallback logic - !(ts.length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol))) + !(length(node.typeArguments) >= getMinTypeArgumentCount(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(nodeSymbol))) ) ) { - return ts.setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); + return setOriginalNode(typeToTypeNodeHelper(getTypeFromTypeNode(node), context), node); } - return ts.factory.updateImportTypeNode( + return factory.updateImportTypeNode( node, - ts.factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), + factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), node.assertions, node.qualifier, - ts.visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, ts.isTypeNode), + visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, isTypeNode), node.isTypeOf ); } - if (ts.isEntityName(node) || ts.isEntityNameExpression(node)) { + if (isEntityName(node) || isEntityNameExpression(node)) { const { introducesError, node: result } = trackExistingEntityName(node, context, includePrivateSymbol); hadError = hadError || introducesError; if (result !== node) { @@ -6997,36 +7195,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (file && ts.isTupleTypeNode(node) && (ts.getLineAndCharacterOfPosition(file, node.pos).line === ts.getLineAndCharacterOfPosition(file, node.end).line)) { - ts.setEmitFlags(node, ts.EmitFlags.SingleLine); + if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) { + setEmitFlags(node, EmitFlags.SingleLine); } - return ts.visitEachChild(node, visitExistingNodeTreeSymbols, ts.nullTransformationContext); + return visitEachChild(node, visitExistingNodeTreeSymbols, nullTransformationContext); - function getEffectiveDotDotDotForParameter(p: ts.ParameterDeclaration) { - return p.dotDotDotToken || (p.type && ts.isJSDocVariadicType(p.type) ? ts.factory.createToken(ts.SyntaxKind.DotDotDotToken) : undefined); + function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) { + return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined); } /** Note that `new:T` parameters are not handled, but should be before calling this function. */ - function getNameForJSDocFunctionParameter(p: ts.ParameterDeclaration, index: number) { - return p.name && ts.isIdentifier(p.name) && p.name.escapedText === "this" ? "this" + function getNameForJSDocFunctionParameter(p: ParameterDeclaration, index: number) { + return p.name && isIdentifier(p.name) && p.name.escapedText === "this" ? "this" : getEffectiveDotDotDotForParameter(p) ? `args` : `arg${index}`; } - function rewriteModuleSpecifier(parent: ts.ImportTypeNode, lit: ts.StringLiteral) { + function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) { if (bundled) { if (context.tracker && context.tracker.moduleResolverHost) { const targetFile = getExternalModuleFileFromDeclaration(parent); if (targetFile) { - const getCanonicalFileName = ts.createGetCanonicalFileName(!!host.useCaseSensitiveFileNames); + const getCanonicalFileName = createGetCanonicalFileName(!!host.useCaseSensitiveFileNames); const resolverHost = { getCanonicalFileName, getCurrentDirectory: () => context.tracker.moduleResolverHost!.getCurrentDirectory(), getCommonSourceDirectory: () => context.tracker.moduleResolverHost!.getCommonSourceDirectory() }; - const newName = ts.getResolvedExternalModuleName(resolverHost, targetFile); - return ts.factory.createStringLiteral(newName); + const newName = getResolvedExternalModuleName(resolverHost, targetFile); + return factory.createStringLiteral(newName); } } } @@ -7043,9 +7241,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function symbolTableToDeclarationStatements(symbolTable: ts.SymbolTable, context: NodeBuilderContext, bundled?: boolean): ts.Statement[] { - const serializePropertySymbolForClass = makeSerializePropertySymbol(ts.factory.createPropertyDeclaration, ts.SyntaxKind.MethodDeclaration, /*useAcessors*/ true); - const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol((mods, name, question, type) => ts.factory.createPropertySignature(mods, name, question, type), ts.SyntaxKind.MethodSignature, /*useAcessors*/ false); + function symbolTableToDeclarationStatements(symbolTable: SymbolTable, context: NodeBuilderContext, bundled?: boolean): Statement[] { + const serializePropertySymbolForClass = makeSerializePropertySymbol(factory.createPropertyDeclaration, SyntaxKind.MethodDeclaration, /*useAcessors*/ true); + const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol((mods, name, question, type) => factory.createPropertySignature(mods, name, question, type), SyntaxKind.MethodSignature, /*useAcessors*/ false); // TODO: Use `setOriginalNode` on original declaration names where possible so these declarations see some kind of // declaration mapping @@ -7054,22 +7252,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // emit codepaths which want to apply more specific contexts (so we can still refer to the root real declaration // we're trying to emit from later on) const enclosingDeclaration = context.enclosingDeclaration!; - let results: ts.Statement[] = []; - const visitedSymbols = new ts.Set(); - const deferredPrivatesStack: ts.ESMap[] = []; + let results: Statement[] = []; + const visitedSymbols = new Set(); + const deferredPrivatesStack: ESMap[] = []; const oldcontext = context; context = { ...oldcontext, - usedSymbolNames: new ts.Set(oldcontext.usedSymbolNames), - remappedSymbolNames: new ts.Map(), + usedSymbolNames: new Set(oldcontext.usedSymbolNames), + remappedSymbolNames: new Map(), tracker: { ...oldcontext.tracker, trackSymbol: (sym, decl, meaning) => { const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeAliases*/ false); - if (accessibleResult.accessibility === ts.SymbolAccessibility.Accessible) { + if (accessibleResult.accessibility === SymbolAccessibility.Accessible) { // Lookup the root symbol of the chain of refs we'll use to access it and serialize it const chain = lookupSymbolChainWorker(sym, context, meaning); - if (!(sym.flags & ts.SymbolFlags.Property)) { + if (!(sym.flags & SymbolFlags.Property)) { includePrivateSymbol(chain[0]); } } @@ -7081,55 +7279,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }, }; context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker); - ts.forEachEntry(symbolTable, (symbol, name) => { - const baseName = ts.unescapeLeadingUnderscores(name); + forEachEntry(symbolTable, (symbol, name) => { + const baseName = unescapeLeadingUnderscores(name); void getInternalSymbolName(symbol, baseName); // Called to cache values into `usedSymbolNames` and `remappedSymbolNames` }); let addingDeclare = !bundled; - const exportEquals = symbolTable.get(ts.InternalSymbolName.ExportEquals); - if (exportEquals && symbolTable.size > 1 && exportEquals.flags & ts.SymbolFlags.Alias) { - symbolTable = ts.createSymbolTable(); + const exportEquals = symbolTable.get(InternalSymbolName.ExportEquals); + if (exportEquals && symbolTable.size > 1 && exportEquals.flags & SymbolFlags.Alias) { + symbolTable = createSymbolTable(); // Remove extraneous elements from root symbol table (they'll be mixed back in when the target of the `export=` is looked up) - symbolTable.set(ts.InternalSymbolName.ExportEquals, exportEquals); + symbolTable.set(InternalSymbolName.ExportEquals, exportEquals); } visitSymbolTable(symbolTable); return mergeRedundantStatements(results); - function isIdentifierAndNotUndefined(node: ts.Node | undefined): node is ts.Identifier { - return !!node && node.kind === ts.SyntaxKind.Identifier; + function isIdentifierAndNotUndefined(node: Node | undefined): node is Identifier { + return !!node && node.kind === SyntaxKind.Identifier; } - function getNamesOfDeclaration(statement: ts.Statement): ts.Identifier[] { - if (ts.isVariableStatement(statement)) { - return ts.filter(ts.map(statement.declarationList.declarations, ts.getNameOfDeclaration), isIdentifierAndNotUndefined); + function getNamesOfDeclaration(statement: Statement): Identifier[] { + if (isVariableStatement(statement)) { + return filter(map(statement.declarationList.declarations, getNameOfDeclaration), isIdentifierAndNotUndefined); } - return ts.filter([ts.getNameOfDeclaration(statement as ts.DeclarationStatement)], isIdentifierAndNotUndefined); + return filter([getNameOfDeclaration(statement as DeclarationStatement)], isIdentifierAndNotUndefined); } - function flattenExportAssignedNamespace(statements: ts.Statement[]) { - const exportAssignment = ts.find(statements, ts.isExportAssignment); - const nsIndex = ts.findIndex(statements, ts.isModuleDeclaration); - let ns = nsIndex !== -1 ? statements[nsIndex] as ts.ModuleDeclaration : undefined; + function flattenExportAssignedNamespace(statements: Statement[]) { + const exportAssignment = find(statements, isExportAssignment); + const nsIndex = findIndex(statements, isModuleDeclaration); + let ns = nsIndex !== -1 ? statements[nsIndex] as ModuleDeclaration : undefined; if (ns && exportAssignment && exportAssignment.isExportEquals && - ts.isIdentifier(exportAssignment.expression) && ts.isIdentifier(ns.name) && ts.idText(ns.name) === ts.idText(exportAssignment.expression) && - ns.body && ts.isModuleBlock(ns.body)) { + isIdentifier(exportAssignment.expression) && isIdentifier(ns.name) && idText(ns.name) === idText(exportAssignment.expression) && + ns.body && isModuleBlock(ns.body)) { // Pass 0: Correct situations where a module has both an `export = ns` and multiple top-level exports by stripping the export modifiers from // the top-level exports and exporting them in the targeted ns, as can occur when a js file has both typedefs and `module.export` assignments - const excessExports = ts.filter(statements, s => !!(ts.getEffectiveModifierFlags(s) & ts.ModifierFlags.Export)); + const excessExports = filter(statements, s => !!(getEffectiveModifierFlags(s) & ModifierFlags.Export)); const name = ns.name; let body = ns.body; - if (ts.length(excessExports)) { - ns = ts.factory.updateModuleDeclaration( + if (length(excessExports)) { + ns = factory.updateModuleDeclaration( ns, ns.modifiers, ns.name, - body = ts.factory.updateModuleBlock( + body = factory.updateModuleBlock( body, - ts.factory.createNodeArray([...ns.body.statements, ts.factory.createExportDeclaration( + factory.createNodeArray([...ns.body.statements, factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports(ts.map(ts.flatMap(excessExports, e => getNamesOfDeclaration(e)), id => ts.factory.createExportSpecifier(/*isTypeOnly*/ false, /*alias*/ undefined, id))), + factory.createNamedExports(map(flatMap(excessExports, e => getNamesOfDeclaration(e)), id => factory.createExportSpecifier(/*isTypeOnly*/ false, /*alias*/ undefined, id))), /*moduleSpecifier*/ undefined )]) ) @@ -7138,46 +7336,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Pass 1: Flatten `export namespace _exports {} export = _exports;` so long as the `export=` only points at a single namespace declaration - if (!ts.find(statements, s => s !== ns && ts.nodeHasName(s, name))) { + if (!find(statements, s => s !== ns && nodeHasName(s, name))) { results = []; // If the namespace contains no export assignments or declarations, and no declarations flagged with `export`, then _everything_ is exported - // to respect this as the top level, we need to add an `export` modifier to everything - const mixinExportFlag = !ts.some(body.statements, s => ts.hasSyntacticModifier(s, ts.ModifierFlags.Export) || ts.isExportAssignment(s) || ts.isExportDeclaration(s)); - ts.forEach(body.statements, s => { - addResult(s, mixinExportFlag ? ts.ModifierFlags.Export : ts.ModifierFlags.None); // Recalculates the ambient (and export, if applicable from above) flag + const mixinExportFlag = !some(body.statements, s => hasSyntacticModifier(s, ModifierFlags.Export) || isExportAssignment(s) || isExportDeclaration(s)); + forEach(body.statements, s => { + addResult(s, mixinExportFlag ? ModifierFlags.Export : ModifierFlags.None); // Recalculates the ambient (and export, if applicable from above) flag }); - statements = [...ts.filter(statements, s => s !== ns && s !== exportAssignment), ...results]; + statements = [...filter(statements, s => s !== ns && s !== exportAssignment), ...results]; } } return statements; } - function mergeExportDeclarations(statements: ts.Statement[]) { + function mergeExportDeclarations(statements: Statement[]) { // Pass 2: Combine all `export {}` declarations - const exports = ts.filter(statements, d => ts.isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && ts.isNamedExports(d.exportClause)) as ts.ExportDeclaration[]; - if (ts.length(exports) > 1) { - const nonExports = ts.filter(statements, d => !ts.isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause); - statements = [...nonExports, ts.factory.createExportDeclaration( + const exports = filter(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[]; + if (length(exports) > 1) { + const nonExports = filter(statements, d => !isExportDeclaration(d) || !!d.moduleSpecifier || !d.exportClause); + statements = [...nonExports, factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports(ts.flatMap(exports, e => ts.cast(e.exportClause, ts.isNamedExports).elements)), + factory.createNamedExports(flatMap(exports, e => cast(e.exportClause, isNamedExports).elements)), /*moduleSpecifier*/ undefined )]; } // Pass 2b: Also combine all `export {} from "..."` declarations as needed - const reexports = ts.filter(statements, d => ts.isExportDeclaration(d) && !!d.moduleSpecifier && !!d.exportClause && ts.isNamedExports(d.exportClause)) as ts.ExportDeclaration[]; - if (ts.length(reexports) > 1) { - const groups = ts.group(reexports, decl => ts.isStringLiteral(decl.moduleSpecifier!) ? ">" + decl.moduleSpecifier.text : ">"); + const reexports = filter(statements, d => isExportDeclaration(d) && !!d.moduleSpecifier && !!d.exportClause && isNamedExports(d.exportClause)) as ExportDeclaration[]; + if (length(reexports) > 1) { + const groups = group(reexports, decl => isStringLiteral(decl.moduleSpecifier!) ? ">" + decl.moduleSpecifier.text : ">"); if (groups.length !== reexports.length) { for (const group of groups) { if (group.length > 1) { // remove group members from statements and then merge group members and add back to statements statements = [ - ...ts.filter(statements, s => group.indexOf(s as ts.ExportDeclaration) === -1), - ts.factory.createExportDeclaration( + ...filter(statements, s => group.indexOf(s as ExportDeclaration) === -1), + factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports(ts.flatMap(group, e => ts.cast(e.exportClause, ts.isNamedExports).elements)), + factory.createNamedExports(flatMap(group, e => cast(e.exportClause, isNamedExports).elements)), group[0].moduleSpecifier ) ]; @@ -7188,36 +7386,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return statements; } - function inlineExportModifiers(statements: ts.Statement[]) { + function inlineExportModifiers(statements: Statement[]) { // Pass 3: Move all `export {}`'s to `export` modifiers where possible - const index = ts.findIndex(statements, d => ts.isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && ts.isNamedExports(d.exportClause)); + const index = findIndex(statements, d => isExportDeclaration(d) && !d.moduleSpecifier && !d.assertClause && !!d.exportClause && isNamedExports(d.exportClause)); if (index >= 0) { - const exportDecl = statements[index] as ts.ExportDeclaration & { readonly exportClause: ts.NamedExports }; - const replacements = ts.mapDefined(exportDecl.exportClause.elements, e => { + const exportDecl = statements[index] as ExportDeclaration & { readonly exportClause: NamedExports }; + const replacements = mapDefined(exportDecl.exportClause.elements, e => { if (!e.propertyName) { // export {name} - look thru `statements` for `name`, and if all results can take an `export` modifier, do so and filter it - const indices = ts.indicesOf(statements); - const associatedIndices = ts.filter(indices, i => ts.nodeHasName(statements[i], e.name)); - if (ts.length(associatedIndices) && ts.every(associatedIndices, i => ts.canHaveExportModifier(statements[i]))) { + const indices = indicesOf(statements); + const associatedIndices = filter(indices, i => nodeHasName(statements[i], e.name)); + if (length(associatedIndices) && every(associatedIndices, i => canHaveExportModifier(statements[i]))) { for (const index of associatedIndices) { - statements[index] = addExportModifier(statements[index] as Extract); + statements[index] = addExportModifier(statements[index] as Extract); } return undefined; } } return e; }); - if (!ts.length(replacements)) { + if (!length(replacements)) { // all clauses removed, remove the export declaration - ts.orderedRemoveItemAt(statements, index); + orderedRemoveItemAt(statements, index); } else { // some items filtered, others not - update the export declaration - statements[index] = ts.factory.updateExportDeclaration( + statements[index] = factory.updateExportDeclaration( exportDecl, exportDecl.modifiers, exportDecl.isTypeOnly, - ts.factory.updateNamedExports( + factory.updateNamedExports( exportDecl.exportClause, replacements ), @@ -7229,7 +7427,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return statements; } - function mergeRedundantStatements(statements: ts.Statement[]) { + function mergeRedundantStatements(statements: Statement[]) { statements = flattenExportAssignedNamespace(statements); statements = mergeExportDeclarations(statements); statements = inlineExportModifiers(statements); @@ -7237,42 +7435,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Not a cleanup, but as a final step: If there is a mix of `export` and non-`export` declarations, but no `export =` or `export {}` add a `export {};` so // declaration privacy is respected. if (enclosingDeclaration && - ((ts.isSourceFile(enclosingDeclaration) && ts.isExternalOrCommonJsModule(enclosingDeclaration)) || ts.isModuleDeclaration(enclosingDeclaration)) && - (!ts.some(statements, ts.isExternalModuleIndicator) || (!ts.hasScopeMarker(statements) && ts.some(statements, ts.needsScopeMarker)))) { - statements.push(ts.createEmptyExports(ts.factory)); + ((isSourceFile(enclosingDeclaration) && isExternalOrCommonJsModule(enclosingDeclaration)) || isModuleDeclaration(enclosingDeclaration)) && + (!some(statements, isExternalModuleIndicator) || (!hasScopeMarker(statements) && some(statements, needsScopeMarker)))) { + statements.push(createEmptyExports(factory)); } return statements; } - function addExportModifier(node: Extract) { - const flags = (ts.getEffectiveModifierFlags(node) | ts.ModifierFlags.Export) & ~ts.ModifierFlags.Ambient; - return ts.factory.updateModifiers(node, flags); + function addExportModifier(node: Extract) { + const flags = (getEffectiveModifierFlags(node) | ModifierFlags.Export) & ~ModifierFlags.Ambient; + return factory.updateModifiers(node, flags); } - function removeExportModifier(node: Extract) { - const flags = ts.getEffectiveModifierFlags(node) & ~ts.ModifierFlags.Export; - return ts.factory.updateModifiers(node, flags); + function removeExportModifier(node: Extract) { + const flags = getEffectiveModifierFlags(node) & ~ModifierFlags.Export; + return factory.updateModifiers(node, flags); } - function visitSymbolTable(symbolTable: ts.SymbolTable, suppressNewPrivateContext?: boolean, propertyAsAlias?: boolean) { + function visitSymbolTable(symbolTable: SymbolTable, suppressNewPrivateContext?: boolean, propertyAsAlias?: boolean) { if (!suppressNewPrivateContext) { - deferredPrivatesStack.push(new ts.Map()); + deferredPrivatesStack.push(new Map()); } - symbolTable.forEach((symbol: ts.Symbol) => { + symbolTable.forEach((symbol: Symbol) => { serializeSymbol(symbol, /*isPrivate*/ false, !!propertyAsAlias); }); if (!suppressNewPrivateContext) { // deferredPrivates will be filled up by visiting the symbol table // And will continue to iterate as elements are added while visited `deferredPrivates` // (As that's how a map iterator is defined to work) - deferredPrivatesStack[deferredPrivatesStack.length - 1].forEach((symbol: ts.Symbol) => { + deferredPrivatesStack[deferredPrivatesStack.length - 1].forEach((symbol: Symbol) => { serializeSymbol(symbol, /*isPrivate*/ true, !!propertyAsAlias); }); deferredPrivatesStack.pop(); } } - function serializeSymbol(symbol: ts.Symbol, isPrivate: boolean, propertyAsAlias: boolean): void { + function serializeSymbol(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void { // cache visited list based on merged symbol, since we want to use the unmerged top-level symbol, but // still skip reserializing it if we encounter the merged product later on const visitedSym = getMergedSymbol(symbol); @@ -7282,7 +7480,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { visitedSymbols.add(getSymbolId(visitedSym)); // Only actually serialize symbols within the correct enclosing declaration, otherwise do nothing with the out-of-context symbol const skipMembershipCheck = !isPrivate; // We only call this on exported symbols when we know they're in the correct scope - if (skipMembershipCheck || (!!ts.length(symbol.declarations) && ts.some(symbol.declarations, d => !!ts.findAncestor(d, n => n === enclosingDeclaration)))) { + if (skipMembershipCheck || (!!length(symbol.declarations) && some(symbol.declarations, d => !!findAncestor(d, n => n === enclosingDeclaration)))) { const oldContext = context; context = cloneNodeBuilderContext(context); serializeSymbolWorker(symbol, isPrivate, propertyAsAlias); @@ -7303,42 +7501,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If it's a property: emit `export default _default` with a `_default` prop // If it's a class/interface/function: emit a class/interface/function with a `default` modifier // These forms can merge, eg (`export default 12; export default interface A {}`) - function serializeSymbolWorker(symbol: ts.Symbol, isPrivate: boolean, propertyAsAlias: boolean): void { - const symbolName = ts.unescapeLeadingUnderscores(symbol.escapedName); - const isDefault = symbol.escapedName === ts.InternalSymbolName.Default; - if (isPrivate && !(context.flags & ts.NodeBuilderFlags.AllowAnonymousIdentifier) && ts.isStringANonContextualKeyword(symbolName) && !isDefault) { + function serializeSymbolWorker(symbol: Symbol, isPrivate: boolean, propertyAsAlias: boolean): void { + const symbolName = unescapeLeadingUnderscores(symbol.escapedName); + const isDefault = symbol.escapedName === InternalSymbolName.Default; + if (isPrivate && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier) && isStringANonContextualKeyword(symbolName) && !isDefault) { // Oh no. We cannot use this symbol's name as it's name... It's likely some jsdoc had an invalid name like `export` or `default` :( context.encounteredError = true; // TODO: Issue error via symbol tracker? return; // If we need to emit a private with a keyword name, we're done for, since something else will try to refer to it by that name } let needsPostExportDefault = isDefault && !!( - symbol.flags & ts.SymbolFlags.ExportDoesNotSupportDefaultModifier - || (symbol.flags & ts.SymbolFlags.Function && ts.length(getPropertiesOfType(getTypeOfSymbol(symbol)))) - ) && !(symbol.flags & ts.SymbolFlags.Alias); // An alias symbol should preclude needing to make an alias ourselves - let needsExportDeclaration = !needsPostExportDefault && !isPrivate && ts.isStringANonContextualKeyword(symbolName) && !isDefault; + symbol.flags & SymbolFlags.ExportDoesNotSupportDefaultModifier + || (symbol.flags & SymbolFlags.Function && length(getPropertiesOfType(getTypeOfSymbol(symbol)))) + ) && !(symbol.flags & SymbolFlags.Alias); // An alias symbol should preclude needing to make an alias ourselves + let needsExportDeclaration = !needsPostExportDefault && !isPrivate && isStringANonContextualKeyword(symbolName) && !isDefault; // `serializeVariableOrProperty` will handle adding the export declaration if it is run (since `getInternalSymbolName` will create the name mapping), so we need to ensuer we unset `needsExportDeclaration` if it is if (needsPostExportDefault || needsExportDeclaration) { isPrivate = true; } - const modifierFlags = (!isPrivate ? ts.ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ts.ModifierFlags.Default : 0); - const isConstMergedWithNS = symbol.flags & ts.SymbolFlags.Module && - symbol.flags & (ts.SymbolFlags.BlockScopedVariable | ts.SymbolFlags.FunctionScopedVariable | ts.SymbolFlags.Property) && - symbol.escapedName !== ts.InternalSymbolName.ExportEquals; + const modifierFlags = (!isPrivate ? ModifierFlags.Export : 0) | (isDefault && !needsPostExportDefault ? ModifierFlags.Default : 0); + const isConstMergedWithNS = symbol.flags & SymbolFlags.Module && + symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) && + symbol.escapedName !== InternalSymbolName.ExportEquals; const isConstMergedWithNSPrintableAsSignatureMerge = isConstMergedWithNS && isTypeRepresentableAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol); - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method) || isConstMergedWithNSPrintableAsSignatureMerge) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) || isConstMergedWithNSPrintableAsSignatureMerge) { serializeAsFunctionNamespaceMerge(getTypeOfSymbol(symbol), symbol, getInternalSymbolName(symbol, symbolName), modifierFlags); } - if (symbol.flags & ts.SymbolFlags.TypeAlias) { + if (symbol.flags & SymbolFlags.TypeAlias) { serializeTypeAlias(symbol, symbolName, modifierFlags); } // Need to skip over export= symbols below - json source files get a single `Property` flagged // symbol of name `export=` which needs to be handled like an alias. It's not great, but it is what it is. - if (symbol.flags & (ts.SymbolFlags.BlockScopedVariable | ts.SymbolFlags.FunctionScopedVariable | ts.SymbolFlags.Property) - && symbol.escapedName !== ts.InternalSymbolName.ExportEquals - && !(symbol.flags & ts.SymbolFlags.Prototype) - && !(symbol.flags & ts.SymbolFlags.Class) - && !(symbol.flags & ts.SymbolFlags.Method) + if (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property) + && symbol.escapedName !== InternalSymbolName.ExportEquals + && !(symbol.flags & SymbolFlags.Prototype) + && !(symbol.flags & SymbolFlags.Class) + && !(symbol.flags & SymbolFlags.Method) && !isConstMergedWithNSPrintableAsSignatureMerge) { if (propertyAsAlias) { const createdExport = serializeMaybeAliasAssignment(symbol); @@ -7350,44 +7548,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { const type = getTypeOfSymbol(symbol); const localName = getInternalSymbolName(symbol, symbolName); - if (!(symbol.flags & ts.SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) { + if (!(symbol.flags & SymbolFlags.Function) && isTypeRepresentableAsFunctionNamespaceMerge(type, symbol)) { // If the type looks like a function declaration + ns could represent it, and it's type is sourced locally, rewrite it into a function declaration + ns serializeAsFunctionNamespaceMerge(type, symbol, localName, modifierFlags); } else { // A Class + Property merge is made for a `module.exports.Member = class {}`, and it doesn't serialize well as either a class _or_ a property symbol - in fact, _it behaves like an alias!_ // `var` is `FunctionScopedVariable`, `const` and `let` are `BlockScopedVariable`, and `module.exports.thing =` is `Property` - const flags = !(symbol.flags & ts.SymbolFlags.BlockScopedVariable) - ? symbol.parent?.valueDeclaration && ts.isSourceFile(symbol.parent?.valueDeclaration) - ? ts.NodeFlags.Const // exports are immutable in es6, which is what we emulate and check; so it's safe to mark all exports as `const` (there's no difference to consumers, but it allows unique symbol type declarations) + const flags = !(symbol.flags & SymbolFlags.BlockScopedVariable) + ? symbol.parent?.valueDeclaration && isSourceFile(symbol.parent?.valueDeclaration) + ? NodeFlags.Const // exports are immutable in es6, which is what we emulate and check; so it's safe to mark all exports as `const` (there's no difference to consumers, but it allows unique symbol type declarations) : undefined : isConstVariable(symbol) - ? ts.NodeFlags.Const - : ts.NodeFlags.Let; - const name = (needsPostExportDefault || !(symbol.flags & ts.SymbolFlags.Property)) ? localName : getUnusedName(localName, symbol); - let textRange: ts.Node | undefined = symbol.declarations && ts.find(symbol.declarations, d => ts.isVariableDeclaration(d)); - if (textRange && ts.isVariableDeclarationList(textRange.parent) && textRange.parent.declarations.length === 1) { + ? NodeFlags.Const + : NodeFlags.Let; + const name = (needsPostExportDefault || !(symbol.flags & SymbolFlags.Property)) ? localName : getUnusedName(localName, symbol); + let textRange: Node | undefined = symbol.declarations && find(symbol.declarations, d => isVariableDeclaration(d)); + if (textRange && isVariableDeclarationList(textRange.parent) && textRange.parent.declarations.length === 1) { textRange = textRange.parent.parent; } - const propertyAccessRequire = symbol.declarations?.find(ts.isPropertyAccessExpression); - if (propertyAccessRequire && ts.isBinaryExpression(propertyAccessRequire.parent) && ts.isIdentifier(propertyAccessRequire.parent.right) - && type.symbol?.valueDeclaration && ts.isSourceFile(type.symbol.valueDeclaration)) { + const propertyAccessRequire = symbol.declarations?.find(isPropertyAccessExpression); + if (propertyAccessRequire && isBinaryExpression(propertyAccessRequire.parent) && isIdentifier(propertyAccessRequire.parent.right) + && type.symbol?.valueDeclaration && isSourceFile(type.symbol.valueDeclaration)) { const alias = localName === propertyAccessRequire.parent.right.escapedText ? undefined : propertyAccessRequire.parent.right; addResult( - ts.factory.createExportDeclaration( + factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports([ts.factory.createExportSpecifier(/*isTypeOnly*/ false, alias, localName)]) + factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, alias, localName)]) ), - ts.ModifierFlags.None + ModifierFlags.None ); - context.tracker.trackSymbol!(type.symbol, context.enclosingDeclaration, ts.SymbolFlags.Value); + context.tracker.trackSymbol!(type.symbol, context.enclosingDeclaration, SymbolFlags.Value); } else { - const statement = ts.setTextRange(ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, includePrivateSymbol, bundled)) + const statement = setTextRange(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, type, symbol, enclosingDeclaration, includePrivateSymbol, bundled)) ], flags)), textRange); - addResult(statement, name !== localName ? modifierFlags & ~ts.ModifierFlags.Export : modifierFlags); + addResult(statement, name !== localName ? modifierFlags & ~ModifierFlags.Export : modifierFlags); if (name !== localName && !isPrivate) { // We rename the variable declaration we generate for Property symbols since they may have a name which // conflicts with a local declaration. For example, given input: @@ -7411,12 +7609,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // ``` // To create an export named `g` that does _not_ shadow the local `g` addResult( - ts.factory.createExportDeclaration( + factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports([ts.factory.createExportSpecifier(/*isTypeOnly*/ false, name, localName)]) + factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, name, localName)]) ), - ts.ModifierFlags.None + ModifierFlags.None ); needsExportDeclaration = false; needsPostExportDefault = false; @@ -7425,14 +7623,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - if (symbol.flags & ts.SymbolFlags.Enum) { + if (symbol.flags & SymbolFlags.Enum) { serializeEnum(symbol, symbolName, modifierFlags); } - if (symbol.flags & ts.SymbolFlags.Class) { - if (symbol.flags & ts.SymbolFlags.Property + if (symbol.flags & SymbolFlags.Class) { + if (symbol.flags & SymbolFlags.Property && symbol.valueDeclaration - && ts.isBinaryExpression(symbol.valueDeclaration.parent) - && ts.isClassExpression(symbol.valueDeclaration.parent.right)) { + && isBinaryExpression(symbol.valueDeclaration.parent) + && isClassExpression(symbol.valueDeclaration.parent.right)) { // Looks like a `module.exports.Sub = class {}` - if we serialize `symbol` as a class, the result will have no members, // since the classiness is actually from the target of the effective alias the symbol is. yes. A BlockScopedVariable|Class|Property // _really_ acts like an Alias, and none of a BlockScopedVariable, Class, or Property. This is the travesty of JS binding today. @@ -7442,128 +7640,128 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { serializeAsClass(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags); } } - if ((symbol.flags & (ts.SymbolFlags.ValueModule | ts.SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge) { + if ((symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge) { serializeModule(symbol, symbolName, modifierFlags); } // The class meaning serialization should handle serializing all interface members - if (symbol.flags & ts.SymbolFlags.Interface && !(symbol.flags & ts.SymbolFlags.Class)) { + if (symbol.flags & SymbolFlags.Interface && !(symbol.flags & SymbolFlags.Class)) { serializeInterface(symbol, symbolName, modifierFlags); } - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { serializeAsAlias(symbol, getInternalSymbolName(symbol, symbolName), modifierFlags); } - if (symbol.flags & ts.SymbolFlags.Property && symbol.escapedName === ts.InternalSymbolName.ExportEquals) { + if (symbol.flags & SymbolFlags.Property && symbol.escapedName === InternalSymbolName.ExportEquals) { serializeMaybeAliasAssignment(symbol); } - if (symbol.flags & ts.SymbolFlags.ExportStar) { + if (symbol.flags & SymbolFlags.ExportStar) { // synthesize export * from "moduleReference" // Straightforward - only one thing to do - make an export declaration if (symbol.declarations) { for (const node of symbol.declarations) { - const resolvedModule = resolveExternalModuleName(node, (node as ts.ExportDeclaration).moduleSpecifier!); + const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier!); if (!resolvedModule) continue; - addResult(ts.factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, ts.factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ts.ModifierFlags.None); + addResult(factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, /*exportClause*/ undefined, factory.createStringLiteral(getSpecifierForModuleSymbol(resolvedModule, context))), ModifierFlags.None); } } } if (needsPostExportDefault) { - addResult(ts.factory.createExportAssignment(/*modifiers*/ undefined, /*isExportAssignment*/ false, ts.factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ts.ModifierFlags.None); + addResult(factory.createExportAssignment(/*modifiers*/ undefined, /*isExportAssignment*/ false, factory.createIdentifier(getInternalSymbolName(symbol, symbolName))), ModifierFlags.None); } else if (needsExportDeclaration) { - addResult(ts.factory.createExportDeclaration( + addResult(factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports([ts.factory.createExportSpecifier(/*isTypeOnly*/ false, getInternalSymbolName(symbol, symbolName), symbolName)]) - ), ts.ModifierFlags.None); + factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, getInternalSymbolName(symbol, symbolName), symbolName)]) + ), ModifierFlags.None); } } - function includePrivateSymbol(symbol: ts.Symbol) { - if (ts.some(symbol.declarations, ts.isParameterDeclaration)) return; - ts.Debug.assertIsDefined(deferredPrivatesStack[deferredPrivatesStack.length - 1]); - getUnusedName(ts.unescapeLeadingUnderscores(symbol.escapedName), symbol); // Call to cache unique name for symbol + function includePrivateSymbol(symbol: Symbol) { + if (some(symbol.declarations, isParameterDeclaration)) return; + Debug.assertIsDefined(deferredPrivatesStack[deferredPrivatesStack.length - 1]); + getUnusedName(unescapeLeadingUnderscores(symbol.escapedName), symbol); // Call to cache unique name for symbol // Blanket moving (import) aliases into the root private context should work, since imports are not valid within namespaces // (so they must have been in the root to begin with if they were real imports) cjs `require` aliases (an upcoming feature) // will throw a wrench in this, since those may have been nested, but we'll need to synthesize them in the outer scope // anyway, as that's the only place the import they translate to is valid. In such a case, we might need to use a unique name // for the moved import; which hopefully the above `getUnusedName` call should produce. - const isExternalImportAlias = !!(symbol.flags & ts.SymbolFlags.Alias) && !ts.some(symbol.declarations, d => - !!ts.findAncestor(d, ts.isExportDeclaration) || - ts.isNamespaceExport(d) || - (ts.isImportEqualsDeclaration(d) && !ts.isExternalModuleReference(d.moduleReference)) + const isExternalImportAlias = !!(symbol.flags & SymbolFlags.Alias) && !some(symbol.declarations, d => + !!findAncestor(d, isExportDeclaration) || + isNamespaceExport(d) || + (isImportEqualsDeclaration(d) && !isExternalModuleReference(d.moduleReference)) ); deferredPrivatesStack[isExternalImportAlias ? 0 : (deferredPrivatesStack.length - 1)].set(getSymbolId(symbol), symbol); } - function isExportingScope(enclosingDeclaration: ts.Node) { - return ((ts.isSourceFile(enclosingDeclaration) && (ts.isExternalOrCommonJsModule(enclosingDeclaration) || ts.isJsonSourceFile(enclosingDeclaration))) || - (ts.isAmbientModule(enclosingDeclaration) && !ts.isGlobalScopeAugmentation(enclosingDeclaration))); + function isExportingScope(enclosingDeclaration: Node) { + return ((isSourceFile(enclosingDeclaration) && (isExternalOrCommonJsModule(enclosingDeclaration) || isJsonSourceFile(enclosingDeclaration))) || + (isAmbientModule(enclosingDeclaration) && !isGlobalScopeAugmentation(enclosingDeclaration))); } // Prepends a `declare` and/or `export` modifier if the context requires it, and then adds `node` to `result` and returns `node` - function addResult(node: ts.Statement, additionalModifierFlags: ts.ModifierFlags) { - if (ts.canHaveModifiers(node)) { - let newModifierFlags: ts.ModifierFlags = ts.ModifierFlags.None; + function addResult(node: Statement, additionalModifierFlags: ModifierFlags) { + if (canHaveModifiers(node)) { + let newModifierFlags: ModifierFlags = ModifierFlags.None; const enclosingDeclaration = context.enclosingDeclaration && - (ts.isJSDocTypeAlias(context.enclosingDeclaration) ? ts.getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration); - if (additionalModifierFlags & ts.ModifierFlags.Export && - enclosingDeclaration && (isExportingScope(enclosingDeclaration) || ts.isModuleDeclaration(enclosingDeclaration)) && - ts.canHaveExportModifier(node) + (isJSDocTypeAlias(context.enclosingDeclaration) ? getSourceFileOfNode(context.enclosingDeclaration) : context.enclosingDeclaration); + if (additionalModifierFlags & ModifierFlags.Export && + enclosingDeclaration && (isExportingScope(enclosingDeclaration) || isModuleDeclaration(enclosingDeclaration)) && + canHaveExportModifier(node) ) { // Classes, namespaces, variables, functions, interfaces, and types should all be `export`ed in a module context if not private - newModifierFlags |= ts.ModifierFlags.Export; + newModifierFlags |= ModifierFlags.Export; } - if (addingDeclare && !(newModifierFlags & ts.ModifierFlags.Export) && - (!enclosingDeclaration || !(enclosingDeclaration.flags & ts.NodeFlags.Ambient)) && - (ts.isEnumDeclaration(node) || ts.isVariableStatement(node) || ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node) || ts.isModuleDeclaration(node))) { + if (addingDeclare && !(newModifierFlags & ModifierFlags.Export) && + (!enclosingDeclaration || !(enclosingDeclaration.flags & NodeFlags.Ambient)) && + (isEnumDeclaration(node) || isVariableStatement(node) || isFunctionDeclaration(node) || isClassDeclaration(node) || isModuleDeclaration(node))) { // Classes, namespaces, variables, enums, and functions all need `declare` modifiers to be valid in a declaration file top-level scope - newModifierFlags |= ts.ModifierFlags.Ambient; + newModifierFlags |= ModifierFlags.Ambient; } - if ((additionalModifierFlags & ts.ModifierFlags.Default) && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node) || ts.isFunctionDeclaration(node))) { - newModifierFlags |= ts.ModifierFlags.Default; + if ((additionalModifierFlags & ModifierFlags.Default) && (isClassDeclaration(node) || isInterfaceDeclaration(node) || isFunctionDeclaration(node))) { + newModifierFlags |= ModifierFlags.Default; } if (newModifierFlags) { - node = ts.factory.updateModifiers(node, newModifierFlags | ts.getEffectiveModifierFlags(node)); + node = factory.updateModifiers(node, newModifierFlags | getEffectiveModifierFlags(node)); } } results.push(node); } - function serializeTypeAlias(symbol: ts.Symbol, symbolName: string, modifierFlags: ts.ModifierFlags) { + function serializeTypeAlias(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { const aliasType = getDeclaredTypeOfTypeAlias(symbol); const typeParams = getSymbolLinks(symbol).typeParameters; - const typeParamDecls = ts.map(typeParams, p => typeParameterToDeclaration(p, context)); - const jsdocAliasDecl = symbol.declarations?.find(ts.isJSDocTypeAlias); - const commentText = ts.getTextOfJSDocComment(jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined); + const typeParamDecls = map(typeParams, p => typeParameterToDeclaration(p, context)); + const jsdocAliasDecl = symbol.declarations?.find(isJSDocTypeAlias); + const commentText = getTextOfJSDocComment(jsdocAliasDecl ? jsdocAliasDecl.comment || jsdocAliasDecl.parent.comment : undefined); const oldFlags = context.flags; - context.flags |= ts.NodeBuilderFlags.InTypeAlias; + context.flags |= NodeBuilderFlags.InTypeAlias; const oldEnclosingDecl = context.enclosingDeclaration; context.enclosingDeclaration = jsdocAliasDecl; const typeNode = jsdocAliasDecl && jsdocAliasDecl.typeExpression - && ts.isJSDocTypeExpression(jsdocAliasDecl.typeExpression) + && isJSDocTypeExpression(jsdocAliasDecl.typeExpression) && serializeExistingTypeNode(context, jsdocAliasDecl.typeExpression.type, includePrivateSymbol, bundled) || typeToTypeNodeHelper(aliasType, context); - addResult(ts.setSyntheticLeadingComments( - ts.factory.createTypeAliasDeclaration(/*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode), - !commentText ? [] : [{ kind: ts.SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }] + addResult(setSyntheticLeadingComments( + factory.createTypeAliasDeclaration(/*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, typeNode), + !commentText ? [] : [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }] ), modifierFlags); context.flags = oldFlags; context.enclosingDeclaration = oldEnclosingDecl; } - function serializeInterface(symbol: ts.Symbol, symbolName: string, modifierFlags: ts.ModifierFlags) { + function serializeInterface(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { const interfaceType = getDeclaredTypeOfClassOrInterface(symbol); const localParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); - const typeParamDecls = ts.map(localParams, p => typeParameterToDeclaration(p, context)); + const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context)); const baseTypes = getBaseTypes(interfaceType); - const baseType = ts.length(baseTypes) ? getIntersectionType(baseTypes) : undefined; - const members = ts.flatMap(getPropertiesOfType(interfaceType), p => serializePropertySymbolForInterface(p, baseType)); - const callSignatures = serializeSignatures(ts.SignatureKind.Call, interfaceType, baseType, ts.SyntaxKind.CallSignature) as ts.CallSignatureDeclaration[]; - const constructSignatures = serializeSignatures(ts.SignatureKind.Construct, interfaceType, baseType, ts.SyntaxKind.ConstructSignature) as ts.ConstructSignatureDeclaration[]; + const baseType = length(baseTypes) ? getIntersectionType(baseTypes) : undefined; + const members = flatMap(getPropertiesOfType(interfaceType), p => serializePropertySymbolForInterface(p, baseType)); + const callSignatures = serializeSignatures(SignatureKind.Call, interfaceType, baseType, SyntaxKind.CallSignature) as CallSignatureDeclaration[]; + const constructSignatures = serializeSignatures(SignatureKind.Construct, interfaceType, baseType, SyntaxKind.ConstructSignature) as ConstructSignatureDeclaration[]; const indexSignatures = serializeIndexSignatures(interfaceType, baseType); - const heritageClauses = !ts.length(baseTypes) ? undefined : [ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, ts.mapDefined(baseTypes, b => trySerializeAsTypeReference(b, ts.SymbolFlags.Value)))]; - addResult(ts.factory.createInterfaceDeclaration( + const heritageClauses = !length(baseTypes) ? undefined : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, mapDefined(baseTypes, b => trySerializeAsTypeReference(b, SymbolFlags.Value)))]; + addResult(factory.createInterfaceDeclaration( /*modifiers*/ undefined, getInternalSymbolName(symbol, symbolName), typeParamDecls, @@ -7572,108 +7770,108 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { ), modifierFlags); } - function getNamespaceMembersForSerialization(symbol: ts.Symbol) { - return !symbol.exports ? [] : ts.filter(ts.arrayFrom(symbol.exports.values()), isNamespaceMember); + function getNamespaceMembersForSerialization(symbol: Symbol) { + return !symbol.exports ? [] : filter(arrayFrom(symbol.exports.values()), isNamespaceMember); } - function isTypeOnlyNamespace(symbol: ts.Symbol) { - return ts.every(getNamespaceMembersForSerialization(symbol), m => !(getAllSymbolFlags(resolveSymbol(m)) & ts.SymbolFlags.Value)); + function isTypeOnlyNamespace(symbol: Symbol) { + return every(getNamespaceMembersForSerialization(symbol), m => !(getAllSymbolFlags(resolveSymbol(m)) & SymbolFlags.Value)); } - function serializeModule(symbol: ts.Symbol, symbolName: string, modifierFlags: ts.ModifierFlags) { + function serializeModule(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { const members = getNamespaceMembersForSerialization(symbol); // Split NS members up by declaration - members whose parent symbol is the ns symbol vs those whose is not (but were added in later via merging) - const locationMap = ts.arrayToMultiMap(members, m => m.parent && m.parent === symbol ? "real" : "merged"); - const realMembers = locationMap.get("real") || ts.emptyArray; - const mergedMembers = locationMap.get("merged") || ts.emptyArray; + const locationMap = arrayToMultiMap(members, m => m.parent && m.parent === symbol ? "real" : "merged"); + const realMembers = locationMap.get("real") || emptyArray; + const mergedMembers = locationMap.get("merged") || emptyArray; // TODO: `suppressNewPrivateContext` is questionable -we need to simply be emitting privates in whatever scope they were declared in, rather // than whatever scope we traverse to them in. That's a bit of a complex rewrite, since we're not _actually_ tracking privates at all in advance, // so we don't even have placeholders to fill in. - if (ts.length(realMembers)) { + if (length(realMembers)) { const localName = getInternalSymbolName(symbol, symbolName); - serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Assignment))); + serializeAsNamespaceDeclaration(realMembers, localName, modifierFlags, !!(symbol.flags & (SymbolFlags.Function | SymbolFlags.Assignment))); } - if (ts.length(mergedMembers)) { - const containingFile = ts.getSourceFileOfNode(context.enclosingDeclaration); + if (length(mergedMembers)) { + const containingFile = getSourceFileOfNode(context.enclosingDeclaration); const localName = getInternalSymbolName(symbol, symbolName); - const nsBody = ts.factory.createModuleBlock([ts.factory.createExportDeclaration( + const nsBody = factory.createModuleBlock([factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports(ts.mapDefined(ts.filter(mergedMembers, n => n.escapedName !== ts.InternalSymbolName.ExportEquals), s => { - const name = ts.unescapeLeadingUnderscores(s.escapedName); + factory.createNamedExports(mapDefined(filter(mergedMembers, n => n.escapedName !== InternalSymbolName.ExportEquals), s => { + const name = unescapeLeadingUnderscores(s.escapedName); const localName = getInternalSymbolName(s, name); const aliasDecl = s.declarations && getDeclarationOfAliasSymbol(s); - if (containingFile && (aliasDecl ? containingFile !== ts.getSourceFileOfNode(aliasDecl) : !ts.some(s.declarations, d => ts.getSourceFileOfNode(d) === containingFile))) { + if (containingFile && (aliasDecl ? containingFile !== getSourceFileOfNode(aliasDecl) : !some(s.declarations, d => getSourceFileOfNode(d) === containingFile))) { context.tracker?.reportNonlocalAugmentation?.(containingFile, symbol, s); return undefined; } const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); includePrivateSymbol(target || s); - const targetName = target ? getInternalSymbolName(target, ts.unescapeLeadingUnderscores(target.escapedName)) : localName; - return ts.factory.createExportSpecifier(/*isTypeOnly*/ false, name === targetName ? undefined : targetName, name); + const targetName = target ? getInternalSymbolName(target, unescapeLeadingUnderscores(target.escapedName)) : localName; + return factory.createExportSpecifier(/*isTypeOnly*/ false, name === targetName ? undefined : targetName, name); })) )]); - addResult(ts.factory.createModuleDeclaration( + addResult(factory.createModuleDeclaration( /*modifiers*/ undefined, - ts.factory.createIdentifier(localName), + factory.createIdentifier(localName), nsBody, - ts.NodeFlags.Namespace - ), ts.ModifierFlags.None); + NodeFlags.Namespace + ), ModifierFlags.None); } } - function serializeEnum(symbol: ts.Symbol, symbolName: string, modifierFlags: ts.ModifierFlags) { - addResult(ts.factory.createEnumDeclaration( - ts.factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ts.ModifierFlags.Const : 0), + function serializeEnum(symbol: Symbol, symbolName: string, modifierFlags: ModifierFlags) { + addResult(factory.createEnumDeclaration( + factory.createModifiersFromModifierFlags(isConstEnumSymbol(symbol) ? ModifierFlags.Const : 0), getInternalSymbolName(symbol, symbolName), - ts.map(ts.filter(getPropertiesOfType(getTypeOfSymbol(symbol)), p => !!(p.flags & ts.SymbolFlags.EnumMember)), p => { + map(filter(getPropertiesOfType(getTypeOfSymbol(symbol)), p => !!(p.flags & SymbolFlags.EnumMember)), p => { // TODO: Handle computed names // I hate that to get the initialized value we need to walk back to the declarations here; but there's no // other way to get the possible const value of an enum member that I'm aware of, as the value is cached // _on the declaration_, not on the declaration's symbol... - const initializedValue = p.declarations && p.declarations[0] && ts.isEnumMember(p.declarations[0]) ? getConstantValue(p.declarations[0]) : undefined; - return ts.factory.createEnumMember(ts.unescapeLeadingUnderscores(p.escapedName), initializedValue === undefined ? undefined : - typeof initializedValue === "string" ? ts.factory.createStringLiteral(initializedValue) : - ts.factory.createNumericLiteral(initializedValue)); + const initializedValue = p.declarations && p.declarations[0] && isEnumMember(p.declarations[0]) ? getConstantValue(p.declarations[0]) : undefined; + return factory.createEnumMember(unescapeLeadingUnderscores(p.escapedName), initializedValue === undefined ? undefined : + typeof initializedValue === "string" ? factory.createStringLiteral(initializedValue) : + factory.createNumericLiteral(initializedValue)); }) ), modifierFlags); } - function serializeAsFunctionNamespaceMerge(type: ts.Type, symbol: ts.Symbol, localName: string, modifierFlags: ts.ModifierFlags) { - const signatures = getSignaturesOfType(type, ts.SignatureKind.Call); + function serializeAsFunctionNamespaceMerge(type: Type, symbol: Symbol, localName: string, modifierFlags: ModifierFlags) { + const signatures = getSignaturesOfType(type, SignatureKind.Call); for (const sig of signatures) { // Each overload becomes a separate function declaration, in order - const decl = signatureToSignatureDeclarationHelper(sig, ts.SyntaxKind.FunctionDeclaration, context, { name: ts.factory.createIdentifier(localName), privateSymbolVisitor: includePrivateSymbol, bundledImports: bundled }) as ts.FunctionDeclaration; - addResult(ts.setTextRange(decl, getSignatureTextRangeLocation(sig)), modifierFlags); + const decl = signatureToSignatureDeclarationHelper(sig, SyntaxKind.FunctionDeclaration, context, { name: factory.createIdentifier(localName), privateSymbolVisitor: includePrivateSymbol, bundledImports: bundled }) as FunctionDeclaration; + addResult(setTextRange(decl, getSignatureTextRangeLocation(sig)), modifierFlags); } // Module symbol emit will take care of module-y members, provided it has exports - if (!(symbol.flags & (ts.SymbolFlags.ValueModule | ts.SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) { - const props = ts.filter(getPropertiesOfType(type), isNamespaceMember); + if (!(symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && !!symbol.exports && !!symbol.exports.size)) { + const props = filter(getPropertiesOfType(type), isNamespaceMember); serializeAsNamespaceDeclaration(props, localName, modifierFlags, /*suppressNewPrivateContext*/ true); } } - function getSignatureTextRangeLocation(signature: ts.Signature) { + function getSignatureTextRangeLocation(signature: Signature) { if (signature.declaration && signature.declaration.parent) { - if (ts.isBinaryExpression(signature.declaration.parent) && ts.getAssignmentDeclarationKind(signature.declaration.parent) === ts.AssignmentDeclarationKind.Property) { + if (isBinaryExpression(signature.declaration.parent) && getAssignmentDeclarationKind(signature.declaration.parent) === AssignmentDeclarationKind.Property) { return signature.declaration.parent; } // for expressions assigned to `var`s, use the `var` as the text range - if (ts.isVariableDeclaration(signature.declaration.parent) && signature.declaration.parent.parent) { + if (isVariableDeclaration(signature.declaration.parent) && signature.declaration.parent.parent) { return signature.declaration.parent.parent; } } return signature.declaration; } - function serializeAsNamespaceDeclaration(props: readonly ts.Symbol[], localName: string, modifierFlags: ts.ModifierFlags, suppressNewPrivateContext: boolean) { - if (ts.length(props)) { - const localVsRemoteMap = ts.arrayToMultiMap(props, p => - !ts.length(p.declarations) || ts.some(p.declarations, d => - ts.getSourceFileOfNode(d) === ts.getSourceFileOfNode(context.enclosingDeclaration!) + function serializeAsNamespaceDeclaration(props: readonly Symbol[], localName: string, modifierFlags: ModifierFlags, suppressNewPrivateContext: boolean) { + if (length(props)) { + const localVsRemoteMap = arrayToMultiMap(props, p => + !length(p.declarations) || some(p.declarations, d => + getSourceFileOfNode(d) === getSourceFileOfNode(context.enclosingDeclaration!) ) ? "local" : "remote" ); - const localProps = localVsRemoteMap.get("local") || ts.emptyArray; + const localProps = localVsRemoteMap.get("local") || emptyArray; // handle remote props first - we need to make an `import` declaration that points at the module containing each remote // prop in the outermost scope (TODO: a namespace within a namespace would need to be appropriately handled by this) // Example: @@ -7691,9 +7889,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Add a namespace // Create namespace as non-synthetic so it is usable as an enclosing declaration - let fakespace = ts.parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, ts.factory.createIdentifier(localName), ts.factory.createModuleBlock([]), ts.NodeFlags.Namespace); - ts.setParent(fakespace, enclosingDeclaration as ts.SourceFile | ts.NamespaceDeclaration); - fakespace.locals = ts.createSymbolTable(props); + let fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, factory.createIdentifier(localName), factory.createModuleBlock([]), NodeFlags.Namespace); + setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); + fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; const oldResults = results; @@ -7704,39 +7902,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const oldContext = context; context = subcontext; // TODO: implement handling for the localVsRemoteMap.get("remote") - should be difficult to trigger (see comment above), as only interesting cross-file js merges should make this possible - visitSymbolTable(ts.createSymbolTable(localProps), suppressNewPrivateContext, /*propertyAsAlias*/ true); + visitSymbolTable(createSymbolTable(localProps), suppressNewPrivateContext, /*propertyAsAlias*/ true); context = oldContext; addingDeclare = oldAddingDeclare; const declarations = results; results = oldResults; // replace namespace with synthetic version - const defaultReplaced = ts.map(declarations, d => ts.isExportAssignment(d) && !d.isExportEquals && ts.isIdentifier(d.expression) ? ts.factory.createExportDeclaration( + const defaultReplaced = map(declarations, d => isExportAssignment(d) && !d.isExportEquals && isIdentifier(d.expression) ? factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports([ts.factory.createExportSpecifier(/*isTypeOnly*/ false, d.expression, ts.factory.createIdentifier(ts.InternalSymbolName.Default))]) + factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, d.expression, factory.createIdentifier(InternalSymbolName.Default))]) ) : d); - const exportModifierStripped = ts.every(defaultReplaced, d => ts.hasSyntacticModifier(d, ts.ModifierFlags.Export)) ? ts.map(defaultReplaced, removeExportModifier) : defaultReplaced; - fakespace = ts.factory.updateModuleDeclaration( + const exportModifierStripped = every(defaultReplaced, d => hasSyntacticModifier(d, ModifierFlags.Export)) ? map(defaultReplaced, removeExportModifier) : defaultReplaced; + fakespace = factory.updateModuleDeclaration( fakespace, fakespace.modifiers, fakespace.name, - ts.factory.createModuleBlock(exportModifierStripped)); + factory.createModuleBlock(exportModifierStripped)); addResult(fakespace, modifierFlags); // namespaces can never be default exported } } - function isNamespaceMember(p: ts.Symbol) { - return !!(p.flags & (ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias)) || - !(p.flags & ts.SymbolFlags.Prototype || p.escapedName === "prototype" || p.valueDeclaration && ts.isStatic(p.valueDeclaration) && ts.isClassLike(p.valueDeclaration.parent)); + function isNamespaceMember(p: Symbol) { + return !!(p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias)) || + !(p.flags & SymbolFlags.Prototype || p.escapedName === "prototype" || p.valueDeclaration && isStatic(p.valueDeclaration) && isClassLike(p.valueDeclaration.parent)); } - function sanitizeJSDocImplements(clauses: readonly ts.ExpressionWithTypeArguments[]): ts.ExpressionWithTypeArguments[] | undefined { - const result = ts.mapDefined(clauses, e => { + function sanitizeJSDocImplements(clauses: readonly ExpressionWithTypeArguments[]): ExpressionWithTypeArguments[] | undefined { + const result = mapDefined(clauses, e => { const oldEnclosing = context.enclosingDeclaration; context.enclosingDeclaration = e; let expr = e.expression; - if (ts.isEntityNameExpression(expr)) { - if (ts.isIdentifier(expr) && ts.idText(expr) === "") { + if (isEntityNameExpression(expr)) { + if (isIdentifier(expr) && idText(expr) === "") { return cleanup(/*result*/ undefined); // Empty heritage clause, should be an error, but prefer emitting no heritage clauses to reemitting the empty one } let introducesError: boolean; @@ -7745,8 +7943,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return cleanup(/*result*/ undefined); } } - return cleanup(ts.factory.createExpressionWithTypeArguments(expr, - ts.map(e.typeArguments, a => + return cleanup(factory.createExpressionWithTypeArguments(expr, + map(e.typeArguments, a => serializeExistingTypeNode(context, a, includePrivateSymbol, bundled) || typeToTypeNodeHelper(getTypeFromTypeNode(a), context) ) @@ -7763,55 +7961,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function serializeAsClass(symbol: ts.Symbol, localName: string, modifierFlags: ts.ModifierFlags) { - const originalDecl = symbol.declarations?.find(ts.isClassLike); + function serializeAsClass(symbol: Symbol, localName: string, modifierFlags: ModifierFlags) { + const originalDecl = symbol.declarations?.find(isClassLike); const oldEnclosing = context.enclosingDeclaration; context.enclosingDeclaration = originalDecl || oldEnclosing; const localParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); - const typeParamDecls = ts.map(localParams, p => typeParameterToDeclaration(p, context)); + const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context)); const classType = getDeclaredTypeOfClassOrInterface(symbol); const baseTypes = getBaseTypes(classType); - const originalImplements = originalDecl && ts.getEffectiveImplementsTypeNodes(originalDecl); + const originalImplements = originalDecl && getEffectiveImplementsTypeNodes(originalDecl); const implementsExpressions = originalImplements && sanitizeJSDocImplements(originalImplements) - || ts.mapDefined(getImplementsTypes(classType), serializeImplementedType); + || mapDefined(getImplementsTypes(classType), serializeImplementedType); const staticType = getTypeOfSymbol(symbol); - const isClass = !!staticType.symbol?.valueDeclaration && ts.isClassLike(staticType.symbol.valueDeclaration); + const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration); const staticBaseType = isClass - ? getBaseConstructorTypeOfClass(staticType as ts.InterfaceType) + ? getBaseConstructorTypeOfClass(staticType as InterfaceType) : anyType; const heritageClauses = [ - ...!ts.length(baseTypes) ? [] : [ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, ts.map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))], - ...!ts.length(implementsExpressions) ? [] : [ts.factory.createHeritageClause(ts.SyntaxKind.ImplementsKeyword, implementsExpressions)] + ...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))], + ...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)] ]; const symbolProps = getNonInheritedProperties(classType, baseTypes, getPropertiesOfType(classType)); - const publicSymbolProps = ts.filter(symbolProps, s => { + const publicSymbolProps = filter(symbolProps, s => { // `valueDeclaration` could be undefined if inherited from // a union/intersection base type, but inherited properties // don't matter here. const valueDecl = s.valueDeclaration; - return !!valueDecl && !(ts.isNamedDeclaration(valueDecl) && ts.isPrivateIdentifier(valueDecl.name)); + return !!valueDecl && !(isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name)); }); - const hasPrivateIdentifier = ts.some(symbolProps, s => { + const hasPrivateIdentifier = some(symbolProps, s => { // `valueDeclaration` could be undefined if inherited from // a union/intersection base type, but inherited properties // don't matter here. const valueDecl = s.valueDeclaration; - return !!valueDecl && ts.isNamedDeclaration(valueDecl) && ts.isPrivateIdentifier(valueDecl.name); + return !!valueDecl && isNamedDeclaration(valueDecl) && isPrivateIdentifier(valueDecl.name); }); // Boil down all private properties into a single one. const privateProperties = hasPrivateIdentifier ? - [ts.factory.createPropertyDeclaration( + [factory.createPropertyDeclaration( /*modifiers*/ undefined, - ts.factory.createPrivateIdentifier("#private"), + factory.createPrivateIdentifier("#private"), /*questionOrExclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined, )] : - ts.emptyArray; - const publicProperties = ts.flatMap(publicSymbolProps, p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0])); + emptyArray; + const publicProperties = flatMap(publicSymbolProps, p => serializePropertySymbolForClass(p, /*isStatic*/ false, baseTypes[0])); // Consider static members empty if symbol also has function or module meaning - function namespacey emit will handle statics - const staticMembers = ts.flatMap( - ts.filter(getPropertiesOfType(staticType), p => !(p.flags & ts.SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)), + const staticMembers = flatMap( + filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)), p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType)); // When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether // the value is ever initialized with a class or function-like value. For cases where `X` could never be @@ -7819,208 +8017,208 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const isNonConstructableClassLikeInJsFile = !isClass && !!symbol.valueDeclaration && - ts.isInJSFile(symbol.valueDeclaration) && - !ts.some(getSignaturesOfType(staticType, ts.SignatureKind.Construct)); + isInJSFile(symbol.valueDeclaration) && + !some(getSignaturesOfType(staticType, SignatureKind.Construct)); const constructors = isNonConstructableClassLikeInJsFile ? - [ts.factory.createConstructorDeclaration(ts.factory.createModifiersFromModifierFlags(ts.ModifierFlags.Private), [], /*body*/ undefined)] : - serializeSignatures(ts.SignatureKind.Construct, staticType, staticBaseType, ts.SyntaxKind.Constructor) as ts.ConstructorDeclaration[]; + [factory.createConstructorDeclaration(factory.createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] : + serializeSignatures(SignatureKind.Construct, staticType, staticBaseType, SyntaxKind.Constructor) as ConstructorDeclaration[]; const indexSignatures = serializeIndexSignatures(classType, baseTypes[0]); context.enclosingDeclaration = oldEnclosing; - addResult(ts.setTextRange(ts.factory.createClassDeclaration( + addResult(setTextRange(factory.createClassDeclaration( /*modifiers*/ undefined, localName, typeParamDecls, heritageClauses, [...indexSignatures, ...staticMembers, ...constructors, ...publicProperties, ...privateProperties] - ), symbol.declarations && ts.filter(symbol.declarations, d => ts.isClassDeclaration(d) || ts.isClassExpression(d))[0]), modifierFlags); + ), symbol.declarations && filter(symbol.declarations, d => isClassDeclaration(d) || isClassExpression(d))[0]), modifierFlags); } - function getSomeTargetNameFromDeclarations(declarations: ts.Declaration[] | undefined) { - return ts.firstDefined(declarations, d => { - if (ts.isImportSpecifier(d) || ts.isExportSpecifier(d)) { - return ts.idText(d.propertyName || d.name); + function getSomeTargetNameFromDeclarations(declarations: Declaration[] | undefined) { + return firstDefined(declarations, d => { + if (isImportSpecifier(d) || isExportSpecifier(d)) { + return idText(d.propertyName || d.name); } - if (ts.isBinaryExpression(d) || ts.isExportAssignment(d)) { - const expression = ts.isExportAssignment(d) ? d.expression : d.right; - if (ts.isPropertyAccessExpression(expression)) { - return ts.idText(expression.name); + if (isBinaryExpression(d) || isExportAssignment(d)) { + const expression = isExportAssignment(d) ? d.expression : d.right; + if (isPropertyAccessExpression(expression)) { + return idText(expression.name); } } if (isAliasSymbolDeclaration(d)) { // This is... heuristic, at best. But it's probably better than always printing the name of the shorthand ambient module. - const name = ts.getNameOfDeclaration(d); - if (name && ts.isIdentifier(name)) { - return ts.idText(name); + const name = getNameOfDeclaration(d); + if (name && isIdentifier(name)) { + return idText(name); } } return undefined; }); } - function serializeAsAlias(symbol: ts.Symbol, localName: string, modifierFlags: ts.ModifierFlags) { + function serializeAsAlias(symbol: Symbol, localName: string, modifierFlags: ModifierFlags) { // synthesize an alias, eg `export { symbolName as Name }` // need to mark the alias `symbol` points at // as something we need to serialize as a private declaration as well const node = getDeclarationOfAliasSymbol(symbol); - if (!node) return ts.Debug.fail(); + if (!node) return Debug.fail(); const target = getMergedSymbol(getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true)); if (!target) { return; } // If `target` refers to a shorthand module symbol, the name we're trying to pull out isn;t recoverable from the target symbol // In such a scenario, we must fall back to looking for an alias declaration on `symbol` and pulling the target name from that - let verbatimTargetName = ts.isShorthandAmbientModuleSymbol(target) && getSomeTargetNameFromDeclarations(symbol.declarations) || ts.unescapeLeadingUnderscores(target.escapedName); - if (verbatimTargetName === ts.InternalSymbolName.ExportEquals && (ts.getESModuleInterop(compilerOptions) || compilerOptions.allowSyntheticDefaultImports)) { + let verbatimTargetName = isShorthandAmbientModuleSymbol(target) && getSomeTargetNameFromDeclarations(symbol.declarations) || unescapeLeadingUnderscores(target.escapedName); + if (verbatimTargetName === InternalSymbolName.ExportEquals && (getESModuleInterop(compilerOptions) || compilerOptions.allowSyntheticDefaultImports)) { // target refers to an `export=` symbol that was hoisted into a synthetic default - rename here to match - verbatimTargetName = ts.InternalSymbolName.Default; + verbatimTargetName = InternalSymbolName.Default; } const targetName = getInternalSymbolName(target, verbatimTargetName); includePrivateSymbol(target); // the target may be within the same scope - attempt to serialize it first switch (node.kind) { - case ts.SyntaxKind.BindingElement: - if (node.parent?.parent?.kind === ts.SyntaxKind.VariableDeclaration) { + case SyntaxKind.BindingElement: + if (node.parent?.parent?.kind === SyntaxKind.VariableDeclaration) { // const { SomeClass } = require('./lib'); const specifier = getSpecifierForModuleSymbol(target.parent || target, context); // './lib' - const { propertyName } = node as ts.BindingElement; - addResult(ts.factory.createImportDeclaration( + const { propertyName } = node as BindingElement; + addResult(factory.createImportDeclaration( /*modifiers*/ undefined, - ts.factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, ts.factory.createNamedImports([ts.factory.createImportSpecifier( + factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamedImports([factory.createImportSpecifier( /*isTypeOnly*/ false, - propertyName && ts.isIdentifier(propertyName) ? ts.factory.createIdentifier(ts.idText(propertyName)) : undefined, - ts.factory.createIdentifier(localName) + propertyName && isIdentifier(propertyName) ? factory.createIdentifier(idText(propertyName)) : undefined, + factory.createIdentifier(localName) )])), - ts.factory.createStringLiteral(specifier), + factory.createStringLiteral(specifier), /*importClause*/ undefined - ), ts.ModifierFlags.None); + ), ModifierFlags.None); break; } // We don't know how to serialize this (nested?) binding element - ts.Debug.failBadSyntaxKind(node.parent?.parent || node, "Unhandled binding element grandparent kind in declaration serialization"); + Debug.failBadSyntaxKind(node.parent?.parent || node, "Unhandled binding element grandparent kind in declaration serialization"); break; - case ts.SyntaxKind.ShorthandPropertyAssignment: - if (node.parent?.parent?.kind === ts.SyntaxKind.BinaryExpression) { + case SyntaxKind.ShorthandPropertyAssignment: + if (node.parent?.parent?.kind === SyntaxKind.BinaryExpression) { // module.exports = { SomeClass } serializeExportSpecifier( - ts.unescapeLeadingUnderscores(symbol.escapedName), + unescapeLeadingUnderscores(symbol.escapedName), targetName ); } break; - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableDeclaration: // commonjs require: const x = require('y') - if (ts.isPropertyAccessExpression((node as ts.VariableDeclaration).initializer!)) { + if (isPropertyAccessExpression((node as VariableDeclaration).initializer!)) { // const x = require('y').z - const initializer = (node as ts.VariableDeclaration).initializer! as ts.PropertyAccessExpression; // require('y').z - const uniqueName = ts.factory.createUniqueName(localName); // _x + const initializer = (node as VariableDeclaration).initializer! as PropertyAccessExpression; // require('y').z + const uniqueName = factory.createUniqueName(localName); // _x const specifier = getSpecifierForModuleSymbol(target.parent || target, context); // 'y' // import _x = require('y'); - addResult(ts.factory.createImportEqualsDeclaration( + addResult(factory.createImportEqualsDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, uniqueName, - ts.factory.createExternalModuleReference(ts.factory.createStringLiteral(specifier)) - ), ts.ModifierFlags.None); + factory.createExternalModuleReference(factory.createStringLiteral(specifier)) + ), ModifierFlags.None); // import x = _x.z - addResult(ts.factory.createImportEqualsDeclaration( + addResult(factory.createImportEqualsDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createIdentifier(localName), - ts.factory.createQualifiedName(uniqueName, initializer.name as ts.Identifier), + factory.createIdentifier(localName), + factory.createQualifiedName(uniqueName, initializer.name as Identifier), ), modifierFlags); break; } // else fall through and treat commonjs require just like import= - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: // This _specifically_ only exists to handle json declarations - where we make aliases, but since // we emit no declarations for the json document, must not refer to it in the declarations - if (target.escapedName === ts.InternalSymbolName.ExportEquals && ts.some(target.declarations, ts.isJsonSourceFile)) { + if (target.escapedName === InternalSymbolName.ExportEquals && some(target.declarations, isJsonSourceFile)) { serializeMaybeAliasAssignment(symbol); break; } // Could be a local `import localName = ns.member` or // an external `import localName = require("whatever")` - const isLocalImport = !(target.flags & ts.SymbolFlags.ValueModule) && !ts.isVariableDeclaration(node); - addResult(ts.factory.createImportEqualsDeclaration( + const isLocalImport = !(target.flags & SymbolFlags.ValueModule) && !isVariableDeclaration(node); + addResult(factory.createImportEqualsDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createIdentifier(localName), + factory.createIdentifier(localName), isLocalImport - ? symbolToName(target, context, ts.SymbolFlags.All, /*expectsIdentifier*/ false) - : ts.factory.createExternalModuleReference(ts.factory.createStringLiteral(getSpecifierForModuleSymbol(target, context))) - ), isLocalImport ? modifierFlags : ts.ModifierFlags.None); + ? symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) + : factory.createExternalModuleReference(factory.createStringLiteral(getSpecifierForModuleSymbol(target, context))) + ), isLocalImport ? modifierFlags : ModifierFlags.None); break; - case ts.SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.NamespaceExportDeclaration: // export as namespace foo // TODO: Not part of a file's local or export symbol tables // Is bound into file.symbol.globalExports instead, which we don't currently traverse - addResult(ts.factory.createNamespaceExportDeclaration(ts.idText((node as ts.NamespaceExportDeclaration).name)), ts.ModifierFlags.None); + addResult(factory.createNamespaceExportDeclaration(idText((node as NamespaceExportDeclaration).name)), ModifierFlags.None); break; - case ts.SyntaxKind.ImportClause: - addResult(ts.factory.createImportDeclaration( + case SyntaxKind.ImportClause: + addResult(factory.createImportDeclaration( /*modifiers*/ undefined, - ts.factory.createImportClause(/*isTypeOnly*/ false, ts.factory.createIdentifier(localName), /*namedBindings*/ undefined), + factory.createImportClause(/*isTypeOnly*/ false, factory.createIdentifier(localName), /*namedBindings*/ undefined), // We use `target.parent || target` below as `target.parent` is unset when the target is a module which has been export assigned // And then made into a default by the `esModuleInterop` or `allowSyntheticDefaultImports` flag // In such cases, the `target` refers to the module itself already - ts.factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), + factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), /*assertClause*/ undefined - ), ts.ModifierFlags.None); + ), ModifierFlags.None); break; - case ts.SyntaxKind.NamespaceImport: - addResult(ts.factory.createImportDeclaration( + case SyntaxKind.NamespaceImport: + addResult(factory.createImportDeclaration( /*modifiers*/ undefined, - ts.factory.createImportClause(/*isTypeOnly*/ false, /*importClause*/ undefined, ts.factory.createNamespaceImport(ts.factory.createIdentifier(localName))), - ts.factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)), + factory.createImportClause(/*isTypeOnly*/ false, /*importClause*/ undefined, factory.createNamespaceImport(factory.createIdentifier(localName))), + factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)), /*assertClause*/ undefined - ), ts.ModifierFlags.None); + ), ModifierFlags.None); break; - case ts.SyntaxKind.NamespaceExport: - addResult(ts.factory.createExportDeclaration( + case SyntaxKind.NamespaceExport: + addResult(factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamespaceExport(ts.factory.createIdentifier(localName)), - ts.factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)) - ), ts.ModifierFlags.None); + factory.createNamespaceExport(factory.createIdentifier(localName)), + factory.createStringLiteral(getSpecifierForModuleSymbol(target, context)) + ), ModifierFlags.None); break; - case ts.SyntaxKind.ImportSpecifier: - addResult(ts.factory.createImportDeclaration( + case SyntaxKind.ImportSpecifier: + addResult(factory.createImportDeclaration( /*modifiers*/ undefined, - ts.factory.createImportClause( + factory.createImportClause( /*isTypeOnly*/ false, /*importClause*/ undefined, - ts.factory.createNamedImports([ - ts.factory.createImportSpecifier( + factory.createNamedImports([ + factory.createImportSpecifier( /*isTypeOnly*/ false, - localName !== verbatimTargetName ? ts.factory.createIdentifier(verbatimTargetName) : undefined, - ts.factory.createIdentifier(localName) + localName !== verbatimTargetName ? factory.createIdentifier(verbatimTargetName) : undefined, + factory.createIdentifier(localName) ) ])), - ts.factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), + factory.createStringLiteral(getSpecifierForModuleSymbol(target.parent || target, context)), /*assertClause*/ undefined - ), ts.ModifierFlags.None); + ), ModifierFlags.None); break; - case ts.SyntaxKind.ExportSpecifier: + case SyntaxKind.ExportSpecifier: // does not use localName because the symbol name in this case refers to the name in the exports table, // which we must exactly preserve - const specifier = (node.parent.parent as ts.ExportDeclaration).moduleSpecifier; + const specifier = (node.parent.parent as ExportDeclaration).moduleSpecifier; // targetName is only used when the target is local, as otherwise the target is an alias that points at // another file serializeExportSpecifier( - ts.unescapeLeadingUnderscores(symbol.escapedName), + unescapeLeadingUnderscores(symbol.escapedName), specifier ? verbatimTargetName : targetName, - specifier && ts.isStringLiteralLike(specifier) ? ts.factory.createStringLiteral(specifier.text) : undefined + specifier && isStringLiteralLike(specifier) ? factory.createStringLiteral(specifier.text) : undefined ); break; - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.ExportAssignment: serializeMaybeAliasAssignment(symbol); break; - case ts.SyntaxKind.BinaryExpression: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.BinaryExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: // Could be best encoded as though an export specifier or as though an export assignment // If name is default or export=, do an export assignment // Otherwise do an export specifier - if (symbol.escapedName === ts.InternalSymbolName.Default || symbol.escapedName === ts.InternalSymbolName.ExportEquals) { + if (symbol.escapedName === InternalSymbolName.Default || symbol.escapedName === InternalSymbolName.ExportEquals) { serializeMaybeAliasAssignment(symbol); } else { @@ -8028,29 +8226,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } break; default: - return ts.Debug.failBadSyntaxKind(node, "Unhandled alias declaration kind in symbol serializer!"); + return Debug.failBadSyntaxKind(node, "Unhandled alias declaration kind in symbol serializer!"); } } - function serializeExportSpecifier(localName: string, targetName: string, specifier?: ts.Expression) { - addResult(ts.factory.createExportDeclaration( + function serializeExportSpecifier(localName: string, targetName: string, specifier?: Expression) { + addResult(factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createNamedExports([ts.factory.createExportSpecifier(/*isTypeOnly*/ false, localName !== targetName ? targetName : undefined, localName)]), + factory.createNamedExports([factory.createExportSpecifier(/*isTypeOnly*/ false, localName !== targetName ? targetName : undefined, localName)]), specifier - ), ts.ModifierFlags.None); + ), ModifierFlags.None); } /** * Returns `true` if an export assignment or declaration was produced for the symbol */ - function serializeMaybeAliasAssignment(symbol: ts.Symbol): boolean { - if (symbol.flags & ts.SymbolFlags.Prototype) { + function serializeMaybeAliasAssignment(symbol: Symbol): boolean { + if (symbol.flags & SymbolFlags.Prototype) { return false; } - const name = ts.unescapeLeadingUnderscores(symbol.escapedName); - const isExportEquals = name === ts.InternalSymbolName.ExportEquals; - const isDefault = name === ts.InternalSymbolName.Default; + const name = unescapeLeadingUnderscores(symbol.escapedName); + const isExportEquals = name === InternalSymbolName.ExportEquals; + const isDefault = name === InternalSymbolName.Default; const isExportAssignmentCompatibleSymbolName = isExportEquals || isDefault; // synthesize export = ref // ref should refer to either be a locally scoped symbol which we need to emit, or @@ -8059,13 +8257,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // serialize what the alias points to, preserve the declaration's initializer const target = aliasDecl && getTargetOfAliasDeclaration(aliasDecl, /*dontRecursivelyResolve*/ true); // If the target resolves and resolves to a thing defined in this file, emit as an alias, otherwise emit as a const - if (target && ts.length(target.declarations) && ts.some(target.declarations, d => ts.getSourceFileOfNode(d) === ts.getSourceFileOfNode(enclosingDeclaration))) { + if (target && length(target.declarations) && some(target.declarations, d => getSourceFileOfNode(d) === getSourceFileOfNode(enclosingDeclaration))) { // In case `target` refers to a namespace member, look at the declaration and serialize the leftmost symbol in it // eg, `namespace A { export class B {} }; exports = A.B;` // Technically, this is all that's required in the case where the assignment is an entity name expression - const expr = aliasDecl && ((ts.isExportAssignment(aliasDecl) || ts.isBinaryExpression(aliasDecl)) ? ts.getExportAssignmentExpression(aliasDecl) : ts.getPropertyAssignmentAliasLikeExpression(aliasDecl as ts.ShorthandPropertyAssignment | ts.PropertyAssignment | ts.PropertyAccessExpression)); - const first = expr && ts.isEntityNameExpression(expr) ? getFirstNonModuleExportsIdentifier(expr) : undefined; - const referenced = first && resolveEntityName(first, ts.SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, enclosingDeclaration); + const expr = aliasDecl && ((isExportAssignment(aliasDecl) || isBinaryExpression(aliasDecl)) ? getExportAssignmentExpression(aliasDecl) : getPropertyAssignmentAliasLikeExpression(aliasDecl as ShorthandPropertyAssignment | PropertyAssignment | PropertyAccessExpression)); + const first = expr && isEntityNameExpression(expr) ? getFirstNonModuleExportsIdentifier(expr) : undefined; + const referenced = first && resolveEntityName(first, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, enclosingDeclaration); if (referenced || target) { includePrivateSymbol(referenced || target); } @@ -8078,29 +8276,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const oldTrack = context.tracker.trackSymbol; context.tracker.trackSymbol = () => false; if (isExportAssignmentCompatibleSymbolName) { - results.push(ts.factory.createExportAssignment( + results.push(factory.createExportAssignment( /*modifiers*/ undefined, isExportEquals, - symbolToExpression(target, context, ts.SymbolFlags.All) + symbolToExpression(target, context, SymbolFlags.All) )); } else { if (first === expr && first) { // serialize as `export {target as name}` - serializeExportSpecifier(name, ts.idText(first)); + serializeExportSpecifier(name, idText(first)); } - else if (expr && ts.isClassExpression(expr)) { - serializeExportSpecifier(name, getInternalSymbolName(target, ts.symbolName(target))); + else if (expr && isClassExpression(expr)) { + serializeExportSpecifier(name, getInternalSymbolName(target, symbolName(target))); } else { // serialize as `import _Ref = t.arg.et; export { _Ref as name }` const varName = getUnusedName(name, symbol); - addResult(ts.factory.createImportEqualsDeclaration( + addResult(factory.createImportEqualsDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - ts.factory.createIdentifier(varName), - symbolToName(target, context, ts.SymbolFlags.All, /*expectsIdentifier*/ false) - ), ts.ModifierFlags.None); + factory.createIdentifier(varName), + symbolToName(target, context, SymbolFlags.All, /*expectsIdentifier*/ false) + ), ModifierFlags.None); serializeExportSpecifier(name, varName); } } @@ -8115,24 +8313,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const typeToSerialize = getWidenedType(getTypeOfSymbol(getMergedSymbol(symbol))); if (isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize, symbol)) { // If there are no index signatures and `typeToSerialize` is an object type, emit as a namespace instead of a const - serializeAsFunctionNamespaceMerge(typeToSerialize, symbol, varName, isExportAssignmentCompatibleSymbolName ? ts.ModifierFlags.None : ts.ModifierFlags.Export); + serializeAsFunctionNamespaceMerge(typeToSerialize, symbol, varName, isExportAssignmentCompatibleSymbolName ? ModifierFlags.None : ModifierFlags.Export); } else { - const statement = ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, typeToSerialize, symbol, enclosingDeclaration, includePrivateSymbol, bundled)) - ], ts.NodeFlags.Const)); + const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(varName, /*exclamationToken*/ undefined, serializeTypeForDeclaration(context, typeToSerialize, symbol, enclosingDeclaration, includePrivateSymbol, bundled)) + ], NodeFlags.Const)); // Inlined JSON types exported with [module.]exports= will already emit an export=, so should use `declare`. // Otherwise, the type itself should be exported. addResult(statement, - target && target.flags & ts.SymbolFlags.Property && target.escapedName === ts.InternalSymbolName.ExportEquals ? ts.ModifierFlags.Ambient - : name === varName ? ts.ModifierFlags.Export - : ts.ModifierFlags.None); + target && target.flags & SymbolFlags.Property && target.escapedName === InternalSymbolName.ExportEquals ? ModifierFlags.Ambient + : name === varName ? ModifierFlags.Export + : ModifierFlags.None); } if (isExportAssignmentCompatibleSymbolName) { - results.push(ts.factory.createExportAssignment( + results.push(factory.createExportAssignment( /*modifiers*/ undefined, isExportEquals, - ts.factory.createIdentifier(varName) + factory.createIdentifier(varName) )); return true; } @@ -8144,69 +8342,69 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize: ts.Type, hostSymbol: ts.Symbol) { + function isTypeRepresentableAsFunctionNamespaceMerge(typeToSerialize: Type, hostSymbol: Symbol) { // Only object types which are not constructable, or indexable, whose members all come from the // context source file, and whose property names are all valid identifiers and not late-bound, _and_ // whose input is not type annotated (if the input symbol has an annotation we can reuse, we should prefer it) - const ctxSrc = ts.getSourceFileOfNode(context.enclosingDeclaration); - return ts.getObjectFlags(typeToSerialize) & (ts.ObjectFlags.Anonymous | ts.ObjectFlags.Mapped) && - !ts.length(getIndexInfosOfType(typeToSerialize)) && + const ctxSrc = getSourceFileOfNode(context.enclosingDeclaration); + return getObjectFlags(typeToSerialize) & (ObjectFlags.Anonymous | ObjectFlags.Mapped) && + !length(getIndexInfosOfType(typeToSerialize)) && !isClassInstanceSide(typeToSerialize) && // While a class instance is potentially representable as a NS, prefer printing a reference to the instance type and serializing the class - !!(ts.length(ts.filter(getPropertiesOfType(typeToSerialize), isNamespaceMember)) || ts.length(getSignaturesOfType(typeToSerialize, ts.SignatureKind.Call))) && - !ts.length(getSignaturesOfType(typeToSerialize, ts.SignatureKind.Construct)) && // TODO: could probably serialize as function + ns + class, now that that's OK + !!(length(filter(getPropertiesOfType(typeToSerialize), isNamespaceMember)) || length(getSignaturesOfType(typeToSerialize, SignatureKind.Call))) && + !length(getSignaturesOfType(typeToSerialize, SignatureKind.Construct)) && // TODO: could probably serialize as function + ns + class, now that that's OK !getDeclarationWithTypeAnnotation(hostSymbol, enclosingDeclaration) && - !(typeToSerialize.symbol && ts.some(typeToSerialize.symbol.declarations, d => ts.getSourceFileOfNode(d) !== ctxSrc)) && - !ts.some(getPropertiesOfType(typeToSerialize), p => isLateBoundName(p.escapedName)) && - !ts.some(getPropertiesOfType(typeToSerialize), p => ts.some(p.declarations, d => ts.getSourceFileOfNode(d) !== ctxSrc)) && - ts.every(getPropertiesOfType(typeToSerialize), p => ts.isIdentifierText(ts.symbolName(p), languageVersion)); - } - - function makeSerializePropertySymbol(createProperty: ( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined - ) => T, methodKind: ts.SignatureDeclaration["kind"], useAccessors: true): (p: ts.Symbol, isStatic: boolean, baseType: ts.Type | undefined) => (T | ts.AccessorDeclaration | (T | ts.AccessorDeclaration)[]); - function makeSerializePropertySymbol(createProperty: ( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined - ) => T, methodKind: ts.SignatureDeclaration["kind"], useAccessors: false): (p: ts.Symbol, isStatic: boolean, baseType: ts.Type | undefined) => (T | T[]); - function makeSerializePropertySymbol(createProperty: ( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined - ) => T, methodKind: ts.SignatureDeclaration["kind"], useAccessors: boolean): (p: ts.Symbol, isStatic: boolean, baseType: ts.Type | undefined) => (T | ts.AccessorDeclaration | (T | ts.AccessorDeclaration)[]) { - return function serializePropertySymbol(p: ts.Symbol, isStatic: boolean, baseType: ts.Type | undefined): (T | ts.AccessorDeclaration | (T | ts.AccessorDeclaration)[]) { - const modifierFlags = ts.getDeclarationModifierFlagsFromSymbol(p); - const isPrivate = !!(modifierFlags & ts.ModifierFlags.Private); - if (isStatic && (p.flags & (ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias))) { + !(typeToSerialize.symbol && some(typeToSerialize.symbol.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) && + !some(getPropertiesOfType(typeToSerialize), p => isLateBoundName(p.escapedName)) && + !some(getPropertiesOfType(typeToSerialize), p => some(p.declarations, d => getSourceFileOfNode(d) !== ctxSrc)) && + every(getPropertiesOfType(typeToSerialize), p => isIdentifierText(symbolName(p), languageVersion)); + } + + function makeSerializePropertySymbol(createProperty: ( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: true): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]); + function makeSerializePropertySymbol(createProperty: ( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: false): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]); + function makeSerializePropertySymbol(createProperty: ( + modifiers: readonly Modifier[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ) => T, methodKind: SignatureDeclaration["kind"], useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) { + return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined): (T | AccessorDeclaration | (T | AccessorDeclaration)[]) { + const modifierFlags = getDeclarationModifierFlagsFromSymbol(p); + const isPrivate = !!(modifierFlags & ModifierFlags.Private); + if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) { // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols // need to be merged namespace members return []; } - if (p.flags & ts.SymbolFlags.Prototype || + if (p.flags & SymbolFlags.Prototype || (baseType && getPropertyOfType(baseType, p.escapedName) && isReadonlySymbol(getPropertyOfType(baseType, p.escapedName)!) === isReadonlySymbol(p) - && (p.flags & ts.SymbolFlags.Optional) === (getPropertyOfType(baseType, p.escapedName)!.flags & ts.SymbolFlags.Optional) + && (p.flags & SymbolFlags.Optional) === (getPropertyOfType(baseType, p.escapedName)!.flags & SymbolFlags.Optional) && isTypeIdenticalTo(getTypeOfSymbol(p), getTypeOfPropertyOfType(baseType, p.escapedName)!))) { return []; } - const flag = (modifierFlags & ~ts.ModifierFlags.Async) | (isStatic ? ts.ModifierFlags.Static : 0); + const flag = (modifierFlags & ~ModifierFlags.Async) | (isStatic ? ModifierFlags.Static : 0); const name = getPropertyNameNodeForSymbol(p, context); - const firstPropertyLikeDecl = p.declarations?.find(ts.or(ts.isPropertyDeclaration, ts.isAccessor, ts.isVariableDeclaration, ts.isPropertySignature, ts.isBinaryExpression, ts.isPropertyAccessExpression)); - if (p.flags & ts.SymbolFlags.Accessor && useAccessors) { - const result: ts.AccessorDeclaration[] = []; - if (p.flags & ts.SymbolFlags.SetAccessor) { - result.push(ts.setTextRange(ts.factory.createSetAccessorDeclaration( - ts.factory.createModifiersFromModifierFlags(flag), + const firstPropertyLikeDecl = p.declarations?.find(or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression)); + if (p.flags & SymbolFlags.Accessor && useAccessors) { + const result: AccessorDeclaration[] = []; + if (p.flags & SymbolFlags.SetAccessor) { + result.push(setTextRange(factory.createSetAccessorDeclaration( + factory.createModifiersFromModifierFlags(flag), name, - [ts.factory.createParameterDeclaration( + [factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "arg", @@ -8214,44 +8412,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled) )], /*body*/ undefined - ), p.declarations?.find(ts.isSetAccessor) || firstPropertyLikeDecl)); + ), p.declarations?.find(isSetAccessor) || firstPropertyLikeDecl)); } - if (p.flags & ts.SymbolFlags.GetAccessor) { - const isPrivate = modifierFlags & ts.ModifierFlags.Private; - result.push(ts.setTextRange(ts.factory.createGetAccessorDeclaration( - ts.factory.createModifiersFromModifierFlags(flag), + if (p.flags & SymbolFlags.GetAccessor) { + const isPrivate = modifierFlags & ModifierFlags.Private; + result.push(setTextRange(factory.createGetAccessorDeclaration( + factory.createModifiersFromModifierFlags(flag), name, [], isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), /*body*/ undefined - ), p.declarations?.find(ts.isGetAccessor) || firstPropertyLikeDecl)); + ), p.declarations?.find(isGetAccessor) || firstPropertyLikeDecl)); } return result; } // This is an else/if as accessors and properties can't merge in TS, but might in JS // If this happens, we assume the accessor takes priority, as it imposes more constraints - else if (p.flags & (ts.SymbolFlags.Property | ts.SymbolFlags.Variable | ts.SymbolFlags.Accessor)) { - return ts.setTextRange(createProperty( - ts.factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ts.ModifierFlags.Readonly : 0) | flag), + else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) { + return setTextRange(createProperty( + factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), name, - p.flags & ts.SymbolFlags.Optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, + p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, isPrivate ? undefined : serializeTypeForDeclaration(context, getWriteTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled), // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357 // interface members can't have initializers, however class members _can_ /*initializer*/ undefined - ), p.declarations?.find(ts.or(ts.isPropertyDeclaration, ts.isVariableDeclaration)) || firstPropertyLikeDecl); + ), p.declarations?.find(or(isPropertyDeclaration, isVariableDeclaration)) || firstPropertyLikeDecl); } - if (p.flags & (ts.SymbolFlags.Method | ts.SymbolFlags.Function)) { + if (p.flags & (SymbolFlags.Method | SymbolFlags.Function)) { const type = getTypeOfSymbol(p); - const signatures = getSignaturesOfType(type, ts.SignatureKind.Call); - if (flag & ts.ModifierFlags.Private) { - return ts.setTextRange(createProperty( - ts.factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ts.ModifierFlags.Readonly : 0) | flag), + const signatures = getSignaturesOfType(type, SignatureKind.Call); + if (flag & ModifierFlags.Private) { + return setTextRange(createProperty( + factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), name, - p.flags & ts.SymbolFlags.Optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, + p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, /*type*/ undefined, /*initializer*/ undefined - ), p.declarations?.find(ts.isFunctionLikeDeclaration) || signatures[0] && signatures[0].declaration || p.declarations && p.declarations[0]); + ), p.declarations?.find(isFunctionLikeDeclaration) || signatures[0] && signatures[0].declaration || p.declarations && p.declarations[0]); } const results = []; @@ -8263,34 +8461,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { context, { name, - questionToken: p.flags & ts.SymbolFlags.Optional ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, - modifiers: flag ? ts.factory.createModifiersFromModifierFlags(flag) : undefined + questionToken: p.flags & SymbolFlags.Optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined, + modifiers: flag ? factory.createModifiersFromModifierFlags(flag) : undefined } ); - const location = sig.declaration && ts.isPrototypePropertyAssignment(sig.declaration.parent) ? sig.declaration.parent : sig.declaration; - results.push(ts.setTextRange(decl, location)); + const location = sig.declaration && isPrototypePropertyAssignment(sig.declaration.parent) ? sig.declaration.parent : sig.declaration; + results.push(setTextRange(decl, location)); } return results as unknown as T[]; } // The `Constructor`'s symbol isn't in the class's properties lists, obviously, since it's a signature on the static - return ts.Debug.fail(`Unhandled class member kind! ${(p as any).__debugFlags || p.flags}`); + return Debug.fail(`Unhandled class member kind! ${(p as any).__debugFlags || p.flags}`); }; } - function serializePropertySymbolForInterface(p: ts.Symbol, baseType: ts.Type | undefined) { + function serializePropertySymbolForInterface(p: Symbol, baseType: Type | undefined) { return serializePropertySymbolForInterfaceWorker(p, /*isStatic*/ false, baseType); } - function serializeSignatures(kind: ts.SignatureKind, input: ts.Type, baseType: ts.Type | undefined, outputKind: ts.SignatureDeclaration["kind"]) { + function serializeSignatures(kind: SignatureKind, input: Type, baseType: Type | undefined, outputKind: SignatureDeclaration["kind"]) { const signatures = getSignaturesOfType(input, kind); - if (kind === ts.SignatureKind.Construct) { - if (!baseType && ts.every(signatures, s => ts.length(s.parameters) === 0)) { + if (kind === SignatureKind.Construct) { + if (!baseType && every(signatures, s => length(s.parameters) === 0)) { return []; // No base type, every constructor is empty - elide the extraneous `constructor()` } if (baseType) { // If there is a base type, if every signature in the class is identical to a signature in the baseType, elide all the declarations - const baseSigs = getSignaturesOfType(baseType, ts.SignatureKind.Construct); - if (!ts.length(baseSigs) && ts.every(signatures, s => ts.length(s.parameters) === 0)) { + const baseSigs = getSignaturesOfType(baseType, SignatureKind.Construct); + if (!length(baseSigs) && every(signatures, s => length(s.parameters) === 0)) { return []; // Base had no explicit signatures, if all our signatures are also implicit, return an empty list } if (baseSigs.length === signatures.length) { @@ -8306,15 +8504,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - let privateProtected: ts.ModifierFlags = 0; + let privateProtected: ModifierFlags = 0; for (const s of signatures) { if (s.declaration) { - privateProtected |= ts.getSelectedEffectiveModifierFlags(s.declaration, ts.ModifierFlags.Private | ts.ModifierFlags.Protected); + privateProtected |= getSelectedEffectiveModifierFlags(s.declaration, ModifierFlags.Private | ModifierFlags.Protected); } } if (privateProtected) { - return [ts.setTextRange(ts.factory.createConstructorDeclaration( - ts.factory.createModifiersFromModifierFlags(privateProtected), + return [setTextRange(factory.createConstructorDeclaration( + factory.createModifiersFromModifierFlags(privateProtected), /*parameters*/ [], /*body*/ undefined, ), signatures[0].declaration)]; @@ -8325,13 +8523,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (const sig of signatures) { // Each overload becomes a separate constructor declaration, in order const decl = signatureToSignatureDeclarationHelper(sig, outputKind, context); - results.push(ts.setTextRange(decl, sig.declaration)); + results.push(setTextRange(decl, sig.declaration)); } return results; } - function serializeIndexSignatures(input: ts.Type, baseType: ts.Type | undefined) { - const results: ts.IndexSignatureDeclaration[] = []; + function serializeIndexSignatures(input: Type, baseType: Type | undefined) { + const results: IndexSignatureDeclaration[] = []; for (const info of getIndexInfosOfType(input)) { if (baseType) { const baseInfo = getIndexInfoOfType(baseType, info.keyType); @@ -8346,48 +8544,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return results; } - function serializeBaseType(t: ts.Type, staticType: ts.Type, rootName: string) { - const ref = trySerializeAsTypeReference(t, ts.SymbolFlags.Value); + function serializeBaseType(t: Type, staticType: Type, rootName: string) { + const ref = trySerializeAsTypeReference(t, SymbolFlags.Value); if (ref) { return ref; } const tempName = getUnusedName(`${rootName}_base`); - const statement = ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ - ts.factory.createVariableDeclaration(tempName, /*exclamationToken*/ undefined, typeToTypeNodeHelper(staticType, context)) - ], ts.NodeFlags.Const)); - addResult(statement, ts.ModifierFlags.None); - return ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier(tempName), /*typeArgs*/ undefined); + const statement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ + factory.createVariableDeclaration(tempName, /*exclamationToken*/ undefined, typeToTypeNodeHelper(staticType, context)) + ], NodeFlags.Const)); + addResult(statement, ModifierFlags.None); + return factory.createExpressionWithTypeArguments(factory.createIdentifier(tempName), /*typeArgs*/ undefined); } - function trySerializeAsTypeReference(t: ts.Type, flags: ts.SymbolFlags) { - let typeArgs: ts.TypeNode[] | undefined; - let reference: ts.Expression | undefined; + function trySerializeAsTypeReference(t: Type, flags: SymbolFlags) { + let typeArgs: TypeNode[] | undefined; + let reference: Expression | undefined; // We don't use `isValueSymbolAccessible` below. since that considers alternative containers (like modules) // which we can't write out in a syntactically valid way as an expression - if ((t as ts.TypeReference).target && isSymbolAccessibleByFlags((t as ts.TypeReference).target.symbol, enclosingDeclaration, flags)) { - typeArgs = ts.map(getTypeArguments(t as ts.TypeReference), t => typeToTypeNodeHelper(t, context)); - reference = symbolToExpression((t as ts.TypeReference).target.symbol, context, ts.SymbolFlags.Type); + if ((t as TypeReference).target && isSymbolAccessibleByFlags((t as TypeReference).target.symbol, enclosingDeclaration, flags)) { + typeArgs = map(getTypeArguments(t as TypeReference), t => typeToTypeNodeHelper(t, context)); + reference = symbolToExpression((t as TypeReference).target.symbol, context, SymbolFlags.Type); } else if (t.symbol && isSymbolAccessibleByFlags(t.symbol, enclosingDeclaration, flags)) { - reference = symbolToExpression(t.symbol, context, ts.SymbolFlags.Type); + reference = symbolToExpression(t.symbol, context, SymbolFlags.Type); } if (reference) { - return ts.factory.createExpressionWithTypeArguments(reference, typeArgs); + return factory.createExpressionWithTypeArguments(reference, typeArgs); } } - function serializeImplementedType(t: ts.Type) { - const ref = trySerializeAsTypeReference(t, ts.SymbolFlags.Type); + function serializeImplementedType(t: Type) { + const ref = trySerializeAsTypeReference(t, SymbolFlags.Type); if (ref) { return ref; } if (t.symbol) { - return ts.factory.createExpressionWithTypeArguments(symbolToExpression(t.symbol, context, ts.SymbolFlags.Type), /*typeArgs*/ undefined); + return factory.createExpressionWithTypeArguments(symbolToExpression(t.symbol, context, SymbolFlags.Type), /*typeArgs*/ undefined); } } - function getUnusedName(input: string, symbol?: ts.Symbol): string { + function getUnusedName(input: string, symbol?: Symbol): string { const id = symbol ? getSymbolId(symbol) : undefined; if (id) { if (context.remappedSymbolNames!.has(id)) { @@ -8410,25 +8608,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return input; } - function getNameCandidateWorker(symbol: ts.Symbol, localName: string) { - if (localName === ts.InternalSymbolName.Default || localName === ts.InternalSymbolName.Class || localName === ts.InternalSymbolName.Function) { + function getNameCandidateWorker(symbol: Symbol, localName: string) { + if (localName === InternalSymbolName.Default || localName === InternalSymbolName.Class || localName === InternalSymbolName.Function) { const flags = context.flags; - context.flags |= ts.NodeBuilderFlags.InInitialEntityName; + context.flags |= NodeBuilderFlags.InInitialEntityName; const nameCandidate = getNameOfSymbolAsWritten(symbol, context); context.flags = flags; - localName = nameCandidate.length > 0 && ts.isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? ts.stripQuotes(nameCandidate) : nameCandidate; + localName = nameCandidate.length > 0 && isSingleOrDoubleQuote(nameCandidate.charCodeAt(0)) ? stripQuotes(nameCandidate) : nameCandidate; } - if (localName === ts.InternalSymbolName.Default) { + if (localName === InternalSymbolName.Default) { localName = "_default"; } - else if (localName === ts.InternalSymbolName.ExportEquals) { + else if (localName === InternalSymbolName.ExportEquals) { localName = "_exports"; } - localName = ts.isIdentifierText(localName, languageVersion) && !ts.isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_"); + localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_"); return localName; } - function getInternalSymbolName(symbol: ts.Symbol, localName: string) { + function getInternalSymbolName(symbol: Symbol, localName: string) { const id = getSymbolId(symbol); if (context.remappedSymbolNames!.has(id)) { return context.remappedSymbolNames!.get(id)!; @@ -8441,34 +8639,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function typePredicateToString(typePredicate: ts.TypePredicate, enclosingDeclaration?: ts.Node, flags: ts.TypeFormatFlags = ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer?: ts.EmitTextWriter): string { - return writer ? typePredicateToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(typePredicateToStringWorker); + function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer?: EmitTextWriter): string { + return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker); - function typePredicateToStringWorker(writer: ts.EmitTextWriter) { - const predicate = ts.factory.createTypePredicateNode( - typePredicate.kind === ts.TypePredicateKind.AssertsThis || typePredicate.kind === ts.TypePredicateKind.AssertsIdentifier ? ts.factory.createToken(ts.SyntaxKind.AssertsKeyword) : undefined, - typePredicate.kind === ts.TypePredicateKind.Identifier || typePredicate.kind === ts.TypePredicateKind.AssertsIdentifier ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), - typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217 + function typePredicateToStringWorker(writer: EmitTextWriter) { + const predicate = factory.createTypePredicateNode( + typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createToken(SyntaxKind.AssertsKeyword) : undefined, + typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(), + typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217 ); - const printer = ts.createPrinter({ removeComments: true }); - const sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); - printer.writeNode(ts.EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer); + const printer = createPrinter({ removeComments: true }); + const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); + printer.writeNode(EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer); return writer; } } - function formatUnionTypes(types: readonly ts.Type[]): ts.Type[] { - const result: ts.Type[] = []; - let flags: ts.TypeFlags = 0; + function formatUnionTypes(types: readonly Type[]): Type[] { + const result: Type[] = []; + let flags: TypeFlags = 0; for (let i = 0; i < types.length; i++) { const t = types[i]; flags |= t.flags; - if (!(t.flags & ts.TypeFlags.Nullable)) { - if (t.flags & (ts.TypeFlags.BooleanLiteral | ts.TypeFlags.EnumLiteral)) { - const baseType = t.flags & ts.TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t as ts.LiteralType); - if (baseType.flags & ts.TypeFlags.Union) { - const count = (baseType as ts.UnionType).types.length; - if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as ts.UnionType).types[count - 1])) { + if (!(t.flags & TypeFlags.Nullable)) { + if (t.flags & (TypeFlags.BooleanLiteral | TypeFlags.EnumLiteral)) { + const baseType = t.flags & TypeFlags.BooleanLiteral ? booleanType : getBaseTypeOfEnumLiteralType(t as LiteralType); + if (baseType.flags & TypeFlags.Union) { + const count = (baseType as UnionType).types.length; + if (i + count <= types.length && getRegularTypeOfLiteralType(types[i + count - 1]) === getRegularTypeOfLiteralType((baseType as UnionType).types[count - 1])) { result.push(baseType); i += count - 1; continue; @@ -8478,78 +8676,78 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result.push(t); } } - if (flags & ts.TypeFlags.Null) result.push(nullType); - if (flags & ts.TypeFlags.Undefined) result.push(undefinedType); + if (flags & TypeFlags.Null) result.push(nullType); + if (flags & TypeFlags.Undefined) result.push(undefinedType); return result || types; } - function visibilityToString(flags: ts.ModifierFlags): string | undefined { - if (flags === ts.ModifierFlags.Private) { + function visibilityToString(flags: ModifierFlags): string | undefined { + if (flags === ModifierFlags.Private) { return "private"; } - if (flags === ts.ModifierFlags.Protected) { + if (flags === ModifierFlags.Protected) { return "protected"; } return "public"; } - function getTypeAliasForTypeLiteral(type: ts.Type): ts.Symbol | undefined { - if (type.symbol && type.symbol.flags & ts.SymbolFlags.TypeLiteral && type.symbol.declarations) { - const node = ts.walkUpParenthesizedTypes(type.symbol.declarations[0].parent); - if (node.kind === ts.SyntaxKind.TypeAliasDeclaration) { + function getTypeAliasForTypeLiteral(type: Type): Symbol | undefined { + if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && type.symbol.declarations) { + const node = walkUpParenthesizedTypes(type.symbol.declarations[0].parent); + if (node.kind === SyntaxKind.TypeAliasDeclaration) { return getSymbolOfNode(node); } } return undefined; } - function isTopLevelInExternalModuleAugmentation(node: ts.Node): boolean { + function isTopLevelInExternalModuleAugmentation(node: Node): boolean { return node && node.parent && - node.parent.kind === ts.SyntaxKind.ModuleBlock && - ts.isExternalModuleAugmentation(node.parent.parent); + node.parent.kind === SyntaxKind.ModuleBlock && + isExternalModuleAugmentation(node.parent.parent); } interface NodeBuilderContext { - enclosingDeclaration: ts.Node | undefined; - flags: ts.NodeBuilderFlags; - tracker: ts.SymbolTracker; + enclosingDeclaration: Node | undefined; + flags: NodeBuilderFlags; + tracker: SymbolTracker; // State encounteredError: boolean; reportedDiagnostic: boolean; - visitedTypes: ts.Set | undefined; - symbolDepth: ts.ESMap | undefined; - inferTypeParameters: ts.TypeParameter[] | undefined; + visitedTypes: Set | undefined; + symbolDepth: ESMap | undefined; + inferTypeParameters: TypeParameter[] | undefined; approximateLength: number; truncating?: boolean; - typeParameterSymbolList?: ts.Set; - typeParameterNames?: ts.ESMap; - typeParameterNamesByText?: ts.Set; - typeParameterNamesByTextNextNameCount?: ts.ESMap; - usedSymbolNames?: ts.Set; - remappedSymbolNames?: ts.ESMap; - reverseMappedStack?: ts.ReverseMappedSymbol[]; + typeParameterSymbolList?: Set; + typeParameterNames?: ESMap; + typeParameterNamesByText?: Set; + typeParameterNamesByTextNextNameCount?: ESMap; + usedSymbolNames?: Set; + remappedSymbolNames?: ESMap; + reverseMappedStack?: ReverseMappedSymbol[]; } - function isDefaultBindingContext(location: ts.Node) { - return location.kind === ts.SyntaxKind.SourceFile || ts.isAmbientModule(location); + function isDefaultBindingContext(location: Node) { + return location.kind === SyntaxKind.SourceFile || isAmbientModule(location); } - function getNameOfSymbolFromNameType(symbol: ts.Symbol, context?: NodeBuilderContext) { + function getNameOfSymbolFromNameType(symbol: Symbol, context?: NodeBuilderContext) { const nameType = getSymbolLinks(symbol).nameType; if (nameType) { - if (nameType.flags & ts.TypeFlags.StringOrNumberLiteral) { - const name = "" + (nameType as ts.StringLiteralType | ts.NumberLiteralType).value; - if (!ts.isIdentifierText(name, ts.getEmitScriptTarget(compilerOptions)) && !ts.isNumericLiteralName(name)) { - return `"${ts.escapeString(name, ts.CharacterCodes.doubleQuote)}"`; + if (nameType.flags & TypeFlags.StringOrNumberLiteral) { + const name = "" + (nameType as StringLiteralType | NumberLiteralType).value; + if (!isIdentifierText(name, getEmitScriptTarget(compilerOptions)) && !isNumericLiteralName(name)) { + return `"${escapeString(name, CharacterCodes.doubleQuote)}"`; } - if (ts.isNumericLiteralName(name) && ts.startsWith(name, "-")) { + if (isNumericLiteralName(name) && startsWith(name, "-")) { return `[${name}]`; } return name; } - if (nameType.flags & ts.TypeFlags.UniqueESSymbol) { - return `[${getNameOfSymbolAsWritten((nameType as ts.UniqueESSymbolType).symbol, context)}]`; + if (nameType.flags & TypeFlags.UniqueESSymbol) { + return `[${getNameOfSymbolAsWritten((nameType as UniqueESSymbolType).symbol, context)}]`; } } } @@ -8561,26 +8759,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Unlike `symbolName(symbol)`, this will include quotes if the name is from a string literal. * It will also use a representation of a number as written instead of a decimal form, e.g. `0o11` instead of `9`. */ - function getNameOfSymbolAsWritten(symbol: ts.Symbol, context?: NodeBuilderContext): string { - if (context && symbol.escapedName === ts.InternalSymbolName.Default && !(context.flags & ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && + function getNameOfSymbolAsWritten(symbol: Symbol, context?: NodeBuilderContext): string { + if (context && symbol.escapedName === InternalSymbolName.Default && !(context.flags & NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope) && // If it's not the first part of an entity name, it must print as `default` - (!(context.flags & ts.NodeBuilderFlags.InInitialEntityName) || + (!(context.flags & NodeBuilderFlags.InInitialEntityName) || // if the symbol is synthesized, it will only be referenced externally it must print as `default` !symbol.declarations || // if not in the same binding context (source file, module declaration), it must print as `default` - (context.enclosingDeclaration && ts.findAncestor(symbol.declarations[0], isDefaultBindingContext) !== ts.findAncestor(context.enclosingDeclaration, isDefaultBindingContext)))) { + (context.enclosingDeclaration && findAncestor(symbol.declarations[0], isDefaultBindingContext) !== findAncestor(context.enclosingDeclaration, isDefaultBindingContext)))) { return "default"; } if (symbol.declarations && symbol.declarations.length) { - let declaration = ts.firstDefined(symbol.declarations, d => ts.getNameOfDeclaration(d) ? d : undefined); // Try using a declaration with a name, first - const name = declaration && ts.getNameOfDeclaration(declaration); + let declaration = firstDefined(symbol.declarations, d => getNameOfDeclaration(d) ? d : undefined); // Try using a declaration with a name, first + const name = declaration && getNameOfDeclaration(declaration); if (declaration && name) { - if (ts.isCallExpression(declaration) && ts.isBindableObjectDefinePropertyCall(declaration)) { - return ts.symbolName(symbol); + if (isCallExpression(declaration) && isBindableObjectDefinePropertyCall(declaration)) { + return symbolName(symbol); } - if (ts.isComputedPropertyName(name) && !(ts.getCheckFlags(symbol) & ts.CheckFlags.Late)) { + if (isComputedPropertyName(name) && !(getCheckFlags(symbol) & CheckFlags.Late)) { const nameType = getSymbolLinks(symbol).nameType; - if (nameType && nameType.flags & ts.TypeFlags.StringOrNumberLiteral) { + if (nameType && nameType.flags & TypeFlags.StringOrNumberLiteral) { // Computed property name isn't late bound, but has a well-known name type - use name type to generate a symbol name const result = getNameOfSymbolFromNameType(symbol, context); if (result !== undefined) { @@ -8588,29 +8786,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return ts.declarationNameToString(name); + return declarationNameToString(name); } if (!declaration) { declaration = symbol.declarations[0]; // Declaration may be nameless, but we'll try anyway } - if (declaration.parent && declaration.parent.kind === ts.SyntaxKind.VariableDeclaration) { - return ts.declarationNameToString((declaration.parent as ts.VariableDeclaration).name); + if (declaration.parent && declaration.parent.kind === SyntaxKind.VariableDeclaration) { + return declarationNameToString((declaration.parent as VariableDeclaration).name); } switch (declaration.kind) { - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - if (context && !context.encounteredError && !(context.flags & ts.NodeBuilderFlags.AllowAnonymousIdentifier)) { + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + if (context && !context.encounteredError && !(context.flags & NodeBuilderFlags.AllowAnonymousIdentifier)) { context.encounteredError = true; } - return declaration.kind === ts.SyntaxKind.ClassExpression ? "(Anonymous class)" : "(Anonymous function)"; + return declaration.kind === SyntaxKind.ClassExpression ? "(Anonymous class)" : "(Anonymous function)"; } } const name = getNameOfSymbolFromNameType(symbol, context); - return name !== undefined ? name : ts.symbolName(symbol); + return name !== undefined ? name : symbolName(symbol); } - function isDeclarationVisible(node: ts.Node): boolean { + function isDeclarationVisible(node: Node): boolean { if (node) { const links = getNodeLinks(node); if (links.isVisible === undefined) { @@ -8623,90 +8821,90 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function determineIfDeclarationIsVisible() { switch (node.kind) { - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocEnumTag: // Top-level jsdoc type aliases are considered exported // First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file - return !!(node.parent && node.parent.parent && node.parent.parent.parent && ts.isSourceFile(node.parent.parent.parent)); - case ts.SyntaxKind.BindingElement: + return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent)); + case SyntaxKind.BindingElement: return isDeclarationVisible(node.parent.parent); - case ts.SyntaxKind.VariableDeclaration: - if (ts.isBindingPattern((node as ts.VariableDeclaration).name) && - !((node as ts.VariableDeclaration).name as ts.BindingPattern).elements.length) { + case SyntaxKind.VariableDeclaration: + if (isBindingPattern((node as VariableDeclaration).name) && + !((node as VariableDeclaration).name as BindingPattern).elements.length) { // If the binding pattern is empty, this variable declaration is not visible return false; } // falls through - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ImportEqualsDeclaration: // external module augmentation is always visible - if (ts.isExternalModuleAugmentation(node)) { + if (isExternalModuleAugmentation(node)) { return true; } const parent = getDeclarationContainer(node); // If the node is not exported or it is not ambient module element (except import declaration) - if (!(ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export) && - !(node.kind !== ts.SyntaxKind.ImportEqualsDeclaration && parent.kind !== ts.SyntaxKind.SourceFile && parent.flags & ts.NodeFlags.Ambient)) { + if (!(getCombinedModifierFlags(node as Declaration) & ModifierFlags.Export) && + !(node.kind !== SyntaxKind.ImportEqualsDeclaration && parent.kind !== SyntaxKind.SourceFile && parent.flags & NodeFlags.Ambient)) { return isGlobalSourceFile(parent); } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible return isDeclarationVisible(parent); - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - if (ts.hasEffectiveModifier(node, ts.ModifierFlags.Private | ts.ModifierFlags.Protected)) { + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + if (hasEffectiveModifier(node, ModifierFlags.Private | ModifierFlags.Protected)) { // Private/protected properties/methods are not visible return false; } // Public properties/methods are visible if its parents are visible, so: // falls through - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.TypeReference: - case ts.SyntaxKind.ArrayType: - case ts.SyntaxKind.TupleType: - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.NamedTupleMember: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.Parameter: + case SyntaxKind.ModuleBlock: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeLiteral: + case SyntaxKind.TypeReference: + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.NamedTupleMember: return isDeclarationVisible(node.parent); // Default binding, import specifier and namespace import is visible // only on demand so by default it is not visible - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportSpecifier: return false; // Type parameters are always visible - case ts.SyntaxKind.TypeParameter: + case SyntaxKind.TypeParameter: // Source file and namespace export are always visible // falls through - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.SourceFile: + case SyntaxKind.NamespaceExportDeclaration: return true; // Export assignments do not create name bindings outside the module - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.ExportAssignment: return false; default: @@ -8715,42 +8913,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function collectLinkedAliases(node: ts.Identifier, setVisibility?: boolean): ts.Node[] | undefined { - let exportSymbol: ts.Symbol | undefined; - if (node.parent && node.parent.kind === ts.SyntaxKind.ExportAssignment) { - exportSymbol = resolveName(node, node.escapedText, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); + function collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined { + let exportSymbol: Symbol | undefined; + if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) { + exportSymbol = resolveName(node, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); } - else if (node.parent.kind === ts.SyntaxKind.ExportSpecifier) { - exportSymbol = getTargetOfExportSpecifier(node.parent as ts.ExportSpecifier, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias); + else if (node.parent.kind === SyntaxKind.ExportSpecifier) { + exportSymbol = getTargetOfExportSpecifier(node.parent as ExportSpecifier, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } - let result: ts.Node[] | undefined; - let visited: ts.Set | undefined; + let result: Node[] | undefined; + let visited: Set | undefined; if (exportSymbol) { - visited = new ts.Set(); + visited = new Set(); visited.add(getSymbolId(exportSymbol)); buildVisibleNodeList(exportSymbol.declarations); } return result; - function buildVisibleNodeList(declarations: ts.Declaration[] | undefined) { - ts.forEach(declarations, declaration => { + function buildVisibleNodeList(declarations: Declaration[] | undefined) { + forEach(declarations, declaration => { const resultNode = getAnyImportSyntax(declaration) || declaration; if (setVisibility) { getNodeLinks(declaration).isVisible = true; } else { result = result || []; - ts.pushIfUnique(result, resultNode); + pushIfUnique(result, resultNode); } - if (ts.isInternalModuleImportEqualsDeclaration(declaration)) { + if (isInternalModuleImportEqualsDeclaration(declaration)) { // Add the referenced top container visible - const internalModuleReference = declaration.moduleReference as ts.Identifier | ts.QualifiedName; - const firstIdentifier = ts.getFirstIdentifier(internalModuleReference); - const importSymbol = resolveName(declaration, firstIdentifier.escapedText, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace, + const internalModuleReference = declaration.moduleReference as Identifier | QualifiedName; + const firstIdentifier = getFirstIdentifier(internalModuleReference); + const importSymbol = resolveName(declaration, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace, undefined, undefined, /*isUse*/ false); if (importSymbol && visited) { - if (ts.tryAddToSet(visited, getSymbolId(importSymbol))) { + if (tryAddToSet(visited, getSymbolId(importSymbol))) { buildVisibleNodeList(importSymbol.declarations); } } @@ -8801,25 +8999,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean { switch (propertyName) { case TypeSystemPropertyName.Type: - return !!getSymbolLinks(target as ts.Symbol).type; + return !!getSymbolLinks(target as Symbol).type; case TypeSystemPropertyName.EnumTagType: - return !!(getNodeLinks(target as ts.JSDocEnumTag).resolvedEnumType); + return !!(getNodeLinks(target as JSDocEnumTag).resolvedEnumType); case TypeSystemPropertyName.DeclaredType: - return !!getSymbolLinks(target as ts.Symbol).declaredType; + return !!getSymbolLinks(target as Symbol).declaredType; case TypeSystemPropertyName.ResolvedBaseConstructorType: - return !!(target as ts.InterfaceType).resolvedBaseConstructorType; + return !!(target as InterfaceType).resolvedBaseConstructorType; case TypeSystemPropertyName.ResolvedReturnType: - return !!(target as ts.Signature).resolvedReturnType; + return !!(target as Signature).resolvedReturnType; case TypeSystemPropertyName.ImmediateBaseConstraint: - return !!(target as ts.Type).immediateBaseConstraint; + return !!(target as Type).immediateBaseConstraint; case TypeSystemPropertyName.ResolvedTypeArguments: - return !!(target as ts.TypeReference).resolvedTypeArguments; + return !!(target as TypeReference).resolvedTypeArguments; case TypeSystemPropertyName.ResolvedBaseTypes: - return !!(target as ts.InterfaceType).baseTypesResolved; + return !!(target as InterfaceType).baseTypesResolved; case TypeSystemPropertyName.WriteType: - return !!getSymbolLinks(target as ts.Symbol).writeType; + return !!getSymbolLinks(target as Symbol).writeType; } - return ts.Debug.assertNever(propertyName); + return Debug.assertNever(propertyName); } /** @@ -8832,15 +9030,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolutionResults.pop()!; } - function getDeclarationContainer(node: ts.Node): ts.Node { - return ts.findAncestor(ts.getRootDeclaration(node), node => { + function getDeclarationContainer(node: Node): Node { + return findAncestor(getRootDeclaration(node), node => { switch (node.kind) { - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.VariableDeclarationList: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.ImportClause: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableDeclarationList: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.NamedImports: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportClause: return false; default: return true; @@ -8848,38 +9046,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { })!.parent; } - function getTypeOfPrototypeProperty(prototype: ts.Symbol): ts.Type { + function getTypeOfPrototypeProperty(prototype: Symbol): Type { // TypeScript 1.0 spec (April 2014): 8.4 // Every class automatically contains a static property member named 'prototype', // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. // It is an error to explicitly declare a static property member with the name 'prototype'. - const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)!) as ts.InterfaceType; - return classType.typeParameters ? createTypeReference(classType as ts.GenericType, ts.map(classType.typeParameters, _ => anyType)) : classType; + const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)!) as InterfaceType; + return classType.typeParameters ? createTypeReference(classType as GenericType, map(classType.typeParameters, _ => anyType)) : classType; } // Return the type of the given property in the given type, or undefined if no such property exists - function getTypeOfPropertyOfType(type: ts.Type, name: ts.__String): ts.Type | undefined { + function getTypeOfPropertyOfType(type: Type, name: __String): Type | undefined { const prop = getPropertyOfType(type, name); return prop ? getTypeOfSymbol(prop) : undefined; } - function getTypeOfPropertyOrIndexSignature(type: ts.Type, name: ts.__String): ts.Type { + function getTypeOfPropertyOrIndexSignature(type: Type, name: __String): Type { return getTypeOfPropertyOfType(type, name) || getApplicableIndexInfoForName(type, name)?.type || unknownType; } - function isTypeAny(type: ts.Type | undefined) { - return type && (type.flags & ts.TypeFlags.Any) !== 0; + function isTypeAny(type: Type | undefined) { + return type && (type.flags & TypeFlags.Any) !== 0; } - function isErrorType(type: ts.Type) { + function isErrorType(type: Type) { // The only 'any' types that have alias symbols are those manufactured by getTypeFromTypeAliasReference for // a reference to an unresolved symbol. We want those to behave like the errorType. - return type === errorType || !!(type.flags & ts.TypeFlags.Any && type.aliasSymbol); + return type === errorType || !!(type.flags & TypeFlags.Any && type.aliasSymbol); } // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been // assigned by contextual typing. - function getTypeForBindingElementParent(node: ts.BindingElementGrandparent, checkMode: CheckMode) { + function getTypeForBindingElementParent(node: BindingElementGrandparent, checkMode: CheckMode) { if (checkMode !== CheckMode.Normal) { return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } @@ -8887,24 +9085,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } - function getRestType(source: ts.Type, properties: ts.PropertyName[], symbol: ts.Symbol | undefined): ts.Type { - source = filterType(source, t => !(t.flags & ts.TypeFlags.Nullable)); - if (source.flags & ts.TypeFlags.Never) { + function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type { + source = filterType(source, t => !(t.flags & TypeFlags.Nullable)); + if (source.flags & TypeFlags.Never) { return emptyObjectType; } - if (source.flags & ts.TypeFlags.Union) { + if (source.flags & TypeFlags.Union) { return mapType(source, t => getRestType(t, properties, symbol)); } - let omitKeyType = getUnionType(ts.map(properties, getLiteralTypeFromPropertyName)); + let omitKeyType = getUnionType(map(properties, getLiteralTypeFromPropertyName)); - const spreadableProperties: ts.Symbol[] = []; - const unspreadableToRestKeys: ts.Type[] = []; + const spreadableProperties: Symbol[] = []; + const unspreadableToRestKeys: Type[] = []; for (const prop of getPropertiesOfType(source)) { - const literalTypeFromProperty = getLiteralTypeFromProperty(prop, ts.TypeFlags.StringOrNumberLiteralOrUnique); + const literalTypeFromProperty = getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique); if (!isTypeAssignableTo(literalTypeFromProperty, omitKeyType) - && !(ts.getDeclarationModifierFlagsFromSymbol(prop) & (ts.ModifierFlags.Private | ts.ModifierFlags.Protected)) + && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) && isSpreadableProperty(prop)) { spreadableProperties.push(prop); } @@ -8921,7 +9119,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { omitKeyType = getUnionType([omitKeyType, ...unspreadableToRestKeys]); } - if (omitKeyType.flags & ts.TypeFlags.Never) { + if (omitKeyType.flags & TypeFlags.Never) { return source; } @@ -8931,21 +9129,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return getTypeAliasInstantiation(omitTypeAlias, [source, omitKeyType]); } - const members = ts.createSymbolTable(); + const members = createSymbolTable(); for (const prop of spreadableProperties) { members.set(prop.escapedName, getSpreadSymbol(prop, /*readonly*/ false)); } - const result = createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, getIndexInfosOfType(source)); - result.objectFlags |= ts.ObjectFlags.ObjectRestType; + const result = createAnonymousType(symbol, members, emptyArray, emptyArray, getIndexInfosOfType(source)); + result.objectFlags |= ObjectFlags.ObjectRestType; return result; } - function isGenericTypeWithUndefinedConstraint(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.Instantiable) && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, ts.TypeFlags.Undefined); + function isGenericTypeWithUndefinedConstraint(type: Type) { + return !!(type.flags & TypeFlags.Instantiable) && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Undefined); } - function getNonUndefinedType(type: ts.Type) { - const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) ? mapType(type, t => t.flags & ts.TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; + function getNonUndefinedType(type: Type) { + const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; return getTypeWithFacts(typeOrConstraint, TypeFacts.NEUndefined); } @@ -8958,23 +9156,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // [ x ] = obj; // Expression // We construct a synthetic element access expression corresponding to 'obj.x' such that the control // flow analyzer doesn't have to handle all the different syntactic forms. - function getFlowTypeOfDestructuring(node: ts.BindingElement | ts.PropertyAssignment | ts.ShorthandPropertyAssignment | ts.Expression, declaredType: ts.Type) { + function getFlowTypeOfDestructuring(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression, declaredType: Type) { const reference = getSyntheticElementAccess(node); return reference ? getFlowTypeOfReference(reference, declaredType) : declaredType; } - function getSyntheticElementAccess(node: ts.BindingElement | ts.PropertyAssignment | ts.ShorthandPropertyAssignment | ts.Expression): ts.ElementAccessExpression | undefined { + function getSyntheticElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression): ElementAccessExpression | undefined { const parentAccess = getParentElementAccess(node); if (parentAccess && parentAccess.flowNode) { const propName = getDestructuringPropertyName(node); if (propName) { - const literal = ts.setTextRange(ts.parseNodeFactory.createStringLiteral(propName), node); - const lhsExpr = ts.isLeftHandSideExpression(parentAccess) ? parentAccess : ts.parseNodeFactory.createParenthesizedExpression(parentAccess); - const result = ts.setTextRange(ts.parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node); - ts.setParent(literal, result); - ts.setParent(result, node); + const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node); + const lhsExpr = isLeftHandSideExpression(parentAccess) ? parentAccess : parseNodeFactory.createParenthesizedExpression(parentAccess); + const result = setTextRange(parseNodeFactory.createElementAccessExpression(lhsExpr, literal), node); + setParent(literal, result); + setParent(result, node); if (lhsExpr !== parentAccess) { - ts.setParent(lhsExpr, result); + setParent(lhsExpr, result); } result.flowNode = parentAccess.flowNode; return result; @@ -8982,52 +9180,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getParentElementAccess(node: ts.BindingElement | ts.PropertyAssignment | ts.ShorthandPropertyAssignment | ts.Expression) { + function getParentElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) { const ancestor = node.parent.parent; switch (ancestor.kind) { - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.PropertyAssignment: - return getSyntheticElementAccess(ancestor as ts.BindingElement | ts.PropertyAssignment); - case ts.SyntaxKind.ArrayLiteralExpression: - return getSyntheticElementAccess(node.parent as ts.Expression); - case ts.SyntaxKind.VariableDeclaration: - return (ancestor as ts.VariableDeclaration).initializer; - case ts.SyntaxKind.BinaryExpression: - return (ancestor as ts.BinaryExpression).right; + case SyntaxKind.BindingElement: + case SyntaxKind.PropertyAssignment: + return getSyntheticElementAccess(ancestor as BindingElement | PropertyAssignment); + case SyntaxKind.ArrayLiteralExpression: + return getSyntheticElementAccess(node.parent as Expression); + case SyntaxKind.VariableDeclaration: + return (ancestor as VariableDeclaration).initializer; + case SyntaxKind.BinaryExpression: + return (ancestor as BinaryExpression).right; } } - function getDestructuringPropertyName(node: ts.BindingElement | ts.PropertyAssignment | ts.ShorthandPropertyAssignment | ts.Expression) { + function getDestructuringPropertyName(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression) { const parent = node.parent; - if (node.kind === ts.SyntaxKind.BindingElement && parent.kind === ts.SyntaxKind.ObjectBindingPattern) { - return getLiteralPropertyNameText((node as ts.BindingElement).propertyName || (node as ts.BindingElement).name as ts.Identifier); + if (node.kind === SyntaxKind.BindingElement && parent.kind === SyntaxKind.ObjectBindingPattern) { + return getLiteralPropertyNameText((node as BindingElement).propertyName || (node as BindingElement).name as Identifier); } - if (node.kind === ts.SyntaxKind.PropertyAssignment || node.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { - return getLiteralPropertyNameText((node as ts.PropertyAssignment | ts.ShorthandPropertyAssignment).name); + if (node.kind === SyntaxKind.PropertyAssignment || node.kind === SyntaxKind.ShorthandPropertyAssignment) { + return getLiteralPropertyNameText((node as PropertyAssignment | ShorthandPropertyAssignment).name); } - return "" + ((parent as ts.BindingPattern | ts.ArrayLiteralExpression).elements as ts.NodeArray).indexOf(node); + return "" + ((parent as BindingPattern | ArrayLiteralExpression).elements as NodeArray).indexOf(node); } - function getLiteralPropertyNameText(name: ts.PropertyName) { + function getLiteralPropertyNameText(name: PropertyName) { const type = getLiteralTypeFromPropertyName(name); - return type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral) ? "" + (type as ts.StringLiteralType | ts.NumberLiteralType).value : undefined; + return type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral) ? "" + (type as StringLiteralType | NumberLiteralType).value : undefined; } /** Return the inferred type for a binding element */ - function getTypeForBindingElement(declaration: ts.BindingElement): ts.Type | undefined { + function getTypeForBindingElement(declaration: BindingElement): Type | undefined { const checkMode = declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal; const parentType = getTypeForBindingElementParent(declaration.parent.parent, checkMode); return parentType && getBindingElementTypeFromParentType(declaration, parentType); } - function getBindingElementTypeFromParentType(declaration: ts.BindingElement, parentType: ts.Type): ts.Type { + function getBindingElementTypeFromParentType(declaration: BindingElement, parentType: Type): Type { // If an any type was inferred for parent, infer that for the binding element if (isTypeAny(parentType)) { return parentType; } const pattern = declaration.parent; // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation - if (strictNullChecks && declaration.flags & ts.NodeFlags.Ambient && ts.isParameterDeclaration(declaration)) { + if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { parentType = getNonNullableType(parentType); } // Filter `undefined` from the type we check against if the parent has an initializer and that initializer is not possibly `undefined` @@ -9035,27 +9233,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined); } - let type: ts.Type | undefined; - if (pattern.kind === ts.SyntaxKind.ObjectBindingPattern) { + let type: Type | undefined; + if (pattern.kind === SyntaxKind.ObjectBindingPattern) { if (declaration.dotDotDotToken) { parentType = getReducedType(parentType); - if (parentType.flags & ts.TypeFlags.Unknown || !isValidSpreadType(parentType)) { - error(declaration, ts.Diagnostics.Rest_types_may_only_be_created_from_object_types); + if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) { + error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types); return errorType; } - const literalMembers: ts.PropertyName[] = []; + const literalMembers: PropertyName[] = []; for (const element of pattern.elements) { if (!element.dotDotDotToken) { - literalMembers.push(element.propertyName || element.name as ts.Identifier); + literalMembers.push(element.propertyName || element.name as Identifier); } } type = getRestType(parentType, literalMembers, declaration.symbol); } else { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) - const name = declaration.propertyName || declaration.name as ts.Identifier; + const name = declaration.propertyName || declaration.name as Identifier; const indexType = getLiteralTypeFromPropertyName(name); - const declaredType = getIndexedAccessType(parentType, indexType, ts.AccessFlags.ExpressionPosition, name); + const declaredType = getIndexedAccessType(parentType, indexType, AccessFlags.ExpressionPosition, name); type = getFlowTypeOfDestructuring(declaration, declaredType); } } @@ -9070,12 +9268,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // remaining tuple element types. Otherwise, the rest element has an array type with same // element type as the parent type. type = everyType(parentType, isTupleType) ? - mapType(parentType, t => sliceTupleType(t as ts.TupleTypeReference, index)) : + mapType(parentType, t => sliceTupleType(t as TupleTypeReference, index)) : createArrayType(elementType); } else if (isArrayLikeType(parentType)) { const indexType = getNumberLiteralType(index); - const accessFlags = ts.AccessFlags.ExpressionPosition | (hasDefaultValue(declaration) ? ts.AccessFlags.NoTupleBoundsCheck : 0); + const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0); const declaredType = getIndexedAccessTypeOrUndefined(parentType, indexType, accessFlags, declaration.name) || errorType; type = getFlowTypeOfDestructuring(declaration, declaredType); } @@ -9086,50 +9284,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!declaration.initializer) { return type; } - if (ts.getEffectiveTypeAnnotationNode(ts.walkUpBindingElementsAndPatterns(declaration))) { + if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. return strictNullChecks && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type; } - return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], ts.UnionReduction.Subtype)); + return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype)); } - function getTypeForDeclarationFromJSDocComment(declaration: ts.Node) { - const jsdocType = ts.getJSDocType(declaration); + function getTypeForDeclarationFromJSDocComment(declaration: Node) { + const jsdocType = getJSDocType(declaration); if (jsdocType) { return getTypeFromTypeNode(jsdocType); } return undefined; } - function isNullOrUndefined(node: ts.Expression) { - const expr = ts.skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return expr.kind === ts.SyntaxKind.NullKeyword || expr.kind === ts.SyntaxKind.Identifier && getResolvedSymbol(expr as ts.Identifier) === undefinedSymbol; + function isNullOrUndefined(node: Expression) { + const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); + return expr.kind === SyntaxKind.NullKeyword || expr.kind === SyntaxKind.Identifier && getResolvedSymbol(expr as Identifier) === undefinedSymbol; } - function isEmptyArrayLiteral(node: ts.Expression) { - const expr = ts.skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return expr.kind === ts.SyntaxKind.ArrayLiteralExpression && (expr as ts.ArrayLiteralExpression).elements.length === 0; + function isEmptyArrayLiteral(node: Expression) { + const expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); + return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0; } - function addOptionality(type: ts.Type, isProperty = false, isOptional = true): ts.Type { + function addOptionality(type: Type, isProperty = false, isOptional = true): Type { return strictNullChecks && isOptional ? getOptionalType(type, isProperty) : type; } // Return the inferred type for a variable, parameter, or property declaration function getTypeForVariableLikeDeclaration( - declaration: ts.ParameterDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.VariableDeclaration | ts.BindingElement | ts.JSDocPropertyLikeTag, + declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, includeOptionality: boolean, checkMode: CheckMode, - ): ts.Type | undefined { + ): Type | undefined { // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === ts.SyntaxKind.ForInStatement) { + if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) { const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode))); - return indexType.flags & (ts.TypeFlags.TypeParameter | ts.TypeFlags.Index) ? getExtractStringType(indexType) : stringType; + return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) : stringType; } - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === ts.SyntaxKind.ForOfStatement) { + if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { // checkRightHandSideOfForOf will return undefined if the for-of expression type was // missing properties/signatures required to get its iteratedType (like // [Symbol.iterator] or next). This may be because we accessed properties from anyType, @@ -9138,14 +9336,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return checkRightHandSideOfForOf(forOfStatement) || anyType; } - if (ts.isBindingPattern(declaration.parent)) { - return getTypeForBindingElement(declaration as ts.BindingElement); + if (isBindingPattern(declaration.parent)) { + return getTypeForBindingElement(declaration as BindingElement); } - const isProperty = ts.isPropertyDeclaration(declaration) && !ts.hasAccessorModifier(declaration) || ts.isPropertySignature(declaration); + const isProperty = isPropertyDeclaration(declaration) && !hasAccessorModifier(declaration) || isPropertySignature(declaration); const isOptional = includeOptionality && ( isProperty && !!declaration.questionToken || - ts.isParameter(declaration) && (!!declaration.questionToken || isJSDocOptionalParameter(declaration)) || + isParameter(declaration) && (!!declaration.questionToken || isJSDocOptionalParameter(declaration)) || isOptionalJSDocPropertyLikeTag(declaration)); // Use type from type annotation if one is present @@ -9154,13 +9352,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return addOptionality(declaredType, isProperty, isOptional); } - if ((noImplicitAny || ts.isInJSFile(declaration)) && - ts.isVariableDeclaration(declaration) && !ts.isBindingPattern(declaration.name) && - !(ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Export) && !(declaration.flags & ts.NodeFlags.Ambient)) { + if ((noImplicitAny || isInJSFile(declaration)) && + isVariableDeclaration(declaration) && !isBindingPattern(declaration.name) && + !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient)) { // If --noImplicitAny is on or the declaration is in a Javascript file, // use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no // initializer or a 'null' or 'undefined' initializer. - if (!(ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { + if (!(getCombinedNodeFlags(declaration) & NodeFlags.Const) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) { return autoType; } // Use control flow tracked 'any[]' type for non-ambient, non-exported variables with an empty array @@ -9170,17 +9368,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isParameter(declaration)) { - const func = declaration.parent as ts.FunctionLikeDeclaration; + if (isParameter(declaration)) { + const func = declaration.parent as FunctionLikeDeclaration; // For a parameter of a set accessor, use the type of the get accessor if one is present - if (func.kind === ts.SyntaxKind.SetAccessor && hasBindableName(func)) { - const getter = ts.getDeclarationOfKind(getSymbolOfNode(declaration.parent), ts.SyntaxKind.GetAccessor); + if (func.kind === SyntaxKind.SetAccessor && hasBindableName(func)) { + const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); - const thisParameter = getAccessorThisParameter(func as ts.AccessorDeclaration); + const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); if (thisParameter && declaration === thisParameter) { // Use the type from the *getter* - ts.Debug.assert(!thisParameter.type); + Debug.assert(!thisParameter.type); return getTypeOfSymbol(getterSignature.thisParameter!); } return getReturnTypeOfSignature(getterSignature); @@ -9189,7 +9387,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const parameterTypeOfTypeTag = getParameterTypeOfTypeTag(func, declaration); if (parameterTypeOfTypeTag) return parameterTypeOfTypeTag; // Use contextual parameter type if one is available - const type = declaration.symbol.escapedName === ts.InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); + const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration); if (type) { return addOptionality(type, /*isProperty*/ false, isOptional); } @@ -9197,9 +9395,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Use the type of the initializer expression if one is present and the declaration is // not a parameter of a contextually typed function - if (ts.hasOnlyExpressionInitializer(declaration) && !!declaration.initializer) { - if (ts.isInJSFile(declaration) && !ts.isParameter(declaration)) { - const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfNode(declaration), ts.getDeclaredExpandoInitializer(declaration)); + if (hasOnlyExpressionInitializer(declaration) && !!declaration.initializer) { + if (isInJSFile(declaration) && !isParameter(declaration)) { + const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfNode(declaration), getDeclaredExpandoInitializer(declaration)); if (containerObjectType) { return containerObjectType; } @@ -9208,26 +9406,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return addOptionality(type, isProperty, isOptional); } - if (ts.isPropertyDeclaration(declaration) && (noImplicitAny || ts.isInJSFile(declaration))) { + if (isPropertyDeclaration(declaration) && (noImplicitAny || isInJSFile(declaration))) { // We have a property declaration with no type annotation or initializer, in noImplicitAny mode or a .js file. // Use control flow analysis of this.xxx assignments in the constructor or static block to determine the type of the property. - if (!ts.hasStaticModifier(declaration)) { + if (!hasStaticModifier(declaration)) { const constructor = findConstructorDeclaration(declaration.parent); const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) : - ts.getEffectiveModifierFlags(declaration) & ts.ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : + getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : undefined; return type && addOptionality(type, /*isProperty*/ true, isOptional); } else { - const staticBlocks = ts.filter(declaration.parent.members, ts.isClassStaticBlockDeclaration); + const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); const type = staticBlocks.length ? getFlowTypeInStaticBlocks(declaration.symbol, staticBlocks) : - ts.getEffectiveModifierFlags(declaration) & ts.ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : + getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : undefined; return type && addOptionality(type, /*isProperty*/ true, isOptional); } } - if (ts.isJsxAttribute(declaration)) { + if (isJsxAttribute(declaration)) { // if JSX attribute doesn't have initializer, by default the attribute will have boolean value of true. // I.e is sugar for return trueType; @@ -9235,7 +9433,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the declaration specifies a binding pattern and is not a parameter of a contextually // typed function, use the type implied by the binding pattern - if (ts.isBindingPattern(declaration.name)) { + if (isBindingPattern(declaration.name)) { return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ false, /*reportErrors*/ true); } @@ -9243,18 +9441,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isConstructorDeclaredProperty(symbol: ts.Symbol) { + function isConstructorDeclaredProperty(symbol: Symbol) { // A property is considered a constructor declared property when all declaration sites are this.xxx assignments, // when no declaration sites have JSDoc type annotations, and when at least one declaration site is in the body of // a class constructor. - if (symbol.valueDeclaration && ts.isBinaryExpression(symbol.valueDeclaration)) { + if (symbol.valueDeclaration && isBinaryExpression(symbol.valueDeclaration)) { const links = getSymbolLinks(symbol); if (links.isConstructorDeclaredProperty === undefined) { links.isConstructorDeclaredProperty = false; - links.isConstructorDeclaredProperty = !!getDeclaringConstructor(symbol) && ts.every(symbol.declarations, declaration => - ts.isBinaryExpression(declaration) && + links.isConstructorDeclaredProperty = !!getDeclaringConstructor(symbol) && every(symbol.declarations, declaration => + isBinaryExpression(declaration) && isPossiblyAliasedThisProperty(declaration) && - (declaration.left.kind !== ts.SyntaxKind.ElementAccessExpression || ts.isStringOrNumericLiteralLike((declaration.left as ts.ElementAccessExpression).argumentExpression)) && + (declaration.left.kind !== SyntaxKind.ElementAccessExpression || isStringOrNumericLiteralLike((declaration.left as ElementAccessExpression).argumentExpression)) && !getAnnotatedTypeForAssignmentDeclaration(/*declaredType*/ undefined, declaration, symbol, declaration)); } return links.isConstructorDeclaredProperty; @@ -9262,55 +9460,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isAutoTypedProperty(symbol: ts.Symbol) { + function isAutoTypedProperty(symbol: Symbol) { // A property is auto-typed when its declaration has no type annotation or initializer and we're in // noImplicitAny mode or a .js file. const declaration = symbol.valueDeclaration; - return declaration && ts.isPropertyDeclaration(declaration) && !ts.getEffectiveTypeAnnotationNode(declaration) && - !declaration.initializer && (noImplicitAny || ts.isInJSFile(declaration)); + return declaration && isPropertyDeclaration(declaration) && !getEffectiveTypeAnnotationNode(declaration) && + !declaration.initializer && (noImplicitAny || isInJSFile(declaration)); } - function getDeclaringConstructor(symbol: ts.Symbol) { + function getDeclaringConstructor(symbol: Symbol) { if (!symbol.declarations) { return; } for (const declaration of symbol.declarations) { - const container = ts.getThisContainer(declaration, /*includeArrowFunctions*/ false); - if (container && (container.kind === ts.SyntaxKind.Constructor || isJSConstructor(container))) { - return container as ts.ConstructorDeclaration; + const container = getThisContainer(declaration, /*includeArrowFunctions*/ false); + if (container && (container.kind === SyntaxKind.Constructor || isJSConstructor(container))) { + return container as ConstructorDeclaration; } } } /** Create a synthetic property access flow node after the last statement of the file */ - function getFlowTypeFromCommonJSExport(symbol: ts.Symbol) { - const file = ts.getSourceFileOfNode(symbol.declarations![0]); - const accessName = ts.unescapeLeadingUnderscores(symbol.escapedName); - const areAllModuleExports = symbol.declarations!.every(d => ts.isInJSFile(d) && ts.isAccessExpression(d) && ts.isModuleExportsAccessExpression(d.expression)); + function getFlowTypeFromCommonJSExport(symbol: Symbol) { + const file = getSourceFileOfNode(symbol.declarations![0]); + const accessName = unescapeLeadingUnderscores(symbol.escapedName); + const areAllModuleExports = symbol.declarations!.every(d => isInJSFile(d) && isAccessExpression(d) && isModuleExportsAccessExpression(d.expression)); const reference = areAllModuleExports - ? ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("module"), ts.factory.createIdentifier("exports")), accessName) - : ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("exports"), accessName); + ? factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(factory.createIdentifier("module"), factory.createIdentifier("exports")), accessName) + : factory.createPropertyAccessExpression(factory.createIdentifier("exports"), accessName); if (areAllModuleExports) { - ts.setParent((reference.expression as ts.PropertyAccessExpression).expression, reference.expression); + setParent((reference.expression as PropertyAccessExpression).expression, reference.expression); } - ts.setParent(reference.expression, reference); - ts.setParent(reference, file); + setParent(reference.expression, reference); + setParent(reference, file); reference.flowNode = file.endFlowNode; return getFlowTypeOfReference(reference, autoType, undefinedType); } - function getFlowTypeInStaticBlocks(symbol: ts.Symbol, staticBlocks: readonly ts.ClassStaticBlockDeclaration[]) { - const accessName = ts.startsWith(symbol.escapedName as string, "__#") - ? ts.factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1]) - : ts.unescapeLeadingUnderscores(symbol.escapedName); + function getFlowTypeInStaticBlocks(symbol: Symbol, staticBlocks: readonly ClassStaticBlockDeclaration[]) { + const accessName = startsWith(symbol.escapedName as string, "__#") + ? factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1]) + : unescapeLeadingUnderscores(symbol.escapedName); for (const staticBlock of staticBlocks) { - const reference = ts.factory.createPropertyAccessExpression(ts.factory.createThis(), accessName); - ts.setParent(reference.expression, reference); - ts.setParent(reference, staticBlock); + const reference = factory.createPropertyAccessExpression(factory.createThis(), accessName); + setParent(reference.expression, reference); + setParent(reference, staticBlock); reference.flowNode = staticBlock.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { - error(symbol.valueDeclaration, ts.Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } // We don't infer a type if assignments are only null or undefined. if (everyType(flowType, isNullableType)) { @@ -9320,35 +9518,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getFlowTypeInConstructor(symbol: ts.Symbol, constructor: ts.ConstructorDeclaration) { - const accessName = ts.startsWith(symbol.escapedName as string, "__#") - ? ts.factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1]) - : ts.unescapeLeadingUnderscores(symbol.escapedName); - const reference = ts.factory.createPropertyAccessExpression(ts.factory.createThis(), accessName); - ts.setParent(reference.expression, reference); - ts.setParent(reference, constructor); + function getFlowTypeInConstructor(symbol: Symbol, constructor: ConstructorDeclaration) { + const accessName = startsWith(symbol.escapedName as string, "__#") + ? factory.createPrivateIdentifier((symbol.escapedName as string).split("@")[1]) + : unescapeLeadingUnderscores(symbol.escapedName); + const reference = factory.createPropertyAccessExpression(factory.createThis(), accessName); + setParent(reference.expression, reference); + setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { - error(symbol.valueDeclaration, ts.Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } // We don't infer a type if assignments are only null or undefined. return everyType(flowType, isNullableType) ? undefined : convertAutoToAny(flowType); } - function getFlowTypeOfProperty(reference: ts.Node, prop: ts.Symbol | undefined) { + function getFlowTypeOfProperty(reference: Node, prop: Symbol | undefined) { const initialType = prop?.valueDeclaration - && (!isAutoTypedProperty(prop) || ts.getEffectiveModifierFlags(prop.valueDeclaration) & ts.ModifierFlags.Ambient) + && (!isAutoTypedProperty(prop) || getEffectiveModifierFlags(prop.valueDeclaration) & ModifierFlags.Ambient) && getTypeOfPropertyInBaseClass(prop) || undefinedType; return getFlowTypeOfReference(reference, autoType, initialType); } - function getWidenedTypeForAssignmentDeclaration(symbol: ts.Symbol, resolvedSymbol?: ts.Symbol) { + function getWidenedTypeForAssignmentDeclaration(symbol: Symbol, resolvedSymbol?: Symbol) { // function/class/{} initializers are themselves containers, so they won't merge in the same way as other initializers - const container = ts.getAssignedExpandoInitializer(symbol.valueDeclaration); + const container = getAssignedExpandoInitializer(symbol.valueDeclaration); if (container) { - const tag = ts.getJSDocTypeTag(container); + const tag = getJSDocTypeTag(container); if (tag && tag.typeExpression) { return getTypeFromTypeNode(tag.typeExpression); } @@ -9364,21 +9562,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { type = getFlowTypeInConstructor(symbol, getDeclaringConstructor(symbol)!); } if (!type) { - let types: ts.Type[] | undefined; + let types: Type[] | undefined; if (symbol.declarations) { - let jsdocType: ts.Type | undefined; + let jsdocType: Type | undefined; for (const declaration of symbol.declarations) { - const expression = (ts.isBinaryExpression(declaration) || ts.isCallExpression(declaration)) ? declaration : - ts.isAccessExpression(declaration) ? ts.isBinaryExpression(declaration.parent) ? declaration.parent : declaration : + const expression = (isBinaryExpression(declaration) || isCallExpression(declaration)) ? declaration : + isAccessExpression(declaration) ? isBinaryExpression(declaration.parent) ? declaration.parent : declaration : undefined; if (!expression) { continue; // Non-assignment declaration merged in (eg, an Identifier to mark the thing as a namespace) - skip over it and pull type info from elsewhere } - const kind = ts.isAccessExpression(expression) - ? ts.getAssignmentDeclarationPropertyAccessKind(expression) - : ts.getAssignmentDeclarationKind(expression); - if (kind === ts.AssignmentDeclarationKind.ThisProperty || ts.isBinaryExpression(expression) && isPossiblyAliasedThisProperty(expression, kind)) { + const kind = isAccessExpression(expression) + ? getAssignmentDeclarationPropertyAccessKind(expression) + : getAssignmentDeclarationKind(expression); + if (kind === AssignmentDeclarationKind.ThisProperty || isBinaryExpression(expression) && isPossiblyAliasedThisProperty(expression, kind)) { if (isDeclarationInConstructor(expression)) { definedInConstructor = true; } @@ -9386,17 +9584,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { definedInMethod = true; } } - if (!ts.isCallExpression(expression)) { + if (!isCallExpression(expression)) { jsdocType = getAnnotatedTypeForAssignmentDeclaration(jsdocType, expression, symbol, declaration); } if (!jsdocType) { - (types || (types = [])).push((ts.isBinaryExpression(expression) || ts.isCallExpression(expression)) ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) : neverType); + (types || (types = [])).push((isBinaryExpression(expression) || isCallExpression(expression)) ? getInitializerTypeFromAssignmentDeclaration(symbol, resolvedSymbol, expression, kind) : neverType); } } type = jsdocType; } if (!type) { - if (!ts.length(types)) { + if (!length(types)) { return errorType; // No types from any declarations :( } let constructorTypes = definedInConstructor && symbol.declarations ? getConstructorDefinedThisAssignmentTypes(types!, symbol.declarations) : undefined; @@ -9408,41 +9606,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { definedInConstructor = true; } } - const sourceTypes = ts.some(constructorTypes, t => !!(t.flags & ~ts.TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217 + const sourceTypes = some(constructorTypes, t => !!(t.flags & ~TypeFlags.Nullable)) ? constructorTypes : types; // TODO: GH#18217 type = getUnionType(sourceTypes!); } } const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor)); - if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~ts.TypeFlags.Nullable)) === neverType) { + if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { reportImplicitAny(symbol.valueDeclaration, anyType); return anyType; } return widened; } - function getJSContainerObjectType(decl: ts.Node, symbol: ts.Symbol, init: ts.Expression | undefined): ts.Type | undefined { - if (!ts.isInJSFile(decl) || !init || !ts.isObjectLiteralExpression(init) || init.properties.length) { + function getJSContainerObjectType(decl: Node, symbol: Symbol, init: Expression | undefined): Type | undefined { + if (!isInJSFile(decl) || !init || !isObjectLiteralExpression(init) || init.properties.length) { return undefined; } - const exports = ts.createSymbolTable(); - while (ts.isBinaryExpression(decl) || ts.isPropertyAccessExpression(decl)) { + const exports = createSymbolTable(); + while (isBinaryExpression(decl) || isPropertyAccessExpression(decl)) { const s = getSymbolOfNode(decl); if (s?.exports?.size) { mergeSymbolTable(exports, s.exports); } - decl = ts.isBinaryExpression(decl) ? decl.parent : decl.parent.parent; + decl = isBinaryExpression(decl) ? decl.parent : decl.parent.parent; } const s = getSymbolOfNode(decl); if (s?.exports?.size) { mergeSymbolTable(exports, s.exports); } - const type = createAnonymousType(symbol, exports, ts.emptyArray, ts.emptyArray, ts.emptyArray); - type.objectFlags |= ts.ObjectFlags.JSLiteral; + const type = createAnonymousType(symbol, exports, emptyArray, emptyArray, emptyArray); + type.objectFlags |= ObjectFlags.JSLiteral; return type; } - function getAnnotatedTypeForAssignmentDeclaration(declaredType: ts.Type | undefined, expression: ts.Expression, symbol: ts.Symbol, declaration: ts.Declaration) { - const typeNode = ts.getEffectiveTypeAnnotationNode(expression.parent); + function getAnnotatedTypeForAssignmentDeclaration(declaredType: Type | undefined, expression: Expression, symbol: Symbol, declaration: Declaration) { + const typeNode = getEffectiveTypeAnnotationNode(expression.parent); if (typeNode) { const type = getWidenedType(getTypeFromTypeNode(typeNode)); if (!declaredType) { @@ -9453,7 +9651,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (symbol.parent?.valueDeclaration) { - const typeNode = ts.getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration); + const typeNode = getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration); if (typeNode) { const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName); if (annotationSymbol) { @@ -9466,24 +9664,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** If we don't have an explicit JSDoc type, get the type from the initializer. */ - function getInitializerTypeFromAssignmentDeclaration(symbol: ts.Symbol, resolvedSymbol: ts.Symbol | undefined, expression: ts.BinaryExpression | ts.CallExpression, kind: ts.AssignmentDeclarationKind) { - if (ts.isCallExpression(expression)) { + function getInitializerTypeFromAssignmentDeclaration(symbol: Symbol, resolvedSymbol: Symbol | undefined, expression: BinaryExpression | CallExpression, kind: AssignmentDeclarationKind) { + if (isCallExpression(expression)) { if (resolvedSymbol) { return getTypeOfSymbol(resolvedSymbol); // This shouldn't happen except under some hopefully forbidden merges of export assignments and object define assignments } - const objectLitType = checkExpressionCached((expression as ts.BindableObjectDefinePropertyCall).arguments[2]); - const valueType = getTypeOfPropertyOfType(objectLitType, "value" as ts.__String); + const objectLitType = checkExpressionCached((expression as BindableObjectDefinePropertyCall).arguments[2]); + const valueType = getTypeOfPropertyOfType(objectLitType, "value" as __String); if (valueType) { return valueType; } - const getFunc = getTypeOfPropertyOfType(objectLitType, "get" as ts.__String); + const getFunc = getTypeOfPropertyOfType(objectLitType, "get" as __String); if (getFunc) { const getSig = getSingleCallSignature(getFunc); if (getSig) { return getReturnTypeOfSignature(getSig); } } - const setFunc = getTypeOfPropertyOfType(objectLitType, "set" as ts.__String); + const setFunc = getTypeOfPropertyOfType(objectLitType, "set" as __String); if (setFunc) { const setSig = getSingleCallSignature(setFunc); if (setSig) { @@ -9495,24 +9693,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (containsSameNamedThisProperty(expression.left, expression.right)) { return anyType; } - const isDirectExport = kind === ts.AssignmentDeclarationKind.ExportsProperty && (ts.isPropertyAccessExpression(expression.left) || ts.isElementAccessExpression(expression.left)) && (ts.isModuleExportsAccessExpression(expression.left.expression) || (ts.isIdentifier(expression.left.expression) && ts.isExportsIdentifier(expression.left.expression))); + const isDirectExport = kind === AssignmentDeclarationKind.ExportsProperty && (isPropertyAccessExpression(expression.left) || isElementAccessExpression(expression.left)) && (isModuleExportsAccessExpression(expression.left.expression) || (isIdentifier(expression.left.expression) && isExportsIdentifier(expression.left.expression))); const type = resolvedSymbol ? getTypeOfSymbol(resolvedSymbol) : isDirectExport ? getRegularTypeOfLiteralType(checkExpressionCached(expression.right)) : getWidenedLiteralType(checkExpressionCached(expression.right)); - if (type.flags & ts.TypeFlags.Object && - kind === ts.AssignmentDeclarationKind.ModuleExports && - symbol.escapedName === ts.InternalSymbolName.ExportEquals) { - const exportedType = resolveStructuredTypeMembers(type as ts.ObjectType); - const members = ts.createSymbolTable(); - ts.copyEntries(exportedType.members, members); + if (type.flags & TypeFlags.Object && + kind === AssignmentDeclarationKind.ModuleExports && + symbol.escapedName === InternalSymbolName.ExportEquals) { + const exportedType = resolveStructuredTypeMembers(type as ObjectType); + const members = createSymbolTable(); + copyEntries(exportedType.members, members); const initialSize = members.size; if (resolvedSymbol && !resolvedSymbol.exports) { - resolvedSymbol.exports = ts.createSymbolTable(); + resolvedSymbol.exports = createSymbolTable(); } (resolvedSymbol || symbol).exports!.forEach((s, name) => { const exportedMember = members.get(name)!; - if (exportedMember && exportedMember !== s && !(s.flags & ts.SymbolFlags.Alias)) { - if (s.flags & ts.SymbolFlags.Value && exportedMember.flags & ts.SymbolFlags.Value) { + if (exportedMember && exportedMember !== s && !(s.flags & SymbolFlags.Alias)) { + if (s.flags & SymbolFlags.Value && exportedMember.flags & SymbolFlags.Value) { // If the member has an additional value-like declaration, union the types from the two declarations, // but issue an error if they occurred in two different files. The purpose is to support a JS file with // a pattern like: @@ -9523,20 +9721,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // but we may have a JS file with `module.exports = { a: true }` along with a TypeScript module augmentation // declaring an `export const a: number`. In that case, we issue a duplicate identifier error, because // it's unclear what that's supposed to mean, so it's probably a mistake. - if (s.valueDeclaration && exportedMember.valueDeclaration && ts.getSourceFileOfNode(s.valueDeclaration) !== ts.getSourceFileOfNode(exportedMember.valueDeclaration)) { - const unescapedName = ts.unescapeLeadingUnderscores(s.escapedName); - const exportedMemberName = ts.tryCast(exportedMember.valueDeclaration, ts.isNamedDeclaration)?.name || exportedMember.valueDeclaration; - ts.addRelatedInfo( - error(s.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0, unescapedName), - ts.createDiagnosticForNode(exportedMemberName, ts.Diagnostics._0_was_also_declared_here, unescapedName)); - ts.addRelatedInfo( - error(exportedMemberName, ts.Diagnostics.Duplicate_identifier_0, unescapedName), - ts.createDiagnosticForNode(s.valueDeclaration, ts.Diagnostics._0_was_also_declared_here, unescapedName)); + if (s.valueDeclaration && exportedMember.valueDeclaration && getSourceFileOfNode(s.valueDeclaration) !== getSourceFileOfNode(exportedMember.valueDeclaration)) { + const unescapedName = unescapeLeadingUnderscores(s.escapedName); + const exportedMemberName = tryCast(exportedMember.valueDeclaration, isNamedDeclaration)?.name || exportedMember.valueDeclaration; + addRelatedInfo( + error(s.valueDeclaration, Diagnostics.Duplicate_identifier_0, unescapedName), + createDiagnosticForNode(exportedMemberName, Diagnostics._0_was_also_declared_here, unescapedName)); + addRelatedInfo( + error(exportedMemberName, Diagnostics.Duplicate_identifier_0, unescapedName), + createDiagnosticForNode(s.valueDeclaration, Diagnostics._0_was_also_declared_here, unescapedName)); } const union = createSymbol(s.flags | exportedMember.flags, name); union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); union.valueDeclaration = exportedMember.valueDeclaration; - union.declarations = ts.concatenate(exportedMember.declarations, s.declarations); + union.declarations = concatenate(exportedMember.declarations, s.declarations); members.set(name, union); } else { @@ -9558,15 +9756,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result.aliasSymbol = type.aliasSymbol; result.aliasTypeArguments = type.aliasTypeArguments; } - if (ts.getObjectFlags(type) & ts.ObjectFlags.Reference) { - result.aliasSymbol = (type as ts.TypeReference).symbol; - const args = getTypeArguments(type as ts.TypeReference); - result.aliasTypeArguments = ts.length(args) ? args : undefined; + if (getObjectFlags(type) & ObjectFlags.Reference) { + result.aliasSymbol = (type as TypeReference).symbol; + const args = getTypeArguments(type as TypeReference); + result.aliasTypeArguments = length(args) ? args : undefined; } } - result.objectFlags |= (ts.getObjectFlags(type) & ts.ObjectFlags.JSLiteral); // Propagate JSLiteral flag - if (result.symbol && result.symbol.flags & ts.SymbolFlags.Class && type === getDeclaredTypeOfClassOrInterface(result.symbol)) { - result.objectFlags |= ts.ObjectFlags.IsClassInstanceClone; // Propagate the knowledge that this type is equivalent to the symbol's class instance type + result.objectFlags |= (getObjectFlags(type) & ObjectFlags.JSLiteral); // Propagate JSLiteral flag + if (result.symbol && result.symbol.flags & SymbolFlags.Class && type === getDeclaredTypeOfClassOrInterface(result.symbol)) { + result.objectFlags |= ObjectFlags.IsClassInstanceClone; // Propagate the knowledge that this type is equivalent to the symbol's class instance type } return result; } @@ -9577,27 +9775,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function containsSameNamedThisProperty(thisProperty: ts.Expression, expression: ts.Expression) { - return ts.isPropertyAccessExpression(thisProperty) - && thisProperty.expression.kind === ts.SyntaxKind.ThisKeyword - && ts.forEachChildRecursively(expression, n => isMatchingReference(thisProperty, n)); + function containsSameNamedThisProperty(thisProperty: Expression, expression: Expression) { + return isPropertyAccessExpression(thisProperty) + && thisProperty.expression.kind === SyntaxKind.ThisKeyword + && forEachChildRecursively(expression, n => isMatchingReference(thisProperty, n)); } - function isDeclarationInConstructor(expression: ts.Expression) { - const thisContainer = ts.getThisContainer(expression, /*includeArrowFunctions*/ false); + function isDeclarationInConstructor(expression: Expression) { + const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false); // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added. // Function expressions that are assigned to the prototype count as methods. - return thisContainer.kind === ts.SyntaxKind.Constructor || - thisContainer.kind === ts.SyntaxKind.FunctionDeclaration || - (thisContainer.kind === ts.SyntaxKind.FunctionExpression && !ts.isPrototypePropertyAssignment(thisContainer.parent)); + return thisContainer.kind === SyntaxKind.Constructor || + thisContainer.kind === SyntaxKind.FunctionDeclaration || + (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent)); } - function getConstructorDefinedThisAssignmentTypes(types: ts.Type[], declarations: ts.Declaration[]): ts.Type[] | undefined { - ts.Debug.assert(types.length === declarations.length); + function getConstructorDefinedThisAssignmentTypes(types: Type[], declarations: Declaration[]): Type[] | undefined { + Debug.assert(types.length === declarations.length); return types.filter((_, i) => { const declaration = declarations[i]; - const expression = ts.isBinaryExpression(declaration) ? declaration : - ts.isBinaryExpression(declaration.parent) ? declaration.parent : undefined; + const expression = isBinaryExpression(declaration) ? declaration : + isBinaryExpression(declaration.parent) ? declaration.parent : undefined; return expression && isDeclarationInConstructor(expression); }); } @@ -9605,15 +9803,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return the type implied by a binding pattern element. This is the type of the initializer of the element if // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding // pattern. Otherwise, it is the type any. - function getTypeFromBindingElement(element: ts.BindingElement, includePatternInType?: boolean, reportErrors?: boolean): ts.Type { + function getTypeFromBindingElement(element: BindingElement, includePatternInType?: boolean, reportErrors?: boolean): Type { if (element.initializer) { // The type implied by a binding pattern is independent of context, so we check the initializer with no // contextual type or, if the element itself is a binding pattern, with the type implied by that binding // pattern. - const contextualType = ts.isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; + const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); } - if (ts.isBindingPattern(element.name)) { + if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); } if (reportErrors && !declarationBelongsToPrivateAmbientMember(element)) { @@ -9627,12 +9825,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Return the type implied by an object binding pattern - function getTypeFromObjectBindingPattern(pattern: ts.ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): ts.Type { - const members = ts.createSymbolTable(); - let stringIndexInfo: ts.IndexInfo | undefined; - let objectFlags = ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral; - ts.forEach(pattern.elements, e => { - const name = e.propertyName || e.name as ts.Identifier; + function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { + const members = createSymbolTable(); + let stringIndexInfo: IndexInfo | undefined; + let objectFlags = ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; + forEach(pattern.elements, e => { + const name = e.propertyName || e.name as Identifier; if (e.dotDotDotToken) { stringIndexInfo = createIndexInfo(stringType, anyType, /*isReadonly*/ false); return; @@ -9641,41 +9839,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const exprType = getLiteralTypeFromPropertyName(name); if (!isTypeUsableAsPropertyName(exprType)) { // do not include computed properties in the implied type - objectFlags |= ts.ObjectFlags.ObjectLiteralPatternWithComputedProperties; + objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; return; } const text = getPropertyNameFromType(exprType); - const flags = ts.SymbolFlags.Property | (e.initializer ? ts.SymbolFlags.Optional : 0); + const flags = SymbolFlags.Property | (e.initializer ? SymbolFlags.Optional : 0); const symbol = createSymbol(flags, text); symbol.type = getTypeFromBindingElement(e, includePatternInType, reportErrors); symbol.bindingElement = e; members.set(symbol.escapedName, symbol); }); - const result = createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, stringIndexInfo ? [stringIndexInfo] : ts.emptyArray); + const result = createAnonymousType(undefined, members, emptyArray, emptyArray, stringIndexInfo ? [stringIndexInfo] : emptyArray); result.objectFlags |= objectFlags; if (includePatternInType) { result.pattern = pattern; - result.objectFlags |= ts.ObjectFlags.ContainsObjectOrArrayLiteral; + result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral; } return result; } // Return the type implied by an array binding pattern - function getTypeFromArrayBindingPattern(pattern: ts.BindingPattern, includePatternInType: boolean, reportErrors: boolean): ts.Type { + function getTypeFromArrayBindingPattern(pattern: BindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { const elements = pattern.elements; - const lastElement = ts.lastOrUndefined(elements); - const restElement = lastElement && lastElement.kind === ts.SyntaxKind.BindingElement && lastElement.dotDotDotToken ? lastElement : undefined; + const lastElement = lastOrUndefined(elements); + const restElement = lastElement && lastElement.kind === SyntaxKind.BindingElement && lastElement.dotDotDotToken ? lastElement : undefined; if (elements.length === 0 || elements.length === 1 && restElement) { - return languageVersion >= ts.ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType; + return languageVersion >= ScriptTarget.ES2015 ? createIterableType(anyType) : anyArrayType; } - const elementTypes = ts.map(elements, e => ts.isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors)); - const minLength = ts.findLastIndex(elements, e => !(e === restElement || ts.isOmittedExpression(e) || hasDefaultValue(e)), elements.length - 1) + 1; - const elementFlags = ts.map(elements, (e, i) => e === restElement ? ts.ElementFlags.Rest : i >= minLength ? ts.ElementFlags.Optional : ts.ElementFlags.Required); - let result = createTupleType(elementTypes, elementFlags) as ts.TypeReference; + const elementTypes = map(elements, e => isOmittedExpression(e) ? anyType : getTypeFromBindingElement(e, includePatternInType, reportErrors)); + const minLength = findLastIndex(elements, e => !(e === restElement || isOmittedExpression(e) || hasDefaultValue(e)), elements.length - 1) + 1; + const elementFlags = map(elements, (e, i) => e === restElement ? ElementFlags.Rest : i >= minLength ? ElementFlags.Optional : ElementFlags.Required); + let result = createTupleType(elementTypes, elementFlags) as TypeReference; if (includePatternInType) { result = cloneTypeReference(result); result.pattern = pattern; - result.objectFlags |= ts.ObjectFlags.ContainsObjectOrArrayLiteral; + result.objectFlags |= ObjectFlags.ContainsObjectOrArrayLiteral; } return result; } @@ -9687,8 +9885,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // used as the contextual type of an initializer associated with the binding pattern. Also, for a destructuring // parameter with no type annotation or initializer, the type implied by the binding pattern becomes the type of // the parameter. - function getTypeFromBindingPattern(pattern: ts.BindingPattern, includePatternInType = false, reportErrors = false): ts.Type { - return pattern.kind === ts.SyntaxKind.ObjectBindingPattern + function getTypeFromBindingPattern(pattern: BindingPattern, includePatternInType = false, reportErrors = false): Type { + return pattern.kind === SyntaxKind.ObjectBindingPattern ? getTypeFromObjectBindingPattern(pattern, includePatternInType, reportErrors) : getTypeFromArrayBindingPattern(pattern, includePatternInType, reportErrors); } @@ -9702,20 +9900,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Here, the array literal [1, "one"] is contextually typed by the type [any, string], which is the implied type of the // binding pattern [x, s = ""]. Because the contextual type is a tuple type, the resulting type of [1, "one"] is the // tuple type [number, string]. Thus, the type inferred for 'x' is number and the type inferred for 's' is string. - function getWidenedTypeForVariableLikeDeclaration(declaration: ts.ParameterDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.VariableDeclaration | ts.BindingElement | ts.JSDocPropertyLikeTag, reportErrors?: boolean): ts.Type { + function getWidenedTypeForVariableLikeDeclaration(declaration: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement | JSDocPropertyLikeTag, reportErrors?: boolean): Type { return widenTypeForVariableLikeDeclaration(getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true, CheckMode.Normal), declaration, reportErrors); } - function isGlobalSymbolConstructor(node: ts.Node) { + function isGlobalSymbolConstructor(node: Node) { const symbol = getSymbolOfNode(node); const globalSymbol = getGlobalESSymbolConstructorTypeSymbol(/*reportErrors*/ false); return globalSymbol && symbol && symbol === globalSymbol; } - function widenTypeForVariableLikeDeclaration(type: ts.Type | undefined, declaration: any, reportErrors?: boolean) { + function widenTypeForVariableLikeDeclaration(type: Type | undefined, declaration: any, reportErrors?: boolean) { if (type) { // TODO: If back compat with pre-3.0/4.0 libs isn't required, remove the following SymbolConstructor special case transforming `symbol` into `unique symbol` - if (type.flags & ts.TypeFlags.ESSymbol && isGlobalSymbolConstructor(declaration.parent)) { + if (type.flags & TypeFlags.ESSymbol && isGlobalSymbolConstructor(declaration.parent)) { type = getESSymbolLikeTypeForNode(declaration); } if (reportErrors) { @@ -9723,7 +9921,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // always widen a 'unique symbol' type if the type was created for a different declaration. - if (type.flags & ts.TypeFlags.UniqueESSymbol && (ts.isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { + if (type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { type = esSymbolType; } @@ -9731,7 +9929,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Rest parameters default to type any[], other parameters default to type any - type = ts.isParameter(declaration) && declaration.dotDotDotToken ? anyArrayType : anyType; + type = isParameter(declaration) && declaration.dotDotDotToken ? anyArrayType : anyType; // Report implicit any errors unless this is a private property within an ambient declaration if (reportErrors) { @@ -9742,34 +9940,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function declarationBelongsToPrivateAmbientMember(declaration: ts.VariableLikeDeclaration) { - const root = ts.getRootDeclaration(declaration); - const memberDeclaration = root.kind === ts.SyntaxKind.Parameter ? root.parent : root; + function declarationBelongsToPrivateAmbientMember(declaration: VariableLikeDeclaration) { + const root = getRootDeclaration(declaration); + const memberDeclaration = root.kind === SyntaxKind.Parameter ? root.parent : root; return isPrivateWithinAmbient(memberDeclaration); } - function tryGetTypeFromEffectiveTypeNode(node: ts.Node) { - const typeNode = ts.getEffectiveTypeAnnotationNode(node); + function tryGetTypeFromEffectiveTypeNode(node: Node) { + const typeNode = getEffectiveTypeAnnotationNode(node); if (typeNode) { return getTypeFromTypeNode(typeNode); } } - function isParameterOfContextSensitiveSignature(symbol: ts.Symbol) { + function isParameterOfContextSensitiveSignature(symbol: Symbol) { let decl = symbol.valueDeclaration; if (!decl) { return false; } - if (ts.isBindingElement(decl)) { - decl = ts.walkUpBindingElementsAndPatterns(decl); + if (isBindingElement(decl)) { + decl = walkUpBindingElementsAndPatterns(decl); } - if (ts.isParameter(decl)) { + if (isParameter(decl)) { return isContextSensitiveFunctionOrObjectLiteralMethod(decl.parent); } return false; } - function getTypeOfVariableOrParameterOrProperty(symbol: ts.Symbol): ts.Type { + function getTypeOfVariableOrParameterOrProperty(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { const type = getTypeOfVariableOrParameterOrPropertyWorker(symbol); @@ -9786,33 +9984,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.type; } - function getTypeOfVariableOrParameterOrPropertyWorker(symbol: ts.Symbol): ts.Type { + function getTypeOfVariableOrParameterOrPropertyWorker(symbol: Symbol): Type { // Handle prototype property - if (symbol.flags & ts.SymbolFlags.Prototype) { + if (symbol.flags & SymbolFlags.Prototype) { return getTypeOfPrototypeProperty(symbol); } // CommonsJS require and module both have type any. if (symbol === requireSymbol) { return anyType; } - if (symbol.flags & ts.SymbolFlags.ModuleExports && symbol.valueDeclaration) { - const fileSymbol = getSymbolOfNode(ts.getSourceFileOfNode(symbol.valueDeclaration)); - const result = createSymbol(fileSymbol.flags, "exports" as ts.__String); + if (symbol.flags & SymbolFlags.ModuleExports && symbol.valueDeclaration) { + const fileSymbol = getSymbolOfNode(getSourceFileOfNode(symbol.valueDeclaration)); + const result = createSymbol(fileSymbol.flags, "exports" as __String); result.declarations = fileSymbol.declarations ? fileSymbol.declarations.slice() : []; result.parent = symbol; result.target = fileSymbol; if (fileSymbol.valueDeclaration) result.valueDeclaration = fileSymbol.valueDeclaration; - if (fileSymbol.members) result.members = new ts.Map(fileSymbol.members); - if (fileSymbol.exports) result.exports = new ts.Map(fileSymbol.exports); - const members = ts.createSymbolTable(); - members.set("exports" as ts.__String, result); - return createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, ts.emptyArray); + if (fileSymbol.members) result.members = new Map(fileSymbol.members); + if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports); + const members = createSymbolTable(); + members.set("exports" as __String, result); + return createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); } // Handle catch clause variables - ts.Debug.assertIsDefined(symbol.valueDeclaration); + Debug.assertIsDefined(symbol.valueDeclaration); const declaration = symbol.valueDeclaration; - if (ts.isCatchClauseVariableDeclarationOrBindingElement(declaration)) { - const typeNode = ts.getEffectiveTypeAnnotationNode(declaration); + if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) { + const typeNode = getEffectiveTypeAnnotationNode(declaration); if (typeNode === undefined) { return useUnknownInCatchVariables ? unknownType : anyType; } @@ -9821,13 +10019,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isTypeAny(type) || type === unknownType ? type : errorType; } // Handle export default expressions - if (ts.isSourceFile(declaration) && ts.isJsonSourceFile(declaration)) { + if (isSourceFile(declaration) && isJsonSourceFile(declaration)) { if (!declaration.statements.length) { return emptyObjectType; } return getWidenedType(getWidenedLiteralType(checkExpression(declaration.statements[0].expression))); } - if (ts.isAccessor(declaration)) { + if (isAccessor(declaration)) { // Binding of certain patterns in JS code will occasionally mark symbols as both properties // and accessors. Here we dispatch to accessor resolution if needed. return getTypeOfAccessors(symbol); @@ -9836,74 +10034,74 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Handle variable, parameter or property if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` - if (symbol.flags & ts.SymbolFlags.ValueModule && !(symbol.flags & ts.SymbolFlags.Assignment)) { + if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } return reportCircularityError(symbol); } - let type: ts.Type; - if (declaration.kind === ts.SyntaxKind.ExportAssignment) { - type = widenTypeForVariableLikeDeclaration(tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionCached((declaration as ts.ExportAssignment).expression), declaration); + let type: Type; + if (declaration.kind === SyntaxKind.ExportAssignment) { + type = widenTypeForVariableLikeDeclaration(tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionCached((declaration as ExportAssignment).expression), declaration); } else if ( - ts.isBinaryExpression(declaration) || - (ts.isInJSFile(declaration) && - (ts.isCallExpression(declaration) || (ts.isPropertyAccessExpression(declaration) || ts.isBindableStaticElementAccessExpression(declaration)) && ts.isBinaryExpression(declaration.parent)))) { + isBinaryExpression(declaration) || + (isInJSFile(declaration) && + (isCallExpression(declaration) || (isPropertyAccessExpression(declaration) || isBindableStaticElementAccessExpression(declaration)) && isBinaryExpression(declaration.parent)))) { type = getWidenedTypeForAssignmentDeclaration(symbol); } - else if (ts.isPropertyAccessExpression(declaration) - || ts.isElementAccessExpression(declaration) - || ts.isIdentifier(declaration) - || ts.isStringLiteralLike(declaration) - || ts.isNumericLiteral(declaration) - || ts.isClassDeclaration(declaration) - || ts.isFunctionDeclaration(declaration) - || (ts.isMethodDeclaration(declaration) && !ts.isObjectLiteralMethod(declaration)) - || ts.isMethodSignature(declaration) - || ts.isSourceFile(declaration)) { + else if (isPropertyAccessExpression(declaration) + || isElementAccessExpression(declaration) + || isIdentifier(declaration) + || isStringLiteralLike(declaration) + || isNumericLiteral(declaration) + || isClassDeclaration(declaration) + || isFunctionDeclaration(declaration) + || (isMethodDeclaration(declaration) && !isObjectLiteralMethod(declaration)) + || isMethodSignature(declaration) + || isSourceFile(declaration)) { // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.Class | ts.SymbolFlags.Enum | ts.SymbolFlags.ValueModule)) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { return getTypeOfFuncClassEnumModule(symbol); } - type = ts.isBinaryExpression(declaration.parent) ? + type = isBinaryExpression(declaration.parent) ? getWidenedTypeForAssignmentDeclaration(symbol) : tryGetTypeFromEffectiveTypeNode(declaration) || anyType; } - else if (ts.isPropertyAssignment(declaration)) { + else if (isPropertyAssignment(declaration)) { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkPropertyAssignment(declaration); } - else if (ts.isJsxAttribute(declaration)) { + else if (isJsxAttribute(declaration)) { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkJsxAttribute(declaration); } - else if (ts.isShorthandPropertyAssignment(declaration)) { + else if (isShorthandPropertyAssignment(declaration)) { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkExpressionForMutableLocation(declaration.name, CheckMode.Normal); } - else if (ts.isObjectLiteralMethod(declaration)) { + else if (isObjectLiteralMethod(declaration)) { type = tryGetTypeFromEffectiveTypeNode(declaration) || checkObjectLiteralMethod(declaration, CheckMode.Normal); } - else if (ts.isParameter(declaration) - || ts.isPropertyDeclaration(declaration) - || ts.isPropertySignature(declaration) - || ts.isVariableDeclaration(declaration) - || ts.isBindingElement(declaration) - || ts.isJSDocPropertyLikeTag(declaration)) { + else if (isParameter(declaration) + || isPropertyDeclaration(declaration) + || isPropertySignature(declaration) + || isVariableDeclaration(declaration) + || isBindingElement(declaration) + || isJSDocPropertyLikeTag(declaration)) { type = getWidenedTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ true); } // getTypeOfSymbol dispatches some JS merges incorrectly because their symbol flags are not mutually exclusive. // Re-dispatch based on valueDeclaration.kind instead. - else if (ts.isEnumDeclaration(declaration)) { + else if (isEnumDeclaration(declaration)) { type = getTypeOfFuncClassEnumModule(symbol); } - else if (ts.isEnumMember(declaration)) { + else if (isEnumMember(declaration)) { type = getTypeOfEnumMember(symbol); } else { - return ts.Debug.fail("Unhandled declaration kind! " + ts.Debug.formatSyntaxKind(declaration.kind) + " for " + ts.Debug.formatSymbol(symbol)); + return Debug.fail("Unhandled declaration kind! " + Debug.formatSyntaxKind(declaration.kind) + " for " + Debug.formatSymbol(symbol)); } if (!popTypeResolution()) { // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` - if (symbol.flags & ts.SymbolFlags.ValueModule && !(symbol.flags & ts.SymbolFlags.Assignment)) { + if (symbol.flags & SymbolFlags.ValueModule && !(symbol.flags & SymbolFlags.Assignment)) { return getTypeOfFuncClassEnumModule(symbol); } return reportCircularityError(symbol); @@ -9911,51 +10109,51 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function getAnnotatedAccessorTypeNode(accessor: ts.AccessorDeclaration | ts.PropertyDeclaration | undefined): ts.TypeNode | undefined { + function getAnnotatedAccessorTypeNode(accessor: AccessorDeclaration | PropertyDeclaration | undefined): TypeNode | undefined { if (accessor) { switch (accessor.kind) { - case ts.SyntaxKind.GetAccessor: - const getterTypeAnnotation = ts.getEffectiveReturnTypeNode(accessor); + case SyntaxKind.GetAccessor: + const getterTypeAnnotation = getEffectiveReturnTypeNode(accessor); return getterTypeAnnotation; - case ts.SyntaxKind.SetAccessor: - const setterTypeAnnotation = ts.getEffectiveSetAccessorTypeAnnotationNode(accessor); + case SyntaxKind.SetAccessor: + const setterTypeAnnotation = getEffectiveSetAccessorTypeAnnotationNode(accessor); return setterTypeAnnotation; - case ts.SyntaxKind.PropertyDeclaration: - ts.Debug.assert(ts.hasAccessorModifier(accessor)); - const accessorTypeAnnotation = ts.getEffectiveTypeAnnotationNode(accessor); + case SyntaxKind.PropertyDeclaration: + Debug.assert(hasAccessorModifier(accessor)); + const accessorTypeAnnotation = getEffectiveTypeAnnotationNode(accessor); return accessorTypeAnnotation; } } return undefined; } - function getAnnotatedAccessorType(accessor: ts.AccessorDeclaration | ts.PropertyDeclaration | undefined): ts.Type | undefined { + function getAnnotatedAccessorType(accessor: AccessorDeclaration | PropertyDeclaration | undefined): Type | undefined { const node = getAnnotatedAccessorTypeNode(accessor); return node && getTypeFromTypeNode(node); } - function getAnnotatedAccessorThisParameter(accessor: ts.AccessorDeclaration): ts.Symbol | undefined { + function getAnnotatedAccessorThisParameter(accessor: AccessorDeclaration): Symbol | undefined { const parameter = getAccessorThisParameter(accessor); return parameter && parameter.symbol; } - function getThisTypeOfDeclaration(declaration: ts.SignatureDeclaration): ts.Type | undefined { + function getThisTypeOfDeclaration(declaration: SignatureDeclaration): Type | undefined { return getThisTypeOfSignature(getSignatureFromDeclaration(declaration)); } - function getTypeOfAccessors(symbol: ts.Symbol): ts.Type { + function getTypeOfAccessors(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return errorType; } - const getter = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.GetAccessor); - const setter = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.SetAccessor); - const accessor = ts.tryCast(ts.getDeclarationOfKind(symbol, ts.SyntaxKind.PropertyDeclaration), ts.isAutoAccessorPropertyDeclaration); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); + const accessor = tryCast(getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration); // We try to resolve a getter type annotation, a setter type annotation, or a getter function // body return type inference, in that order. - let type = getter && ts.isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) || + let type = getter && isInJSFile(getter) && getTypeForDeclarationFromJSDocComment(getter) || getAnnotatedAccessorType(getter) || getAnnotatedAccessorType(setter) || getAnnotatedAccessorType(accessor) || @@ -9963,28 +10161,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { accessor && accessor.initializer && getWidenedTypeForVariableLikeDeclaration(accessor, /*includeOptionality*/ true); if (!type) { if (setter && !isPrivateWithinAmbient(setter)) { - errorOrSuggestion(noImplicitAny, setter, ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); + errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); } else if (getter && !isPrivateWithinAmbient(getter)) { - errorOrSuggestion(noImplicitAny, getter, ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); + errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); } else if (accessor && !isPrivateWithinAmbient(accessor)) { - errorOrSuggestion(noImplicitAny, accessor, ts.Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), "any"); + errorOrSuggestion(noImplicitAny, accessor, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), "any"); } type = anyType; } if (!popTypeResolution()) { if (getAnnotatedAccessorTypeNode(getter)) { - error(getter, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error(getter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); } else if (getAnnotatedAccessorTypeNode(setter)) { - error(setter, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); } else if (getAnnotatedAccessorTypeNode(accessor)) { - error(setter, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); } else if (getter && noImplicitAny) { - error(getter, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); + error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } type = anyType; } @@ -9993,19 +10191,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.type; } - function getWriteTypeOfAccessors(symbol: ts.Symbol): ts.Type { + function getWriteTypeOfAccessors(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.writeType) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.WriteType)) { return errorType; } - const setter = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.SetAccessor) - ?? ts.tryCast(ts.getDeclarationOfKind(symbol, ts.SyntaxKind.PropertyDeclaration), ts.isAutoAccessorPropertyDeclaration); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor) + ?? tryCast(getDeclarationOfKind(symbol, SyntaxKind.PropertyDeclaration), isAutoAccessorPropertyDeclaration); let writeType = getAnnotatedAccessorType(setter); if (!popTypeResolution()) { if (getAnnotatedAccessorTypeNode(setter)) { - error(setter, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); + error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); } writeType = anyType; } @@ -10015,14 +10213,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.writeType; } - function getBaseTypeVariableOfClass(symbol: ts.Symbol) { + function getBaseTypeVariableOfClass(symbol: Symbol) { const baseConstructorType = getBaseConstructorTypeOfClass(getDeclaredTypeOfClassOrInterface(symbol)); - return baseConstructorType.flags & ts.TypeFlags.TypeVariable ? baseConstructorType : - baseConstructorType.flags & ts.TypeFlags.Intersection ? ts.find((baseConstructorType as ts.IntersectionType).types, t => !!(t.flags & ts.TypeFlags.TypeVariable)) : + return baseConstructorType.flags & TypeFlags.TypeVariable ? baseConstructorType : + baseConstructorType.flags & TypeFlags.Intersection ? find((baseConstructorType as IntersectionType).types, t => !!(t.flags & TypeFlags.TypeVariable)) : undefined; } - function getTypeOfFuncClassEnumModule(symbol: ts.Symbol): ts.Type { + function getTypeOfFuncClassEnumModule(symbol: Symbol): Type { let links = getSymbolLinks(symbol); const originalLinks = links; if (!links.type) { @@ -10039,23 +10237,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.type; } - function getTypeOfFuncClassEnumModuleWorker(symbol: ts.Symbol): ts.Type { + function getTypeOfFuncClassEnumModuleWorker(symbol: Symbol): Type { const declaration = symbol.valueDeclaration; - if (symbol.flags & ts.SymbolFlags.Module && ts.isShorthandAmbientModuleSymbol(symbol)) { + if (symbol.flags & SymbolFlags.Module && isShorthandAmbientModuleSymbol(symbol)) { return anyType; } - else if (declaration && (declaration.kind === ts.SyntaxKind.BinaryExpression || - ts.isAccessExpression(declaration) && - declaration.parent.kind === ts.SyntaxKind.BinaryExpression)) { + else if (declaration && (declaration.kind === SyntaxKind.BinaryExpression || + isAccessExpression(declaration) && + declaration.parent.kind === SyntaxKind.BinaryExpression)) { return getWidenedTypeForAssignmentDeclaration(symbol); } - else if (symbol.flags & ts.SymbolFlags.ValueModule && declaration && ts.isSourceFile(declaration) && declaration.commonJsModuleIndicator) { + else if (symbol.flags & SymbolFlags.ValueModule && declaration && isSourceFile(declaration) && declaration.commonJsModuleIndicator) { const resolvedModule = resolveExternalModuleSymbol(symbol); if (resolvedModule !== symbol) { if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return errorType; } - const exportEquals = getMergedSymbol(symbol.exports!.get(ts.InternalSymbolName.ExportEquals)!); + const exportEquals = getMergedSymbol(symbol.exports!.get(InternalSymbolName.ExportEquals)!); const type = getWidenedTypeForAssignmentDeclaration(exportEquals, exportEquals === resolvedModule ? undefined : resolvedModule); if (!popTypeResolution()) { return reportCircularityError(symbol); @@ -10063,27 +10261,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } } - const type = createObjectType(ts.ObjectFlags.Anonymous, symbol); - if (symbol.flags & ts.SymbolFlags.Class) { + const type = createObjectType(ObjectFlags.Anonymous, symbol); + if (symbol.flags & SymbolFlags.Class) { const baseTypeVariable = getBaseTypeVariableOfClass(symbol); return baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - return strictNullChecks && symbol.flags & ts.SymbolFlags.Optional ? getOptionalType(type) : type; + return strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type) : type; } } - function getTypeOfEnumMember(symbol: ts.Symbol): ts.Type { + function getTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); return links.type || (links.type = getDeclaredTypeOfEnumMember(symbol)); } - function getTypeOfAlias(symbol: ts.Symbol): ts.Type { + function getTypeOfAlias(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.type) { const targetSymbol = resolveAlias(symbol); const exportSymbol = symbol.declarations && getTargetOfAliasDeclaration(getDeclarationOfAliasSymbol(symbol)!, /*dontResolveAlias*/ true); - const declaredType = ts.firstDefined(exportSymbol?.declarations, d => ts.isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined); + const declaredType = firstDefined(exportSymbol?.declarations, d => isExportAssignment(d) ? tryGetTypeFromEffectiveTypeNode(d) : undefined); // It only makes sense to get the type of a value symbol. If the result of resolving // the alias is not a value, then it has no type. To get the type associated with a // type symbol, call getDeclaredTypeOfSymbol. @@ -10092,33 +10290,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { links.type = exportSymbol?.declarations && isDuplicatedCommonJSExport(exportSymbol.declarations) && symbol.declarations!.length ? getFlowTypeFromCommonJSExport(exportSymbol) : isDuplicatedCommonJSExport(symbol.declarations) ? autoType : declaredType ? declaredType - : getAllSymbolFlags(targetSymbol) & ts.SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) + : getAllSymbolFlags(targetSymbol) & SymbolFlags.Value ? getTypeOfSymbol(targetSymbol) : errorType; } return links.type; } - function getTypeOfInstantiatedSymbol(symbol: ts.Symbol): ts.Type { + function getTypeOfInstantiatedSymbol(symbol: Symbol): Type { const links = getSymbolLinks(symbol); return links.type || (links.type = instantiateType(getTypeOfSymbol(links.target!), links.mapper)); } - function getWriteTypeOfInstantiatedSymbol(symbol: ts.Symbol): ts.Type { + function getWriteTypeOfInstantiatedSymbol(symbol: Symbol): Type { const links = getSymbolLinks(symbol); return links.writeType || (links.writeType = instantiateType(getWriteTypeOfSymbol(links.target!), links.mapper)); } - function reportCircularityError(symbol: ts.Symbol) { - const declaration = symbol.valueDeclaration as ts.VariableLikeDeclaration; + function reportCircularityError(symbol: Symbol) { + const declaration = symbol.valueDeclaration as VariableLikeDeclaration; // Check if variable has type annotation that circularly references the variable itself - if (ts.getEffectiveTypeAnnotationNode(declaration)) { - error(symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, + if (getEffectiveTypeAnnotationNode(declaration)) { + error(symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); return errorType; } // Check if variable has initializer that circularly references the variable itself - if (noImplicitAny && (declaration.kind !== ts.SyntaxKind.Parameter || (declaration as ts.HasInitializer).initializer)) { - error(symbol.valueDeclaration, ts.Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, + if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) { + error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } // Circularities could also result from parameters in function expressions that end up @@ -10127,22 +10325,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return anyType; } - function getTypeOfSymbolWithDeferredType(symbol: ts.Symbol) { + function getTypeOfSymbolWithDeferredType(symbol: Symbol) { const links = getSymbolLinks(symbol); if (!links.type) { - ts.Debug.assertIsDefined(links.deferralParent); - ts.Debug.assertIsDefined(links.deferralConstituents); - links.type = links.deferralParent.flags & ts.TypeFlags.Union ? getUnionType(links.deferralConstituents) : getIntersectionType(links.deferralConstituents); + Debug.assertIsDefined(links.deferralParent); + Debug.assertIsDefined(links.deferralConstituents); + links.type = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralConstituents) : getIntersectionType(links.deferralConstituents); } return links.type; } - function getWriteTypeOfSymbolWithDeferredType(symbol: ts.Symbol): ts.Type | undefined { + function getWriteTypeOfSymbolWithDeferredType(symbol: Symbol): Type | undefined { const links = getSymbolLinks(symbol); if (!links.writeType && links.deferralWriteConstituents) { - ts.Debug.assertIsDefined(links.deferralParent); - ts.Debug.assertIsDefined(links.deferralConstituents); - links.writeType = links.deferralParent.flags & ts.TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents); + Debug.assertIsDefined(links.deferralParent); + Debug.assertIsDefined(links.deferralConstituents); + links.writeType = links.deferralParent.flags & TypeFlags.Union ? getUnionType(links.deferralWriteConstituents) : getIntersectionType(links.deferralWriteConstituents); } return links.writeType; } @@ -10152,80 +10350,80 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * properties deriving from set accessors will either pre-compute or defer the union or * intersection of the writeTypes of their constituents. */ - function getWriteTypeOfSymbol(symbol: ts.Symbol): ts.Type { - const checkFlags = ts.getCheckFlags(symbol); - if (symbol.flags & ts.SymbolFlags.Property) { - return checkFlags & ts.CheckFlags.SyntheticProperty ? - checkFlags & ts.CheckFlags.DeferredType ? + function getWriteTypeOfSymbol(symbol: Symbol): Type { + const checkFlags = getCheckFlags(symbol); + if (symbol.flags & SymbolFlags.Property) { + return checkFlags & CheckFlags.SyntheticProperty ? + checkFlags & CheckFlags.DeferredType ? getWriteTypeOfSymbolWithDeferredType(symbol) || getTypeOfSymbolWithDeferredType(symbol) : - (symbol as ts.TransientSymbol).writeType || (symbol as ts.TransientSymbol).type! : + (symbol as TransientSymbol).writeType || (symbol as TransientSymbol).type! : getTypeOfSymbol(symbol); } - if (symbol.flags & ts.SymbolFlags.Accessor) { - return checkFlags & ts.CheckFlags.Instantiated ? + if (symbol.flags & SymbolFlags.Accessor) { + return checkFlags & CheckFlags.Instantiated ? getWriteTypeOfInstantiatedSymbol(symbol) : getWriteTypeOfAccessors(symbol); } return getTypeOfSymbol(symbol); } - function getTypeOfSymbol(symbol: ts.Symbol): ts.Type { - const checkFlags = ts.getCheckFlags(symbol); - if (checkFlags & ts.CheckFlags.DeferredType) { + function getTypeOfSymbol(symbol: Symbol): Type { + const checkFlags = getCheckFlags(symbol); + if (checkFlags & CheckFlags.DeferredType) { return getTypeOfSymbolWithDeferredType(symbol); } - if (checkFlags & ts.CheckFlags.Instantiated) { + if (checkFlags & CheckFlags.Instantiated) { return getTypeOfInstantiatedSymbol(symbol); } - if (checkFlags & ts.CheckFlags.Mapped) { - return getTypeOfMappedSymbol(symbol as ts.MappedSymbol); + if (checkFlags & CheckFlags.Mapped) { + return getTypeOfMappedSymbol(symbol as MappedSymbol); } - if (checkFlags & ts.CheckFlags.ReverseMapped) { - return getTypeOfReverseMappedSymbol(symbol as ts.ReverseMappedSymbol); + if (checkFlags & CheckFlags.ReverseMapped) { + return getTypeOfReverseMappedSymbol(symbol as ReverseMappedSymbol); } - if (symbol.flags & (ts.SymbolFlags.Variable | ts.SymbolFlags.Property)) { + if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { return getTypeOfVariableOrParameterOrProperty(symbol); } - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.Class | ts.SymbolFlags.Enum | ts.SymbolFlags.ValueModule)) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) { return getTypeOfFuncClassEnumModule(symbol); } - if (symbol.flags & ts.SymbolFlags.EnumMember) { + if (symbol.flags & SymbolFlags.EnumMember) { return getTypeOfEnumMember(symbol); } - if (symbol.flags & ts.SymbolFlags.Accessor) { + if (symbol.flags & SymbolFlags.Accessor) { return getTypeOfAccessors(symbol); } - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { return getTypeOfAlias(symbol); } return errorType; } - function getNonMissingTypeOfSymbol(symbol: ts.Symbol) { - return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & ts.SymbolFlags.Optional)); + function getNonMissingTypeOfSymbol(symbol: Symbol) { + return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional)); } - function isReferenceToType(type: ts.Type, target: ts.Type) { + function isReferenceToType(type: Type, target: Type) { return type !== undefined && target !== undefined - && (ts.getObjectFlags(type) & ts.ObjectFlags.Reference) !== 0 - && (type as ts.TypeReference).target === target; + && (getObjectFlags(type) & ObjectFlags.Reference) !== 0 + && (type as TypeReference).target === target; } - function getTargetType(type: ts.Type): ts.Type { - return ts.getObjectFlags(type) & ts.ObjectFlags.Reference ? (type as ts.TypeReference).target : type; + function getTargetType(type: Type): Type { + return getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target : type; } // TODO: GH#18217 If `checkBase` is undefined, we should not call this because this will always return false. - function hasBaseType(type: ts.Type, checkBase: ts.Type | undefined) { + function hasBaseType(type: Type, checkBase: Type | undefined) { return check(type); - function check(type: ts.Type): boolean { - if (ts.getObjectFlags(type) & (ts.ObjectFlags.ClassOrInterface | ts.ObjectFlags.Reference)) { - const target = getTargetType(type) as ts.InterfaceType; - return target === checkBase || ts.some(getBaseTypes(target), check); + function check(type: Type): boolean { + if (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) { + const target = getTargetType(type) as InterfaceType; + return target === checkBase || some(getBaseTypes(target), check); } - else if (type.flags & ts.TypeFlags.Intersection) { - return ts.some((type as ts.IntersectionType).types, check); + else if (type.flags & TypeFlags.Intersection) { + return some((type as IntersectionType).types, check); } return false; } @@ -10234,23 +10432,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Appends the type parameters given by a list of declarations to a set of type parameters and returns the resulting set. // The function allocates a new array if the input type parameter set is undefined, but otherwise it modifies the set // in-place and returns the same array. - function appendTypeParameters(typeParameters: ts.TypeParameter[] | undefined, declarations: readonly ts.TypeParameterDeclaration[]): ts.TypeParameter[] | undefined { + function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: readonly TypeParameterDeclaration[]): TypeParameter[] | undefined { for (const declaration of declarations) { - typeParameters = ts.appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); + typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); } return typeParameters; } // Return the outer type parameters of a node or undefined if the node has no outer type parameters. - function getOuterTypeParameters(node: ts.Node, includeThisTypes?: boolean): ts.TypeParameter[] | undefined { + function getOuterTypeParameters(node: Node, includeThisTypes?: boolean): TypeParameter[] | undefined { while (true) { node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead - if (node && ts.isBinaryExpression(node)) { + if (node && isBinaryExpression(node)) { // prototype assignments get the outer type parameters of their constructor function - const assignmentKind = ts.getAssignmentDeclarationKind(node); - if (assignmentKind === ts.AssignmentDeclarationKind.Prototype || assignmentKind === ts.AssignmentDeclarationKind.PrototypeProperty) { + const assignmentKind = getAssignmentDeclarationKind(node); + if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) { const symbol = getSymbolOfNode(node.left); - if (symbol && symbol.parent && !ts.findAncestor(symbol.parent.valueDeclaration, d => node === d)) { + if (symbol && symbol.parent && !findAncestor(symbol.parent.valueDeclaration, d => node === d)) { node = symbol.parent.valueDeclaration!; } } @@ -10259,49 +10457,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.JSDocFunctionType: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.JSDocTemplateTag: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocEnumTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.MappedType: - case ts.SyntaxKind.ConditionalType: { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.JSDocTemplateTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.MappedType: + case SyntaxKind.ConditionalType: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); - if (node.kind === ts.SyntaxKind.MappedType) { - return ts.append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node as ts.MappedTypeNode).typeParameter))); + if (node.kind === SyntaxKind.MappedType) { + return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node as MappedTypeNode).typeParameter))); } - else if (node.kind === ts.SyntaxKind.ConditionalType) { - return ts.concatenate(outerTypeParameters, getInferTypeParameters(node as ts.ConditionalTypeNode)); + else if (node.kind === SyntaxKind.ConditionalType) { + return concatenate(outerTypeParameters, getInferTypeParameters(node as ConditionalTypeNode)); } - const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, ts.getEffectiveTypeParameterDeclarations(node as ts.DeclarationWithTypeParameters)); + const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters)); const thisType = includeThisTypes && - (node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ClassExpression || node.kind === ts.SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) && - getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ts.ClassLikeDeclaration | ts.InterfaceDeclaration)).thisType; - return thisType ? ts.append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; + (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) && + getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType; + return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } - case ts.SyntaxKind.JSDocParameterTag: - const paramSymbol = ts.getParameterSymbolFromJSDoc(node as ts.JSDocParameterTag); + case SyntaxKind.JSDocParameterTag: + const paramSymbol = getParameterSymbolFromJSDoc(node as JSDocParameterTag); if (paramSymbol) { node = paramSymbol.valueDeclaration!; } break; - case ts.SyntaxKind.JSDoc: { + case SyntaxKind.JSDoc: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); - return (node as ts.JSDoc).tags - ? appendTypeParameters(outerTypeParameters, ts.flatMap((node as ts.JSDoc).tags, t => ts.isJSDocTemplateTag(t) ? t.typeParameters : undefined)) + return (node as JSDoc).tags + ? appendTypeParameters(outerTypeParameters, flatMap((node as JSDoc).tags, t => isJSDocTemplateTag(t) ? t.typeParameters : undefined)) : outerTypeParameters; } } @@ -10309,27 +10507,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // The outer type parameters are those defined by enclosing generic classes, methods, or functions. - function getOuterTypeParametersOfClassOrInterface(symbol: ts.Symbol): ts.TypeParameter[] | undefined { - const declaration = symbol.flags & ts.SymbolFlags.Class ? symbol.valueDeclaration : ts.getDeclarationOfKind(symbol, ts.SyntaxKind.InterfaceDeclaration)!; - ts.Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations"); + function getOuterTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { + const declaration = symbol.flags & SymbolFlags.Class ? symbol.valueDeclaration : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration)!; + Debug.assert(!!declaration, "Class was missing valueDeclaration -OR- non-class had no interface declarations"); return getOuterTypeParameters(declaration); } // The local type parameters are the combined set of type parameters from all declarations of the class, // interface, or type alias. - function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: ts.Symbol): ts.TypeParameter[] | undefined { + function getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol: Symbol): TypeParameter[] | undefined { if (!symbol.declarations) { return; } - let result: ts.TypeParameter[] | undefined; + let result: TypeParameter[] | undefined; for (const node of symbol.declarations) { - if (node.kind === ts.SyntaxKind.InterfaceDeclaration || - node.kind === ts.SyntaxKind.ClassDeclaration || - node.kind === ts.SyntaxKind.ClassExpression || + if (node.kind === SyntaxKind.InterfaceDeclaration || + node.kind === SyntaxKind.ClassDeclaration || + node.kind === SyntaxKind.ClassExpression || isJSConstructor(node) || - ts.isTypeAlias(node)) { - const declaration = node as ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.JSDocTypedefTag | ts.JSDocCallbackTag; - result = appendTypeParameters(result, ts.getEffectiveTypeParameterDeclarations(declaration)); + isTypeAlias(node)) { + const declaration = node as InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag; + result = appendTypeParameters(result, getEffectiveTypeParameterDeclarations(declaration)); } } return result; @@ -10337,14 +10535,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The full set of type parameters for a generic class or interface type consists of its outer type parameters plus // its locally declared type parameters. - function getTypeParametersOfClassOrInterface(symbol: ts.Symbol): ts.TypeParameter[] | undefined { - return ts.concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); + function getTypeParametersOfClassOrInterface(symbol: Symbol): TypeParameter[] | undefined { + return concatenate(getOuterTypeParametersOfClassOrInterface(symbol), getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol)); } // A type is a mixin constructor if it has a single construct signature taking no type parameters and a single // rest parameter of type any[]. - function isMixinConstructorType(type: ts.Type) { - const signatures = getSignaturesOfType(type, ts.SignatureKind.Construct); + function isMixinConstructorType(type: Type) { + const signatures = getSignaturesOfType(type, SignatureKind.Construct); if (signatures.length === 1) { const s = signatures[0]; if (!s.typeParameters && s.parameters.length === 1 && signatureHasRestParameter(s)) { @@ -10355,33 +10553,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isConstructorType(type: ts.Type): boolean { - if (getSignaturesOfType(type, ts.SignatureKind.Construct).length > 0) { + function isConstructorType(type: Type): boolean { + if (getSignaturesOfType(type, SignatureKind.Construct).length > 0) { return true; } - if (type.flags & ts.TypeFlags.TypeVariable) { + if (type.flags & TypeFlags.TypeVariable) { const constraint = getBaseConstraintOfType(type); return !!constraint && isMixinConstructorType(constraint); } return false; } - function getBaseTypeNodeOfClass(type: ts.InterfaceType): ts.ExpressionWithTypeArguments | undefined { - const decl = ts.getClassLikeDeclarationOfSymbol(type.symbol); - return decl && ts.getEffectiveBaseTypeNode(decl); + function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined { + const decl = getClassLikeDeclarationOfSymbol(type.symbol); + return decl && getEffectiveBaseTypeNode(decl); } - function getConstructorsForTypeArguments(type: ts.Type, typeArgumentNodes: readonly ts.TypeNode[] | undefined, location: ts.Node): readonly ts.Signature[] { - const typeArgCount = ts.length(typeArgumentNodes); - const isJavascript = ts.isInJSFile(location); - return ts.filter(getSignaturesOfType(type, ts.SignatureKind.Construct), - sig => (isJavascript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= ts.length(sig.typeParameters)); + function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] { + const typeArgCount = length(typeArgumentNodes); + const isJavascript = isInJSFile(location); + return filter(getSignaturesOfType(type, SignatureKind.Construct), + sig => (isJavascript || typeArgCount >= getMinTypeArgumentCount(sig.typeParameters)) && typeArgCount <= length(sig.typeParameters)); } - function getInstantiatedConstructorsForTypeArguments(type: ts.Type, typeArgumentNodes: readonly ts.TypeNode[] | undefined, location: ts.Node): readonly ts.Signature[] { + function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: readonly TypeNode[] | undefined, location: Node): readonly Signature[] { const signatures = getConstructorsForTypeArguments(type, typeArgumentNodes, location); - const typeArguments = ts.map(typeArgumentNodes, getTypeFromTypeNode); - return ts.sameMap(signatures, sig => ts.some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, ts.isInJSFile(location)) : sig); + const typeArguments = map(typeArgumentNodes, getTypeFromTypeNode); + return sameMap(signatures, sig => some(sig.typeParameters) ? getSignatureInstantiation(sig, typeArguments, isInJSFile(location)) : sig); } /** @@ -10392,10 +10590,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * anyType if the extends expression has type any, or * * an object type with at least one construct signature. */ - function getBaseConstructorTypeOfClass(type: ts.InterfaceType): ts.Type { + function getBaseConstructorTypeOfClass(type: InterfaceType): Type { if (!type.resolvedBaseConstructorType) { - const decl = ts.getClassLikeDeclarationOfSymbol(type.symbol); - const extended = decl && ts.getEffectiveBaseTypeNode(decl); + const decl = getClassLikeDeclarationOfSymbol(type.symbol); + const extended = decl && getEffectiveBaseTypeNode(decl); const baseTypeNode = getBaseTypeNodeOfClass(type); if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; @@ -10405,31 +10603,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const baseConstructorType = checkExpression(baseTypeNode.expression); if (extended && baseTypeNode !== extended) { - ts.Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag + Debug.assert(!extended.typeArguments); // Because this is in a JS file, and baseTypeNode is in an @extends tag checkExpression(extended.expression); } - if (baseConstructorType.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection)) { + if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection)) { // Resolving the members of a class requires us to resolve the base class of that class. // We force resolution here such that we catch circularities now. - resolveStructuredTypeMembers(baseConstructorType as ts.ObjectType); + resolveStructuredTypeMembers(baseConstructorType as ObjectType); } if (!popTypeResolution()) { - error(type.symbol.valueDeclaration, ts.Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); + error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol)); return type.resolvedBaseConstructorType = errorType; } - if (!(baseConstructorType.flags & ts.TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { - const err = error(baseTypeNode.expression, ts.Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); - if (baseConstructorType.flags & ts.TypeFlags.TypeParameter) { + if (!(baseConstructorType.flags & TypeFlags.Any) && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) { + const err = error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType)); + if (baseConstructorType.flags & TypeFlags.TypeParameter) { const constraint = getConstraintFromTypeParameter(baseConstructorType); - let ctorReturn: ts.Type = unknownType; + let ctorReturn: Type = unknownType; if (constraint) { - const ctorSig = getSignaturesOfType(constraint, ts.SignatureKind.Construct); + const ctorSig = getSignaturesOfType(constraint, SignatureKind.Construct); if (ctorSig[0]) { ctorReturn = getReturnTypeOfSignature(ctorSig[0]); } } if (baseConstructorType.symbol.declarations) { - ts.addRelatedInfo(err, ts.createDiagnosticForNode(baseConstructorType.symbol.declarations[0], ts.Diagnostics.Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1, symbolToString(baseConstructorType.symbol), typeToString(ctorReturn))); + addRelatedInfo(err, createDiagnosticForNode(baseConstructorType.symbol.declarations[0], Diagnostics.Did_you_mean_for_0_to_be_constrained_to_type_new_args_Colon_any_1, symbolToString(baseConstructorType.symbol), typeToString(ctorReturn))); } } return type.resolvedBaseConstructorType = errorType; @@ -10439,17 +10637,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedBaseConstructorType; } - function getImplementsTypes(type: ts.InterfaceType): ts.BaseType[] { - let resolvedImplementsTypes: ts.BaseType[] = ts.emptyArray; + function getImplementsTypes(type: InterfaceType): BaseType[] { + let resolvedImplementsTypes: BaseType[] = emptyArray; if (type.symbol.declarations) { for (const declaration of type.symbol.declarations) { - const implementsTypeNodes = ts.getEffectiveImplementsTypeNodes(declaration as ts.ClassLikeDeclaration); + const implementsTypeNodes = getEffectiveImplementsTypeNodes(declaration as ClassLikeDeclaration); if (!implementsTypeNodes) continue; for (const node of implementsTypeNodes) { const implementsType = getTypeFromTypeNode(node); if (!isErrorType(implementsType)) { - if (resolvedImplementsTypes === ts.emptyArray) { - resolvedImplementsTypes = [implementsType as ts.ObjectType]; + if (resolvedImplementsTypes === emptyArray) { + resolvedImplementsTypes = [implementsType as ObjectType]; } else { resolvedImplementsTypes.push(implementsType); @@ -10461,30 +10659,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolvedImplementsTypes; } - function reportCircularBaseType(node: ts.Node, type: ts.Type) { - error(node, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.WriteArrayAsGenericType)); + function reportCircularBaseType(node: Node, type: Type) { + error(node, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); } - function getBaseTypes(type: ts.InterfaceType): ts.BaseType[] { + function getBaseTypes(type: InterfaceType): BaseType[] { if (!type.baseTypesResolved) { if (pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseTypes)) { - if (type.objectFlags & ts.ObjectFlags.Tuple) { - type.resolvedBaseTypes = [getTupleBaseType(type as ts.TupleType)]; + if (type.objectFlags & ObjectFlags.Tuple) { + type.resolvedBaseTypes = [getTupleBaseType(type as TupleType)]; } - else if (type.symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface)) { - if (type.symbol.flags & ts.SymbolFlags.Class) { + else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { + if (type.symbol.flags & SymbolFlags.Class) { resolveBaseTypesOfClass(type); } - if (type.symbol.flags & ts.SymbolFlags.Interface) { + if (type.symbol.flags & SymbolFlags.Interface) { resolveBaseTypesOfInterface(type); } } else { - ts.Debug.fail("type must be class or interface"); + Debug.fail("type must be class or interface"); } if (!popTypeResolution() && type.symbol.declarations) { for (const declaration of type.symbol.declarations) { - if (declaration.kind === ts.SyntaxKind.ClassDeclaration || declaration.kind === ts.SyntaxKind.InterfaceDeclaration) { + if (declaration.kind === SyntaxKind.ClassDeclaration || declaration.kind === SyntaxKind.InterfaceDeclaration) { reportCircularBaseType(declaration, type); } } @@ -10495,28 +10693,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedBaseTypes; } - function getTupleBaseType(type: ts.TupleType) { - const elementTypes = ts.sameMap(type.typeParameters, (t, i) => type.elementFlags[i] & ts.ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); - return createArrayType(getUnionType(elementTypes || ts.emptyArray), type.readonly); + function getTupleBaseType(type: TupleType) { + const elementTypes = sameMap(type.typeParameters, (t, i) => type.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); + return createArrayType(getUnionType(elementTypes || emptyArray), type.readonly); } - function resolveBaseTypesOfClass(type: ts.InterfaceType) { - type.resolvedBaseTypes = ts.resolvingEmptyArray; + function resolveBaseTypesOfClass(type: InterfaceType) { + type.resolvedBaseTypes = resolvingEmptyArray; const baseConstructorType = getApparentType(getBaseConstructorTypeOfClass(type)); - if (!(baseConstructorType.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.Any))) { - return type.resolvedBaseTypes = ts.emptyArray; + if (!(baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Any))) { + return type.resolvedBaseTypes = emptyArray; } const baseTypeNode = getBaseTypeNodeOfClass(type)!; - let baseType: ts.Type; + let baseType: Type; const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined; - if (baseConstructorType.symbol && baseConstructorType.symbol.flags & ts.SymbolFlags.Class && + if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class && areAllOuterTypeParametersApplied(originalBaseType!)) { // When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the // class and all return the instance type of the class. There is no need for further checks and we can apply the // type arguments in the same manner as a type reference to get the same error reporting experience. baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol); } - else if (baseConstructorType.flags & ts.TypeFlags.Any) { + else if (baseConstructorType.flags & TypeFlags.Any) { baseType = baseConstructorType; } else { @@ -10525,28 +10723,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // we check that all instantiated signatures return the same type. const constructors = getInstantiatedConstructorsForTypeArguments(baseConstructorType, baseTypeNode.typeArguments, baseTypeNode); if (!constructors.length) { - error(baseTypeNode.expression, ts.Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); - return type.resolvedBaseTypes = ts.emptyArray; + error(baseTypeNode.expression, Diagnostics.No_base_constructor_has_the_specified_number_of_type_arguments); + return type.resolvedBaseTypes = emptyArray; } baseType = getReturnTypeOfSignature(constructors[0]); } if (isErrorType(baseType)) { - return type.resolvedBaseTypes = ts.emptyArray; + return type.resolvedBaseTypes = emptyArray; } const reducedBaseType = getReducedType(baseType); if (!isValidBaseType(reducedBaseType)) { const elaboration = elaborateNeverIntersection(/*errorInfo*/ undefined, baseType); - const diagnostic = ts.chainDiagnosticMessages(elaboration, ts.Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType)); - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(baseTypeNode.expression, diagnostic)); - return type.resolvedBaseTypes = ts.emptyArray; + const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.Base_constructor_return_type_0_is_not_an_object_type_or_intersection_of_object_types_with_statically_known_members, typeToString(reducedBaseType)); + diagnostics.add(createDiagnosticForNodeFromMessageChain(baseTypeNode.expression, diagnostic)); + return type.resolvedBaseTypes = emptyArray; } if (type === reducedBaseType || hasBaseType(reducedBaseType, type)) { - error(type.symbol.valueDeclaration, ts.Diagnostics.Type_0_recursively_references_itself_as_a_base_type, - typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.WriteArrayAsGenericType)); - return type.resolvedBaseTypes = ts.emptyArray; + error(type.symbol.valueDeclaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType)); + return type.resolvedBaseTypes = emptyArray; } - if (type.resolvedBaseTypes === ts.resolvingEmptyArray) { + if (type.resolvedBaseTypes === resolvingEmptyArray) { // Circular reference, likely through instantiation of default parameters // (otherwise there'd be an error from hasBaseType) - this is fine, but `.members` should be reset // as `getIndexedAccessType` via `instantiateType` via `getTypeFromClassOrInterfaceReference` forces a @@ -10556,21 +10754,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedBaseTypes = [reducedBaseType]; } - function areAllOuterTypeParametersApplied(type: ts.Type): boolean { // TODO: GH#18217 Shouldn't this take an InterfaceType? + function areAllOuterTypeParametersApplied(type: Type): boolean { // TODO: GH#18217 Shouldn't this take an InterfaceType? // An unapplied type parameter has its symbol still the same as the matching argument symbol. // Since parameters are applied outer-to-inner, only the last outer parameter needs to be checked. - const outerTypeParameters = (type as ts.InterfaceType).outerTypeParameters; + const outerTypeParameters = (type as InterfaceType).outerTypeParameters; if (outerTypeParameters) { const last = outerTypeParameters.length - 1; - const typeArguments = getTypeArguments(type as ts.TypeReference); + const typeArguments = getTypeArguments(type as TypeReference); return outerTypeParameters[last].symbol !== typeArguments[last].symbol; } return true; } // A valid base type is `any`, an object type or intersection of object types. - function isValidBaseType(type: ts.Type): type is ts.BaseType { - if (type.flags & ts.TypeFlags.TypeParameter) { + function isValidBaseType(type: Type): type is BaseType { + if (type.flags & TypeFlags.TypeParameter) { const constraint = getBaseConstraintOfType(type); if (constraint) { return isValidBaseType(constraint); @@ -10578,22 +10776,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // TODO: Given that we allow type parmeters here now, is this `!isGenericMappedType(type)` check really needed? // There's no reason a `T` should be allowed while a `Readonly` should not. - return !!(type.flags & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive | ts.TypeFlags.Any) && !isGenericMappedType(type) || - type.flags & ts.TypeFlags.Intersection && ts.every((type as ts.IntersectionType).types, isValidBaseType)); + return !!(type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.Any) && !isGenericMappedType(type) || + type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isValidBaseType)); } - function resolveBaseTypesOfInterface(type: ts.InterfaceType): void { - type.resolvedBaseTypes = type.resolvedBaseTypes || ts.emptyArray; + function resolveBaseTypesOfInterface(type: InterfaceType): void { + type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray; if (type.symbol.declarations) { for (const declaration of type.symbol.declarations) { - if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration && ts.getInterfaceBaseTypeNodes(declaration as ts.InterfaceDeclaration)) { - for (const node of ts.getInterfaceBaseTypeNodes(declaration as ts.InterfaceDeclaration)!) { + if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)) { + for (const node of getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration)!) { const baseType = getReducedType(getTypeFromTypeNode(node)); if (!isErrorType(baseType)) { if (isValidBaseType(baseType)) { if (type !== baseType && !hasBaseType(baseType, type)) { - if (type.resolvedBaseTypes === ts.emptyArray) { - type.resolvedBaseTypes = [baseType as ts.ObjectType]; + if (type.resolvedBaseTypes === emptyArray) { + type.resolvedBaseTypes = [baseType as ObjectType]; } else { type.resolvedBaseTypes.push(baseType); @@ -10604,7 +10802,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else { - error(node, ts.Diagnostics.An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_members); + error(node, Diagnostics.An_interface_can_only_extend_an_object_type_or_intersection_of_object_types_with_statically_known_members); } } } @@ -10620,21 +10818,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * to "this" in its body, if all base types are interfaces, * and if none of the base interfaces have a "this" type. */ - function isThislessInterface(symbol: ts.Symbol): boolean { + function isThislessInterface(symbol: Symbol): boolean { if (!symbol.declarations) { return true; } for (const declaration of symbol.declarations) { - if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration) { - if (declaration.flags & ts.NodeFlags.ContainsThis) { + if (declaration.kind === SyntaxKind.InterfaceDeclaration) { + if (declaration.flags & NodeFlags.ContainsThis) { return false; } - const baseTypeNodes = ts.getInterfaceBaseTypeNodes(declaration as ts.InterfaceDeclaration); + const baseTypeNodes = getInterfaceBaseTypeNodes(declaration as InterfaceDeclaration); if (baseTypeNodes) { for (const node of baseTypeNodes) { - if (ts.isEntityNameExpression(node.expression)) { - const baseSymbol = resolveEntityName(node.expression, ts.SymbolFlags.Type, /*ignoreErrors*/ true); - if (!baseSymbol || !(baseSymbol.flags & ts.SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { + if (isEntityNameExpression(node.expression)) { + const baseSymbol = resolveEntityName(node.expression, SymbolFlags.Type, /*ignoreErrors*/ true); + if (!baseSymbol || !(baseSymbol.flags & SymbolFlags.Interface) || getDeclaredTypeOfClassOrInterface(baseSymbol).thisType) { return false; } } @@ -10645,18 +10843,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function getDeclaredTypeOfClassOrInterface(symbol: ts.Symbol): ts.InterfaceType { + function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType { let links = getSymbolLinks(symbol); const originalLinks = links; if (!links.declaredType) { - const kind = symbol.flags & ts.SymbolFlags.Class ? ts.ObjectFlags.Class : ts.ObjectFlags.Interface; + const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface; const merged = mergeJSSymbols(symbol, symbol.valueDeclaration && getAssignedClassSymbol(symbol.valueDeclaration)); if (merged) { // note:we overwrite links because we just cloned the symbol symbol = links = merged; } - const type = originalLinks.declaredType = links.declaredType = createObjectType(kind, symbol) as ts.InterfaceType; + const type = originalLinks.declaredType = links.declaredType = createObjectType(kind, symbol) as InterfaceType; const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol); const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); // A class or interface is generic if it has type parameters or a "this" type. We always give classes a "this" type @@ -10664,24 +10862,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // property types inferred from initializers and method return types inferred from return statements are very hard // to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of // "this" references. - if (outerTypeParameters || localTypeParameters || kind === ts.ObjectFlags.Class || !isThislessInterface(symbol)) { - type.objectFlags |= ts.ObjectFlags.Reference; - type.typeParameters = ts.concatenate(outerTypeParameters, localTypeParameters); + if (outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isThislessInterface(symbol)) { + type.objectFlags |= ObjectFlags.Reference; + type.typeParameters = concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; type.localTypeParameters = localTypeParameters; - (type as ts.GenericType).instantiations = new ts.Map(); - (type as ts.GenericType).instantiations.set(getTypeListId(type.typeParameters), type as ts.GenericType); - (type as ts.GenericType).target = type as ts.GenericType; - (type as ts.GenericType).resolvedTypeArguments = type.typeParameters; + (type as GenericType).instantiations = new Map(); + (type as GenericType).instantiations.set(getTypeListId(type.typeParameters), type as GenericType); + (type as GenericType).target = type as GenericType; + (type as GenericType).resolvedTypeArguments = type.typeParameters; type.thisType = createTypeParameter(symbol); type.thisType.isThisType = true; type.thisType.constraint = type; } } - return links.declaredType as ts.InterfaceType; + return links.declaredType as InterfaceType; } - function getDeclaredTypeOfTypeAlias(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { // Note that we use the links object as the target here because the symbol object is used as the unique @@ -10690,8 +10888,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return errorType; } - const declaration = ts.Debug.checkDefined(symbol.declarations?.find(ts.isTypeAlias), "Type alias symbol with no valid declaration found"); - const typeNode = ts.isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type; + const declaration = Debug.checkDefined(symbol.declarations?.find(isTypeAlias), "Type alias symbol with no valid declaration found"); + const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type; // If typeNode is missing, we will error in checkJSDocTypedefTag. let type = typeNode ? getTypeFromTypeNode(typeNode) : errorType; @@ -10701,17 +10899,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Initialize the instantiation cache for generic type aliases. The declared type corresponds to // an instantiation of the type alias with the type parameters supplied as type arguments. links.typeParameters = typeParameters; - links.instantiations = new ts.Map(); + links.instantiations = new Map(); links.instantiations.set(getTypeListId(typeParameters), type); } } else { type = errorType; - if (declaration.kind === ts.SyntaxKind.JSDocEnumTag) { - error(declaration.typeExpression.type, ts.Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); + if (declaration.kind === SyntaxKind.JSDocEnumTag) { + error(declaration.typeExpression.type, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); } else { - error(ts.isNamedDeclaration(declaration) ? declaration.name || declaration : declaration, ts.Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); + error(isNamedDeclaration(declaration) ? declaration.name || declaration : declaration, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol)); } } links.declaredType = type; @@ -10719,24 +10917,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.declaredType; } - function getBaseTypeOfEnumLiteralType(type: ts.Type) { - return type.flags & ts.TypeFlags.EnumLiteral && !(type.flags & ts.TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; + function getBaseTypeOfEnumLiteralType(type: Type) { + return type.flags & TypeFlags.EnumLiteral && !(type.flags & TypeFlags.Union) ? getDeclaredTypeOfSymbol(getParentOfSymbol(type.symbol)!) : type; } - function getDeclaredTypeOfEnum(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfEnum(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { - const memberTypeList: ts.Type[] = []; + const memberTypeList: Type[] = []; if (symbol.declarations) { for (const declaration of symbol.declarations) { - if (declaration.kind === ts.SyntaxKind.EnumDeclaration) { - for (const member of (declaration as ts.EnumDeclaration).members) { + if (declaration.kind === SyntaxKind.EnumDeclaration) { + for (const member of (declaration as EnumDeclaration).members) { if (hasBindableName(member)) { const memberSymbol = getSymbolOfNode(member); const value = getEnumMemberValue(member); const memberType = value !== undefined ? getFreshTypeOfLiteralType(getEnumLiteralType(value, getSymbolId(symbol), memberSymbol)) : - createTypeWithSymbol(ts.TypeFlags.Enum, memberSymbol); + createTypeWithSymbol(TypeFlags.Enum, memberSymbol); getSymbolLinks(memberSymbol).declaredType = memberType; memberTypeList.push(getRegularTypeOfLiteralType(memberType)); } @@ -10745,10 +10943,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } const enumType = memberTypeList.length ? - getUnionType(memberTypeList, ts.UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) : - createTypeWithSymbol(ts.TypeFlags.Enum, symbol); - if (enumType.flags & ts.TypeFlags.Union) { - enumType.flags |= ts.TypeFlags.EnumLiteral; + getUnionType(memberTypeList, UnionReduction.Literal, symbol, /*aliasTypeArguments*/ undefined) : + createTypeWithSymbol(TypeFlags.Enum, symbol); + if (enumType.flags & TypeFlags.Union) { + enumType.flags |= TypeFlags.EnumLiteral; enumType.symbol = symbol; } links.declaredType = enumType; @@ -10756,7 +10954,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.declaredType; } - function getDeclaredTypeOfEnumMember(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfEnumMember(symbol: Symbol): Type { const links = getSymbolLinks(symbol); if (!links.declaredType) { const enumType = getDeclaredTypeOfEnum(getParentOfSymbol(symbol)!); @@ -10767,37 +10965,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.declaredType; } - function getDeclaredTypeOfTypeParameter(symbol: ts.Symbol): ts.TypeParameter { + function getDeclaredTypeOfTypeParameter(symbol: Symbol): TypeParameter { const links = getSymbolLinks(symbol); return links.declaredType || (links.declaredType = createTypeParameter(symbol)); } - function getDeclaredTypeOfAlias(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfAlias(symbol: Symbol): Type { const links = getSymbolLinks(symbol); return links.declaredType || (links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol))); } - function getDeclaredTypeOfSymbol(symbol: ts.Symbol): ts.Type { + function getDeclaredTypeOfSymbol(symbol: Symbol): Type { return tryGetDeclaredTypeOfSymbol(symbol) || errorType; } - function tryGetDeclaredTypeOfSymbol(symbol: ts.Symbol): ts.Type | undefined { - if (symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface)) { + function tryGetDeclaredTypeOfSymbol(symbol: Symbol): Type | undefined { + if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { return getDeclaredTypeOfClassOrInterface(symbol); } - if (symbol.flags & ts.SymbolFlags.TypeAlias) { + if (symbol.flags & SymbolFlags.TypeAlias) { return getDeclaredTypeOfTypeAlias(symbol); } - if (symbol.flags & ts.SymbolFlags.TypeParameter) { + if (symbol.flags & SymbolFlags.TypeParameter) { return getDeclaredTypeOfTypeParameter(symbol); } - if (symbol.flags & ts.SymbolFlags.Enum) { + if (symbol.flags & SymbolFlags.Enum) { return getDeclaredTypeOfEnum(symbol); } - if (symbol.flags & ts.SymbolFlags.EnumMember) { + if (symbol.flags & SymbolFlags.EnumMember) { return getDeclaredTypeOfEnumMember(symbol); } - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { return getDeclaredTypeOfAlias(symbol); } return undefined; @@ -10808,32 +11006,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * literal type, an array with an element type that is free of this references, or a type reference that is * free of this references. */ - function isThislessType(node: ts.TypeNode): boolean { + function isThislessType(node: TypeNode): boolean { switch (node.kind) { - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.UnknownKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.ObjectKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.UndefinedKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.LiteralType: + case SyntaxKind.AnyKeyword: + case SyntaxKind.UnknownKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.LiteralType: return true; - case ts.SyntaxKind.ArrayType: - return isThislessType((node as ts.ArrayTypeNode).elementType); - case ts.SyntaxKind.TypeReference: - return !(node as ts.TypeReferenceNode).typeArguments || (node as ts.TypeReferenceNode).typeArguments!.every(isThislessType); + case SyntaxKind.ArrayType: + return isThislessType((node as ArrayTypeNode).elementType); + case SyntaxKind.TypeReference: + return !(node as TypeReferenceNode).typeArguments || (node as TypeReferenceNode).typeArguments!.every(isThislessType); } return false; } /** A type parameter is thisless if its constraint is thisless, or if it has no constraint. */ - function isThislessTypeParameter(node: ts.TypeParameterDeclaration) { - const constraint = ts.getEffectiveConstraintOfTypeParameter(node); + function isThislessTypeParameter(node: TypeParameterDeclaration) { + const constraint = getEffectiveConstraintOfTypeParameter(node); return !constraint || isThislessType(constraint); } @@ -10841,9 +11039,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * A variable-like declaration is free of this references if it has a type annotation * that is thisless, or if it has no type annotation and no initializer (and is thus of type any). */ - function isThislessVariableLikeDeclaration(node: ts.VariableLikeDeclaration): boolean { - const typeNode = ts.getEffectiveTypeAnnotationNode(node); - return typeNode ? isThislessType(typeNode) : !ts.hasInitializer(node); + function isThislessVariableLikeDeclaration(node: VariableLikeDeclaration): boolean { + const typeNode = getEffectiveTypeAnnotationNode(node); + return typeNode ? isThislessType(typeNode) : !hasInitializer(node); } /** @@ -10851,10 +11049,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * annotation that is free of this references and if each parameter is thisless and if * each type parameter (if present) is thisless. */ - function isThislessFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration): boolean { - const returnType = ts.getEffectiveReturnTypeNode(node); - const typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - return (node.kind === ts.SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) && + function isThislessFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { + const returnType = getEffectiveReturnTypeNode(node); + const typeParameters = getEffectiveTypeParameterDeclarations(node); + return (node.kind === SyntaxKind.Constructor || (!!returnType && isThislessType(returnType))) && node.parameters.every(isThislessVariableLikeDeclaration) && typeParameters.every(isThislessTypeParameter); } @@ -10866,20 +11064,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * inferred from their initializers and function members with inferred return types are conservatively * assumed not to be free of "this" references. */ - function isThisless(symbol: ts.Symbol): boolean { + function isThisless(symbol: Symbol): boolean { if (symbol.declarations && symbol.declarations.length === 1) { const declaration = symbol.declarations[0]; if (declaration) { switch (declaration.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - return isThislessVariableLikeDeclaration(declaration as ts.VariableLikeDeclaration); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return isThislessFunctionLikeDeclaration(declaration as ts.FunctionLikeDeclaration | ts.AccessorDeclaration); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return isThislessVariableLikeDeclaration(declaration as VariableLikeDeclaration); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return isThislessFunctionLikeDeclaration(declaration as FunctionLikeDeclaration | AccessorDeclaration); } } } @@ -10888,15 +11086,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The mappingThisOnly flag indicates that the only type parameter being mapped is "this". When the flag is true, // we check symbols to see if we can quickly conclude they are free of "this" references, thus needing no instantiation. - function createInstantiatedSymbolTable(symbols: ts.Symbol[], mapper: ts.TypeMapper, mappingThisOnly: boolean): ts.SymbolTable { - const result = ts.createSymbolTable(); + function createInstantiatedSymbolTable(symbols: Symbol[], mapper: TypeMapper, mappingThisOnly: boolean): SymbolTable { + const result = createSymbolTable(); for (const symbol of symbols) { result.set(symbol.escapedName, mappingThisOnly && isThisless(symbol) ? symbol : instantiateSymbol(symbol, mapper)); } return result; } - function addInheritedMembers(symbols: ts.SymbolTable, baseSymbols: ts.Symbol[]) { + function addInheritedMembers(symbols: SymbolTable, baseSymbols: Symbol[]) { for (const s of baseSymbols) { if (!symbols.has(s.escapedName) && !isStaticPrivateIdentifierProperty(s)) { symbols.set(s.escapedName, s); @@ -10904,32 +11102,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isStaticPrivateIdentifierProperty(s: ts.Symbol): boolean { - return !!s.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(s.valueDeclaration) && ts.isStatic(s.valueDeclaration); + function isStaticPrivateIdentifierProperty(s: Symbol): boolean { + return !!s.valueDeclaration && isPrivateIdentifierClassElementDeclaration(s.valueDeclaration) && isStatic(s.valueDeclaration); } - function resolveDeclaredMembers(type: ts.InterfaceType): ts.InterfaceTypeWithDeclaredMembers { - if (!(type as ts.InterfaceTypeWithDeclaredMembers).declaredProperties) { + function resolveDeclaredMembers(type: InterfaceType): InterfaceTypeWithDeclaredMembers { + if (!(type as InterfaceTypeWithDeclaredMembers).declaredProperties) { const symbol = type.symbol; const members = getMembersOfSymbol(symbol); - (type as ts.InterfaceTypeWithDeclaredMembers).declaredProperties = getNamedMembers(members); + (type as InterfaceTypeWithDeclaredMembers).declaredProperties = getNamedMembers(members); // Start with signatures at empty array in case of recursive types - (type as ts.InterfaceTypeWithDeclaredMembers).declaredCallSignatures = ts.emptyArray; - (type as ts.InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = ts.emptyArray; - (type as ts.InterfaceTypeWithDeclaredMembers).declaredIndexInfos = ts.emptyArray; + (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = emptyArray; + (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = emptyArray; + (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = emptyArray; - (type as ts.InterfaceTypeWithDeclaredMembers).declaredCallSignatures = getSignaturesOfSymbol(members.get(ts.InternalSymbolName.Call)); - (type as ts.InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = getSignaturesOfSymbol(members.get(ts.InternalSymbolName.New)); - (type as ts.InterfaceTypeWithDeclaredMembers).declaredIndexInfos = getIndexInfosOfSymbol(symbol); + (type as InterfaceTypeWithDeclaredMembers).declaredCallSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); + (type as InterfaceTypeWithDeclaredMembers).declaredConstructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New)); + (type as InterfaceTypeWithDeclaredMembers).declaredIndexInfos = getIndexInfosOfSymbol(symbol); } - return type as ts.InterfaceTypeWithDeclaredMembers; + return type as InterfaceTypeWithDeclaredMembers; } /** * Indicates whether a type can be used as a property name. */ - function isTypeUsableAsPropertyName(type: ts.Type): type is ts.StringLiteralType | ts.NumberLiteralType | ts.UniqueESSymbolType { - return !!(type.flags & ts.TypeFlags.StringOrNumberLiteralOrUnique); + function isTypeUsableAsPropertyName(type: Type): type is StringLiteralType | NumberLiteralType | UniqueESSymbolType { + return !!(type.flags & TypeFlags.StringOrNumberLiteralOrUnique); } /** @@ -10940,54 +11138,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * `ElementAccessExpression` consisting only of these same three types of nodes. * - The type of its expression is a string or numeric literal type, or is a `unique symbol` type. */ - function isLateBindableName(node: ts.DeclarationName): node is ts.LateBoundName { - if (!ts.isComputedPropertyName(node) && !ts.isElementAccessExpression(node)) { + function isLateBindableName(node: DeclarationName): node is LateBoundName { + if (!isComputedPropertyName(node) && !isElementAccessExpression(node)) { return false; } - const expr = ts.isComputedPropertyName(node) ? node.expression : node.argumentExpression; - return ts.isEntityNameExpression(expr) - && isTypeUsableAsPropertyName(ts.isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr)); + const expr = isComputedPropertyName(node) ? node.expression : node.argumentExpression; + return isEntityNameExpression(expr) + && isTypeUsableAsPropertyName(isComputedPropertyName(node) ? checkComputedPropertyName(node) : checkExpressionCached(expr)); } - function isLateBoundName(name: ts.__String): boolean { - return (name as string).charCodeAt(0) === ts.CharacterCodes._ && - (name as string).charCodeAt(1) === ts.CharacterCodes._ && - (name as string).charCodeAt(2) === ts.CharacterCodes.at; + function isLateBoundName(name: __String): boolean { + return (name as string).charCodeAt(0) === CharacterCodes._ && + (name as string).charCodeAt(1) === CharacterCodes._ && + (name as string).charCodeAt(2) === CharacterCodes.at; } /** * Indicates whether a declaration has a late-bindable dynamic name. */ - function hasLateBindableName(node: ts.Declaration): node is ts.LateBoundDeclaration | ts.LateBoundBinaryExpressionDeclaration { - const name = ts.getNameOfDeclaration(node); + function hasLateBindableName(node: Declaration): node is LateBoundDeclaration | LateBoundBinaryExpressionDeclaration { + const name = getNameOfDeclaration(node); return !!name && isLateBindableName(name); } /** * Indicates whether a declaration has an early-bound name or a dynamic name that can be late-bound. */ - function hasBindableName(node: ts.Declaration) { - return !ts.hasDynamicName(node) || hasLateBindableName(node); + function hasBindableName(node: Declaration) { + return !hasDynamicName(node) || hasLateBindableName(node); } /** * Indicates whether a declaration name is a dynamic name that cannot be late-bound. */ - function isNonBindableDynamicName(node: ts.DeclarationName) { - return ts.isDynamicName(node) && !isLateBindableName(node); + function isNonBindableDynamicName(node: DeclarationName) { + return isDynamicName(node) && !isLateBindableName(node); } /** * Gets the symbolic name for a member from its type. */ - function getPropertyNameFromType(type: ts.StringLiteralType | ts.NumberLiteralType | ts.UniqueESSymbolType): ts.__String { - if (type.flags & ts.TypeFlags.UniqueESSymbol) { - return (type as ts.UniqueESSymbolType).escapedName; + function getPropertyNameFromType(type: StringLiteralType | NumberLiteralType | UniqueESSymbolType): __String { + if (type.flags & TypeFlags.UniqueESSymbol) { + return (type as UniqueESSymbolType).escapedName; } - if (type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) { - return ts.escapeLeadingUnderscores("" + (type as ts.StringLiteralType | ts.NumberLiteralType).value); + if (type.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { + return escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value); } - return ts.Debug.fail(); + return Debug.fail(); } /** @@ -10995,8 +11193,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound * members. */ - function addDeclarationToLateBoundSymbol(symbol: ts.Symbol, member: ts.LateBoundDeclaration | ts.BinaryExpression, symbolFlags: ts.SymbolFlags) { - ts.Debug.assert(!!(ts.getCheckFlags(symbol) & ts.CheckFlags.Late), "Expected a late-bound symbol."); + function addDeclarationToLateBoundSymbol(symbol: Symbol, member: LateBoundDeclaration | BinaryExpression, symbolFlags: SymbolFlags) { + Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; getSymbolLinks(member.symbol).lateSymbol = symbol; if (!symbol.declarations) { @@ -11005,7 +11203,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else if(!member.symbol.isReplaceableByMethod) { symbol.declarations.push(member); } - if (symbolFlags & ts.SymbolFlags.Value) { + if (symbolFlags & SymbolFlags.Value) { if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) { symbol.valueDeclaration = member; } @@ -11040,22 +11238,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param lateSymbols The late-bound symbols of the parent. * @param decl The member to bind. */ - function lateBindMember(parent: ts.Symbol, earlySymbols: ts.SymbolTable | undefined, lateSymbols: ts.UnderscoreEscapedMap, decl: ts.LateBoundDeclaration | ts.LateBoundBinaryExpressionDeclaration) { - ts.Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); + function lateBindMember(parent: Symbol, earlySymbols: SymbolTable | undefined, lateSymbols: UnderscoreEscapedMap, decl: LateBoundDeclaration | LateBoundBinaryExpressionDeclaration) { + Debug.assert(!!decl.symbol, "The member is expected to have a symbol."); const links = getNodeLinks(decl); if (!links.resolvedSymbol) { // In the event we attempt to resolve the late-bound name of this member recursively, // fall back to the early-bound name of this member. links.resolvedSymbol = decl.symbol; - const declName = ts.isBinaryExpression(decl) ? decl.left : decl.name; - const type = ts.isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName); + const declName = isBinaryExpression(decl) ? decl.left : decl.name; + const type = isElementAccessExpression(declName) ? checkExpressionCached(declName.argumentExpression) : checkComputedPropertyName(declName); if (isTypeUsableAsPropertyName(type)) { const memberName = getPropertyNameFromType(type); const symbolFlags = decl.symbol.flags; // Get or add a late-bound symbol for the member. This allows us to merge late-bound accessor declarations. let lateSymbol = lateSymbols.get(memberName); - if (!lateSymbol) lateSymbols.set(memberName, lateSymbol = createSymbol(ts.SymbolFlags.None, memberName, ts.CheckFlags.Late)); + if (!lateSymbol) lateSymbols.set(memberName, lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late)); // Report an error if a late-bound member has the same name as an early-bound member, // or if we have another early-bound symbol declaration with the same name and @@ -11064,16 +11262,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (lateSymbol.flags & getExcludedSymbolFlags(symbolFlags) || earlySymbol) { // If we have an existing early-bound member, combine its declarations so that we can // report an error at each declaration. - const declarations = earlySymbol ? ts.concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations; - const name = !(type.flags & ts.TypeFlags.UniqueESSymbol) && ts.unescapeLeadingUnderscores(memberName) || ts.declarationNameToString(declName); - ts.forEach(declarations, declaration => error(ts.getNameOfDeclaration(declaration) || declaration, ts.Diagnostics.Property_0_was_also_declared_here, name)); - error(declName || decl, ts.Diagnostics.Duplicate_property_0, name); - lateSymbol = createSymbol(ts.SymbolFlags.None, memberName, ts.CheckFlags.Late); + const declarations = earlySymbol ? concatenate(earlySymbol.declarations, lateSymbol.declarations) : lateSymbol.declarations; + const name = !(type.flags & TypeFlags.UniqueESSymbol) && unescapeLeadingUnderscores(memberName) || declarationNameToString(declName); + forEach(declarations, declaration => error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Property_0_was_also_declared_here, name)); + error(declName || decl, Diagnostics.Duplicate_property_0, name); + lateSymbol = createSymbol(SymbolFlags.None, memberName, CheckFlags.Late); } lateSymbol.nameType = type; addDeclarationToLateBoundSymbol(lateSymbol, decl, symbolFlags); if (lateSymbol.parent) { - ts.Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one"); + Debug.assert(lateSymbol.parent === parent, "Existing symbol parent should match new one"); } else { lateSymbol.parent = parent; @@ -11084,12 +11282,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedSymbol; } - function getResolvedMembersOrExportsOfSymbol(symbol: ts.Symbol, resolutionKind: MembersOrExportsResolutionKind): ts.UnderscoreEscapedMap { + function getResolvedMembersOrExportsOfSymbol(symbol: Symbol, resolutionKind: MembersOrExportsResolutionKind): UnderscoreEscapedMap { const links = getSymbolLinks(symbol); if (!links[resolutionKind]) { const isStatic = resolutionKind === MembersOrExportsResolutionKind.resolvedExports; const earlySymbols = !isStatic ? symbol.members : - symbol.flags & ts.SymbolFlags.Module ? getExportsOfModuleWorker(symbol) : + symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol) : symbol.exports; // In the event we recursively resolve the members/exports of the symbol, we @@ -11098,12 +11296,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { links[resolutionKind] = earlySymbols || emptySymbols; // fill in any as-yet-unresolved late-bound members. - const lateSymbols = ts.createSymbolTable() as ts.UnderscoreEscapedMap; - for (const decl of symbol.declarations || ts.emptyArray) { - const members = ts.getMembersOfDeclaration(decl); + const lateSymbols = createSymbolTable() as UnderscoreEscapedMap; + for (const decl of symbol.declarations || emptyArray) { + const members = getMembersOfDeclaration(decl); if (members) { for (const member of members) { - if (isStatic === ts.hasStaticModifier(member)) { + if (isStatic === hasStaticModifier(member)) { if (hasLateBindableName(member)) { lateBindMember(symbol, earlySymbols, lateSymbols, member); } @@ -11113,13 +11311,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const assignments = symbol.assignmentDeclarationMembers; if (assignments) { - const decls = ts.arrayFrom(assignments.values()); + const decls = arrayFrom(assignments.values()); for (const member of decls) { - const assignmentKind = ts.getAssignmentDeclarationKind(member as ts.BinaryExpression | ts.CallExpression); - const isInstanceMember = assignmentKind === ts.AssignmentDeclarationKind.PrototypeProperty - || ts.isBinaryExpression(member) && isPossiblyAliasedThisProperty(member, assignmentKind) - || assignmentKind === ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty - || assignmentKind === ts.AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name + const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression); + const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty + || isBinaryExpression(member) && isPossiblyAliasedThisProperty(member, assignmentKind) + || assignmentKind === AssignmentDeclarationKind.ObjectDefinePrototypeProperty + || assignmentKind === AssignmentDeclarationKind.Prototype; // A straight `Prototype` assignment probably can never have a computed name if (isStatic === !isInstanceMember) { if (hasLateBindableName(member)) { lateBindMember(symbol, earlySymbols, lateSymbols, member); @@ -11139,8 +11337,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * For a description of late-binding, see `lateBindMember`. */ - function getMembersOfSymbol(symbol: ts.Symbol) { - return symbol.flags & ts.SymbolFlags.LateBindingContainer + function getMembersOfSymbol(symbol: Symbol) { + return symbol.flags & SymbolFlags.LateBindingContainer ? getResolvedMembersOrExportsOfSymbol(symbol, MembersOrExportsResolutionKind.resolvedMembers) : symbol.members || emptySymbols; } @@ -11151,13 +11349,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * For a description of late-binding, see `lateBindMember`. */ - function getLateBoundSymbol(symbol: ts.Symbol): ts.Symbol { - if (symbol.flags & ts.SymbolFlags.ClassMember && symbol.escapedName === ts.InternalSymbolName.Computed) { + function getLateBoundSymbol(symbol: Symbol): Symbol { + if (symbol.flags & SymbolFlags.ClassMember && symbol.escapedName === InternalSymbolName.Computed) { const links = getSymbolLinks(symbol); - if (!links.lateSymbol && ts.some(symbol.declarations, hasLateBindableName)) { + if (!links.lateSymbol && some(symbol.declarations, hasLateBindableName)) { // force late binding of members/exports. This will set the late-bound symbol const parent = getMergedSymbol(symbol.parent)!; - if (ts.some(symbol.declarations, ts.hasStaticModifier)) { + if (some(symbol.declarations, hasStaticModifier)) { getExportsOfSymbol(parent); } else { @@ -11169,30 +11367,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol; } - function getTypeWithThisArgument(type: ts.Type, thisArgument?: ts.Type, needApparentType?: boolean): ts.Type { - if (ts.getObjectFlags(type) & ts.ObjectFlags.Reference) { - const target = (type as ts.TypeReference).target; - const typeArguments = getTypeArguments(type as ts.TypeReference); - if (ts.length(target.typeParameters) === ts.length(typeArguments)) { - const ref = createTypeReference(target, ts.concatenate(typeArguments, [thisArgument || target.thisType!])); + function getTypeWithThisArgument(type: Type, thisArgument?: Type, needApparentType?: boolean): Type { + if (getObjectFlags(type) & ObjectFlags.Reference) { + const target = (type as TypeReference).target; + const typeArguments = getTypeArguments(type as TypeReference); + if (length(target.typeParameters) === length(typeArguments)) { + const ref = createTypeReference(target, concatenate(typeArguments, [thisArgument || target.thisType!])); return needApparentType ? getApparentType(ref) : ref; } } - else if (type.flags & ts.TypeFlags.Intersection) { - const types = ts.sameMap((type as ts.IntersectionType).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType)); - return types !== (type as ts.IntersectionType).types ? getIntersectionType(types) : type; + else if (type.flags & TypeFlags.Intersection) { + const types = sameMap((type as IntersectionType).types, t => getTypeWithThisArgument(t, thisArgument, needApparentType)); + return types !== (type as IntersectionType).types ? getIntersectionType(types) : type; } return needApparentType ? getApparentType(type) : type; } - function resolveObjectTypeMembers(type: ts.ObjectType, source: ts.InterfaceTypeWithDeclaredMembers, typeParameters: readonly ts.TypeParameter[], typeArguments: readonly ts.Type[]) { - let mapper: ts.TypeMapper | undefined; - let members: ts.SymbolTable; - let callSignatures: readonly ts.Signature[]; - let constructSignatures: readonly ts.Signature[]; - let indexInfos: readonly ts.IndexInfo[]; - if (ts.rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) { - members = source.symbol ? getMembersOfSymbol(source.symbol) : ts.createSymbolTable(source.declaredProperties); + function resolveObjectTypeMembers(type: ObjectType, source: InterfaceTypeWithDeclaredMembers, typeParameters: readonly TypeParameter[], typeArguments: readonly Type[]) { + let mapper: TypeMapper | undefined; + let members: SymbolTable; + let callSignatures: readonly Signature[]; + let constructSignatures: readonly Signature[]; + let indexInfos: readonly IndexInfo[]; + if (rangeEquals(typeParameters, typeArguments, 0, typeParameters.length)) { + members = source.symbol ? getMembersOfSymbol(source.symbol) : createSymbolTable(source.declaredProperties); callSignatures = source.declaredCallSignatures; constructSignatures = source.declaredConstructSignatures; indexInfos = source.declaredIndexInfos; @@ -11207,44 +11405,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const baseTypes = getBaseTypes(source); if (baseTypes.length) { if (source.symbol && members === getMembersOfSymbol(source.symbol)) { - members = ts.createSymbolTable(source.declaredProperties); + members = createSymbolTable(source.declaredProperties); } setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); - const thisArgument = ts.lastOrUndefined(typeArguments); + const thisArgument = lastOrUndefined(typeArguments); for (const baseType of baseTypes) { const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType; addInheritedMembers(members, getPropertiesOfType(instantiatedBaseType)); - callSignatures = ts.concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, ts.SignatureKind.Call)); - constructSignatures = ts.concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, ts.SignatureKind.Construct)); + callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call)); + constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct)); const inheritedIndexInfos = instantiatedBaseType !== anyType ? getIndexInfosOfType(instantiatedBaseType) : [createIndexInfo(stringType, anyType, /*isReadonly*/ false)]; - indexInfos = ts.concatenate(indexInfos, ts.filter(inheritedIndexInfos, info => !findIndexInfo(indexInfos, info.keyType))); + indexInfos = concatenate(indexInfos, filter(inheritedIndexInfos, info => !findIndexInfo(indexInfos, info.keyType))); } } setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); } - function resolveClassOrInterfaceMembers(type: ts.InterfaceType): void { - resolveObjectTypeMembers(type, resolveDeclaredMembers(type), ts.emptyArray, ts.emptyArray); + function resolveClassOrInterfaceMembers(type: InterfaceType): void { + resolveObjectTypeMembers(type, resolveDeclaredMembers(type), emptyArray, emptyArray); } - function resolveTypeReferenceMembers(type: ts.TypeReference): void { + function resolveTypeReferenceMembers(type: TypeReference): void { const source = resolveDeclaredMembers(type.target); - const typeParameters = ts.concatenate(source.typeParameters!, [source.thisType!]); + const typeParameters = concatenate(source.typeParameters!, [source.thisType!]); const typeArguments = getTypeArguments(type); - const paddedTypeArguments = typeArguments.length === typeParameters.length ? typeArguments : ts.concatenate(typeArguments, [type]); + const paddedTypeArguments = typeArguments.length === typeParameters.length ? typeArguments : concatenate(typeArguments, [type]); resolveObjectTypeMembers(type, source, typeParameters, paddedTypeArguments); } function createSignature( - declaration: ts.SignatureDeclaration | ts.JSDocSignature | undefined, - typeParameters: readonly ts.TypeParameter[] | undefined, - thisParameter: ts.Symbol | undefined, - parameters: readonly ts.Symbol[], - resolvedReturnType: ts.Type | undefined, - resolvedTypePredicate: ts.TypePredicate | undefined, + declaration: SignatureDeclaration | JSDocSignature | undefined, + typeParameters: readonly TypeParameter[] | undefined, + thisParameter: Symbol | undefined, + parameters: readonly Symbol[], + resolvedReturnType: Type | undefined, + resolvedTypePredicate: TypePredicate | undefined, minArgumentCount: number, - flags: ts.SignatureFlags - ): ts.Signature { + flags: SignatureFlags + ): Signature { const sig = new Signature(checker, flags); sig.declaration = declaration; sig.typeParameters = typeParameters; @@ -11261,9 +11459,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return sig; } - function cloneSignature(sig: ts.Signature): ts.Signature { + function cloneSignature(sig: Signature): Signature { const result = createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, /*resolvedReturnType*/ undefined, - /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & ts.SignatureFlags.PropagatingFlags); + /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags); result.target = sig.target; result.mapper = sig.mapper; result.compositeSignatures = sig.compositeSignatures; @@ -11271,94 +11469,94 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function createUnionSignature(signature: ts.Signature, unionSignatures: ts.Signature[]) { + function createUnionSignature(signature: Signature, unionSignatures: Signature[]) { const result = cloneSignature(signature); result.compositeSignatures = unionSignatures; - result.compositeKind = ts.TypeFlags.Union; + result.compositeKind = TypeFlags.Union; result.target = undefined; result.mapper = undefined; return result; } - function getOptionalCallSignature(signature: ts.Signature, callChainFlags: ts.SignatureFlags): ts.Signature { - if ((signature.flags & ts.SignatureFlags.CallChainFlags) === callChainFlags) { + function getOptionalCallSignature(signature: Signature, callChainFlags: SignatureFlags): Signature { + if ((signature.flags & SignatureFlags.CallChainFlags) === callChainFlags) { return signature; } if (!signature.optionalCallSignatureCache) { signature.optionalCallSignatureCache = {}; } - const key = callChainFlags === ts.SignatureFlags.IsInnerCallChain ? "inner" : "outer"; + const key = callChainFlags === SignatureFlags.IsInnerCallChain ? "inner" : "outer"; return signature.optionalCallSignatureCache[key] || (signature.optionalCallSignatureCache[key] = createOptionalCallSignature(signature, callChainFlags)); } - function createOptionalCallSignature(signature: ts.Signature, callChainFlags: ts.SignatureFlags) { - ts.Debug.assert(callChainFlags === ts.SignatureFlags.IsInnerCallChain || callChainFlags === ts.SignatureFlags.IsOuterCallChain, + function createOptionalCallSignature(signature: Signature, callChainFlags: SignatureFlags) { + Debug.assert(callChainFlags === SignatureFlags.IsInnerCallChain || callChainFlags === SignatureFlags.IsOuterCallChain, "An optional call signature can either be for an inner call chain or an outer call chain, but not both."); const result = cloneSignature(signature); result.flags |= callChainFlags; return result; } - function getExpandedParameters(sig: ts.Signature, skipUnionExpanding?: boolean): readonly (readonly ts.Symbol[])[] { + function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] { if (signatureHasRestParameter(sig)) { const restIndex = sig.parameters.length - 1; const restType = getTypeOfSymbol(sig.parameters[restIndex]); if (isTupleType(restType)) { return [expandSignatureParametersWithTupleMembers(restType, restIndex)]; } - else if (!skipUnionExpanding && restType.flags & ts.TypeFlags.Union && ts.every((restType as ts.UnionType).types, isTupleType)) { - return ts.map((restType as ts.UnionType).types, t => expandSignatureParametersWithTupleMembers(t as ts.TupleTypeReference, restIndex)); + else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) { + return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex)); } } return [sig.parameters]; - function expandSignatureParametersWithTupleMembers(restType: ts.TupleTypeReference, restIndex: number) { + function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) { const elementTypes = getTypeArguments(restType); const associatedNames = restType.target.labeledElementDeclarations; - const restParams = ts.map(elementTypes, (t, i) => { + const restParams = map(elementTypes, (t, i) => { // Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name const tupleLabelName = !!associatedNames && getTupleElementLabel(associatedNames[i]); const name = tupleLabelName || getParameterNameAtPosition(sig, restIndex + i, restType); const flags = restType.target.elementFlags[i]; - const checkFlags = flags & ts.ElementFlags.Variable ? ts.CheckFlags.RestParameter : - flags & ts.ElementFlags.Optional ? ts.CheckFlags.OptionalParameter : 0; - const symbol = createSymbol(ts.SymbolFlags.FunctionScopedVariable, name, checkFlags); - symbol.type = flags & ts.ElementFlags.Rest ? createArrayType(t) : t; + const checkFlags = flags & ElementFlags.Variable ? CheckFlags.RestParameter : + flags & ElementFlags.Optional ? CheckFlags.OptionalParameter : 0; + const symbol = createSymbol(SymbolFlags.FunctionScopedVariable, name, checkFlags); + symbol.type = flags & ElementFlags.Rest ? createArrayType(t) : t; return symbol; }); - return ts.concatenate(sig.parameters.slice(0, restIndex), restParams); + return concatenate(sig.parameters.slice(0, restIndex), restParams); } } - function getDefaultConstructSignatures(classType: ts.InterfaceType): ts.Signature[] { + function getDefaultConstructSignatures(classType: InterfaceType): Signature[] { const baseConstructorType = getBaseConstructorTypeOfClass(classType); - const baseSignatures = getSignaturesOfType(baseConstructorType, ts.SignatureKind.Construct); - const declaration = ts.getClassLikeDeclarationOfSymbol(classType.symbol); - const isAbstract = !!declaration && ts.hasSyntacticModifier(declaration, ts.ModifierFlags.Abstract); + const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); + const declaration = getClassLikeDeclarationOfSymbol(classType.symbol); + const isAbstract = !!declaration && hasSyntacticModifier(declaration, ModifierFlags.Abstract); if (baseSignatures.length === 0) { - return [createSignature(undefined, classType.localTypeParameters, undefined, ts.emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, isAbstract ? ts.SignatureFlags.Abstract : ts.SignatureFlags.None)]; + return [createSignature(undefined, classType.localTypeParameters, undefined, emptyArray, classType, /*resolvedTypePredicate*/ undefined, 0, isAbstract ? SignatureFlags.Abstract : SignatureFlags.None)]; } const baseTypeNode = getBaseTypeNodeOfClass(classType)!; - const isJavaScript = ts.isInJSFile(baseTypeNode); + const isJavaScript = isInJSFile(baseTypeNode); const typeArguments = typeArgumentsFromTypeReferenceNode(baseTypeNode); - const typeArgCount = ts.length(typeArguments); - const result: ts.Signature[] = []; + const typeArgCount = length(typeArguments); + const result: Signature[] = []; for (const baseSig of baseSignatures) { const minTypeArgumentCount = getMinTypeArgumentCount(baseSig.typeParameters); - const typeParamCount = ts.length(baseSig.typeParameters); + const typeParamCount = length(baseSig.typeParameters); if (isJavaScript || typeArgCount >= minTypeArgumentCount && typeArgCount <= typeParamCount) { const sig = typeParamCount ? createSignatureInstantiation(baseSig, fillMissingTypeArguments(typeArguments, baseSig.typeParameters, minTypeArgumentCount, isJavaScript)) : cloneSignature(baseSig); sig.typeParameters = classType.localTypeParameters; sig.resolvedReturnType = classType; - sig.flags = isAbstract ? sig.flags | ts.SignatureFlags.Abstract : sig.flags & ~ts.SignatureFlags.Abstract; + sig.flags = isAbstract ? sig.flags | SignatureFlags.Abstract : sig.flags & ~SignatureFlags.Abstract; result.push(sig); } } return result; } - function findMatchingSignature(signatureList: readonly ts.Signature[], signature: ts.Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): ts.Signature | undefined { + function findMatchingSignature(signatureList: readonly Signature[], signature: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean): Signature | undefined { for (const s of signatureList) { if (compareSignaturesIdentical(s, signature, partialMatch, ignoreThisTypes, ignoreReturnTypes, partialMatch ? compareTypesSubtypeOf : compareTypesIdentical)) { return s; @@ -11366,7 +11564,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function findMatchingSignatures(signatureLists: readonly (readonly ts.Signature[])[], signature: ts.Signature, listIndex: number): ts.Signature[] | undefined { + function findMatchingSignatures(signatureLists: readonly (readonly Signature[])[], signature: Signature, listIndex: number): Signature[] | undefined { if (signature.typeParameters) { // We require an exact match for generic signatures, so we only return signatures from the first // signature list and only if they have exact matches in the other signature lists. @@ -11380,7 +11578,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return [signature]; } - let result: ts.Signature[] | undefined; + let result: Signature[] | undefined; for (let i = 0; i < signatureLists.length; i++) { // Allow matching non-generic signatures to have excess parameters and different return types. // Prefer matching this types if possible. @@ -11388,7 +11586,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!match) { return undefined; } - result = ts.appendIfUnique(result, match); + result = appendIfUnique(result, match); } return result; } @@ -11397,11 +11595,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Generic signatures must match exactly, but non-generic signatures are allowed to have extra optional // parameters and may differ in return types. When signatures differ in return types, the resulting return // type is the union of the constituent return types. - function getUnionSignatures(signatureLists: readonly (readonly ts.Signature[])[]): ts.Signature[] { - let result: ts.Signature[] | undefined; + function getUnionSignatures(signatureLists: readonly (readonly Signature[])[]): Signature[] { + let result: Signature[] | undefined; let indexWithLengthOverOne: number | undefined; for (let i = 0; i < signatureLists.length; i++) { - if (signatureLists[i].length === 0) return ts.emptyArray; + if (signatureLists[i].length === 0) return emptyArray; if (signatureLists[i].length > 1) { indexWithLengthOverOne = indexWithLengthOverOne === undefined ? i : -1; // -1 is a signal there are multiple overload sets } @@ -11414,9 +11612,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Union the result types when more than one signature matches if (unionSignatures.length > 1) { let thisParameter = signature.thisParameter; - const firstThisParameterOfUnionSignatures = ts.forEach(unionSignatures, sig => sig.thisParameter); + const firstThisParameterOfUnionSignatures = forEach(unionSignatures, sig => sig.thisParameter); if (firstThisParameterOfUnionSignatures) { - const thisType = getIntersectionType(ts.mapDefined(unionSignatures, sig => sig.thisParameter && getTypeOfSymbol(sig.thisParameter))); + const thisType = getIntersectionType(mapDefined(unionSignatures, sig => sig.thisParameter && getTypeOfSymbol(sig.thisParameter))); thisParameter = createSymbolWithType(firstThisParameterOfUnionSignatures, thisType); } s = createUnionSignature(signature, unionSignatures); @@ -11427,18 +11625,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - if (!ts.length(result) && indexWithLengthOverOne !== -1) { + if (!length(result) && indexWithLengthOverOne !== -1) { // No sufficiently similar signature existed to subsume all the other signatures in the union - time to see if we can make a single // signature that handles all over them. We only do this when there are overloads in only one constituent. // (Overloads are conditional in nature and having overloads in multiple constituents would necessitate making a power set of // signatures from the type, whose ordering would be non-obvious) const masterList = signatureLists[indexWithLengthOverOne !== undefined ? indexWithLengthOverOne : 0]; - let results: ts.Signature[] | undefined = masterList.slice(); + let results: Signature[] | undefined = masterList.slice(); for (const signatures of signatureLists) { if (signatures !== masterList) { const signature = signatures[0]; - ts.Debug.assert(!!signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass"); - results = !!signature.typeParameters && ts.some(results, s => !!s.typeParameters && !compareTypeParametersIdentical(signature.typeParameters, s.typeParameters)) ? undefined : ts.map(results, sig => combineSignaturesOfUnionMembers(sig, signature)); + Debug.assert(!!signature, "getUnionSignatures bails early on empty signature lists and should not have empty lists on second pass"); + results = !!signature.typeParameters && some(results, s => !!s.typeParameters && !compareTypeParametersIdentical(signature.typeParameters, s.typeParameters)) ? undefined : map(results, sig => combineSignaturesOfUnionMembers(sig, signature)); if (!results) { break; } @@ -11446,11 +11644,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } result = results; } - return result || ts.emptyArray; + return result || emptyArray; } - function compareTypeParametersIdentical(sourceParams: readonly ts.TypeParameter[] | undefined, targetParams: readonly ts.TypeParameter[] | undefined): boolean { - if (ts.length(sourceParams) !== ts.length(targetParams)) { + function compareTypeParametersIdentical(sourceParams: readonly TypeParameter[] | undefined, targetParams: readonly TypeParameter[] | undefined): boolean { + if (length(sourceParams) !== length(targetParams)) { return false; } if (!sourceParams || !targetParams) { @@ -11473,7 +11671,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function combineUnionThisParam(left: ts.Symbol | undefined, right: ts.Symbol | undefined, mapper: ts.TypeMapper | undefined): ts.Symbol | undefined { + function combineUnionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined { if (!left || !right) { return left || right; } @@ -11484,7 +11682,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createSymbolWithType(left, thisType); } - function combineUnionParameters(left: ts.Signature, right: ts.Signature, mapper: ts.TypeMapper | undefined) { + function combineUnionParameters(left: Signature, right: Signature, mapper: TypeMapper | undefined) { const leftCount = getParameterCount(left); const rightCount = getParameterCount(right); const longest = leftCount >= rightCount ? left : right; @@ -11492,7 +11690,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const longestCount = longest === left ? leftCount : rightCount; const eitherHasEffectiveRest = (hasEffectiveRestParameter(left) || hasEffectiveRestParameter(right)); const needsExtraRestElement = eitherHasEffectiveRest && !hasEffectiveRestParameter(longest); - const params = new Array(longestCount + (needsExtraRestElement ? 1 : 0)); + const params = new Array(longestCount + (needsExtraRestElement ? 1 : 0)); for (let i = 0; i < longestCount; i++) { let longestParamType = tryGetTypeAtPosition(longest, i)!; if (longest === right) { @@ -11513,14 +11711,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !rightName ? leftName : undefined; const paramSymbol = createSymbol( - ts.SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? ts.SymbolFlags.Optional : 0), - paramName || `arg${i}` as ts.__String + SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0), + paramName || `arg${i}` as __String ); paramSymbol.type = isRestParam ? createArrayType(unionParamType) : unionParamType; params[i] = paramSymbol; } if (needsExtraRestElement) { - const restParamSymbol = createSymbol(ts.SymbolFlags.FunctionScopedVariable, "args" as ts.__String); + const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String); restParamSymbol.type = createArrayType(getTypeAtPosition(shorter, longestCount)); if (shorter === right) { restParamSymbol.type = instantiateType(restParamSymbol.type, mapper); @@ -11530,9 +11728,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return params; } - function combineSignaturesOfUnionMembers(left: ts.Signature, right: ts.Signature): ts.Signature { + function combineSignaturesOfUnionMembers(left: Signature, right: Signature): Signature { const typeParams = left.typeParameters || right.typeParameters; - let paramMapper: ts.TypeMapper | undefined; + let paramMapper: TypeMapper | undefined; if (left.typeParameters && right.typeParameters) { paramMapper = createTypeMapper(right.typeParameters, left.typeParameters); // We just use the type parameter defaults from the first signature @@ -11549,79 +11747,79 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, minArgCount, - (left.flags | right.flags) & ts.SignatureFlags.PropagatingFlags + (left.flags | right.flags) & SignatureFlags.PropagatingFlags ); - result.compositeKind = ts.TypeFlags.Union; - result.compositeSignatures = ts.concatenate(left.compositeKind !== ts.TypeFlags.Intersection && left.compositeSignatures || [left], [right]); + result.compositeKind = TypeFlags.Union; + result.compositeSignatures = concatenate(left.compositeKind !== TypeFlags.Intersection && left.compositeSignatures || [left], [right]); if (paramMapper) { - result.mapper = left.compositeKind !== ts.TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; + result.mapper = left.compositeKind !== TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; } return result; } - function getUnionIndexInfos(types: readonly ts.Type[]): ts.IndexInfo[] { + function getUnionIndexInfos(types: readonly Type[]): IndexInfo[] { const sourceInfos = getIndexInfosOfType(types[0]); if (sourceInfos) { const result = []; for (const info of sourceInfos) { const indexType = info.keyType; - if (ts.every(types, t => !!getIndexInfoOfType(t, indexType))) { - result.push(createIndexInfo(indexType, getUnionType(ts.map(types, t => getIndexTypeOfType(t, indexType)!)), - ts.some(types, t => getIndexInfoOfType(t, indexType)!.isReadonly))); + if (every(types, t => !!getIndexInfoOfType(t, indexType))) { + result.push(createIndexInfo(indexType, getUnionType(map(types, t => getIndexTypeOfType(t, indexType)!)), + some(types, t => getIndexInfoOfType(t, indexType)!.isReadonly))); } } return result; } - return ts.emptyArray; + return emptyArray; } - function resolveUnionTypeMembers(type: ts.UnionType) { + function resolveUnionTypeMembers(type: UnionType) { // The members and properties collections are empty for union types. To get all properties of a union // type use getPropertiesOfType (only the language service uses this). - const callSignatures = getUnionSignatures(ts.map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, ts.SignatureKind.Call))); - const constructSignatures = getUnionSignatures(ts.map(type.types, t => getSignaturesOfType(t, ts.SignatureKind.Construct))); + const callSignatures = getUnionSignatures(map(type.types, t => t === globalFunctionType ? [unknownSignature] : getSignaturesOfType(t, SignatureKind.Call))); + const constructSignatures = getUnionSignatures(map(type.types, t => getSignaturesOfType(t, SignatureKind.Construct))); const indexInfos = getUnionIndexInfos(type.types); setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, indexInfos); } - function intersectTypes(type1: ts.Type, type2: ts.Type): ts.Type; - function intersectTypes(type1: ts.Type | undefined, type2: ts.Type | undefined): ts.Type | undefined; - function intersectTypes(type1: ts.Type | undefined, type2: ts.Type | undefined): ts.Type | undefined { + function intersectTypes(type1: Type, type2: Type): Type; + function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined; + function intersectTypes(type1: Type | undefined, type2: Type | undefined): Type | undefined { return !type1 ? type2 : !type2 ? type1 : getIntersectionType([type1, type2]); } - function findMixins(types: readonly ts.Type[]): readonly boolean[] { - const constructorTypeCount = ts.countWhere(types, (t) => getSignaturesOfType(t, ts.SignatureKind.Construct).length > 0); - const mixinFlags = ts.map(types, isMixinConstructorType); - if (constructorTypeCount > 0 && constructorTypeCount === ts.countWhere(mixinFlags, (b) => b)) { + function findMixins(types: readonly Type[]): readonly boolean[] { + const constructorTypeCount = countWhere(types, (t) => getSignaturesOfType(t, SignatureKind.Construct).length > 0); + const mixinFlags = map(types, isMixinConstructorType); + if (constructorTypeCount > 0 && constructorTypeCount === countWhere(mixinFlags, (b) => b)) { const firstMixinIndex = mixinFlags.indexOf(/*searchElement*/ true); mixinFlags[firstMixinIndex] = false; } return mixinFlags; } - function includeMixinType(type: ts.Type, types: readonly ts.Type[], mixinFlags: readonly boolean[], index: number): ts.Type { - const mixedTypes: ts.Type[] = []; + function includeMixinType(type: Type, types: readonly Type[], mixinFlags: readonly boolean[], index: number): Type { + const mixedTypes: Type[] = []; for (let i = 0; i < types.length; i++) { if (i === index) { mixedTypes.push(type); } else if (mixinFlags[i]) { - mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], ts.SignatureKind.Construct)[0])); + mixedTypes.push(getReturnTypeOfSignature(getSignaturesOfType(types[i], SignatureKind.Construct)[0])); } } return getIntersectionType(mixedTypes); } - function resolveIntersectionTypeMembers(type: ts.IntersectionType) { + function resolveIntersectionTypeMembers(type: IntersectionType) { // The members and properties collections are empty for intersection types. To get all properties of an // intersection type use getPropertiesOfType (only the language service uses this). - let callSignatures: ts.Signature[] | undefined; - let constructSignatures: ts.Signature[] | undefined; - let indexInfos: ts.IndexInfo[] | undefined; + let callSignatures: Signature[] | undefined; + let constructSignatures: Signature[] | undefined; + let indexInfos: IndexInfo[] | undefined; const types = type.types; const mixinFlags = findMixins(types); - const mixinCount = ts.countWhere(mixinFlags, (b) => b); + const mixinCount = countWhere(mixinFlags, (b) => b); for (let i = 0; i < types.length; i++) { const t = type.types[i]; // When an intersection type contains mixin constructor types, the construct signatures from @@ -11630,9 +11828,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // '{ new(...args: any[]) => A } & { new(s: string) => B }' has a single construct signature // 'new(s: string) => A & B'. if (!mixinFlags[i]) { - let signatures = getSignaturesOfType(t, ts.SignatureKind.Construct); + let signatures = getSignaturesOfType(t, SignatureKind.Construct); if (signatures.length && mixinCount > 0) { - signatures = ts.map(signatures, s => { + signatures = map(signatures, s => { const clone = cloneSignature(s); clone.resolvedReturnType = includeMixinType(getReturnTypeOfSignature(s), types, mixinFlags, i); return clone; @@ -11640,22 +11838,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } constructSignatures = appendSignatures(constructSignatures, signatures); } - callSignatures = appendSignatures(callSignatures, getSignaturesOfType(t, ts.SignatureKind.Call)); - indexInfos = ts.reduceLeft(getIndexInfosOfType(t), (infos, newInfo) => appendIndexInfo(infos, newInfo, /*union*/ false), indexInfos); + callSignatures = appendSignatures(callSignatures, getSignaturesOfType(t, SignatureKind.Call)); + indexInfos = reduceLeft(getIndexInfosOfType(t), (infos, newInfo) => appendIndexInfo(infos, newInfo, /*union*/ false), indexInfos); } - setStructuredTypeMembers(type, emptySymbols, callSignatures || ts.emptyArray, constructSignatures || ts.emptyArray, indexInfos || ts.emptyArray); + setStructuredTypeMembers(type, emptySymbols, callSignatures || emptyArray, constructSignatures || emptyArray, indexInfos || emptyArray); } - function appendSignatures(signatures: ts.Signature[] | undefined, newSignatures: readonly ts.Signature[]) { + function appendSignatures(signatures: Signature[] | undefined, newSignatures: readonly Signature[]) { for (const sig of newSignatures) { - if (!signatures || ts.every(signatures, s => !compareSignaturesIdentical(s, sig, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, compareTypesIdentical))) { - signatures = ts.append(signatures, sig); + if (!signatures || every(signatures, s => !compareSignaturesIdentical(s, sig, /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, compareTypesIdentical))) { + signatures = append(signatures, sig); } } return signatures; } - function appendIndexInfo(indexInfos: ts.IndexInfo[] | undefined, newInfo: ts.IndexInfo, union: boolean) { + function appendIndexInfo(indexInfos: IndexInfo[] | undefined, newInfo: IndexInfo, union: boolean) { if (indexInfos) { for (let i = 0; i < indexInfos.length; i++) { const info = indexInfos[i]; @@ -11667,54 +11865,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return ts.append(indexInfos, newInfo); + return append(indexInfos, newInfo); } /** * Converts an AnonymousType to a ResolvedType. */ - function resolveAnonymousTypeMembers(type: ts.AnonymousType) { + function resolveAnonymousTypeMembers(type: AnonymousType) { if (type.target) { - setStructuredTypeMembers(type, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray); const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper!, /*mappingThisOnly*/ false); - const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, ts.SignatureKind.Call), type.mapper!); - const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, ts.SignatureKind.Construct), type.mapper!); + const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper!); + const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper!); const indexInfos = instantiateIndexInfos(getIndexInfosOfType(type.target), type.mapper!); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); return; } const symbol = getMergedSymbol(type.symbol); - if (symbol.flags & ts.SymbolFlags.TypeLiteral) { - setStructuredTypeMembers(type, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + if (symbol.flags & SymbolFlags.TypeLiteral) { + setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray); const members = getMembersOfSymbol(symbol); - const callSignatures = getSignaturesOfSymbol(members.get(ts.InternalSymbolName.Call)); - const constructSignatures = getSignaturesOfSymbol(members.get(ts.InternalSymbolName.New)); + const callSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.Call)); + const constructSignatures = getSignaturesOfSymbol(members.get(InternalSymbolName.New)); const indexInfos = getIndexInfosOfSymbol(symbol); setStructuredTypeMembers(type, members, callSignatures, constructSignatures, indexInfos); return; } // Combinations of function, class, enum and module let members = emptySymbols; - let indexInfos: ts.IndexInfo[] | undefined; + let indexInfos: IndexInfo[] | undefined; if (symbol.exports) { members = getExportsOfSymbol(symbol); if (symbol === globalThisSymbol) { - const varsOnly = new ts.Map() as ts.SymbolTable; + const varsOnly = new Map() as SymbolTable; members.forEach(p => { - if (!(p.flags & ts.SymbolFlags.BlockScoped) && !(p.flags & ts.SymbolFlags.ValueModule && p.declarations?.length && ts.every(p.declarations, ts.isAmbientModule))) { + if (!(p.flags & SymbolFlags.BlockScoped) && !(p.flags & SymbolFlags.ValueModule && p.declarations?.length && every(p.declarations, isAmbientModule))) { varsOnly.set(p.escapedName, p); } }); members = varsOnly; } } - let baseConstructorIndexInfo: ts.IndexInfo | undefined; - setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, ts.emptyArray); - if (symbol.flags & ts.SymbolFlags.Class) { + let baseConstructorIndexInfo: IndexInfo | undefined; + setStructuredTypeMembers(type, members, emptyArray, emptyArray, emptyArray); + if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); const baseConstructorType = getBaseConstructorTypeOfClass(classType); - if (baseConstructorType.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.TypeVariable)) { - members = ts.createSymbolTable(getNamedOrIndexSignatureMembers(members)); + if (baseConstructorType.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.TypeVariable)) { + members = createSymbolTable(getNamedOrIndexSignatureMembers(members)); addInheritedMembers(members, getPropertiesOfType(baseConstructorType)); } else if (baseConstructorType === anyType) { @@ -11728,30 +11926,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { if (baseConstructorIndexInfo) { - indexInfos = ts.append(indexInfos, baseConstructorIndexInfo); + indexInfos = append(indexInfos, baseConstructorIndexInfo); } - if (symbol.flags & ts.SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & ts.TypeFlags.Enum || - ts.some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & ts.TypeFlags.NumberLike)))) { - indexInfos = ts.append(indexInfos, enumNumberIndexInfo); + if (symbol.flags & SymbolFlags.Enum && (getDeclaredTypeOfSymbol(symbol).flags & TypeFlags.Enum || + some(type.properties, prop => !!(getTypeOfSymbol(prop).flags & TypeFlags.NumberLike)))) { + indexInfos = append(indexInfos, enumNumberIndexInfo); } } - setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, indexInfos || ts.emptyArray); + setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos || emptyArray); // We resolve the members before computing the signatures because a signature may use // typeof with a qualified name expression that circularly references the type we are // in the process of resolving (see issue #6072). The temporarily empty signature list // will never be observed because a qualified name can't reference signatures. - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method)) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { type.callSignatures = getSignaturesOfSymbol(symbol); } // And likewise for construct signatures for classes - if (symbol.flags & ts.SymbolFlags.Class) { + if (symbol.flags & SymbolFlags.Class) { const classType = getDeclaredTypeOfClassOrInterface(symbol); - let constructSignatures = symbol.members ? getSignaturesOfSymbol(symbol.members.get(ts.InternalSymbolName.Constructor)) : ts.emptyArray; - if (symbol.flags & ts.SymbolFlags.Function) { - constructSignatures = ts.addRange(constructSignatures.slice(), ts.mapDefined( + let constructSignatures = symbol.members ? getSignaturesOfSymbol(symbol.members.get(InternalSymbolName.Constructor)) : emptyArray; + if (symbol.flags & SymbolFlags.Function) { + constructSignatures = addRange(constructSignatures.slice(), mapDefined( type.callSignatures, sig => isJSConstructor(sig.declaration) ? - createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & ts.SignatureFlags.PropagatingFlags) : + createSignature(sig.declaration, sig.typeParameters, sig.thisParameter, sig.parameters, classType, /*resolvedTypePredicate*/ undefined, sig.minArgumentCount, sig.flags & SignatureFlags.PropagatingFlags) : undefined)); } if (!constructSignatures.length) { @@ -11761,37 +11959,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - type ReplaceableIndexedAccessType = ts.IndexedAccessType & { objectType: ts.TypeParameter, indexType: ts.TypeParameter }; - function replaceIndexedAccess(instantiable: ts.Type, type: ReplaceableIndexedAccessType, replacement: ts.Type) { + type ReplaceableIndexedAccessType = IndexedAccessType & { objectType: TypeParameter, indexType: TypeParameter }; + function replaceIndexedAccess(instantiable: Type, type: ReplaceableIndexedAccessType, replacement: Type) { // map type.indexType to 0 // map type.objectType to `[TReplacement]` // thus making the indexed access `[TReplacement][0]` or `TReplacement` return instantiateType(instantiable, createTypeMapper([type.indexType, type.objectType], [getNumberLiteralType(0), createTupleType([replacement])])); } - function resolveReverseMappedTypeMembers(type: ts.ReverseMappedType) { + function resolveReverseMappedTypeMembers(type: ReverseMappedType) { const indexInfo = getIndexInfoOfType(type.source, stringType); const modifiers = getMappedTypeModifiers(type.mappedType); const readonlyMask = modifiers & MappedTypeModifiers.IncludeReadonly ? false : true; - const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : ts.SymbolFlags.Optional; - const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : ts.emptyArray; - const members = ts.createSymbolTable(); + const optionalMask = modifiers & MappedTypeModifiers.IncludeOptional ? 0 : SymbolFlags.Optional; + const indexInfos = indexInfo ? [createIndexInfo(stringType, inferReverseMappedType(indexInfo.type, type.mappedType, type.constraintType), readonlyMask && indexInfo.isReadonly)] : emptyArray; + const members = createSymbolTable(); for (const prop of getPropertiesOfType(type.source)) { - const checkFlags = ts.CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? ts.CheckFlags.Readonly : 0); - const inferredProp = createSymbol(ts.SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ts.ReverseMappedSymbol; + const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); + const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; inferredProp.declarations = prop.declarations; inferredProp.nameType = getSymbolLinks(prop).nameType; inferredProp.propertyType = getTypeOfSymbol(prop); - if (type.constraintType.type.flags & ts.TypeFlags.IndexedAccess - && (type.constraintType.type as ts.IndexedAccessType).objectType.flags & ts.TypeFlags.TypeParameter - && (type.constraintType.type as ts.IndexedAccessType).indexType.flags & ts.TypeFlags.TypeParameter) { + if (type.constraintType.type.flags & TypeFlags.IndexedAccess + && (type.constraintType.type as IndexedAccessType).objectType.flags & TypeFlags.TypeParameter + && (type.constraintType.type as IndexedAccessType).indexType.flags & TypeFlags.TypeParameter) { // A reverse mapping of `{[K in keyof T[K_1]]: T[K_1]}` is the same as that of `{[K in keyof T]: T}`, since all we care about is // inferring to the "type parameter" (or indexed access) shared by the constraint and template. So, to reduce the number of // type identities produced, we simplify such indexed access occurences - const newTypeParam = (type.constraintType.type as ts.IndexedAccessType).objectType; + const newTypeParam = (type.constraintType.type as IndexedAccessType).objectType; const newMappedType = replaceIndexedAccess(type.mappedType, type.constraintType.type as ReplaceableIndexedAccessType, newTypeParam); - inferredProp.mappedType = newMappedType as ts.MappedType; - inferredProp.constraintType = getIndexType(newTypeParam) as ts.IndexType; + inferredProp.mappedType = newMappedType as MappedType; + inferredProp.constraintType = getIndexType(newTypeParam) as IndexType; } else { inferredProp.mappedType = type.mappedType; @@ -11799,56 +11997,56 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } members.set(prop.escapedName, inferredProp); } - setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, indexInfos); + setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos); } // Return the lower bound of the key type in a mapped type. Intuitively, the lower // bound includes those keys that are known to always be present, for example because // because of constraints on type parameters (e.g. 'keyof T' for a constrained T). - function getLowerBoundOfKeyType(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Index) { - const t = getApparentType((type as ts.IndexType).type); + function getLowerBoundOfKeyType(type: Type): Type { + if (type.flags & TypeFlags.Index) { + const t = getApparentType((type as IndexType).type); return isGenericTupleType(t) ? getKnownKeysOfTupleType(t) : getIndexType(t); } - if (type.flags & ts.TypeFlags.Conditional) { - if ((type as ts.ConditionalType).root.isDistributive) { - const checkType = (type as ts.ConditionalType).checkType; + if (type.flags & TypeFlags.Conditional) { + if ((type as ConditionalType).root.isDistributive) { + const checkType = (type as ConditionalType).checkType; const constraint = getLowerBoundOfKeyType(checkType); if (constraint !== checkType) { - return getConditionalTypeInstantiation(type as ts.ConditionalType, prependTypeMapping((type as ts.ConditionalType).root.checkType, constraint, (type as ts.ConditionalType).mapper)); + return getConditionalTypeInstantiation(type as ConditionalType, prependTypeMapping((type as ConditionalType).root.checkType, constraint, (type as ConditionalType).mapper)); } } return type; } - if (type.flags & ts.TypeFlags.Union) { - return mapType(type as ts.UnionType, getLowerBoundOfKeyType); + if (type.flags & TypeFlags.Union) { + return mapType(type as UnionType, getLowerBoundOfKeyType); } - if (type.flags & ts.TypeFlags.Intersection) { + if (type.flags & TypeFlags.Intersection) { // Similarly to getTypeFromIntersectionTypeNode, we preserve the special string & {}, number & {}, // and bigint & {} intersections that are used to prevent subtype reduction in union types. - const types = (type as ts.IntersectionType).types; - if (types.length === 2 && !!(types[0].flags & (ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType) { + const types = (type as IntersectionType).types; + if (types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType) { return type; } - return getIntersectionType(ts.sameMap((type as ts.UnionType).types, getLowerBoundOfKeyType)); + return getIntersectionType(sameMap((type as UnionType).types, getLowerBoundOfKeyType)); } return type; } - function getIsLateCheckFlag(s: ts.Symbol): ts.CheckFlags { - return ts.getCheckFlags(s) & ts.CheckFlags.Late; + function getIsLateCheckFlag(s: Symbol): CheckFlags { + return getCheckFlags(s) & CheckFlags.Late; } - function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: ts.Type, include: ts.TypeFlags, stringsOnly: boolean, cb: (keyType: ts.Type) => void) { + function forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(type: Type, include: TypeFlags, stringsOnly: boolean, cb: (keyType: Type) => void) { for (const prop of getPropertiesOfType(type)) { cb(getLiteralTypeFromProperty(prop, include)); } - if (type.flags & ts.TypeFlags.Any) { + if (type.flags & TypeFlags.Any) { cb(stringType); } else { for (const info of getIndexInfosOfType(type)) { - if (!stringsOnly || info.keyType.flags & (ts.TypeFlags.String | ts.TypeFlags.TemplateLiteral)) { + if (!stringsOnly || info.keyType.flags & (TypeFlags.String | TypeFlags.TemplateLiteral)) { cb(info.keyType); } } @@ -11856,20 +12054,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** Resolve the members of a mapped type { [P in K]: T } */ - function resolveMappedTypeMembers(type: ts.MappedType) { - const members: ts.SymbolTable = ts.createSymbolTable(); - let indexInfos: ts.IndexInfo[] | undefined; + function resolveMappedTypeMembers(type: MappedType) { + const members: SymbolTable = createSymbolTable(); + let indexInfos: IndexInfo[] | undefined; // Resolve upfront such that recursive references see an empty object type. - setStructuredTypeMembers(type, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + setStructuredTypeMembers(type, emptySymbols, emptyArray, emptyArray, emptyArray); // In { [P in K]: T }, we refer to P as the type parameter type, K as the constraint type, // and T as the template type. const typeParameter = getTypeParameterFromMappedType(type); const constraintType = getConstraintTypeFromMappedType(type); - const nameType = getNameTypeFromMappedType(type.target as ts.MappedType || type); - const templateType = getTemplateTypeFromMappedType(type.target as ts.MappedType || type); + const nameType = getNameTypeFromMappedType(type.target as MappedType || type); + const templateType = getTemplateTypeFromMappedType(type.target as MappedType || type); const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' const templateModifiers = getMappedTypeModifiers(type); - const include = keyofStringsOnly ? ts.TypeFlags.StringLiteral : ts.TypeFlags.StringOrNumberLiteralOrUnique; + const include = keyofStringsOnly ? TypeFlags.StringLiteral : TypeFlags.StringOrNumberLiteralOrUnique; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, include, keyofStringsOnly, addMemberForKeyType); @@ -11877,14 +12075,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { forEachType(getLowerBoundOfKeyType(constraintType), addMemberForKeyType); } - setStructuredTypeMembers(type, members, ts.emptyArray, ts.emptyArray, indexInfos || ts.emptyArray); + setStructuredTypeMembers(type, members, emptyArray, emptyArray, indexInfos || emptyArray); - function addMemberForKeyType(keyType: ts.Type) { + function addMemberForKeyType(keyType: Type) { const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; forEachType(propNameType, t => addMemberForKeyTypeWorker(keyType, t)); } - function addMemberForKeyTypeWorker(keyType: ts.Type, propNameType: ts.Type) { + function addMemberForKeyTypeWorker(keyType: Type, propNameType: Type) { // If the current iteration type constituent is a string literal type, create a property. // Otherwise, for type string create a string index signature. if (isTypeUsableAsPropertyName(propNameType)) { @@ -11892,7 +12090,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // String enum members from separate enums with identical values // are distinct types with the same property name. Make the resulting // property symbol's name type be the union of those enum member types. - const existingProp = members.get(propName) as ts.MappedSymbol | undefined; + const existingProp = members.get(propName) as MappedSymbol | undefined; if (existingProp) { existingProp.nameType = getUnionType([existingProp.nameType!, propNameType]); existingProp.keyType = getUnionType([existingProp.keyType, keyType]); @@ -11900,13 +12098,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { const modifiersProp = isTypeUsableAsPropertyName(keyType) ? getPropertyOfType(modifiersType, getPropertyNameFromType(keyType)) : undefined; const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional || - !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & ts.SymbolFlags.Optional); + !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp)); - const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & ts.SymbolFlags.Optional; - const lateFlag: ts.CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0; - const prop = createSymbol(ts.SymbolFlags.Property | (isOptional ? ts.SymbolFlags.Optional : 0), propName, - lateFlag | ts.CheckFlags.Mapped | (isReadonly ? ts.CheckFlags.Readonly : 0) | (stripOptional ? ts.CheckFlags.StripOptional : 0)) as ts.MappedSymbol; + const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; + const lateFlag: CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0; + const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, + lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)) as MappedSymbol; prop.mappedType = type; prop.nameType = propNameType; prop.keyType = keyType; @@ -11919,9 +12117,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { members.set(propName, prop); } } - else if (isValidIndexKeyType(propNameType) || propNameType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Enum)) { - const indexKeyType = propNameType.flags & (ts.TypeFlags.Any | ts.TypeFlags.String) ? stringType : - propNameType.flags & (ts.TypeFlags.Number | ts.TypeFlags.Enum) ? numberType : + else if (isValidIndexKeyType(propNameType) || propNameType.flags & (TypeFlags.Any | TypeFlags.Enum)) { + const indexKeyType = propNameType.flags & (TypeFlags.Any | TypeFlags.String) ? stringType : + propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType : propNameType; const propType = instantiateType(templateType, appendTypeMapping(type.mapper, typeParameter, keyType)); const indexInfo = createIndexInfo(indexKeyType, propType, !!(templateModifiers & MappedTypeModifiers.IncludeReadonly)); @@ -11930,24 +12128,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeOfMappedSymbol(symbol: ts.MappedSymbol) { + function getTypeOfMappedSymbol(symbol: MappedSymbol) { if (!symbol.type) { const mappedType = symbol.mappedType; if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { mappedType.containsError = true; return errorType; } - const templateType = getTemplateTypeFromMappedType(mappedType.target as ts.MappedType || mappedType); + const templateType = getTemplateTypeFromMappedType(mappedType.target as MappedType || mappedType); const mapper = appendTypeMapping(mappedType.mapper, getTypeParameterFromMappedType(mappedType), symbol.keyType); const propType = instantiateType(templateType, mapper); // When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks // mode, if the underlying property is optional we remove 'undefined' from the type. - let type = strictNullChecks && symbol.flags & ts.SymbolFlags.Optional && !maybeTypeOfKind(propType, ts.TypeFlags.Undefined | ts.TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : - symbol.checkFlags & ts.CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) : + let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : + symbol.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) : propType; if (!popTypeResolution()) { - error(currentNode, ts.Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType)); + error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType)); type = errorType; } symbol.type = type; @@ -11955,147 +12153,147 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol.type; } - function getTypeParameterFromMappedType(type: ts.MappedType) { + function getTypeParameterFromMappedType(type: MappedType) { return type.typeParameter || (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter))); } - function getConstraintTypeFromMappedType(type: ts.MappedType) { + function getConstraintTypeFromMappedType(type: MappedType) { return type.constraintType || (type.constraintType = getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)) || errorType); } - function getNameTypeFromMappedType(type: ts.MappedType) { + function getNameTypeFromMappedType(type: MappedType) { return type.declaration.nameType ? type.nameType || (type.nameType = instantiateType(getTypeFromTypeNode(type.declaration.nameType), type.mapper)) : undefined; } - function getTemplateTypeFromMappedType(type: ts.MappedType) { + function getTemplateTypeFromMappedType(type: MappedType) { return type.templateType || (type.templateType = type.declaration.type ? instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) : errorType); } - function getConstraintDeclarationForMappedType(type: ts.MappedType) { - return ts.getEffectiveConstraintOfTypeParameter(type.declaration.typeParameter); + function getConstraintDeclarationForMappedType(type: MappedType) { + return getEffectiveConstraintOfTypeParameter(type.declaration.typeParameter); } - function isMappedTypeWithKeyofConstraintDeclaration(type: ts.MappedType) { + function isMappedTypeWithKeyofConstraintDeclaration(type: MappedType) { const constraintDeclaration = getConstraintDeclarationForMappedType(type)!; // TODO: GH#18217 - return constraintDeclaration.kind === ts.SyntaxKind.TypeOperator && - (constraintDeclaration as ts.TypeOperatorNode).operator === ts.SyntaxKind.KeyOfKeyword; + return constraintDeclaration.kind === SyntaxKind.TypeOperator && + (constraintDeclaration as TypeOperatorNode).operator === SyntaxKind.KeyOfKeyword; } - function getModifiersTypeFromMappedType(type: ts.MappedType) { + function getModifiersTypeFromMappedType(type: MappedType) { if (!type.modifiersType) { if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // If the constraint declaration is a 'keyof T' node, the modifiers type is T. We check // AST nodes here because, when T is a non-generic type, the logic below eagerly resolves // 'keyof T' to a literal union type and we can't recover T from that type. - type.modifiersType = instantiateType(getTypeFromTypeNode((getConstraintDeclarationForMappedType(type) as ts.TypeOperatorNode).type), type.mapper); + type.modifiersType = instantiateType(getTypeFromTypeNode((getConstraintDeclarationForMappedType(type) as TypeOperatorNode).type), type.mapper); } else { // Otherwise, get the declared constraint type, and if the constraint type is a type parameter, // get the constraint of that type parameter. If the resulting type is an indexed type 'keyof T', // the modifiers type is T. Otherwise, the modifiers type is unknown. - const declaredType = getTypeFromMappedTypeNode(type.declaration) as ts.MappedType; + const declaredType = getTypeFromMappedTypeNode(type.declaration) as MappedType; const constraint = getConstraintTypeFromMappedType(declaredType); - const extendedConstraint = constraint && constraint.flags & ts.TypeFlags.TypeParameter ? getConstraintOfTypeParameter(constraint as ts.TypeParameter) : constraint; - type.modifiersType = extendedConstraint && extendedConstraint.flags & ts.TypeFlags.Index ? instantiateType((extendedConstraint as ts.IndexType).type, type.mapper) : unknownType; + const extendedConstraint = constraint && constraint.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(constraint as TypeParameter) : constraint; + type.modifiersType = extendedConstraint && extendedConstraint.flags & TypeFlags.Index ? instantiateType((extendedConstraint as IndexType).type, type.mapper) : unknownType; } } return type.modifiersType; } - function getMappedTypeModifiers(type: ts.MappedType): MappedTypeModifiers { + function getMappedTypeModifiers(type: MappedType): MappedTypeModifiers { const declaration = type.declaration; - return (declaration.readonlyToken ? declaration.readonlyToken.kind === ts.SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeReadonly : MappedTypeModifiers.IncludeReadonly : 0) | - (declaration.questionToken ? declaration.questionToken.kind === ts.SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeOptional : MappedTypeModifiers.IncludeOptional : 0); + return (declaration.readonlyToken ? declaration.readonlyToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeReadonly : MappedTypeModifiers.IncludeReadonly : 0) | + (declaration.questionToken ? declaration.questionToken.kind === SyntaxKind.MinusToken ? MappedTypeModifiers.ExcludeOptional : MappedTypeModifiers.IncludeOptional : 0); } - function getMappedTypeOptionality(type: ts.MappedType): number { + function getMappedTypeOptionality(type: MappedType): number { const modifiers = getMappedTypeModifiers(type); return modifiers & MappedTypeModifiers.ExcludeOptional ? -1 : modifiers & MappedTypeModifiers.IncludeOptional ? 1 : 0; } - function getCombinedMappedTypeOptionality(type: ts.MappedType): number { + function getCombinedMappedTypeOptionality(type: MappedType): number { const optionality = getMappedTypeOptionality(type); const modifiersType = getModifiersTypeFromMappedType(type); return optionality || (isGenericMappedType(modifiersType) ? getMappedTypeOptionality(modifiersType) : 0); } - function isPartialMappedType(type: ts.Type) { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Mapped && getMappedTypeModifiers(type as ts.MappedType) & MappedTypeModifiers.IncludeOptional); + function isPartialMappedType(type: Type) { + return !!(getObjectFlags(type) & ObjectFlags.Mapped && getMappedTypeModifiers(type as MappedType) & MappedTypeModifiers.IncludeOptional); } - function isGenericMappedType(type: ts.Type): type is ts.MappedType { - if (ts.getObjectFlags(type) & ts.ObjectFlags.Mapped) { - const constraint = getConstraintTypeFromMappedType(type as ts.MappedType); + function isGenericMappedType(type: Type): type is MappedType { + if (getObjectFlags(type) & ObjectFlags.Mapped) { + const constraint = getConstraintTypeFromMappedType(type as MappedType); if (isGenericIndexType(constraint)) { return true; } // A mapped type is generic if the 'as' clause references generic types other than the iteration type. // To determine this, we substitute the constraint type (that we now know isn't generic) for the iteration // type and check whether the resulting type is generic. - const nameType = getNameTypeFromMappedType(type as ts.MappedType); - if (nameType && isGenericIndexType(instantiateType(nameType, makeUnaryTypeMapper(getTypeParameterFromMappedType(type as ts.MappedType), constraint)))) { + const nameType = getNameTypeFromMappedType(type as MappedType); + if (nameType && isGenericIndexType(instantiateType(nameType, makeUnaryTypeMapper(getTypeParameterFromMappedType(type as MappedType), constraint)))) { return true; } } return false; } - function resolveStructuredTypeMembers(type: ts.StructuredType): ts.ResolvedType { - if (!(type as ts.ResolvedType).members) { - if (type.flags & ts.TypeFlags.Object) { - if ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference) { - resolveTypeReferenceMembers(type as ts.TypeReference); + function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { + if (!(type as ResolvedType).members) { + if (type.flags & TypeFlags.Object) { + if ((type as ObjectType).objectFlags & ObjectFlags.Reference) { + resolveTypeReferenceMembers(type as TypeReference); } - else if ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.ClassOrInterface) { - resolveClassOrInterfaceMembers(type as ts.InterfaceType); + else if ((type as ObjectType).objectFlags & ObjectFlags.ClassOrInterface) { + resolveClassOrInterfaceMembers(type as InterfaceType); } - else if ((type as ts.ReverseMappedType).objectFlags & ts.ObjectFlags.ReverseMapped) { - resolveReverseMappedTypeMembers(type as ts.ReverseMappedType); + else if ((type as ReverseMappedType).objectFlags & ObjectFlags.ReverseMapped) { + resolveReverseMappedTypeMembers(type as ReverseMappedType); } - else if ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Anonymous) { - resolveAnonymousTypeMembers(type as ts.AnonymousType); + else if ((type as ObjectType).objectFlags & ObjectFlags.Anonymous) { + resolveAnonymousTypeMembers(type as AnonymousType); } - else if ((type as ts.MappedType).objectFlags & ts.ObjectFlags.Mapped) { - resolveMappedTypeMembers(type as ts.MappedType); + else if ((type as MappedType).objectFlags & ObjectFlags.Mapped) { + resolveMappedTypeMembers(type as MappedType); } else { - ts.Debug.fail("Unhandled object type " + ts.Debug.formatObjectFlags(type.objectFlags)); + Debug.fail("Unhandled object type " + Debug.formatObjectFlags(type.objectFlags)); } } - else if (type.flags & ts.TypeFlags.Union) { - resolveUnionTypeMembers(type as ts.UnionType); + else if (type.flags & TypeFlags.Union) { + resolveUnionTypeMembers(type as UnionType); } - else if (type.flags & ts.TypeFlags.Intersection) { - resolveIntersectionTypeMembers(type as ts.IntersectionType); + else if (type.flags & TypeFlags.Intersection) { + resolveIntersectionTypeMembers(type as IntersectionType); } else { - ts.Debug.fail("Unhandled type " + ts.Debug.formatTypeFlags(type.flags)); + Debug.fail("Unhandled type " + Debug.formatTypeFlags(type.flags)); } } - return type as ts.ResolvedType; + return type as ResolvedType; } /** Return properties of an object type or an empty array for other types */ - function getPropertiesOfObjectType(type: ts.Type): ts.Symbol[] { - if (type.flags & ts.TypeFlags.Object) { - return resolveStructuredTypeMembers(type as ts.ObjectType).properties; + function getPropertiesOfObjectType(type: Type): Symbol[] { + if (type.flags & TypeFlags.Object) { + return resolveStructuredTypeMembers(type as ObjectType).properties; } - return ts.emptyArray; + return emptyArray; } /** If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ - function getPropertyOfObjectType(type: ts.Type, name: ts.__String): ts.Symbol | undefined { - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function getPropertyOfObjectType(type: Type, name: __String): Symbol | undefined { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); const symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol)) { return symbol; @@ -12103,9 +12301,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getPropertiesOfUnionOrIntersectionType(type: ts.UnionOrIntersectionType): ts.Symbol[] { + function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] { if (!type.resolvedProperties) { - const members = ts.createSymbolTable(); + const members = createSymbolTable(); for (const current of type.types) { for (const prop of getPropertiesOfType(current)) { if (!members.has(prop.escapedName)) { @@ -12117,7 +12315,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // The properties of a union type are those that are present in all constituent types, so // we only need to check the properties of the first type without index signature - if (type.flags & ts.TypeFlags.Union && getIndexInfosOfType(current).length === 0) { + if (type.flags & TypeFlags.Union && getIndexInfosOfType(current).length === 0) { break; } } @@ -12126,17 +12324,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedProperties; } - function getPropertiesOfType(type: ts.Type): ts.Symbol[] { + function getPropertiesOfType(type: Type): Symbol[] { type = getReducedApparentType(type); - return type.flags & ts.TypeFlags.UnionOrIntersection ? - getPropertiesOfUnionOrIntersectionType(type as ts.UnionType) : + return type.flags & TypeFlags.UnionOrIntersection ? + getPropertiesOfUnionOrIntersectionType(type as UnionType) : getPropertiesOfObjectType(type); } - function forEachPropertyOfType(type: ts.Type, action: (symbol: ts.Symbol, escapedName: ts.__String) => void): void { + function forEachPropertyOfType(type: Type, action: (symbol: Symbol, escapedName: __String) => void): void { type = getReducedApparentType(type); - if (type.flags & ts.TypeFlags.StructuredType) { - resolveStructuredTypeMembers(type as ts.StructuredType).members.forEach((symbol, escapedName) => { + if (type.flags & TypeFlags.StructuredType) { + resolveStructuredTypeMembers(type as StructuredType).members.forEach((symbol, escapedName) => { if (isNamedMember(symbol, escapedName)) { action(symbol, escapedName); } @@ -12144,8 +12342,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isTypeInvalidDueToUnionDiscriminant(contextualType: ts.Type, obj: ts.ObjectLiteralExpression | ts.JsxAttributes): boolean { - const list = obj.properties as ts.NodeArray; + function isTypeInvalidDueToUnionDiscriminant(contextualType: Type, obj: ObjectLiteralExpression | JsxAttributes): boolean { + const list = obj.properties as NodeArray; return list.some(property => { const nameType = property.name && getLiteralTypeFromPropertyName(property.name); const name = nameType && isTypeUsableAsPropertyName(nameType) ? getPropertyNameFromType(nameType) : undefined; @@ -12154,50 +12352,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function getAllPossiblePropertiesOfTypes(types: readonly ts.Type[]): ts.Symbol[] { + function getAllPossiblePropertiesOfTypes(types: readonly Type[]): Symbol[] { const unionType = getUnionType(types); - if (!(unionType.flags & ts.TypeFlags.Union)) { + if (!(unionType.flags & TypeFlags.Union)) { return getAugmentedPropertiesOfType(unionType); } - const props = ts.createSymbolTable(); + const props = createSymbolTable(); for (const memberType of types) { for (const { escapedName } of getAugmentedPropertiesOfType(memberType)) { if (!props.has(escapedName)) { - const prop = createUnionOrIntersectionProperty(unionType as ts.UnionType, escapedName); + const prop = createUnionOrIntersectionProperty(unionType as UnionType, escapedName); // May be undefined if the property is private if (prop) props.set(escapedName, prop); } } } - return ts.arrayFrom(props.values()); + return arrayFrom(props.values()); } - function getConstraintOfType(type: ts.InstantiableType | ts.UnionOrIntersectionType): ts.Type | undefined { - return type.flags & ts.TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type as ts.TypeParameter) : - type.flags & ts.TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type as ts.IndexedAccessType) : - type.flags & ts.TypeFlags.Conditional ? getConstraintOfConditionalType(type as ts.ConditionalType) : + function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined { + return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(type as TypeParameter) : + type.flags & TypeFlags.IndexedAccess ? getConstraintOfIndexedAccess(type as IndexedAccessType) : + type.flags & TypeFlags.Conditional ? getConstraintOfConditionalType(type as ConditionalType) : getBaseConstraintOfType(type); } - function getConstraintOfTypeParameter(typeParameter: ts.TypeParameter): ts.Type | undefined { + function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type | undefined { return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined; } - function getConstraintOfIndexedAccess(type: ts.IndexedAccessType) { + function getConstraintOfIndexedAccess(type: IndexedAccessType) { return hasNonCircularBaseConstraint(type) ? getConstraintFromIndexedAccess(type) : undefined; } - function getSimplifiedTypeOrConstraint(type: ts.Type) { + function getSimplifiedTypeOrConstraint(type: Type) { const simplified = getSimplifiedType(type, /*writing*/ false); return simplified !== type ? simplified : getConstraintOfType(type); } - function getConstraintFromIndexedAccess(type: ts.IndexedAccessType) { + function getConstraintFromIndexedAccess(type: IndexedAccessType) { if (isMappedTypeGenericIndexedAccess(type)) { // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic, // we substitute an instantiation of E where P is replaced with X. - return substituteIndexedMappedType(type.objectType as ts.MappedType, type.indexType); + return substituteIndexedMappedType(type.objectType as MappedType, type.indexType); } const indexConstraint = getSimplifiedTypeOrConstraint(type.indexType); if (indexConstraint && indexConstraint !== type.indexType) { @@ -12213,7 +12411,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getDefaultConstraintOfConditionalType(type: ts.ConditionalType) { + function getDefaultConstraintOfConditionalType(type: ConditionalType) { if (!type.resolvedDefaultConstraint) { // An `any` branch of a conditional type would normally be viral - specifically, without special handling here, // a conditional type with a single branch of type `any` would be assignable to anything, since it's constraint would simplify to @@ -12226,7 +12424,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedDefaultConstraint; } - function getConstraintOfDistributiveConditionalType(type: ts.ConditionalType): ts.Type | undefined { + function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type | undefined { // Check if we have a conditional type of the form 'T extends U ? X : Y', where T is a constrained // type parameter. If so, create an instantiation of the conditional type where T is replaced // with its constraint. We do this because if the constraint is a union type it will be distributed @@ -12243,7 +12441,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified; if (constraint && constraint !== type.checkType) { const instantiated = getConditionalTypeInstantiation(type, prependTypeMapping(type.root.checkType, constraint, type.mapper)); - if (!(instantiated.flags & ts.TypeFlags.Never)) { + if (!(instantiated.flags & TypeFlags.Never)) { return instantiated; } } @@ -12251,33 +12449,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getConstraintFromConditionalType(type: ts.ConditionalType) { + function getConstraintFromConditionalType(type: ConditionalType) { return getConstraintOfDistributiveConditionalType(type) || getDefaultConstraintOfConditionalType(type); } - function getConstraintOfConditionalType(type: ts.ConditionalType) { + function getConstraintOfConditionalType(type: ConditionalType) { return hasNonCircularBaseConstraint(type) ? getConstraintFromConditionalType(type) : undefined; } - function getEffectiveConstraintOfIntersection(types: readonly ts.Type[], targetIsUnion: boolean) { - let constraints: ts.Type[] | undefined; + function getEffectiveConstraintOfIntersection(types: readonly Type[], targetIsUnion: boolean) { + let constraints: Type[] | undefined; let hasDisjointDomainType = false; for (const t of types) { - if (t.flags & ts.TypeFlags.Instantiable) { + if (t.flags & TypeFlags.Instantiable) { // We keep following constraints as long as we have an instantiable type that is known // not to be circular or infinite (hence we stop on index access types). let constraint = getConstraintOfType(t); - while (constraint && constraint.flags & (ts.TypeFlags.TypeParameter | ts.TypeFlags.Index | ts.TypeFlags.Conditional)) { + while (constraint && constraint.flags & (TypeFlags.TypeParameter | TypeFlags.Index | TypeFlags.Conditional)) { constraint = getConstraintOfType(constraint); } if (constraint) { - constraints = ts.append(constraints, constraint); + constraints = append(constraints, constraint); if (targetIsUnion) { - constraints = ts.append(constraints, t); + constraints = append(constraints, t); } } } - else if (t.flags & ts.TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) { + else if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) { hasDisjointDomainType = true; } } @@ -12288,8 +12486,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We add any types belong to one of the disjoint domains because they might cause the final // intersection operation to reduce the union constraints. for (const t of types) { - if (t.flags & ts.TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) { - constraints = ts.append(constraints, t); + if (t.flags & TypeFlags.DisjointDomains || isEmptyAnonymousObjectType(t)) { + constraints = append(constraints, t); } } } @@ -12299,23 +12497,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getBaseConstraintOfType(type: ts.Type): ts.Type | undefined { - if (type.flags & (ts.TypeFlags.InstantiableNonPrimitive | ts.TypeFlags.UnionOrIntersection | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping)) { - const constraint = getResolvedBaseConstraint(type as ts.InstantiableType | ts.UnionOrIntersectionType); + function getBaseConstraintOfType(type: Type): Type | undefined { + if (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral | TypeFlags.StringMapping)) { + const constraint = getResolvedBaseConstraint(type as InstantiableType | UnionOrIntersectionType); return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined; } - return type.flags & ts.TypeFlags.Index ? keyofConstraintType : undefined; + return type.flags & TypeFlags.Index ? keyofConstraintType : undefined; } /** * This is similar to `getBaseConstraintOfType` except it returns the input type if there's no base constraint, instead of `undefined` * It also doesn't map indexes to `string`, as where this is used this would be unneeded (and likely undesirable) */ - function getBaseConstraintOrType(type: ts.Type) { + function getBaseConstraintOrType(type: Type) { return getBaseConstraintOfType(type) || type; } - function hasNonCircularBaseConstraint(type: ts.InstantiableType): boolean { + function hasNonCircularBaseConstraint(type: InstantiableType): boolean { return getResolvedBaseConstraint(type) !== circularConstraintType; } @@ -12324,14 +12522,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * type variable has no constraint, and the circularConstraintType singleton is returned if the constraint * circularly references the type variable. */ - function getResolvedBaseConstraint(type: ts.InstantiableType | ts.UnionOrIntersectionType): ts.Type { + function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type { if (type.resolvedBaseConstraint) { return type.resolvedBaseConstraint; } const stack: object[] = []; return type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type); - function getImmediateBaseConstraint(t: ts.Type): ts.Type { + function getImmediateBaseConstraint(t: Type): Type { if (!t.immediateBaseConstraint) { if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) { return circularConstraintType; @@ -12344,18 +12542,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // yet triggered the deeply nested limiter. We have no test cases that actually get to 50 levels of // nesting, so it is effectively just a safety stop. const identity = getRecursionIdentity(t); - if (stack.length < 10 || stack.length < 50 && !ts.contains(stack, identity)) { + if (stack.length < 10 || stack.length < 50 && !contains(stack, identity)) { stack.push(identity); result = computeBaseConstraint(getSimplifiedType(t, /*writing*/ false)); stack.pop(); } if (!popTypeResolution()) { - if (t.flags & ts.TypeFlags.TypeParameter) { - const errorNode = getConstraintDeclaration(t as ts.TypeParameter); + if (t.flags & TypeFlags.TypeParameter) { + const errorNode = getConstraintDeclaration(t as TypeParameter); if (errorNode) { - const diagnostic = error(errorNode, ts.Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(t)); - if (currentNode && !ts.isNodeDescendantOf(errorNode, currentNode) && !ts.isNodeDescendantOf(currentNode, errorNode)) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(currentNode, ts.Diagnostics.Circularity_originates_in_type_at_this_location)); + const diagnostic = error(errorNode, Diagnostics.Type_parameter_0_has_a_circular_constraint, typeToString(t)); + if (currentNode && !isNodeDescendantOf(errorNode, currentNode) && !isNodeDescendantOf(currentNode, errorNode)) { + addRelatedInfo(diagnostic, createDiagnosticForNode(currentNode, Diagnostics.Circularity_originates_in_type_at_this_location)); } } } @@ -12366,21 +12564,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return t.immediateBaseConstraint; } - function getBaseConstraint(t: ts.Type): ts.Type | undefined { + function getBaseConstraint(t: Type): Type | undefined { const c = getImmediateBaseConstraint(t); return c !== noConstraintType && c !== circularConstraintType ? c : undefined; } - function computeBaseConstraint(t: ts.Type): ts.Type | undefined { - if (t.flags & ts.TypeFlags.TypeParameter) { - const constraint = getConstraintFromTypeParameter(t as ts.TypeParameter); - return (t as ts.TypeParameter).isThisType || !constraint ? + function computeBaseConstraint(t: Type): Type | undefined { + if (t.flags & TypeFlags.TypeParameter) { + const constraint = getConstraintFromTypeParameter(t as TypeParameter); + return (t as TypeParameter).isThisType || !constraint ? constraint : getBaseConstraint(constraint); } - if (t.flags & ts.TypeFlags.UnionOrIntersection) { - const types = (t as ts.UnionOrIntersectionType).types; - const baseTypes: ts.Type[] = []; + if (t.flags & TypeFlags.UnionOrIntersection) { + const types = (t as UnionOrIntersectionType).types; + const baseTypes: Type[] = []; let different = false; for (const type of types) { const baseType = getBaseConstraint(type); @@ -12397,49 +12595,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!different) { return t; } - return t.flags & ts.TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) : - t.flags & ts.TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) : + return t.flags & TypeFlags.Union && baseTypes.length === types.length ? getUnionType(baseTypes) : + t.flags & TypeFlags.Intersection && baseTypes.length ? getIntersectionType(baseTypes) : undefined; } - if (t.flags & ts.TypeFlags.Index) { + if (t.flags & TypeFlags.Index) { return keyofConstraintType; } - if (t.flags & ts.TypeFlags.TemplateLiteral) { - const types = (t as ts.TemplateLiteralType).types; - const constraints = ts.mapDefined(types, getBaseConstraint); - return constraints.length === types.length ? getTemplateLiteralType((t as ts.TemplateLiteralType).texts, constraints) : stringType; + if (t.flags & TypeFlags.TemplateLiteral) { + const types = (t as TemplateLiteralType).types; + const constraints = mapDefined(types, getBaseConstraint); + return constraints.length === types.length ? getTemplateLiteralType((t as TemplateLiteralType).texts, constraints) : stringType; } - if (t.flags & ts.TypeFlags.StringMapping) { - const constraint = getBaseConstraint((t as ts.StringMappingType).type); - return constraint && constraint !== (t as ts.StringMappingType).type ? getStringMappingType((t as ts.StringMappingType).symbol, constraint) : stringType; + if (t.flags & TypeFlags.StringMapping) { + const constraint = getBaseConstraint((t as StringMappingType).type); + return constraint && constraint !== (t as StringMappingType).type ? getStringMappingType((t as StringMappingType).symbol, constraint) : stringType; } - if (t.flags & ts.TypeFlags.IndexedAccess) { + if (t.flags & TypeFlags.IndexedAccess) { if (isMappedTypeGenericIndexedAccess(t)) { // For indexed access types of the form { [P in K]: E }[X], where K is non-generic and X is generic, // we substitute an instantiation of E where P is replaced with X. - return getBaseConstraint(substituteIndexedMappedType((t as ts.IndexedAccessType).objectType as ts.MappedType, (t as ts.IndexedAccessType).indexType)); + return getBaseConstraint(substituteIndexedMappedType((t as IndexedAccessType).objectType as MappedType, (t as IndexedAccessType).indexType)); } - const baseObjectType = getBaseConstraint((t as ts.IndexedAccessType).objectType); - const baseIndexType = getBaseConstraint((t as ts.IndexedAccessType).indexType); - const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, (t as ts.IndexedAccessType).accessFlags); + const baseObjectType = getBaseConstraint((t as IndexedAccessType).objectType); + const baseIndexType = getBaseConstraint((t as IndexedAccessType).indexType); + const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, (t as IndexedAccessType).accessFlags); return baseIndexedAccess && getBaseConstraint(baseIndexedAccess); } - if (t.flags & ts.TypeFlags.Conditional) { - const constraint = getConstraintFromConditionalType(t as ts.ConditionalType); + if (t.flags & TypeFlags.Conditional) { + const constraint = getConstraintFromConditionalType(t as ConditionalType); return constraint && getBaseConstraint(constraint); } - if (t.flags & ts.TypeFlags.Substitution) { - return getBaseConstraint(getSubstitutionIntersection(t as ts.SubstitutionType)); + if (t.flags & TypeFlags.Substitution) { + return getBaseConstraint(getSubstitutionIntersection(t as SubstitutionType)); } return t; } } - function getApparentTypeOfIntersectionType(type: ts.IntersectionType) { + function getApparentTypeOfIntersectionType(type: IntersectionType) { return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true)); } - function getResolvedTypeParameterDefault(typeParameter: ts.TypeParameter): ts.Type | undefined { + function getResolvedTypeParameterDefault(typeParameter: TypeParameter): Type | undefined { if (!typeParameter.default) { if (typeParameter.target) { const targetDefault = getResolvedTypeParameterDefault(typeParameter.target); @@ -12448,7 +12646,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // To block recursion, set the initial value to the resolvingDefaultType. typeParameter.default = resolvingDefaultType; - const defaultDeclaration = typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, decl => ts.isTypeParameterDeclaration(decl) && decl.default); + const defaultDeclaration = typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default); const defaultType = defaultDeclaration ? getTypeFromTypeNode(defaultDeclaration) : noConstraintType; if (typeParameter.default === resolvingDefaultType) { // If we have not been called recursively, set the correct default type. @@ -12470,27 +12668,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * default type of its target. If the type parameter has no default type or the default is * circular, `undefined` is returned. */ - function getDefaultFromTypeParameter(typeParameter: ts.TypeParameter): ts.Type | undefined { + function getDefaultFromTypeParameter(typeParameter: TypeParameter): Type | undefined { const defaultType = getResolvedTypeParameterDefault(typeParameter); return defaultType !== noConstraintType && defaultType !== circularConstraintType ? defaultType : undefined; } - function hasNonCircularTypeParameterDefault(typeParameter: ts.TypeParameter) { + function hasNonCircularTypeParameterDefault(typeParameter: TypeParameter) { return getResolvedTypeParameterDefault(typeParameter) !== circularConstraintType; } /** * Indicates whether the declaration of a typeParameter has a default type. */ - function hasTypeParameterDefault(typeParameter: ts.TypeParameter): boolean { - return !!(typeParameter.symbol && ts.forEach(typeParameter.symbol.declarations, decl => ts.isTypeParameterDeclaration(decl) && decl.default)); + function hasTypeParameterDefault(typeParameter: TypeParameter): boolean { + return !!(typeParameter.symbol && forEach(typeParameter.symbol.declarations, decl => isTypeParameterDeclaration(decl) && decl.default)); } - function getApparentTypeOfMappedType(type: ts.MappedType) { + function getApparentTypeOfMappedType(type: MappedType) { return type.resolvedApparentType || (type.resolvedApparentType = getResolvedApparentTypeOfMappedType(type)); } - function getResolvedApparentTypeOfMappedType(type: ts.MappedType) { + function getResolvedApparentTypeOfMappedType(type: MappedType) { const typeVariable = getHomomorphicTypeVariable(type); if (typeVariable && !type.declaration.nameType) { const constraint = getConstraintOfTypeParameter(typeVariable); @@ -12501,11 +12699,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function isMappedTypeGenericIndexedAccess(type: ts.Type) { + function isMappedTypeGenericIndexedAccess(type: Type) { let objectType; - return !!(type.flags & ts.TypeFlags.IndexedAccess && ts.getObjectFlags(objectType = (type as ts.IndexedAccessType).objectType) & ts.ObjectFlags.Mapped && - !isGenericMappedType(objectType) && isGenericIndexType((type as ts.IndexedAccessType).indexType) && - !(getMappedTypeModifiers(objectType as ts.MappedType) & MappedTypeModifiers.ExcludeOptional) && !(objectType as ts.MappedType).declaration.nameType); + return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped && + !isGenericMappedType(objectType) && isGenericIndexType((type as IndexedAccessType).indexType) && + !(getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.ExcludeOptional) && !(objectType as MappedType).declaration.nameType); } /** @@ -12513,22 +12711,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * boolean, and symbol primitive types, return the corresponding object types. Otherwise return the * type itself. */ - function getApparentType(type: ts.Type): ts.Type { - const t = !(type.flags & ts.TypeFlags.Instantiable) ? type : getBaseConstraintOfType(type) || unknownType; - return ts.getObjectFlags(t) & ts.ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as ts.MappedType) : - t.flags & ts.TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as ts.IntersectionType) : - t.flags & ts.TypeFlags.StringLike ? globalStringType : - t.flags & ts.TypeFlags.NumberLike ? globalNumberType : - t.flags & ts.TypeFlags.BigIntLike ? getGlobalBigIntType() : - t.flags & ts.TypeFlags.BooleanLike ? globalBooleanType : - t.flags & ts.TypeFlags.ESSymbolLike ? getGlobalESSymbolType() : - t.flags & ts.TypeFlags.NonPrimitive ? emptyObjectType : - t.flags & ts.TypeFlags.Index ? keyofConstraintType : - t.flags & ts.TypeFlags.Unknown && !strictNullChecks ? emptyObjectType : + function getApparentType(type: Type): Type { + const t = !(type.flags & TypeFlags.Instantiable) ? type : getBaseConstraintOfType(type) || unknownType; + return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) : + t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType) : + t.flags & TypeFlags.StringLike ? globalStringType : + t.flags & TypeFlags.NumberLike ? globalNumberType : + t.flags & TypeFlags.BigIntLike ? getGlobalBigIntType() : + t.flags & TypeFlags.BooleanLike ? globalBooleanType : + t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType() : + t.flags & TypeFlags.NonPrimitive ? emptyObjectType : + t.flags & TypeFlags.Index ? keyofConstraintType : + t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType : t; } - function getReducedApparentType(type: ts.Type): ts.Type { + function getReducedApparentType(type: Type): Type { // Since getApparentType may return a non-reduced union or intersection type, we need to perform // type reduction both before and after obtaining the apparent type. For example, given a type parameter // 'T extends A | B', the type 'T & X' becomes 'A & X | B & X' after obtaining the apparent type, and @@ -12536,26 +12734,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getReducedType(getApparentType(getReducedType(type))); } - function createUnionOrIntersectionProperty(containingType: ts.UnionOrIntersectionType, name: ts.__String, skipObjectFunctionPropertyAugment?: boolean): ts.Symbol | undefined { - let singleProp: ts.Symbol | undefined; - let propSet: ts.ESMap | undefined; - let indexTypes: ts.Type[] | undefined; - const isUnion = containingType.flags & ts.TypeFlags.Union; + function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { + let singleProp: Symbol | undefined; + let propSet: ESMap | undefined; + let indexTypes: Type[] | undefined; + const isUnion = containingType.flags & TypeFlags.Union; // Flags we want to propagate to the result if they exist in all source symbols - let optionalFlag: ts.SymbolFlags | undefined; - let syntheticFlag = ts.CheckFlags.SyntheticMethod; - let checkFlags = isUnion ? 0 : ts.CheckFlags.Readonly; + let optionalFlag: SymbolFlags | undefined; + let syntheticFlag = CheckFlags.SyntheticMethod; + let checkFlags = isUnion ? 0 : CheckFlags.Readonly; let mergedInstantiations = false; for (const current of containingType.types) { const type = getApparentType(current); - if (!(isErrorType(type) || type.flags & ts.TypeFlags.Never)) { + if (!(isErrorType(type) || type.flags & TypeFlags.Never)) { const prop = getPropertyOfType(type, name, skipObjectFunctionPropertyAugment); - const modifiers = prop ? ts.getDeclarationModifierFlagsFromSymbol(prop) : 0; + const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0; if (prop) { - if (prop.flags & ts.SymbolFlags.ClassMember) { - optionalFlag ??= isUnion ? ts.SymbolFlags.None : ts.SymbolFlags.Optional; + if (prop.flags & SymbolFlags.ClassMember) { + optionalFlag ??= isUnion ? SymbolFlags.None : SymbolFlags.Optional; if (isUnion) { - optionalFlag |= (prop.flags & ts.SymbolFlags.Optional); + optionalFlag |= (prop.flags & SymbolFlags.Optional); } else { optionalFlag &= prop.flags; @@ -12569,15 +12767,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the symbols are instances of one another with identical types - consider the symbols // equivalent and just use the first one, which thus allows us to avoid eliding private // members when intersecting a (this-)instantiations of a class with its raw base or another instance - if (isInstantiation && compareProperties(singleProp, prop, (a, b) => a === b ? ts.Ternary.True : ts.Ternary.False) === ts.Ternary.True) { + if (isInstantiation && compareProperties(singleProp, prop, (a, b) => a === b ? Ternary.True : Ternary.False) === Ternary.True) { // If we merged instantiations of a generic type, we replicate the symbol parent resetting behavior we used // to do when we recorded multiple distinct symbols so that we still get, eg, `Array.length` printed // back and not `Array.length` when we're looking at a `.length` access on a `string[] | number[]` - mergedInstantiations = !!singleProp.parent && !!ts.length(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.parent)); + mergedInstantiations = !!singleProp.parent && !!length(getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(singleProp.parent)); } else { if (!propSet) { - propSet = new ts.Map(); + propSet = new Map(); propSet.set(getSymbolId(singleProp), singleProp); } const id = getSymbolId(prop); @@ -12587,67 +12785,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (isUnion && isReadonlySymbol(prop)) { - checkFlags |= ts.CheckFlags.Readonly; + checkFlags |= CheckFlags.Readonly; } else if (!isUnion && !isReadonlySymbol(prop)) { - checkFlags &= ~ts.CheckFlags.Readonly; + checkFlags &= ~CheckFlags.Readonly; } - checkFlags |= (!(modifiers & ts.ModifierFlags.NonPublicAccessibilityModifier) ? ts.CheckFlags.ContainsPublic : 0) | - (modifiers & ts.ModifierFlags.Protected ? ts.CheckFlags.ContainsProtected : 0) | - (modifiers & ts.ModifierFlags.Private ? ts.CheckFlags.ContainsPrivate : 0) | - (modifiers & ts.ModifierFlags.Static ? ts.CheckFlags.ContainsStatic : 0); + checkFlags |= (!(modifiers & ModifierFlags.NonPublicAccessibilityModifier) ? CheckFlags.ContainsPublic : 0) | + (modifiers & ModifierFlags.Protected ? CheckFlags.ContainsProtected : 0) | + (modifiers & ModifierFlags.Private ? CheckFlags.ContainsPrivate : 0) | + (modifiers & ModifierFlags.Static ? CheckFlags.ContainsStatic : 0); if (!isPrototypeProperty(prop)) { - syntheticFlag = ts.CheckFlags.SyntheticProperty; + syntheticFlag = CheckFlags.SyntheticProperty; } } else if (isUnion) { const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name); if (indexInfo) { - checkFlags |= ts.CheckFlags.WritePartial | (indexInfo.isReadonly ? ts.CheckFlags.Readonly : 0); - indexTypes = ts.append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type); + checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0); + indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type); } - else if (isObjectLiteralType(type) && !(ts.getObjectFlags(type) & ts.ObjectFlags.ContainsSpread)) { - checkFlags |= ts.CheckFlags.WritePartial; - indexTypes = ts.append(indexTypes, undefinedType); + else if (isObjectLiteralType(type) && !(getObjectFlags(type) & ObjectFlags.ContainsSpread)) { + checkFlags |= CheckFlags.WritePartial; + indexTypes = append(indexTypes, undefinedType); } else { - checkFlags |= ts.CheckFlags.ReadPartial; + checkFlags |= CheckFlags.ReadPartial; } } } } if (!singleProp || isUnion && - (propSet || checkFlags & ts.CheckFlags.Partial) && - checkFlags & (ts.CheckFlags.ContainsPrivate | ts.CheckFlags.ContainsProtected) && - !(propSet && getCommonDeclarationsOfSymbols(ts.arrayFrom(propSet.values()))) + (propSet || checkFlags & CheckFlags.Partial) && + checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected) && + !(propSet && getCommonDeclarationsOfSymbols(arrayFrom(propSet.values()))) ) { // No property was found, or, in a union, a property has a private or protected declaration in one // constituent, but is missing or has a different declaration in another constituent. return undefined; } - if (!propSet && !(checkFlags & ts.CheckFlags.ReadPartial) && !indexTypes) { + if (!propSet && !(checkFlags & CheckFlags.ReadPartial) && !indexTypes) { if (mergedInstantiations) { // No symbol from a union/intersection should have a `.parent` set (since unions/intersections don't act as symbol parents) // Unless that parent is "reconstituted" from the "first value declaration" on the symbol (which is likely different than its instantiated parent!) // They also have a `.containingType` set, which affects some services endpoints behavior, like `getRootSymbol` - const clone = createSymbolWithType(singleProp, (singleProp as ts.TransientSymbol).type); + const clone = createSymbolWithType(singleProp, (singleProp as TransientSymbol).type); clone.parent = singleProp.valueDeclaration?.symbol?.parent; clone.containingType = containingType; - clone.mapper = (singleProp as ts.TransientSymbol).mapper; + clone.mapper = (singleProp as TransientSymbol).mapper; return clone; } else { return singleProp; } } - const props = propSet ? ts.arrayFrom(propSet.values()) : [singleProp]; - let declarations: ts.Declaration[] | undefined; - let firstType: ts.Type | undefined; - let nameType: ts.Type | undefined; - const propTypes: ts.Type[] = []; - let writeTypes: ts.Type[] | undefined; - let firstValueDeclaration: ts.Declaration | undefined; + const props = propSet ? arrayFrom(propSet.values()) : [singleProp]; + let declarations: Declaration[] | undefined; + let firstType: Type | undefined; + let nameType: Type | undefined; + const propTypes: Type[] = []; + let writeTypes: Type[] | undefined; + let firstValueDeclaration: Declaration | undefined; let hasNonUniformValueDeclaration = false; for (const prop of props) { if (!firstValueDeclaration) { @@ -12656,7 +12854,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else if (prop.valueDeclaration && prop.valueDeclaration !== firstValueDeclaration) { hasNonUniformValueDeclaration = true; } - declarations = ts.addRange(declarations, prop.declarations); + declarations = addRange(declarations, prop.declarations); const type = getTypeOfSymbol(prop); if (!firstType) { firstType = type; @@ -12664,21 +12862,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const writeType = getWriteTypeOfSymbol(prop); if (writeTypes || writeType !== type) { - writeTypes = ts.append(!writeTypes ? propTypes.slice() : writeTypes, writeType); + writeTypes = append(!writeTypes ? propTypes.slice() : writeTypes, writeType); } else if (type !== firstType) { - checkFlags |= ts.CheckFlags.HasNonUniformType; + checkFlags |= CheckFlags.HasNonUniformType; } if (isLiteralType(type) || isPatternLiteralType(type) || type === uniqueLiteralType) { - checkFlags |= ts.CheckFlags.HasLiteralType; + checkFlags |= CheckFlags.HasLiteralType; } - if (type.flags & ts.TypeFlags.Never && type !== uniqueLiteralType) { - checkFlags |= ts.CheckFlags.HasNeverType; + if (type.flags & TypeFlags.Never && type !== uniqueLiteralType) { + checkFlags |= CheckFlags.HasNeverType; } propTypes.push(type); } - ts.addRange(propTypes, indexTypes); - const result = createSymbol(ts.SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags); + addRange(propTypes, indexTypes); + const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags); result.containingType = containingType; if (!hasNonUniformValueDeclaration && firstValueDeclaration) { result.valueDeclaration = firstValueDeclaration; @@ -12693,7 +12891,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result.nameType = nameType; if (propTypes.length > 2) { // When `propTypes` has the potential to explode in size when normalized, defer normalization until absolutely needed - result.checkFlags |= ts.CheckFlags.DeferredType; + result.checkFlags |= CheckFlags.DeferredType; result.deferralParent = containingType; result.deferralConstituents = propTypes; result.deferralWriteConstituents = writeTypes; @@ -12712,33 +12910,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. - function getUnionOrIntersectionProperty(type: ts.UnionOrIntersectionType, name: ts.__String, skipObjectFunctionPropertyAugment?: boolean): ts.Symbol | undefined { + function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) || !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined; if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { const properties = skipObjectFunctionPropertyAugment ? - type.propertyCacheWithoutObjectFunctionPropertyAugment ||= ts.createSymbolTable() : - type.propertyCache ||= ts.createSymbolTable(); + type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() : + type.propertyCache ||= createSymbolTable(); properties.set(name, property); } } return property; } - function getCommonDeclarationsOfSymbols(symbols: readonly ts.Symbol[]) { - let commonDeclarations: ts.Set | undefined; + function getCommonDeclarationsOfSymbols(symbols: readonly Symbol[]) { + let commonDeclarations: Set | undefined; for (const symbol of symbols) { if (!symbol.declarations) { return undefined; } if (!commonDeclarations) { - commonDeclarations = new ts.Set(symbol.declarations); + commonDeclarations = new Set(symbol.declarations); continue; } commonDeclarations.forEach(declaration => { - if (!ts.contains(symbol.declarations, declaration)) { + if (!contains(symbol.declarations, declaration)) { commonDeclarations!.delete(declaration); } }); @@ -12749,10 +12947,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return commonDeclarations; } - function getPropertyOfUnionOrIntersectionType(type: ts.UnionOrIntersectionType, name: ts.__String, skipObjectFunctionPropertyAugment?: boolean): ts.Symbol | undefined { + function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { const property = getUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); // We need to filter out partial properties in union types - return property && !(ts.getCheckFlags(property) & ts.CheckFlags.ReadPartial) ? property : undefined; + return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined; } /** @@ -12761,60 +12959,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * For all other types, it is simply the type itself. Discriminant properties are considered mutually exclusive when * no constituent property has type 'never', but the intersection of the constituent property types is 'never'. */ - function getReducedType(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Union && (type as ts.UnionType).objectFlags & ts.ObjectFlags.ContainsIntersections) { - return (type as ts.UnionType).resolvedReducedType || ((type as ts.UnionType).resolvedReducedType = getReducedUnionType(type as ts.UnionType)); + function getReducedType(type: Type): Type { + if (type.flags & TypeFlags.Union && (type as UnionType).objectFlags & ObjectFlags.ContainsIntersections) { + return (type as UnionType).resolvedReducedType || ((type as UnionType).resolvedReducedType = getReducedUnionType(type as UnionType)); } - else if (type.flags & ts.TypeFlags.Intersection) { - if (!((type as ts.IntersectionType).objectFlags & ts.ObjectFlags.IsNeverIntersectionComputed)) { - (type as ts.IntersectionType).objectFlags |= ts.ObjectFlags.IsNeverIntersectionComputed | - (ts.some(getPropertiesOfUnionOrIntersectionType(type as ts.IntersectionType), isNeverReducedProperty) ? ts.ObjectFlags.IsNeverIntersection : 0); + else if (type.flags & TypeFlags.Intersection) { + if (!((type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) { + (type as IntersectionType).objectFlags |= ObjectFlags.IsNeverIntersectionComputed | + (some(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0); } - return (type as ts.IntersectionType).objectFlags & ts.ObjectFlags.IsNeverIntersection ? neverType : type; + return (type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type; } return type; } - function getReducedUnionType(unionType: ts.UnionType) { - const reducedTypes = ts.sameMap(unionType.types, getReducedType); + function getReducedUnionType(unionType: UnionType) { + const reducedTypes = sameMap(unionType.types, getReducedType); if (reducedTypes === unionType.types) { return unionType; } const reduced = getUnionType(reducedTypes); - if (reduced.flags & ts.TypeFlags.Union) { - (reduced as ts.UnionType).resolvedReducedType = reduced; + if (reduced.flags & TypeFlags.Union) { + (reduced as UnionType).resolvedReducedType = reduced; } return reduced; } - function isNeverReducedProperty(prop: ts.Symbol) { + function isNeverReducedProperty(prop: Symbol) { return isDiscriminantWithNeverType(prop) || isConflictingPrivateProperty(prop); } - function isDiscriminantWithNeverType(prop: ts.Symbol) { + function isDiscriminantWithNeverType(prop: Symbol) { // Return true for a synthetic non-optional property with non-uniform types, where at least one is // a literal type and none is never, that reduces to never. - return !(prop.flags & ts.SymbolFlags.Optional) && - (ts.getCheckFlags(prop) & (ts.CheckFlags.Discriminant | ts.CheckFlags.HasNeverType)) === ts.CheckFlags.Discriminant && - !!(getTypeOfSymbol(prop).flags & ts.TypeFlags.Never); + return !(prop.flags & SymbolFlags.Optional) && + (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant && + !!(getTypeOfSymbol(prop).flags & TypeFlags.Never); } - function isConflictingPrivateProperty(prop: ts.Symbol) { + function isConflictingPrivateProperty(prop: Symbol) { // Return true for a synthetic property with multiple declarations, at least one of which is private. - return !prop.valueDeclaration && !!(ts.getCheckFlags(prop) & ts.CheckFlags.ContainsPrivate); + return !prop.valueDeclaration && !!(getCheckFlags(prop) & CheckFlags.ContainsPrivate); } - function elaborateNeverIntersection(errorInfo: ts.DiagnosticMessageChain | undefined, type: ts.Type) { - if (type.flags & ts.TypeFlags.Intersection && ts.getObjectFlags(type) & ts.ObjectFlags.IsNeverIntersection) { - const neverProp = ts.find(getPropertiesOfUnionOrIntersectionType(type as ts.IntersectionType), isDiscriminantWithNeverType); + function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: Type) { + if (type.flags & TypeFlags.Intersection && getObjectFlags(type) & ObjectFlags.IsNeverIntersection) { + const neverProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isDiscriminantWithNeverType); if (neverProp) { - return ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, - typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp)); } - const privateProp = ts.find(getPropertiesOfUnionOrIntersectionType(type as ts.IntersectionType), isConflictingPrivateProperty); + const privateProp = find(getPropertiesOfUnionOrIntersectionType(type as IntersectionType), isConflictingPrivateProperty); if (privateProp) { - return ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, - typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); + return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some, + typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp)); } } return errorInfo; @@ -12828,10 +13026,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param type a type to look up property from * @param name a name of property to look up in a given type */ - function getPropertyOfType(type: ts.Type, name: ts.__String, skipObjectFunctionPropertyAugment?: boolean, includeTypeOnlyMembers?: boolean): ts.Symbol | undefined { + function getPropertyOfType(type: Type, name: __String, skipObjectFunctionPropertyAugment?: boolean, includeTypeOnlyMembers?: boolean): Symbol | undefined { type = getReducedApparentType(type); - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); const symbol = resolved.members.get(name); if (symbol && symbolIsValue(symbol, includeTypeOnlyMembers)) { return symbol; @@ -12849,37 +13047,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return getPropertyOfObjectType(globalObjectType, name); } - if (type.flags & ts.TypeFlags.UnionOrIntersection) { - return getPropertyOfUnionOrIntersectionType(type as ts.UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment); + if (type.flags & TypeFlags.UnionOrIntersection) { + return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment); } return undefined; } - function getSignaturesOfStructuredType(type: ts.Type, kind: ts.SignatureKind): readonly ts.Signature[] { - if (type.flags & ts.TypeFlags.StructuredType) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); - return kind === ts.SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures; + function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): readonly Signature[] { + if (type.flags & TypeFlags.StructuredType) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); + return kind === SignatureKind.Call ? resolved.callSignatures : resolved.constructSignatures; } - return ts.emptyArray; + return emptyArray; } /** * Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and * maps primitive types and type parameters are to their apparent types. */ - function getSignaturesOfType(type: ts.Type, kind: ts.SignatureKind): readonly ts.Signature[] { + function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] { return getSignaturesOfStructuredType(getReducedApparentType(type), kind); } - function findIndexInfo(indexInfos: readonly ts.IndexInfo[], keyType: ts.Type) { - return ts.find(indexInfos, info => info.keyType === keyType); + function findIndexInfo(indexInfos: readonly IndexInfo[], keyType: Type) { + return find(indexInfos, info => info.keyType === keyType); } - function findApplicableIndexInfo(indexInfos: readonly ts.IndexInfo[], keyType: ts.Type) { + function findApplicableIndexInfo(indexInfos: readonly IndexInfo[], keyType: Type) { // Index signatures for type 'string' are considered only when no other index signatures apply. - let stringIndexInfo: ts.IndexInfo | undefined; - let applicableInfo: ts.IndexInfo | undefined; - let applicableInfos: ts.IndexInfo[] | undefined; + let stringIndexInfo: IndexInfo | undefined; + let applicableInfo: IndexInfo | undefined; + let applicableInfos: IndexInfo[] | undefined; for (const info of indexInfos) { if (info.keyType === stringType) { stringIndexInfo = info; @@ -12896,71 +13094,71 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When more than one index signature is applicable we create a synthetic IndexInfo. Instead of computing // the intersected key type, we just use unknownType for the key type as nothing actually depends on the // keyType property of the returned IndexInfo. - return applicableInfos ? createIndexInfo(unknownType, getIntersectionType(ts.map(applicableInfos, info => info.type)), - ts.reduceLeft(applicableInfos, (isReadonly, info) => isReadonly && info.isReadonly, /*initial*/ true)) : + return applicableInfos ? createIndexInfo(unknownType, getIntersectionType(map(applicableInfos, info => info.type)), + reduceLeft(applicableInfos, (isReadonly, info) => isReadonly && info.isReadonly, /*initial*/ true)) : applicableInfo ? applicableInfo : stringIndexInfo && isApplicableIndexType(keyType, stringType) ? stringIndexInfo : undefined; } - function isApplicableIndexType(source: ts.Type, target: ts.Type): boolean { + function isApplicableIndexType(source: Type, target: Type): boolean { // A 'string' index signature applies to types assignable to 'string' or 'number', and a 'number' index // signature applies to types assignable to 'number', `${number}` and numeric string literal types. return isTypeAssignableTo(source, target) || target === stringType && isTypeAssignableTo(source, numberType) || - target === numberType && (source === numericStringType || !!(source.flags & ts.TypeFlags.StringLiteral) && ts.isNumericLiteralName((source as ts.StringLiteralType).value)); + target === numberType && (source === numericStringType || !!(source.flags & TypeFlags.StringLiteral) && isNumericLiteralName((source as StringLiteralType).value)); } - function getIndexInfosOfStructuredType(type: ts.Type): readonly ts.IndexInfo[] { - if (type.flags & ts.TypeFlags.StructuredType) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function getIndexInfosOfStructuredType(type: Type): readonly IndexInfo[] { + if (type.flags & TypeFlags.StructuredType) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); return resolved.indexInfos; } - return ts.emptyArray; + return emptyArray; } - function getIndexInfosOfType(type: ts.Type): readonly ts.IndexInfo[] { + function getIndexInfosOfType(type: Type): readonly IndexInfo[] { return getIndexInfosOfStructuredType(getReducedApparentType(type)); } // Return the indexing info of the given kind in the given type. Creates synthetic union index types when necessary and // maps primitive types and type parameters are to their apparent types. - function getIndexInfoOfType(type: ts.Type, keyType: ts.Type): ts.IndexInfo | undefined { + function getIndexInfoOfType(type: Type, keyType: Type): IndexInfo | undefined { return findIndexInfo(getIndexInfosOfType(type), keyType); } // Return the index type of the given kind in the given type. Creates synthetic union index types when necessary and // maps primitive types and type parameters are to their apparent types. - function getIndexTypeOfType(type: ts.Type, keyType: ts.Type): ts.Type | undefined { + function getIndexTypeOfType(type: Type, keyType: Type): Type | undefined { return getIndexInfoOfType(type, keyType)?.type; } - function getApplicableIndexInfos(type: ts.Type, keyType: ts.Type): ts.IndexInfo[] { + function getApplicableIndexInfos(type: Type, keyType: Type): IndexInfo[] { return getIndexInfosOfType(type).filter(info => isApplicableIndexType(keyType, info.keyType)); } - function getApplicableIndexInfo(type: ts.Type, keyType: ts.Type): ts.IndexInfo | undefined { + function getApplicableIndexInfo(type: Type, keyType: Type): IndexInfo | undefined { return findApplicableIndexInfo(getIndexInfosOfType(type), keyType); } - function getApplicableIndexInfoForName(type: ts.Type, name: ts.__String): ts.IndexInfo | undefined { - return getApplicableIndexInfo(type, isLateBoundName(name) ? esSymbolType : getStringLiteralType(ts.unescapeLeadingUnderscores(name))); + function getApplicableIndexInfoForName(type: Type, name: __String): IndexInfo | undefined { + return getApplicableIndexInfo(type, isLateBoundName(name) ? esSymbolType : getStringLiteralType(unescapeLeadingUnderscores(name))); } // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(declaration: ts.DeclarationWithTypeParameters): readonly ts.TypeParameter[] | undefined { - let result: ts.TypeParameter[] | undefined; - for (const node of ts.getEffectiveTypeParameterDeclarations(declaration)) { - result = ts.appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); + function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): readonly TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; + for (const node of getEffectiveTypeParameterDeclarations(declaration)) { + result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); } return result?.length ? result - : ts.isFunctionDeclaration(declaration) ? getSignatureOfTypeTag(declaration)?.typeParameters + : isFunctionDeclaration(declaration) ? getSignatureOfTypeTag(declaration)?.typeParameters : undefined; } - function symbolsToArray(symbols: ts.SymbolTable): ts.Symbol[] { - const result: ts.Symbol[] = []; + function symbolsToArray(symbols: SymbolTable): Symbol[] { + const result: Symbol[] = []; symbols.forEach((symbol, id) => { if (!isReservedMemberName(id)) { result.push(symbol); @@ -12969,38 +13167,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function isJSDocOptionalParameter(node: ts.ParameterDeclaration) { - return ts.isInJSFile(node) && ( + function isJSDocOptionalParameter(node: ParameterDeclaration) { + return isInJSFile(node) && ( // node.type should only be a JSDocOptionalType when node is a parameter of a JSDocFunctionType - node.type && node.type.kind === ts.SyntaxKind.JSDocOptionalType - || ts.getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) => - isBracketed || !!typeExpression && typeExpression.type.kind === ts.SyntaxKind.JSDocOptionalType)); + node.type && node.type.kind === SyntaxKind.JSDocOptionalType + || getJSDocParameterTags(node).some(({ isBracketed, typeExpression }) => + isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType)); } function tryFindAmbientModule(moduleName: string, withAugmentations: boolean) { - if (ts.isExternalModuleNameRelative(moduleName)) { + if (isExternalModuleNameRelative(moduleName)) { return undefined; } - const symbol = getSymbol(globals, '"' + moduleName + '"' as ts.__String, ts.SymbolFlags.ValueModule); + const symbol = getSymbol(globals, '"' + moduleName + '"' as __String, SymbolFlags.ValueModule); // merged symbol is module declaration symbol combined with all augmentations return symbol && withAugmentations ? getMergedSymbol(symbol) : symbol; } - function isOptionalParameter(node: ts.ParameterDeclaration | ts.JSDocParameterTag | ts.JSDocPropertyTag) { - if (ts.hasQuestionToken(node) || isOptionalJSDocPropertyLikeTag(node) || isJSDocOptionalParameter(node)) { + function isOptionalParameter(node: ParameterDeclaration | JSDocParameterTag | JSDocPropertyTag) { + if (hasQuestionToken(node) || isOptionalJSDocPropertyLikeTag(node) || isJSDocOptionalParameter(node)) { return true; } if (node.initializer) { const signature = getSignatureFromDeclaration(node.parent); const parameterIndex = node.parent.parameters.indexOf(node); - ts.Debug.assert(parameterIndex >= 0); + Debug.assert(parameterIndex >= 0); // Only consider syntactic or instantiated parameters as optional, not `void` parameters as this function is used // in grammar checks and checking for `void` too early results in parameter types widening too early // and causes some noImplicitAny errors to be lost. return parameterIndex >= getMinArgumentCount(signature, MinArgumentCountFlags.StrongArityForUntypedJS | MinArgumentCountFlags.VoidIsNonOptional); } - const iife = ts.getImmediatelyInvokedFunctionExpression(node.parent); + const iife = getImmediatelyInvokedFunctionExpression(node.parent); if (iife) { return !node.type && !node.dotDotDotToken && @@ -13010,27 +13208,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isOptionalPropertyDeclaration(node: ts.Declaration) { - return ts.isPropertyDeclaration(node) && !ts.hasAccessorModifier(node) && node.questionToken; + function isOptionalPropertyDeclaration(node: Declaration) { + return isPropertyDeclaration(node) && !hasAccessorModifier(node) && node.questionToken; } - function isOptionalJSDocPropertyLikeTag(node: ts.Node): node is ts.JSDocPropertyLikeTag { - if (!ts.isJSDocPropertyLikeTag(node)) { + function isOptionalJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag { + if (!isJSDocPropertyLikeTag(node)) { return false; } const { isBracketed, typeExpression } = node; - return isBracketed || !!typeExpression && typeExpression.type.kind === ts.SyntaxKind.JSDocOptionalType; + return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType; } - function createTypePredicate(kind: ts.TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: ts.Type | undefined): ts.TypePredicate { - return { kind, parameterName, parameterIndex, type } as ts.TypePredicate; + function createTypePredicate(kind: TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: Type | undefined): TypePredicate { + return { kind, parameterName, parameterIndex, type } as TypePredicate; } /** * Gets the minimum number of type arguments needed to satisfy all non-optional type * parameters. */ - function getMinTypeArgumentCount(typeParameters: readonly ts.TypeParameter[] | undefined): number { + function getMinTypeArgumentCount(typeParameters: readonly TypeParameter[] | undefined): number { let minTypeArgumentCount = 0; if (typeParameters) { for (let i = 0; i < typeParameters.length; i++) { @@ -13050,14 +13248,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param typeParameters The requested type parameters. * @param minTypeArgumentCount The minimum number of required type arguments. */ - function fillMissingTypeArguments(typeArguments: readonly ts.Type[], typeParameters: readonly ts.TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): ts.Type[]; - function fillMissingTypeArguments(typeArguments: readonly ts.Type[] | undefined, typeParameters: readonly ts.TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): ts.Type[] | undefined; - function fillMissingTypeArguments(typeArguments: readonly ts.Type[] | undefined, typeParameters: readonly ts.TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { - const numTypeParameters = ts.length(typeParameters); + function fillMissingTypeArguments(typeArguments: readonly Type[], typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[]; + function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean): Type[] | undefined; + function fillMissingTypeArguments(typeArguments: readonly Type[] | undefined, typeParameters: readonly TypeParameter[] | undefined, minTypeArgumentCount: number, isJavaScriptImplicitAny: boolean) { + const numTypeParameters = length(typeParameters); if (!numTypeParameters) { return []; } - const numTypeArguments = ts.length(typeArguments); + const numTypeArguments = length(typeArguments); if (isJavaScriptImplicitAny || (numTypeArguments >= minTypeArgumentCount && numTypeArguments <= numTypeParameters)) { const result = typeArguments ? typeArguments.slice() : []; // Map invalid forward references in default types to the error type @@ -13078,23 +13276,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeArguments && typeArguments.slice(); } - function getSignatureFromDeclaration(declaration: ts.SignatureDeclaration | ts.JSDocSignature): ts.Signature { + function getSignatureFromDeclaration(declaration: SignatureDeclaration | JSDocSignature): Signature { const links = getNodeLinks(declaration); if (!links.resolvedSignature) { - const parameters: ts.Symbol[] = []; - let flags = ts.SignatureFlags.None; + const parameters: Symbol[] = []; + let flags = SignatureFlags.None; let minArgumentCount = 0; - let thisParameter: ts.Symbol | undefined; + let thisParameter: Symbol | undefined; let hasThisParameter = false; - const iife = ts.getImmediatelyInvokedFunctionExpression(declaration); - const isJSConstructSignature = ts.isJSDocConstructSignature(declaration); + const iife = getImmediatelyInvokedFunctionExpression(declaration); + const isJSConstructSignature = isJSDocConstructSignature(declaration); const isUntypedSignatureInJSFile = !iife && - ts.isInJSFile(declaration) && - ts.isValueSignatureDeclaration(declaration) && - !ts.hasJSDocParameterTags(declaration) && - !ts.getJSDocType(declaration); + isInJSFile(declaration) && + isValueSignatureDeclaration(declaration) && + !hasJSDocParameterTags(declaration) && + !getJSDocType(declaration); if (isUntypedSignatureInJSFile) { - flags |= ts.SignatureFlags.IsUntypedSignatureInJSFile; + flags |= SignatureFlags.IsUntypedSignatureInJSFile; } // If this is a JSDoc construct signature, then skip the first parameter in the @@ -13104,13 +13302,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const param = declaration.parameters[i]; let paramSymbol = param.symbol; - const type = ts.isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; + const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type; // Include parameter symbol instead of property symbol in the signature - if (paramSymbol && !!(paramSymbol.flags & ts.SymbolFlags.Property) && !ts.isBindingPattern(param.name)) { - const resolvedSymbol = resolveName(param, paramSymbol.escapedName, ts.SymbolFlags.Value, undefined, undefined, /*isUse*/ false); + if (paramSymbol && !!(paramSymbol.flags & SymbolFlags.Property) && !isBindingPattern(param.name)) { + const resolvedSymbol = resolveName(param, paramSymbol.escapedName, SymbolFlags.Value, undefined, undefined, /*isUse*/ false); paramSymbol = resolvedSymbol!; } - if (i === 0 && paramSymbol.escapedName === ts.InternalSymbolName.This) { + if (i === 0 && paramSymbol.escapedName === InternalSymbolName.This) { hasThisParameter = true; thisParameter = param.symbol; } @@ -13118,13 +13316,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { parameters.push(paramSymbol); } - if (type && type.kind === ts.SyntaxKind.LiteralType) { - flags |= ts.SignatureFlags.HasLiteralTypes; + if (type && type.kind === SyntaxKind.LiteralType) { + flags |= SignatureFlags.HasLiteralTypes; } // Record a new minimum argument count if this is not an optional parameter const isOptionalParameter = isOptionalJSDocPropertyLikeTag(param) || - param.initializer || param.questionToken || ts.isRestParameter(param) || + param.initializer || param.questionToken || isRestParameter(param) || iife && parameters.length > iife.arguments.length && !type || isJSDocOptionalParameter(param); if (!isOptionalParameter) { @@ -13133,26 +13331,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // If only one accessor includes a this-type annotation, the other behaves as if it had the same type annotation - if ((declaration.kind === ts.SyntaxKind.GetAccessor || declaration.kind === ts.SyntaxKind.SetAccessor) && + if ((declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) && hasBindableName(declaration) && (!hasThisParameter || !thisParameter)) { - const otherKind = declaration.kind === ts.SyntaxKind.GetAccessor ? ts.SyntaxKind.SetAccessor : ts.SyntaxKind.GetAccessor; - const other = ts.getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); + const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; + const other = getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } } - const classType = declaration.kind === ts.SyntaxKind.Constructor ? - getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ts.ClassDeclaration).symbol)) + const classType = declaration.kind === SyntaxKind.Constructor ? + getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol)) : undefined; const typeParameters = classType ? classType.localTypeParameters : getTypeParametersFromDeclaration(declaration); - if (ts.hasRestParameter(declaration) || ts.isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) { - flags |= ts.SignatureFlags.HasRestParameter; + if (hasRestParameter(declaration) || isInJSFile(declaration) && maybeAddJsSyntheticRestParameter(declaration, parameters)) { + flags |= SignatureFlags.HasRestParameter; } - if (ts.isConstructorTypeNode(declaration) && ts.hasSyntacticModifier(declaration, ts.ModifierFlags.Abstract) || - ts.isConstructorDeclaration(declaration) && ts.hasSyntacticModifier(declaration.parent, ts.ModifierFlags.Abstract)) { - flags |= ts.SignatureFlags.Abstract; + if (isConstructorTypeNode(declaration) && hasSyntacticModifier(declaration, ModifierFlags.Abstract) || + isConstructorDeclaration(declaration) && hasSyntacticModifier(declaration.parent, ModifierFlags.Abstract)) { + flags |= SignatureFlags.Abstract; } links.resolvedSignature = createSignature(declaration, typeParameters, thisParameter, parameters, /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, @@ -13167,16 +13365,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * OR * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...` */ - function maybeAddJsSyntheticRestParameter(declaration: ts.SignatureDeclaration | ts.JSDocSignature, parameters: ts.Symbol[]): boolean { - if (ts.isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) { + function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration | JSDocSignature, parameters: Symbol[]): boolean { + if (isJSDocSignature(declaration) || !containsArgumentsReference(declaration)) { return false; } - const lastParam = ts.lastOrUndefined(declaration.parameters); - const lastParamTags = lastParam ? ts.getJSDocParameterTags(lastParam) : ts.getJSDocTags(declaration).filter(ts.isJSDocParameterTag); - const lastParamVariadicType = ts.firstDefined(lastParamTags, p => - p.typeExpression && ts.isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined); + const lastParam = lastOrUndefined(declaration.parameters); + const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter(isJSDocParameterTag); + const lastParamVariadicType = firstDefined(lastParamTags, p => + p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined); - const syntheticArgsSymbol = createSymbol(ts.SymbolFlags.Variable, "args" as ts.__String, ts.CheckFlags.RestParameter); + const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String, CheckFlags.RestParameter); if (lastParamVariadicType) { // Parameter has effective annotation, lock in type syntheticArgsSymbol.type = createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)); @@ -13185,7 +13383,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Parameter has no annotation // By using a `DeferredType` symbol, we allow the type of this rest arg to be overriden by contextual type assignment so long as its type hasn't been // cached by `getTypeOfSymbol` yet. - syntheticArgsSymbol.checkFlags |= ts.CheckFlags.DeferredType; + syntheticArgsSymbol.checkFlags |= CheckFlags.DeferredType; syntheticArgsSymbol.deferralParent = neverType; syntheticArgsSymbol.deferralConstituents = [anyArrayType]; syntheticArgsSymbol.deferralWriteConstituents = [anyArrayType]; @@ -13198,73 +13396,73 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function getSignatureOfTypeTag(node: ts.SignatureDeclaration | ts.JSDocSignature) { + function getSignatureOfTypeTag(node: SignatureDeclaration | JSDocSignature) { // should be attached to a function declaration or expression - if (!(ts.isInJSFile(node) && ts.isFunctionLikeDeclaration(node))) return undefined; - const typeTag = ts.getJSDocTypeTag(node); + if (!(isInJSFile(node) && isFunctionLikeDeclaration(node))) return undefined; + const typeTag = getJSDocTypeTag(node); return typeTag?.typeExpression && getSingleCallSignature(getTypeFromTypeNode(typeTag.typeExpression)); } - function getParameterTypeOfTypeTag(func: ts.FunctionLikeDeclaration, parameter: ts.ParameterDeclaration) { + function getParameterTypeOfTypeTag(func: FunctionLikeDeclaration, parameter: ParameterDeclaration) { const signature = getSignatureOfTypeTag(func); if (!signature) return undefined; const pos = func.parameters.indexOf(parameter); return parameter.dotDotDotToken ? getRestTypeAtPosition(signature, pos) : getTypeAtPosition(signature, pos); } - function getReturnTypeOfTypeTag(node: ts.SignatureDeclaration | ts.JSDocSignature) { + function getReturnTypeOfTypeTag(node: SignatureDeclaration | JSDocSignature) { const signature = getSignatureOfTypeTag(node); return signature && getReturnTypeOfSignature(signature); } - function containsArgumentsReference(declaration: ts.SignatureDeclaration): boolean { + function containsArgumentsReference(declaration: SignatureDeclaration): boolean { const links = getNodeLinks(declaration); if (links.containsArgumentsReference === undefined) { - if (links.flags & ts.NodeCheckFlags.CaptureArguments) { + if (links.flags & NodeCheckFlags.CaptureArguments) { links.containsArgumentsReference = true; } else { - links.containsArgumentsReference = traverse((declaration as ts.FunctionLikeDeclaration).body!); + links.containsArgumentsReference = traverse((declaration as FunctionLikeDeclaration).body!); } } return links.containsArgumentsReference; - function traverse(node: ts.Node): boolean { + function traverse(node: Node): boolean { if (!node) return false; switch (node.kind) { - case ts.SyntaxKind.Identifier: - return (node as ts.Identifier).escapedText === argumentsSymbol.escapedName && getReferencedValueSymbol(node as ts.Identifier) === argumentsSymbol; + case SyntaxKind.Identifier: + return (node as Identifier).escapedText === argumentsSymbol.escapedName && getReferencedValueSymbol(node as Identifier) === argumentsSymbol; - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return (node as ts.NamedDeclaration).name!.kind === ts.SyntaxKind.ComputedPropertyName - && traverse((node as ts.NamedDeclaration).name!); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return (node as NamedDeclaration).name!.kind === SyntaxKind.ComputedPropertyName + && traverse((node as NamedDeclaration).name!); - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - return traverse((node as ts.PropertyAccessExpression | ts.ElementAccessExpression).expression); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + return traverse((node as PropertyAccessExpression | ElementAccessExpression).expression); - case ts.SyntaxKind.PropertyAssignment: - return traverse((node as ts.PropertyAssignment).initializer); + case SyntaxKind.PropertyAssignment: + return traverse((node as PropertyAssignment).initializer); default: - return !ts.nodeStartsNewLexicalEnvironment(node) && !ts.isPartOfTypeNode(node) && !!ts.forEachChild(node, traverse); + return !nodeStartsNewLexicalEnvironment(node) && !isPartOfTypeNode(node) && !!forEachChild(node, traverse); } } } - function getSignaturesOfSymbol(symbol: ts.Symbol | undefined): ts.Signature[] { - if (!symbol || !symbol.declarations) return ts.emptyArray; - const result: ts.Signature[] = []; + function getSignaturesOfSymbol(symbol: Symbol | undefined): Signature[] { + if (!symbol || !symbol.declarations) return emptyArray; + const result: Signature[] = []; for (let i = 0; i < symbol.declarations.length; i++) { const decl = symbol.declarations[i]; - if (!ts.isFunctionLike(decl)) continue; + if (!isFunctionLike(decl)) continue; // Don't include signature if node is the implementation of an overloaded function. A node is considered // an implementation node if it has a body and the previous node is of the same kind and immediately // precedes the implementation node (i.e. has the same parent and ends where the implementation starts). - if (i > 0 && (decl as ts.FunctionLikeDeclaration).body) { + if (i > 0 && (decl as FunctionLikeDeclaration).body) { const previous = symbol.declarations[i - 1]; if (decl.parent === previous.parent && decl.kind === previous.kind && decl.pos === previous.end) { continue; @@ -13273,8 +13471,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters. // Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would supress checks that the two are compatible. result.push( - (!ts.isFunctionExpressionOrArrowFunction(decl) && - !ts.isObjectLiteralMethod(decl) && + (!isFunctionExpressionOrArrowFunction(decl) && + !isObjectLiteralMethod(decl) && getSignatureOfTypeTag(decl)) || getSignatureFromDeclaration(decl) ); @@ -13282,7 +13480,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function resolveExternalModuleTypeByLiteral(name: ts.StringLiteral) { + function resolveExternalModuleTypeByLiteral(name: StringLiteral) { const moduleSym = resolveExternalModuleName(name, name); if (moduleSym) { const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); @@ -13294,13 +13492,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return anyType; } - function getThisTypeOfSignature(signature: ts.Signature): ts.Type | undefined { + function getThisTypeOfSignature(signature: Signature): Type | undefined { if (signature.thisParameter) { return getTypeOfSymbol(signature.thisParameter); } } - function getTypePredicateOfSignature(signature: ts.Signature): ts.TypePredicate | undefined { + function getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined { if (!signature.resolvedTypePredicate) { if (signature.target) { const targetTypePredicate = getTypePredicateOfSignature(signature.target); @@ -13310,65 +13508,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { signature.resolvedTypePredicate = getUnionOrIntersectionTypePredicate(signature.compositeSignatures, signature.compositeKind) || noTypePredicate; } else { - const type = signature.declaration && ts.getEffectiveReturnTypeNode(signature.declaration); - let jsdocPredicate: ts.TypePredicate | undefined; + const type = signature.declaration && getEffectiveReturnTypeNode(signature.declaration); + let jsdocPredicate: TypePredicate | undefined; if (!type) { const jsdocSignature = getSignatureOfTypeTag(signature.declaration!); if (jsdocSignature && signature !== jsdocSignature) { jsdocPredicate = getTypePredicateOfSignature(jsdocSignature); } } - signature.resolvedTypePredicate = type && ts.isTypePredicateNode(type) ? + signature.resolvedTypePredicate = type && isTypePredicateNode(type) ? createTypePredicateFromTypePredicateNode(type, signature) : jsdocPredicate || noTypePredicate; } - ts.Debug.assert(!!signature.resolvedTypePredicate); + Debug.assert(!!signature.resolvedTypePredicate); } return signature.resolvedTypePredicate === noTypePredicate ? undefined : signature.resolvedTypePredicate; } - function createTypePredicateFromTypePredicateNode(node: ts.TypePredicateNode, signature: ts.Signature): ts.TypePredicate { + function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): TypePredicate { const parameterName = node.parameterName; const type = node.type && getTypeFromTypeNode(node.type); - return parameterName.kind === ts.SyntaxKind.ThisType ? - createTypePredicate(node.assertsModifier ? ts.TypePredicateKind.AssertsThis : ts.TypePredicateKind.This, /*parameterName*/ undefined, /*parameterIndex*/ undefined, type) : - createTypePredicate(node.assertsModifier ? ts.TypePredicateKind.AssertsIdentifier : ts.TypePredicateKind.Identifier, parameterName.escapedText as string, - ts.findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), type); + return parameterName.kind === SyntaxKind.ThisType ? + createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsThis : TypePredicateKind.This, /*parameterName*/ undefined, /*parameterIndex*/ undefined, type) : + createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsIdentifier : TypePredicateKind.Identifier, parameterName.escapedText as string, + findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), type); } - function getUnionOrIntersectionType(types: ts.Type[], kind: ts.TypeFlags | undefined, unionReduction?: ts.UnionReduction) { - return kind !== ts.TypeFlags.Intersection ? getUnionType(types, unionReduction) : getIntersectionType(types); + function getUnionOrIntersectionType(types: Type[], kind: TypeFlags | undefined, unionReduction?: UnionReduction) { + return kind !== TypeFlags.Intersection ? getUnionType(types, unionReduction) : getIntersectionType(types); } - function getReturnTypeOfSignature(signature: ts.Signature): ts.Type { + function getReturnTypeOfSignature(signature: Signature): Type { if (!signature.resolvedReturnType) { if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) { return errorType; } let type = signature.target ? instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper) : - signature.compositeSignatures ? instantiateType(getUnionOrIntersectionType(ts.map(signature.compositeSignatures, getReturnTypeOfSignature), signature.compositeKind, ts.UnionReduction.Subtype), signature.mapper) : + signature.compositeSignatures ? instantiateType(getUnionOrIntersectionType(map(signature.compositeSignatures, getReturnTypeOfSignature), signature.compositeKind, UnionReduction.Subtype), signature.mapper) : getReturnTypeFromAnnotation(signature.declaration!) || - (ts.nodeIsMissing((signature.declaration as ts.FunctionLikeDeclaration).body) ? anyType : getReturnTypeFromBody(signature.declaration as ts.FunctionLikeDeclaration)); - if (signature.flags & ts.SignatureFlags.IsInnerCallChain) { + (nodeIsMissing((signature.declaration as FunctionLikeDeclaration).body) ? anyType : getReturnTypeFromBody(signature.declaration as FunctionLikeDeclaration)); + if (signature.flags & SignatureFlags.IsInnerCallChain) { type = addOptionalTypeMarker(type); } - else if (signature.flags & ts.SignatureFlags.IsOuterCallChain) { + else if (signature.flags & SignatureFlags.IsOuterCallChain) { type = getOptionalType(type); } if (!popTypeResolution()) { if (signature.declaration) { - const typeNode = ts.getEffectiveReturnTypeNode(signature.declaration); + const typeNode = getEffectiveReturnTypeNode(signature.declaration); if (typeNode) { - error(typeNode, ts.Diagnostics.Return_type_annotation_circularly_references_itself); + error(typeNode, Diagnostics.Return_type_annotation_circularly_references_itself); } else if (noImplicitAny) { - const declaration = signature.declaration as ts.Declaration; - const name = ts.getNameOfDeclaration(declaration); + const declaration = signature.declaration as Declaration; + const name = getNameOfDeclaration(declaration); if (name) { - error(name, ts.Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, ts.declarationNameToString(name)); + error(name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(name)); } else { - error(declaration, ts.Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions); + error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions); } } } @@ -13379,23 +13577,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return signature.resolvedReturnType; } - function getReturnTypeFromAnnotation(declaration: ts.SignatureDeclaration | ts.JSDocSignature) { - if (declaration.kind === ts.SyntaxKind.Constructor) { - return getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ts.ClassDeclaration).symbol)); + function getReturnTypeFromAnnotation(declaration: SignatureDeclaration | JSDocSignature) { + if (declaration.kind === SyntaxKind.Constructor) { + return getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent as ClassDeclaration).symbol)); } - if (ts.isJSDocConstructSignature(declaration)) { - return getTypeFromTypeNode((declaration.parameters[0] as ts.ParameterDeclaration).type!); // TODO: GH#18217 + if (isJSDocConstructSignature(declaration)) { + return getTypeFromTypeNode((declaration.parameters[0] as ParameterDeclaration).type!); // TODO: GH#18217 } - const typeNode = ts.getEffectiveReturnTypeNode(declaration); + const typeNode = getEffectiveReturnTypeNode(declaration); if (typeNode) { return getTypeFromTypeNode(typeNode); } - if (declaration.kind === ts.SyntaxKind.GetAccessor && hasBindableName(declaration)) { - const jsDocType = ts.isInJSFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration); + if (declaration.kind === SyntaxKind.GetAccessor && hasBindableName(declaration)) { + const jsDocType = isInJSFile(declaration) && getTypeForDeclarationFromJSDocComment(declaration); if (jsDocType) { return jsDocType; } - const setter = ts.getDeclarationOfKind(getSymbolOfNode(declaration), ts.SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); const setterType = getAnnotatedAccessorType(setter); if (setterType) { return setterType; @@ -13404,15 +13602,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getReturnTypeOfTypeTag(declaration); } - function isResolvingReturnTypeOfSignature(signature: ts.Signature) { + function isResolvingReturnTypeOfSignature(signature: Signature) { return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0; } - function getRestTypeOfSignature(signature: ts.Signature): ts.Type { + function getRestTypeOfSignature(signature: Signature): Type { return tryGetRestTypeOfSignature(signature) || anyType; } - function tryGetRestTypeOfSignature(signature: ts.Signature): ts.Type | undefined { + function tryGetRestTypeOfSignature(signature: Signature): Type | undefined { if (signatureHasRestParameter(signature)) { const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType; @@ -13421,7 +13619,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getSignatureInstantiation(signature: ts.Signature, typeArguments: ts.Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly ts.TypeParameter[]): ts.Signature { + function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean, inferredTypeParameters?: readonly TypeParameter[]): Signature { const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, fillMissingTypeArguments(typeArguments, signature.typeParameters, getMinTypeArgumentCount(signature.typeParameters), isJavascript)); if (inferredTypeParameters) { const returnSignature = getSingleCallOrConstructSignature(getReturnTypeOfSignature(instantiatedSignature)); @@ -13436,8 +13634,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return instantiatedSignature; } - function getSignatureInstantiationWithoutFillingInTypeArguments(signature: ts.Signature, typeArguments: readonly ts.Type[] | undefined): ts.Signature { - const instantiations = signature.instantiations || (signature.instantiations = new ts.Map()); + function getSignatureInstantiationWithoutFillingInTypeArguments(signature: Signature, typeArguments: readonly Type[] | undefined): Signature { + const instantiations = signature.instantiations || (signature.instantiations = new Map()); const id = getTypeListId(typeArguments); let instantiation = instantiations.get(id); if (!instantiation) { @@ -13446,32 +13644,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return instantiation; } - function createSignatureInstantiation(signature: ts.Signature, typeArguments: readonly ts.Type[] | undefined): ts.Signature { + function createSignatureInstantiation(signature: Signature, typeArguments: readonly Type[] | undefined): Signature { return instantiateSignature(signature, createSignatureTypeMapper(signature, typeArguments), /*eraseTypeParameters*/ true); } - function createSignatureTypeMapper(signature: ts.Signature, typeArguments: readonly ts.Type[] | undefined): ts.TypeMapper { + function createSignatureTypeMapper(signature: Signature, typeArguments: readonly Type[] | undefined): TypeMapper { return createTypeMapper(signature.typeParameters!, typeArguments); } - function getErasedSignature(signature: ts.Signature): ts.Signature { + function getErasedSignature(signature: Signature): Signature { return signature.typeParameters ? signature.erasedSignatureCache || (signature.erasedSignatureCache = createErasedSignature(signature)) : signature; } - function createErasedSignature(signature: ts.Signature) { + function createErasedSignature(signature: Signature) { // Create an instantiation of the signature where all type arguments are the any type. return instantiateSignature(signature, createTypeEraser(signature.typeParameters!), /*eraseTypeParameters*/ true); } - function getCanonicalSignature(signature: ts.Signature): ts.Signature { + function getCanonicalSignature(signature: Signature): Signature { return signature.typeParameters ? signature.canonicalSignatureCache || (signature.canonicalSignatureCache = createCanonicalSignature(signature)) : signature; } - function createCanonicalSignature(signature: ts.Signature) { + function createCanonicalSignature(signature: Signature) { // Create an instantiation of the signature where each unconstrained type parameter is replaced with // its original. When a generic class or interface is instantiated, each generic method in the class or // interface is instantiated with a fresh set of cloned type parameters (which we need to handle scenarios @@ -13480,19 +13678,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // that uses the original type identities for all unconstrained type parameters. return getSignatureInstantiation( signature, - ts.map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp), - ts.isInJSFile(signature.declaration)); + map(signature.typeParameters, tp => tp.target && !getConstraintOfTypeParameter(tp.target) ? tp.target : tp), + isInJSFile(signature.declaration)); } - function getBaseSignature(signature: ts.Signature) { + function getBaseSignature(signature: Signature) { const typeParameters = signature.typeParameters; if (typeParameters) { if (signature.baseSignatureCache) { return signature.baseSignatureCache; } const typeEraser = createTypeEraser(typeParameters); - const baseConstraintMapper = createTypeMapper(typeParameters, ts.map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType)); - let baseConstraints: readonly ts.Type[] = ts.map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType); + const baseConstraintMapper = createTypeMapper(typeParameters, map(typeParameters, tp => getConstraintOfTypeParameter(tp) || unknownType)); + let baseConstraints: readonly Type[] = map(typeParameters, tp => instantiateType(tp, baseConstraintMapper) || unknownType); // Run N type params thru the immediate constraint mapper up to N times // This way any noncircular interdependent type parameters are definitely resolved to their external dependencies for (let i = 0; i < typeParameters.length - 1; i++) { @@ -13505,7 +13703,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return signature; } - function getOrCreateTypeFromSignature(signature: ts.Signature): ts.ObjectType { + function getOrCreateTypeFromSignature(signature: Signature): ObjectType { // There are two ways to declare a construct signature, one is by declaring a class constructor // using the constructor keyword, and the other is declaring a bare construct signature in an // object type literal or interface (using the new keyword). Each way of declaring a constructor @@ -13514,48 +13712,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const kind = signature.declaration?.kind; // If declaration is undefined, it is likely to be the signature of the default constructor. - const isConstructor = kind === undefined || kind === ts.SyntaxKind.Constructor || kind === ts.SyntaxKind.ConstructSignature || kind === ts.SyntaxKind.ConstructorType; + const isConstructor = kind === undefined || kind === SyntaxKind.Constructor || kind === SyntaxKind.ConstructSignature || kind === SyntaxKind.ConstructorType; - const type = createObjectType(ts.ObjectFlags.Anonymous); + const type = createObjectType(ObjectFlags.Anonymous); type.members = emptySymbols; - type.properties = ts.emptyArray; - type.callSignatures = !isConstructor ? [signature] : ts.emptyArray; - type.constructSignatures = isConstructor ? [signature] : ts.emptyArray; - type.indexInfos = ts.emptyArray; + type.properties = emptyArray; + type.callSignatures = !isConstructor ? [signature] : emptyArray; + type.constructSignatures = isConstructor ? [signature] : emptyArray; + type.indexInfos = emptyArray; signature.isolatedSignatureType = type; } return signature.isolatedSignatureType; } - function getIndexSymbol(symbol: ts.Symbol): ts.Symbol | undefined { + function getIndexSymbol(symbol: Symbol): Symbol | undefined { return symbol.members ? getIndexSymbolFromSymbolTable(symbol.members) : undefined; } - function getIndexSymbolFromSymbolTable(symbolTable: ts.SymbolTable): ts.Symbol | undefined { - return symbolTable.get(ts.InternalSymbolName.Index); + function getIndexSymbolFromSymbolTable(symbolTable: SymbolTable): Symbol | undefined { + return symbolTable.get(InternalSymbolName.Index); } - function createIndexInfo(keyType: ts.Type, type: ts.Type, isReadonly: boolean, declaration?: ts.IndexSignatureDeclaration): ts.IndexInfo { + function createIndexInfo(keyType: Type, type: Type, isReadonly: boolean, declaration?: IndexSignatureDeclaration): IndexInfo { return { keyType, type, isReadonly, declaration }; } - function getIndexInfosOfSymbol(symbol: ts.Symbol): ts.IndexInfo[] { + function getIndexInfosOfSymbol(symbol: Symbol): IndexInfo[] { const indexSymbol = getIndexSymbol(symbol); - return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol) : ts.emptyArray; + return indexSymbol ? getIndexInfosOfIndexSymbol(indexSymbol) : emptyArray; } - function getIndexInfosOfIndexSymbol(indexSymbol: ts.Symbol): ts.IndexInfo[] { + function getIndexInfosOfIndexSymbol(indexSymbol: Symbol): IndexInfo[] { if (indexSymbol.declarations) { - const indexInfos: ts.IndexInfo[] = []; - for (const declaration of (indexSymbol.declarations as ts.IndexSignatureDeclaration[])) { + const indexInfos: IndexInfo[] = []; + for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) { if (declaration.parameters.length === 1) { const parameter = declaration.parameters[0]; if (parameter.type) { forEachType(getTypeFromTypeNode(parameter.type), keyType => { if (isValidIndexKeyType(keyType) && !findIndexInfo(indexInfos, keyType)) { indexInfos.push(createIndexInfo(keyType, declaration.type ? getTypeFromTypeNode(declaration.type) : anyType, - ts.hasEffectiveModifier(declaration, ts.ModifierFlags.Readonly), declaration)); + hasEffectiveModifier(declaration, ModifierFlags.Readonly), declaration)); } }); } @@ -13563,33 +13761,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return indexInfos; } - return ts.emptyArray; + return emptyArray; } - function isValidIndexKeyType(type: ts.Type): boolean { - return !!(type.flags & (ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.ESSymbol)) || isPatternLiteralType(type) || - !!(type.flags & ts.TypeFlags.Intersection) && !isGenericType(type) && ts.some((type as ts.IntersectionType).types, isValidIndexKeyType); + function isValidIndexKeyType(type: Type): boolean { + return !!(type.flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.ESSymbol)) || isPatternLiteralType(type) || + !!(type.flags & TypeFlags.Intersection) && !isGenericType(type) && some((type as IntersectionType).types, isValidIndexKeyType); } - function getConstraintDeclaration(type: ts.TypeParameter): ts.TypeNode | undefined { - return ts.mapDefined(ts.filter(type.symbol && type.symbol.declarations, ts.isTypeParameterDeclaration), ts.getEffectiveConstraintOfTypeParameter)[0]; + function getConstraintDeclaration(type: TypeParameter): TypeNode | undefined { + return mapDefined(filter(type.symbol && type.symbol.declarations, isTypeParameterDeclaration), getEffectiveConstraintOfTypeParameter)[0]; } - function getInferredTypeParameterConstraint(typeParameter: ts.TypeParameter, omitTypeReferences?: boolean) { - let inferences: ts.Type[] | undefined; + function getInferredTypeParameterConstraint(typeParameter: TypeParameter, omitTypeReferences?: boolean) { + let inferences: Type[] | undefined; if (typeParameter.symbol?.declarations) { for (const declaration of typeParameter.symbol.declarations) { - if (declaration.parent.kind === ts.SyntaxKind.InferType) { + if (declaration.parent.kind === SyntaxKind.InferType) { // When an 'infer T' declaration is immediately contained in a type reference node // (such as 'Foo'), T's constraint is inferred from the constraint of the // corresponding type parameter in 'Foo'. When multiple 'infer T' declarations are // present, we form an intersection of the inferred constraint types. - const [childTypeParameter = declaration.parent, grandParent] = ts.walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent); - if (grandParent.kind === ts.SyntaxKind.TypeReference && !omitTypeReferences) { - const typeReference = grandParent as ts.TypeReferenceNode; + const [childTypeParameter = declaration.parent, grandParent] = walkUpParenthesizedTypesAndGetParentAndChild(declaration.parent.parent); + if (grandParent.kind === SyntaxKind.TypeReference && !omitTypeReferences) { + const typeReference = grandParent as TypeReferenceNode; const typeParameters = getTypeParametersForTypeReference(typeReference); if (typeParameters) { - const index = typeReference.typeArguments!.indexOf(childTypeParameter as ts.TypeNode); + const index = typeReference.typeArguments!.indexOf(childTypeParameter as TypeNode); if (index < typeParameters.length) { const declaredConstraint = getConstraintOfTypeParameter(typeParameters[index]); if (declaredConstraint) { @@ -13604,7 +13802,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { })); const constraint = instantiateType(declaredConstraint, mapper); if (constraint !== typeParameter) { - inferences = ts.append(inferences, constraint); + inferences = append(inferences, constraint); } } } @@ -13612,31 +13810,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // When an 'infer T' declaration is immediately contained in a rest parameter declaration, a rest type // or a named rest tuple element, we infer an 'unknown[]' constraint. - else if (grandParent.kind === ts.SyntaxKind.Parameter && (grandParent as ts.ParameterDeclaration).dotDotDotToken || - grandParent.kind === ts.SyntaxKind.RestType || - grandParent.kind === ts.SyntaxKind.NamedTupleMember && (grandParent as ts.NamedTupleMember).dotDotDotToken) { - inferences = ts.append(inferences, createArrayType(unknownType)); + else if (grandParent.kind === SyntaxKind.Parameter && (grandParent as ParameterDeclaration).dotDotDotToken || + grandParent.kind === SyntaxKind.RestType || + grandParent.kind === SyntaxKind.NamedTupleMember && (grandParent as NamedTupleMember).dotDotDotToken) { + inferences = append(inferences, createArrayType(unknownType)); } // When an 'infer T' declaration is immediately contained in a string template type, we infer a 'string' // constraint. - else if (grandParent.kind === ts.SyntaxKind.TemplateLiteralTypeSpan) { - inferences = ts.append(inferences, stringType); + else if (grandParent.kind === SyntaxKind.TemplateLiteralTypeSpan) { + inferences = append(inferences, stringType); } // When an 'infer T' declaration is in the constraint position of a mapped type, we infer a 'keyof any' // constraint. - else if (grandParent.kind === ts.SyntaxKind.TypeParameter && grandParent.parent.kind === ts.SyntaxKind.MappedType) { - inferences = ts.append(inferences, keyofConstraintType); + else if (grandParent.kind === SyntaxKind.TypeParameter && grandParent.parent.kind === SyntaxKind.MappedType) { + inferences = append(inferences, keyofConstraintType); } // When an 'infer T' declaration is the template of a mapped type, and that mapped type is the extends // clause of a conditional whose check type is also a mapped type, give it a constraint equal to the template // of the check type's mapped type - else if (grandParent.kind === ts.SyntaxKind.MappedType && (grandParent as ts.MappedTypeNode).type && - ts.skipParentheses((grandParent as ts.MappedTypeNode).type!) === declaration.parent && grandParent.parent.kind === ts.SyntaxKind.ConditionalType && - (grandParent.parent as ts.ConditionalTypeNode).extendsType === grandParent && (grandParent.parent as ts.ConditionalTypeNode).checkType.kind === ts.SyntaxKind.MappedType && - ((grandParent.parent as ts.ConditionalTypeNode).checkType as ts.MappedTypeNode).type) { - const checkMappedType = (grandParent.parent as ts.ConditionalTypeNode).checkType as ts.MappedTypeNode; + else if (grandParent.kind === SyntaxKind.MappedType && (grandParent as MappedTypeNode).type && + skipParentheses((grandParent as MappedTypeNode).type!) === declaration.parent && grandParent.parent.kind === SyntaxKind.ConditionalType && + (grandParent.parent as ConditionalTypeNode).extendsType === grandParent && (grandParent.parent as ConditionalTypeNode).checkType.kind === SyntaxKind.MappedType && + ((grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode).type) { + const checkMappedType = (grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode; const nodeType = getTypeFromTypeNode(checkMappedType.type!); - inferences = ts.append(inferences, instantiateType(nodeType, + inferences = append(inferences, instantiateType(nodeType, makeUnaryTypeMapper(getDeclaredTypeOfTypeParameter(getSymbolOfNode(checkMappedType.typeParameter)), checkMappedType.typeParameter.constraint ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) : keyofConstraintType) )); } @@ -13647,7 +13845,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** This is a worker function. Use getConstraintOfTypeParameter which guards against circular constraints. */ - function getConstraintFromTypeParameter(typeParameter: ts.TypeParameter): ts.Type | undefined { + function getConstraintFromTypeParameter(typeParameter: TypeParameter): Type | undefined { if (!typeParameter.constraint) { if (typeParameter.target) { const targetConstraint = getConstraintOfTypeParameter(typeParameter.target); @@ -13660,10 +13858,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { let type = getTypeFromTypeNode(constraintDeclaration); - if (type.flags & ts.TypeFlags.Any && !isErrorType(type)) { // Allow errorType to propegate to keep downstream errors suppressed + if (type.flags & TypeFlags.Any && !isErrorType(type)) { // Allow errorType to propegate to keep downstream errors suppressed // use keyofConstraintType as the base constraint for mapped type key constraints (unknown isn;t assignable to that, but `any` was), // use unknown otherwise - type = constraintDeclaration.parent.parent.kind === ts.SyntaxKind.MappedType ? keyofConstraintType : unknownType; + type = constraintDeclaration.parent.parent.kind === SyntaxKind.MappedType ? keyofConstraintType : unknownType; } typeParameter.constraint = type; } @@ -13672,13 +13870,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeParameter.constraint === noConstraintType ? undefined : typeParameter.constraint; } - function getParentSymbolOfTypeParameter(typeParameter: ts.TypeParameter): ts.Symbol | undefined { - const tp = ts.getDeclarationOfKind(typeParameter.symbol, ts.SyntaxKind.TypeParameter)!; - const host = ts.isJSDocTemplateTag(tp.parent) ? ts.getEffectiveContainerForJSDocTemplateTag(tp.parent) : tp.parent; + function getParentSymbolOfTypeParameter(typeParameter: TypeParameter): Symbol | undefined { + const tp = getDeclarationOfKind(typeParameter.symbol, SyntaxKind.TypeParameter)!; + const host = isJSDocTemplateTag(tp.parent) ? getEffectiveContainerForJSDocTemplateTag(tp.parent) : tp.parent; return host && getSymbolOfNode(host); } - function getTypeListId(types: readonly ts.Type[] | undefined) { + function getTypeListId(types: readonly Type[] | undefined) { let result = ""; if (types) { const length = types.length; @@ -13702,7 +13900,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getAliasId(aliasSymbol: ts.Symbol | undefined, aliasTypeArguments: readonly ts.Type[] | undefined) { + function getAliasId(aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { return aliasSymbol ? `@${getSymbolId(aliasSymbol)}` + (aliasTypeArguments ? `:${getTypeListId(aliasTypeArguments)}` : "") : ""; } @@ -13710,21 +13908,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // It is only necessary to do so if a constituent type might be the undefined type, the null type, the type // of an object literal or a non-inferrable type. This is because there are operations in the type checker // that care about the presence of such types at arbitrary depth in a containing type. - function getPropagatingFlagsOfTypes(types: readonly ts.Type[], excludeKinds?: ts.TypeFlags): ts.ObjectFlags { - let result: ts.ObjectFlags = 0; + function getPropagatingFlagsOfTypes(types: readonly Type[], excludeKinds?: TypeFlags): ObjectFlags { + let result: ObjectFlags = 0; for (const type of types) { if (excludeKinds === undefined || !(type.flags & excludeKinds)) { - result |= ts.getObjectFlags(type); + result |= getObjectFlags(type); } } - return result & ts.ObjectFlags.PropagatingFlags; + return result & ObjectFlags.PropagatingFlags; } - function createTypeReference(target: ts.GenericType, typeArguments: readonly ts.Type[] | undefined): ts.TypeReference { + function createTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined): TypeReference { const id = getTypeListId(typeArguments); let type = target.instantiations.get(id); if (!type) { - type = createObjectType(ts.ObjectFlags.Reference, target.symbol) as ts.TypeReference; + type = createObjectType(ObjectFlags.Reference, target.symbol) as TypeReference; target.instantiations.set(id, type); type.objectFlags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments) : 0; type.target = target; @@ -13733,21 +13931,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function cloneTypeReference(source: ts.TypeReference): ts.TypeReference { - const type = createTypeWithSymbol(source.flags, source.symbol) as ts.TypeReference; + function cloneTypeReference(source: TypeReference): TypeReference { + const type = createTypeWithSymbol(source.flags, source.symbol) as TypeReference; type.objectFlags = source.objectFlags; type.target = source.target; type.resolvedTypeArguments = source.resolvedTypeArguments; return type; } - function createDeferredTypeReference(target: ts.GenericType, node: ts.TypeReferenceNode | ts.ArrayTypeNode | ts.TupleTypeNode, mapper?: ts.TypeMapper, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.DeferredTypeReference { + function createDeferredTypeReference(target: GenericType, node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, mapper?: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): DeferredTypeReference { if (!aliasSymbol) { aliasSymbol = getAliasSymbolForTypeNode(node); const localAliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); aliasTypeArguments = mapper ? instantiateTypes(localAliasTypeArguments, mapper) : localAliasTypeArguments; } - const type = createObjectType(ts.ObjectFlags.Reference, target.symbol) as ts.DeferredTypeReference; + const type = createObjectType(ObjectFlags.Reference, target.symbol) as DeferredTypeReference; type.target = target; type.node = node; type.mapper = mapper; @@ -13756,24 +13954,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function getTypeArguments(type: ts.TypeReference): readonly ts.Type[] { + function getTypeArguments(type: TypeReference): readonly Type[] { if (!type.resolvedTypeArguments) { if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedTypeArguments)) { - return type.target.localTypeParameters?.map(() => errorType) || ts.emptyArray; + return type.target.localTypeParameters?.map(() => errorType) || emptyArray; } const node = type.node; - const typeArguments = !node ? ts.emptyArray : - node.kind === ts.SyntaxKind.TypeReference ? ts.concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) : - node.kind === ts.SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : - ts.map(node.elements, getTypeFromTypeNode); + const typeArguments = !node ? emptyArray : + node.kind === SyntaxKind.TypeReference ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) : + node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : + map(node.elements, getTypeFromTypeNode); if (popTypeResolution()) { type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments; } else { - type.resolvedTypeArguments = type.target.localTypeParameters?.map(() => errorType) || ts.emptyArray; + type.resolvedTypeArguments = type.target.localTypeParameters?.map(() => errorType) || emptyArray; error( type.node || currentNode, - type.target.symbol ? ts.Diagnostics.Type_arguments_for_0_circularly_reference_themselves : ts.Diagnostics.Tuple_type_arguments_circularly_reference_themselves, + type.target.symbol ? Diagnostics.Type_arguments_for_0_circularly_reference_themselves : Diagnostics.Tuple_type_arguments_circularly_reference_themselves, type.target.symbol && symbolToString(type.target.symbol) ); } @@ -13781,52 +13979,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.resolvedTypeArguments; } - function getTypeReferenceArity(type: ts.TypeReference): number { - return ts.length(type.target.typeParameters); + function getTypeReferenceArity(type: TypeReference): number { + return length(type.target.typeParameters); } /** * Get type from type-reference that reference to class or interface */ - function getTypeFromClassOrInterfaceReference(node: ts.NodeWithTypeArguments, symbol: ts.Symbol): ts.Type { - const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)) as ts.InterfaceType; + function getTypeFromClassOrInterfaceReference(node: NodeWithTypeArguments, symbol: Symbol): Type { + const type = getDeclaredTypeOfSymbol(getMergedSymbol(symbol)) as InterfaceType; const typeParameters = type.localTypeParameters; if (typeParameters) { - const numTypeArguments = ts.length(node.typeArguments); + const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); - const isJs = ts.isInJSFile(node); + const isJs = isInJSFile(node); const isJsImplicitAny = !noImplicitAny && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { - const missingAugmentsTag = isJs && ts.isExpressionWithTypeArguments(node) && !ts.isJSDocAugmentsTag(node.parent); + const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) && !isJSDocAugmentsTag(node.parent); const diag = minTypeArgumentCount === typeParameters.length ? missingAugmentsTag ? - ts.Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag : - ts.Diagnostics.Generic_type_0_requires_1_type_argument_s : + Diagnostics.Expected_0_type_arguments_provide_these_with_an_extends_tag : + Diagnostics.Generic_type_0_requires_1_type_argument_s : missingAugmentsTag ? - ts.Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag : - ts.Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; + Diagnostics.Expected_0_1_type_arguments_provide_these_with_an_extends_tag : + Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments; - const typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.WriteArrayAsGenericType); + const typeStr = typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType); error(node, diag, typeStr, minTypeArgumentCount, typeParameters.length); if (!isJs) { // TODO: Adopt same permissive behavior in TS as in JS to reduce follow-on editing experience failures (requires editing fillMissingTypeArguments) return errorType; } } - if (node.kind === ts.SyntaxKind.TypeReference && isDeferredTypeReferenceNode(node as ts.TypeReferenceNode, ts.length(node.typeArguments) !== typeParameters.length)) { - return createDeferredTypeReference(type as ts.GenericType, node as ts.TypeReferenceNode, /*mapper*/ undefined); + if (node.kind === SyntaxKind.TypeReference && isDeferredTypeReferenceNode(node as TypeReferenceNode, length(node.typeArguments) !== typeParameters.length)) { + return createDeferredTypeReference(type as GenericType, node as TypeReferenceNode, /*mapper*/ undefined); } // In a type reference, the outer type parameters of the referenced class or interface are automatically // supplied as type arguments and the type reference only specifies arguments for the local type parameters // of the class or interface. - const typeArguments = ts.concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgumentsFromTypeReferenceNode(node), typeParameters, minTypeArgumentCount, isJs)); - return createTypeReference(type as ts.GenericType, typeArguments); + const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgumentsFromTypeReferenceNode(node), typeParameters, minTypeArgumentCount, isJs)); + return createTypeReference(type as GenericType, typeArguments); } return checkNoTypeArguments(node, symbol) ? type : errorType; } - function getTypeAliasInstantiation(symbol: ts.Symbol, typeArguments: readonly ts.Type[] | undefined, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type { + function getTypeAliasInstantiation(symbol: Symbol, typeArguments: readonly Type[] | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { const type = getDeclaredTypeOfSymbol(symbol); if (type === intrinsicMarkerType && intrinsicTypeKinds.has(symbol.escapedName as string) && typeArguments && typeArguments.length === 1) { return getStringMappingType(symbol, typeArguments[0]); @@ -13837,7 +14035,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let instantiation = links.instantiations!.get(id); if (!instantiation) { links.instantiations!.set(id, instantiation = instantiateTypeWithAlias(type, - createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), ts.isInJSFile(symbol.valueDeclaration))), + createTypeMapper(typeParameters, fillMissingTypeArguments(typeArguments, typeParameters, getMinTypeArgumentCount(typeParameters), isInJSFile(symbol.valueDeclaration))), aliasSymbol, aliasTypeArguments)); } return instantiation; @@ -13848,13 +14046,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the * declared type. Instantiations are cached using the type identities of the type arguments as the key. */ - function getTypeFromTypeAliasReference(node: ts.NodeWithTypeArguments, symbol: ts.Symbol): ts.Type { - if (ts.getCheckFlags(symbol) & ts.CheckFlags.Unresolved) { + function getTypeFromTypeAliasReference(node: NodeWithTypeArguments, symbol: Symbol): Type { + if (getCheckFlags(symbol) & CheckFlags.Unresolved) { const typeArguments = typeArgumentsFromTypeReferenceNode(node); const id = getAliasId(symbol, typeArguments); let errorType = errorTypes.get(id); if (!errorType) { - errorType = createIntrinsicType(ts.TypeFlags.Any, "error"); + errorType = createIntrinsicType(TypeFlags.Any, "error"); errorType.aliasSymbol = symbol; errorType.aliasTypeArguments = typeArguments; errorTypes.set(id, errorType); @@ -13864,13 +14062,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const type = getDeclaredTypeOfSymbol(symbol); const typeParameters = getSymbolLinks(symbol).typeParameters; if (typeParameters) { - const numTypeArguments = ts.length(node.typeArguments); + const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); if (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length) { error(node, minTypeArgumentCount === typeParameters.length ? - ts.Diagnostics.Generic_type_0_requires_1_type_argument_s : - ts.Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments, + Diagnostics.Generic_type_0_requires_1_type_argument_s : + Diagnostics.Generic_type_0_requires_between_1_and_2_type_arguments, symbolToString(symbol), minTypeArgumentCount, typeParameters.length); @@ -13887,20 +14085,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return checkNoTypeArguments(node, symbol) ? type : errorType; } - function isLocalTypeAlias(symbol: ts.Symbol) { - const declaration = symbol.declarations?.find(ts.isTypeAlias); - return !!(declaration && ts.getContainingFunction(declaration)); + function isLocalTypeAlias(symbol: Symbol) { + const declaration = symbol.declarations?.find(isTypeAlias); + return !!(declaration && getContainingFunction(declaration)); } - function getTypeReferenceName(node: ts.TypeReferenceType): ts.EntityNameOrEntityNameExpression | undefined { + function getTypeReferenceName(node: TypeReferenceType): EntityNameOrEntityNameExpression | undefined { switch (node.kind) { - case ts.SyntaxKind.TypeReference: + case SyntaxKind.TypeReference: return node.typeName; - case ts.SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.ExpressionWithTypeArguments: // We only support expressions that are simple qualified names. For other // expressions this produces undefined. const expr = node.expression; - if (ts.isEntityNameExpression(expr)) { + if (isEntityNameExpression(expr)) { return expr; } // fall through; @@ -13909,23 +14107,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getSymbolPath(symbol: ts.Symbol): string { + function getSymbolPath(symbol: Symbol): string { return symbol.parent ? `${getSymbolPath(symbol.parent)}.${symbol.escapedName}` : symbol.escapedName as string; } - function getUnresolvedSymbolForEntityName(name: ts.EntityNameOrEntityNameExpression) { - const identifier = name.kind === ts.SyntaxKind.QualifiedName ? name.right : - name.kind === ts.SyntaxKind.PropertyAccessExpression ? name.name : + function getUnresolvedSymbolForEntityName(name: EntityNameOrEntityNameExpression) { + const identifier = name.kind === SyntaxKind.QualifiedName ? name.right : + name.kind === SyntaxKind.PropertyAccessExpression ? name.name : name; const text = identifier.escapedText; if (text) { - const parentSymbol = name.kind === ts.SyntaxKind.QualifiedName ? getUnresolvedSymbolForEntityName(name.left) : - name.kind === ts.SyntaxKind.PropertyAccessExpression ? getUnresolvedSymbolForEntityName(name.expression) : + const parentSymbol = name.kind === SyntaxKind.QualifiedName ? getUnresolvedSymbolForEntityName(name.left) : + name.kind === SyntaxKind.PropertyAccessExpression ? getUnresolvedSymbolForEntityName(name.expression) : undefined; const path = parentSymbol ? `${getSymbolPath(parentSymbol)}.${text}` : text as string; let result = unresolvedSymbols.get(path); if (!result) { - unresolvedSymbols.set(path, result = createSymbol(ts.SymbolFlags.TypeAlias, text, ts.CheckFlags.Unresolved)); + unresolvedSymbols.set(path, result = createSymbol(SymbolFlags.TypeAlias, text, CheckFlags.Unresolved)); result.parent = parentSymbol; result.declaredType = unresolvedType; } @@ -13934,7 +14132,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return unknownSymbol; } - function resolveTypeReferenceName(typeReference: ts.TypeReferenceType, meaning: ts.SymbolFlags, ignoreErrors?: boolean) { + function resolveTypeReferenceName(typeReference: TypeReferenceType, meaning: SymbolFlags, ignoreErrors?: boolean) { const name = getTypeReferenceName(typeReference); if (!name) { return unknownSymbol; @@ -13944,15 +14142,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { ignoreErrors ? unknownSymbol : getUnresolvedSymbolForEntityName(name); } - function getTypeReferenceType(node: ts.NodeWithTypeArguments, symbol: ts.Symbol): ts.Type { + function getTypeReferenceType(node: NodeWithTypeArguments, symbol: Symbol): Type { if (symbol === unknownSymbol) { return errorType; } symbol = getExpandoSymbol(symbol) || symbol; - if (symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface)) { + if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { return getTypeFromClassOrInterfaceReference(node, symbol); } - if (symbol.flags & ts.SymbolFlags.TypeAlias) { + if (symbol.flags & SymbolFlags.TypeAlias) { return getTypeFromTypeAliasReference(node, symbol); } // Get type from reference to named type that cannot be generic (enum or type parameter) @@ -13960,14 +14158,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (res) { return checkNoTypeArguments(node, symbol) ? getRegularTypeOfLiteralType(res) : errorType; } - if (symbol.flags & ts.SymbolFlags.Value && isJSDocTypeReference(node)) { + if (symbol.flags & SymbolFlags.Value && isJSDocTypeReference(node)) { const jsdocType = getTypeFromJSDocValueReference(node, symbol); if (jsdocType) { return jsdocType; } else { // Resolve the type reference as a Type for the purpose of reporting errors. - resolveTypeReferenceName(node, ts.SymbolFlags.Type); + resolveTypeReferenceName(node, SymbolFlags.Type); return getTypeOfSymbol(symbol); } } @@ -13978,13 +14176,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * A JSdoc TypeReference may be to a value, but resolve it as a type anyway. * Example: import('./b').ConstructorFunction */ - function getTypeFromJSDocValueReference(node: ts.NodeWithTypeArguments, symbol: ts.Symbol): ts.Type | undefined { + function getTypeFromJSDocValueReference(node: NodeWithTypeArguments, symbol: Symbol): Type | undefined { const links = getNodeLinks(node); if (!links.resolvedJSDocType) { const valueType = getTypeOfSymbol(symbol); let typeType = valueType; if (symbol.valueDeclaration) { - const isImportTypeWithQualifier = node.kind === ts.SyntaxKind.ImportType && (node as ts.ImportTypeNode).qualifier; + const isImportTypeWithQualifier = node.kind === SyntaxKind.ImportType && (node as ImportTypeNode).qualifier; // valueType might not have a symbol, eg, {import('./b').STRING_LITERAL} if (valueType.symbol && valueType.symbol !== symbol && isImportTypeWithQualifier) { typeType = getTypeReferenceType(node, valueType.symbol); @@ -13995,8 +14193,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedJSDocType; } - function getSubstitutionType(baseType: ts.Type, constraint: ts.Type) { - if (constraint.flags & ts.TypeFlags.AnyOrUnknown || constraint === baseType || + function getSubstitutionType(baseType: Type, constraint: Type) { + if (constraint.flags & TypeFlags.AnyOrUnknown || constraint === baseType || !isGenericType(baseType) && !isGenericType(constraint)) { return baseType; } @@ -14005,55 +14203,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (cached) { return cached; } - const result = createType(ts.TypeFlags.Substitution) as ts.SubstitutionType; + const result = createType(TypeFlags.Substitution) as SubstitutionType; result.baseType = baseType; result.constraint = constraint; substitutionTypes.set(id, result); return result; } - function getSubstitutionIntersection(substitutionType: ts.SubstitutionType) { + function getSubstitutionIntersection(substitutionType: SubstitutionType) { return getIntersectionType([substitutionType.constraint, substitutionType.baseType]); } - function isUnaryTupleTypeNode(node: ts.TypeNode) { - return node.kind === ts.SyntaxKind.TupleType && (node as ts.TupleTypeNode).elements.length === 1; + function isUnaryTupleTypeNode(node: TypeNode) { + return node.kind === SyntaxKind.TupleType && (node as TupleTypeNode).elements.length === 1; } - function getImpliedConstraint(type: ts.Type, checkNode: ts.TypeNode, extendsNode: ts.TypeNode): ts.Type | undefined { - return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as ts.TupleTypeNode).elements[0], (extendsNode as ts.TupleTypeNode).elements[0]) : + function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined { + return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (checkNode as TupleTypeNode).elements[0], (extendsNode as TupleTypeNode).elements[0]) : getActualTypeVariable(getTypeFromTypeNode(checkNode)) === getActualTypeVariable(type) ? getTypeFromTypeNode(extendsNode) : undefined; } - function getConditionalFlowTypeOfType(type: ts.Type, node: ts.Node) { - let constraints: ts.Type[] | undefined; + function getConditionalFlowTypeOfType(type: Type, node: Node) { + let constraints: Type[] | undefined; let covariant = true; - while (node && !ts.isStatement(node) && node.kind !== ts.SyntaxKind.JSDoc) { + while (node && !isStatement(node) && node.kind !== SyntaxKind.JSDoc) { const parent = node.parent; // only consider variance flipped by parameter locations - `keyof` types would usually be considered variance inverting, but // often get used in indexed accesses where they behave sortof invariantly, but our checking is lax - if (parent.kind === ts.SyntaxKind.Parameter) { + if (parent.kind === SyntaxKind.Parameter) { covariant = !covariant; } // Always substitute on type parameters, regardless of variance, since even // in contravariant positions, they may rely on substituted constraints to be valid - if ((covariant || type.flags & ts.TypeFlags.TypeVariable) && parent.kind === ts.SyntaxKind.ConditionalType && node === (parent as ts.ConditionalTypeNode).trueType) { - const constraint = getImpliedConstraint(type, (parent as ts.ConditionalTypeNode).checkType, (parent as ts.ConditionalTypeNode).extendsType); + if ((covariant || type.flags & TypeFlags.TypeVariable) && parent.kind === SyntaxKind.ConditionalType && node === (parent as ConditionalTypeNode).trueType) { + const constraint = getImpliedConstraint(type, (parent as ConditionalTypeNode).checkType, (parent as ConditionalTypeNode).extendsType); if (constraint) { - constraints = ts.append(constraints, constraint); + constraints = append(constraints, constraint); } } // Given a homomorphic mapped type { [K in keyof T]: XXX }, where T is constrained to an array or tuple type, in the // template type XXX, K has an added constraint of number | `${number}`. - else if (type.flags & ts.TypeFlags.TypeParameter && parent.kind === ts.SyntaxKind.MappedType && node === (parent as ts.MappedTypeNode).type) { - const mappedType = getTypeFromTypeNode(parent as ts.TypeNode) as ts.MappedType; + else if (type.flags & TypeFlags.TypeParameter && parent.kind === SyntaxKind.MappedType && node === (parent as MappedTypeNode).type) { + const mappedType = getTypeFromTypeNode(parent as TypeNode) as MappedType; if (getTypeParameterFromMappedType(mappedType) === getActualTypeVariable(type)) { const typeParameter = getHomomorphicTypeVariable(mappedType); if (typeParameter) { const constraint = getConstraintOfTypeParameter(typeParameter); if (constraint && everyType(constraint, isArrayOrTupleType)) { - constraints = ts.append(constraints, getUnionType([numberType, numericStringType])); + constraints = append(constraints, getUnionType([numberType, numericStringType])); } } } @@ -14063,20 +14261,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return constraints ? getSubstitutionType(type, getIntersectionType(constraints)) : type; } - function isJSDocTypeReference(node: ts.Node): node is ts.TypeReferenceNode { - return !!(node.flags & ts.NodeFlags.JSDoc) && (node.kind === ts.SyntaxKind.TypeReference || node.kind === ts.SyntaxKind.ImportType); + function isJSDocTypeReference(node: Node): node is TypeReferenceNode { + return !!(node.flags & NodeFlags.JSDoc) && (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.ImportType); } - function checkNoTypeArguments(node: ts.NodeWithTypeArguments, symbol?: ts.Symbol) { + function checkNoTypeArguments(node: NodeWithTypeArguments, symbol?: Symbol) { if (node.typeArguments) { - error(node, ts.Diagnostics.Type_0_is_not_generic, symbol ? symbolToString(symbol) : (node as ts.TypeReferenceNode).typeName ? ts.declarationNameToString((node as ts.TypeReferenceNode).typeName) : anon); + error(node, Diagnostics.Type_0_is_not_generic, symbol ? symbolToString(symbol) : (node as TypeReferenceNode).typeName ? declarationNameToString((node as TypeReferenceNode).typeName) : anon); return false; } return true; } - function getIntendedTypeFromJSDocTypeReference(node: ts.TypeReferenceNode): ts.Type | undefined { - if (ts.isIdentifier(node.typeName)) { + function getIntendedTypeFromJSDocTypeReference(node: TypeReferenceNode): Type | undefined { + if (isIdentifier(node.typeName)) { const typeArgs = node.typeArguments; switch (node.typeName.escapedText) { case "String": @@ -14107,11 +14305,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return (!typeArgs || !typeArgs.length) && !noImplicitAny ? createPromiseType(anyType) : undefined; case "Object": if (typeArgs && typeArgs.length === 2) { - if (ts.isJSDocIndexSignature(node)) { + if (isJSDocIndexSignature(node)) { const indexed = getTypeFromTypeNode(typeArgs[0]); const target = getTypeFromTypeNode(typeArgs[1]); - const indexInfo = indexed === stringType || indexed === numberType ? [createIndexInfo(indexed, target, /*isReadonly*/ false)] : ts.emptyArray; - return createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, indexInfo); + const indexInfo = indexed === stringType || indexed === numberType ? [createIndexInfo(indexed, target, /*isReadonly*/ false)] : emptyArray; + return createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, indexInfo); } return anyType; } @@ -14121,28 +14319,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeFromJSDocNullableTypeNode(node: ts.JSDocNullableType) { + function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) { const type = getTypeFromTypeNode(node.type); - return strictNullChecks ? getNullableType(type, ts.TypeFlags.Null) : type; + return strictNullChecks ? getNullableType(type, TypeFlags.Null) : type; } - function getTypeFromTypeReference(node: ts.TypeReferenceType): ts.Type { + function getTypeFromTypeReference(node: TypeReferenceType): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // handle LS queries on the `const` in `x as const` by resolving to the type of `x` - if (ts.isConstTypeReference(node) && ts.isAssertionExpression(node.parent)) { + if (isConstTypeReference(node) && isAssertionExpression(node.parent)) { links.resolvedSymbol = unknownSymbol; return links.resolvedType = checkExpressionCached(node.parent.expression); } - let symbol: ts.Symbol | undefined; - let type: ts.Type | undefined; - const meaning = ts.SymbolFlags.Type; + let symbol: Symbol | undefined; + let type: Type | undefined; + const meaning = SymbolFlags.Type; if (isJSDocTypeReference(node)) { type = getIntendedTypeFromJSDocTypeReference(node); if (!type) { symbol = resolveTypeReferenceName(node, meaning, /*ignoreErrors*/ true); if (symbol === unknownSymbol) { - symbol = resolveTypeReferenceName(node, meaning | ts.SymbolFlags.Value); + symbol = resolveTypeReferenceName(node, meaning | SymbolFlags.Value); } else { resolveTypeReferenceName(node, meaning); // Resolve again to mark errors, if any @@ -14162,11 +14360,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function typeArgumentsFromTypeReferenceNode(node: ts.NodeWithTypeArguments): ts.Type[] | undefined { - return ts.map(node.typeArguments, getTypeFromTypeNode); + function typeArgumentsFromTypeReferenceNode(node: NodeWithTypeArguments): Type[] | undefined { + return map(node.typeArguments, getTypeFromTypeNode); } - function getTypeFromTypeQueryNode(node: ts.TypeQueryNode): ts.Type { + function getTypeFromTypeQueryNode(node: TypeQueryNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // TypeScript 1.0 spec (April 2014): 3.6.3 @@ -14179,16 +14377,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function getTypeOfGlobalSymbol(symbol: ts.Symbol | undefined, arity: number): ts.ObjectType { + function getTypeOfGlobalSymbol(symbol: Symbol | undefined, arity: number): ObjectType { - function getTypeDeclaration(symbol: ts.Symbol): ts.Declaration | undefined { + function getTypeDeclaration(symbol: Symbol): Declaration | undefined { const declarations = symbol.declarations; if (declarations) { for (const declaration of declarations) { switch (declaration.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: return declaration; } } @@ -14199,271 +14397,271 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return arity ? emptyGenericType : emptyObjectType; } const type = getDeclaredTypeOfSymbol(symbol); - if (!(type.flags & ts.TypeFlags.Object)) { - error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_be_a_class_or_interface_type, ts.symbolName(symbol)); + if (!(type.flags & TypeFlags.Object)) { + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_be_a_class_or_interface_type, symbolName(symbol)); return arity ? emptyGenericType : emptyObjectType; } - if (ts.length((type as ts.InterfaceType).typeParameters) !== arity) { - error(getTypeDeclaration(symbol), ts.Diagnostics.Global_type_0_must_have_1_type_parameter_s, ts.symbolName(symbol), arity); + if (length((type as InterfaceType).typeParameters) !== arity) { + error(getTypeDeclaration(symbol), Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity); return arity ? emptyGenericType : emptyObjectType; } - return type as ts.ObjectType; + return type as ObjectType; } - function getGlobalValueSymbol(name: ts.__String, reportErrors: boolean): ts.Symbol | undefined { - return getGlobalSymbol(name, ts.SymbolFlags.Value, reportErrors ? ts.Diagnostics.Cannot_find_global_value_0 : undefined); + function getGlobalValueSymbol(name: __String, reportErrors: boolean): Symbol | undefined { + return getGlobalSymbol(name, SymbolFlags.Value, reportErrors ? Diagnostics.Cannot_find_global_value_0 : undefined); } - function getGlobalTypeSymbol(name: ts.__String, reportErrors: boolean): ts.Symbol | undefined { - return getGlobalSymbol(name, ts.SymbolFlags.Type, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); + function getGlobalTypeSymbol(name: __String, reportErrors: boolean): Symbol | undefined { + return getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); } - function getGlobalTypeAliasSymbol(name: ts.__String, arity: number, reportErrors: boolean): ts.Symbol | undefined { - const symbol = getGlobalSymbol(name, ts.SymbolFlags.Type, reportErrors ? ts.Diagnostics.Cannot_find_global_type_0 : undefined); + function getGlobalTypeAliasSymbol(name: __String, arity: number, reportErrors: boolean): Symbol | undefined { + const symbol = getGlobalSymbol(name, SymbolFlags.Type, reportErrors ? Diagnostics.Cannot_find_global_type_0 : undefined); if (symbol) { // Resolve the declared type of the symbol. This resolves type parameters for the type // alias so that we can check arity. getDeclaredTypeOfSymbol(symbol); - if (ts.length(getSymbolLinks(symbol).typeParameters) !== arity) { - const decl = symbol.declarations && ts.find(symbol.declarations, ts.isTypeAliasDeclaration); - error(decl, ts.Diagnostics.Global_type_0_must_have_1_type_parameter_s, ts.symbolName(symbol), arity); + if (length(getSymbolLinks(symbol).typeParameters) !== arity) { + const decl = symbol.declarations && find(symbol.declarations, isTypeAliasDeclaration); + error(decl, Diagnostics.Global_type_0_must_have_1_type_parameter_s, symbolName(symbol), arity); return undefined; } } return symbol; } - function getGlobalSymbol(name: ts.__String, meaning: ts.SymbolFlags, diagnostic: ts.DiagnosticMessage | undefined): ts.Symbol | undefined { + function getGlobalSymbol(name: __String, meaning: SymbolFlags, diagnostic: DiagnosticMessage | undefined): Symbol | undefined { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary return resolveName(undefined, name, meaning, diagnostic, name, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ false); } - function getGlobalType(name: ts.__String, arity: 0, reportErrors: true): ts.ObjectType; - function getGlobalType(name: ts.__String, arity: 0, reportErrors: boolean): ts.ObjectType | undefined; - function getGlobalType(name: ts.__String, arity: number, reportErrors: true): ts.GenericType; - function getGlobalType(name: ts.__String, arity: number, reportErrors: boolean): ts.GenericType | undefined; - function getGlobalType(name: ts.__String, arity: number, reportErrors: boolean): ts.ObjectType | undefined { + function getGlobalType(name: __String, arity: 0, reportErrors: true): ObjectType; + function getGlobalType(name: __String, arity: 0, reportErrors: boolean): ObjectType | undefined; + function getGlobalType(name: __String, arity: number, reportErrors: true): GenericType; + function getGlobalType(name: __String, arity: number, reportErrors: boolean): GenericType | undefined; + function getGlobalType(name: __String, arity: number, reportErrors: boolean): ObjectType | undefined { const symbol = getGlobalTypeSymbol(name, reportErrors); return symbol || reportErrors ? getTypeOfGlobalSymbol(symbol, arity) : undefined; } function getGlobalTypedPropertyDescriptorType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as ts.__String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType; + return deferredGlobalTypedPropertyDescriptorType ||= getGlobalType("TypedPropertyDescriptor" as __String, /*arity*/ 1, /*reportErrors*/ true) || emptyGenericType; } function getGlobalTemplateStringsArrayType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalTemplateStringsArrayType ||= getGlobalType("TemplateStringsArray" as ts.__String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; + return deferredGlobalTemplateStringsArrayType ||= getGlobalType("TemplateStringsArray" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; } function getGlobalImportMetaType() { // We always report an error, so store a result in the event we could not resolve the symbol to prevent reporting it multiple times - return deferredGlobalImportMetaType ||= getGlobalType("ImportMeta" as ts.__String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; + return deferredGlobalImportMetaType ||= getGlobalType("ImportMeta" as __String, /*arity*/ 0, /*reportErrors*/ true) || emptyObjectType; } function getGlobalImportMetaExpressionType() { if (!deferredGlobalImportMetaExpressionType) { // Create a synthetic type `ImportMetaExpression { meta: MetaProperty }` - const symbol = createSymbol(ts.SymbolFlags.None, "ImportMetaExpression" as ts.__String); + const symbol = createSymbol(SymbolFlags.None, "ImportMetaExpression" as __String); const importMetaType = getGlobalImportMetaType(); - const metaPropertySymbol = createSymbol(ts.SymbolFlags.Property, "meta" as ts.__String, ts.CheckFlags.Readonly); + const metaPropertySymbol = createSymbol(SymbolFlags.Property, "meta" as __String, CheckFlags.Readonly); metaPropertySymbol.parent = symbol; metaPropertySymbol.type = importMetaType; - const members = ts.createSymbolTable([metaPropertySymbol]); + const members = createSymbolTable([metaPropertySymbol]); symbol.members = members; - deferredGlobalImportMetaExpressionType = createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, ts.emptyArray); + deferredGlobalImportMetaExpressionType = createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); } return deferredGlobalImportMetaExpressionType; } function getGlobalImportCallOptionsType(reportErrors: boolean) { - return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as ts.__String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalImportCallOptionsType ||= getGlobalType("ImportCallOptions" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } - function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): ts.Symbol | undefined { - return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as ts.__String, reportErrors); + function getGlobalESSymbolConstructorSymbol(reportErrors: boolean): Symbol | undefined { + return deferredGlobalESSymbolConstructorSymbol ||= getGlobalValueSymbol("Symbol" as __String, reportErrors); } - function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean): ts.Symbol | undefined { - return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol("SymbolConstructor" as ts.__String, reportErrors); + function getGlobalESSymbolConstructorTypeSymbol(reportErrors: boolean): Symbol | undefined { + return deferredGlobalESSymbolConstructorTypeSymbol ||= getGlobalTypeSymbol("SymbolConstructor" as __String, reportErrors); } function getGlobalESSymbolType() { - return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as ts.__String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; + return (deferredGlobalESSymbolType ||= getGlobalType("Symbol" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; } function getGlobalPromiseType(reportErrors: boolean) { - return (deferredGlobalPromiseType ||= getGlobalType("Promise" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalPromiseType ||= getGlobalType("Promise" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalPromiseLikeType(reportErrors: boolean) { - return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalPromiseLikeType ||= getGlobalType("PromiseLike" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalPromiseConstructorSymbol(reportErrors: boolean): ts.Symbol | undefined { - return deferredGlobalPromiseConstructorSymbol ||= getGlobalValueSymbol("Promise" as ts.__String, reportErrors); + function getGlobalPromiseConstructorSymbol(reportErrors: boolean): Symbol | undefined { + return deferredGlobalPromiseConstructorSymbol ||= getGlobalValueSymbol("Promise" as __String, reportErrors); } function getGlobalPromiseConstructorLikeType(reportErrors: boolean) { - return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType("PromiseConstructorLike" as ts.__String, /*arity*/ 0, reportErrors)) || emptyObjectType; + return (deferredGlobalPromiseConstructorLikeType ||= getGlobalType("PromiseConstructorLike" as __String, /*arity*/ 0, reportErrors)) || emptyObjectType; } function getGlobalAsyncIterableType(reportErrors: boolean) { - return (deferredGlobalAsyncIterableType ||= getGlobalType("AsyncIterable" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIterableType ||= getGlobalType("AsyncIterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncIteratorType(reportErrors: boolean) { - return (deferredGlobalAsyncIteratorType ||= getGlobalType("AsyncIterator" as ts.__String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIteratorType ||= getGlobalType("AsyncIterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; } function getGlobalAsyncIterableIteratorType(reportErrors: boolean) { - return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncIterableIteratorType ||= getGlobalType("AsyncIterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalAsyncGeneratorType(reportErrors: boolean) { - return (deferredGlobalAsyncGeneratorType ||= getGlobalType("AsyncGenerator" as ts.__String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalAsyncGeneratorType ||= getGlobalType("AsyncGenerator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; } function getGlobalIterableType(reportErrors: boolean) { - return (deferredGlobalIterableType ||= getGlobalType("Iterable" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIterableType ||= getGlobalType("Iterable" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorType(reportErrors: boolean) { - return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as ts.__String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorType ||= getGlobalType("Iterator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; } function getGlobalIterableIteratorType(reportErrors: boolean) { - return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIterableIteratorType ||= getGlobalType("IterableIterator" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalGeneratorType(reportErrors: boolean) { - return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as ts.__String, /*arity*/ 3, reportErrors)) || emptyGenericType; + return (deferredGlobalGeneratorType ||= getGlobalType("Generator" as __String, /*arity*/ 3, reportErrors)) || emptyGenericType; } function getGlobalIteratorYieldResultType(reportErrors: boolean) { - return (deferredGlobalIteratorYieldResultType ||= getGlobalType("IteratorYieldResult" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorYieldResultType ||= getGlobalType("IteratorYieldResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } function getGlobalIteratorReturnResultType(reportErrors: boolean) { - return (deferredGlobalIteratorReturnResultType ||= getGlobalType("IteratorReturnResult" as ts.__String, /*arity*/ 1, reportErrors)) || emptyGenericType; + return (deferredGlobalIteratorReturnResultType ||= getGlobalType("IteratorReturnResult" as __String, /*arity*/ 1, reportErrors)) || emptyGenericType; } - function getGlobalTypeOrUndefined(name: ts.__String, arity = 0): ts.ObjectType | undefined { - const symbol = getGlobalSymbol(name, ts.SymbolFlags.Type, /*diagnostic*/ undefined); - return symbol && getTypeOfGlobalSymbol(symbol, arity) as ts.GenericType; + function getGlobalTypeOrUndefined(name: __String, arity = 0): ObjectType | undefined { + const symbol = getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined); + return symbol && getTypeOfGlobalSymbol(symbol, arity) as GenericType; } - function getGlobalExtractSymbol(): ts.Symbol | undefined { + function getGlobalExtractSymbol(): Symbol | undefined { // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times - deferredGlobalExtractSymbol ||= getGlobalTypeAliasSymbol("Extract" as ts.__String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + deferredGlobalExtractSymbol ||= getGlobalTypeAliasSymbol("Extract" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; return deferredGlobalExtractSymbol === unknownSymbol ? undefined : deferredGlobalExtractSymbol; } - function getGlobalOmitSymbol(): ts.Symbol | undefined { + function getGlobalOmitSymbol(): Symbol | undefined { // We always report an error, so cache a result in the event we could not resolve the symbol to prevent reporting it multiple times - deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as ts.__String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + deferredGlobalOmitSymbol ||= getGlobalTypeAliasSymbol("Omit" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; return deferredGlobalOmitSymbol === unknownSymbol ? undefined : deferredGlobalOmitSymbol; } - function getGlobalAwaitedSymbol(reportErrors: boolean): ts.Symbol | undefined { + function getGlobalAwaitedSymbol(reportErrors: boolean): Symbol | undefined { // Only cache `unknownSymbol` if we are reporting errors so that we don't report the error more than once. - deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as ts.__String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined); + deferredGlobalAwaitedSymbol ||= getGlobalTypeAliasSymbol("Awaited" as __String, /*arity*/ 1, reportErrors) || (reportErrors ? unknownSymbol : undefined); return deferredGlobalAwaitedSymbol === unknownSymbol ? undefined : deferredGlobalAwaitedSymbol; } function getGlobalBigIntType() { - return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as ts.__String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; + return (deferredGlobalBigIntType ||= getGlobalType("BigInt" as __String, /*arity*/ 0, /*reportErrors*/ false)) || emptyObjectType; } - function getGlobalNaNSymbol(): ts.Symbol | undefined { - return (deferredGlobalNaNSymbol ||= getGlobalValueSymbol("NaN" as ts.__String, /*reportErrors*/ false)); + function getGlobalNaNSymbol(): Symbol | undefined { + return (deferredGlobalNaNSymbol ||= getGlobalValueSymbol("NaN" as __String, /*reportErrors*/ false)); } - function getGlobalRecordSymbol(): ts.Symbol | undefined { - deferredGlobalRecordSymbol ||= getGlobalTypeAliasSymbol("Record" as ts.__String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; + function getGlobalRecordSymbol(): Symbol | undefined { + deferredGlobalRecordSymbol ||= getGlobalTypeAliasSymbol("Record" as __String, /*arity*/ 2, /*reportErrors*/ true) || unknownSymbol; return deferredGlobalRecordSymbol === unknownSymbol ? undefined : deferredGlobalRecordSymbol; } /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ - function createTypeFromGenericGlobalType(genericGlobalType: ts.GenericType, typeArguments: readonly ts.Type[]): ts.ObjectType { + function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: readonly Type[]): ObjectType { return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType; } - function createTypedPropertyDescriptorType(propertyType: ts.Type): ts.Type { + function createTypedPropertyDescriptorType(propertyType: Type): Type { return createTypeFromGenericGlobalType(getGlobalTypedPropertyDescriptorType(), [propertyType]); } - function createIterableType(iteratedType: ts.Type): ts.Type { + function createIterableType(iteratedType: Type): Type { return createTypeFromGenericGlobalType(getGlobalIterableType(/*reportErrors*/ true), [iteratedType]); } - function createArrayType(elementType: ts.Type, readonly?: boolean): ts.ObjectType { + function createArrayType(elementType: Type, readonly?: boolean): ObjectType { return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]); } - function getTupleElementFlags(node: ts.TypeNode) { + function getTupleElementFlags(node: TypeNode) { switch (node.kind) { - case ts.SyntaxKind.OptionalType: - return ts.ElementFlags.Optional; - case ts.SyntaxKind.RestType: - return getRestTypeElementFlags(node as ts.RestTypeNode); - case ts.SyntaxKind.NamedTupleMember: - return (node as ts.NamedTupleMember).questionToken ? ts.ElementFlags.Optional : - (node as ts.NamedTupleMember).dotDotDotToken ? getRestTypeElementFlags(node as ts.NamedTupleMember) : - ts.ElementFlags.Required; + case SyntaxKind.OptionalType: + return ElementFlags.Optional; + case SyntaxKind.RestType: + return getRestTypeElementFlags(node as RestTypeNode); + case SyntaxKind.NamedTupleMember: + return (node as NamedTupleMember).questionToken ? ElementFlags.Optional : + (node as NamedTupleMember).dotDotDotToken ? getRestTypeElementFlags(node as NamedTupleMember) : + ElementFlags.Required; default: - return ts.ElementFlags.Required; + return ElementFlags.Required; } } - function getRestTypeElementFlags(node: ts.RestTypeNode | ts.NamedTupleMember) { - return getArrayElementTypeNode(node.type) ? ts.ElementFlags.Rest : ts.ElementFlags.Variadic; + function getRestTypeElementFlags(node: RestTypeNode | NamedTupleMember) { + return getArrayElementTypeNode(node.type) ? ElementFlags.Rest : ElementFlags.Variadic; } - function getArrayOrTupleTargetType(node: ts.ArrayTypeNode | ts.TupleTypeNode): ts.GenericType { + function getArrayOrTupleTargetType(node: ArrayTypeNode | TupleTypeNode): GenericType { const readonly = isReadonlyTypeOperator(node.parent); const elementType = getArrayElementTypeNode(node); if (elementType) { return readonly ? globalReadonlyArrayType : globalArrayType; } - const elementFlags = ts.map((node as ts.TupleTypeNode).elements, getTupleElementFlags); - const missingName = ts.some((node as ts.TupleTypeNode).elements, e => e.kind !== ts.SyntaxKind.NamedTupleMember); - return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as ts.TupleTypeNode).elements as readonly ts.NamedTupleMember[]); + const elementFlags = map((node as TupleTypeNode).elements, getTupleElementFlags); + const missingName = some((node as TupleTypeNode).elements, e => e.kind !== SyntaxKind.NamedTupleMember); + return getTupleTargetType(elementFlags, readonly, /*associatedNames*/ missingName ? undefined : (node as TupleTypeNode).elements as readonly NamedTupleMember[]); } // Return true if the given type reference node is directly aliased or if it needs to be deferred // because it is possibly contained in a circular chain of eagerly resolved types. - function isDeferredTypeReferenceNode(node: ts.TypeReferenceNode | ts.ArrayTypeNode | ts.TupleTypeNode, hasDefaultTypeArguments?: boolean) { + function isDeferredTypeReferenceNode(node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, hasDefaultTypeArguments?: boolean) { return !!getAliasSymbolForTypeNode(node) || isResolvedByTypeAlias(node) && ( - node.kind === ts.SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) : - node.kind === ts.SyntaxKind.TupleType ? ts.some(node.elements, mayResolveTypeAlias) : - hasDefaultTypeArguments || ts.some(node.typeArguments, mayResolveTypeAlias)); + node.kind === SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) : + node.kind === SyntaxKind.TupleType ? some(node.elements, mayResolveTypeAlias) : + hasDefaultTypeArguments || some(node.typeArguments, mayResolveTypeAlias)); } // Return true when the given node is transitively contained in type constructs that eagerly // resolve their constituent types. We include SyntaxKind.TypeReference because type arguments // of type aliases are eagerly resolved. - function isResolvedByTypeAlias(node: ts.Node): boolean { + function isResolvedByTypeAlias(node: Node): boolean { const parent = node.parent; switch (parent.kind) { - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.NamedTupleMember: - case ts.SyntaxKind.TypeReference: - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.IndexedAccessType: - case ts.SyntaxKind.ConditionalType: - case ts.SyntaxKind.TypeOperator: - case ts.SyntaxKind.ArrayType: - case ts.SyntaxKind.TupleType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.NamedTupleMember: + case SyntaxKind.TypeReference: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.IndexedAccessType: + case SyntaxKind.ConditionalType: + case SyntaxKind.TypeOperator: + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: return isResolvedByTypeAlias(parent); - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeAliasDeclaration: return true; } return false; @@ -14471,74 +14669,74 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if resolving the given node (i.e. getTypeFromTypeNode) possibly causes resolution // of a type alias. - function mayResolveTypeAlias(node: ts.Node): boolean { + function mayResolveTypeAlias(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.TypeReference: - return isJSDocTypeReference(node) || !!(resolveTypeReferenceName(node as ts.TypeReferenceNode, ts.SymbolFlags.Type).flags & ts.SymbolFlags.TypeAlias); - case ts.SyntaxKind.TypeQuery: + case SyntaxKind.TypeReference: + return isJSDocTypeReference(node) || !!(resolveTypeReferenceName(node as TypeReferenceNode, SymbolFlags.Type).flags & SymbolFlags.TypeAlias); + case SyntaxKind.TypeQuery: return true; - case ts.SyntaxKind.TypeOperator: - return (node as ts.TypeOperatorNode).operator !== ts.SyntaxKind.UniqueKeyword && mayResolveTypeAlias((node as ts.TypeOperatorNode).type); - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.OptionalType: - case ts.SyntaxKind.NamedTupleMember: - case ts.SyntaxKind.JSDocOptionalType: - case ts.SyntaxKind.JSDocNullableType: - case ts.SyntaxKind.JSDocNonNullableType: - case ts.SyntaxKind.JSDocTypeExpression: - return mayResolveTypeAlias((node as ts.ParenthesizedTypeNode | ts.OptionalTypeNode | ts.JSDocTypeReferencingNode | ts.NamedTupleMember).type); - case ts.SyntaxKind.RestType: - return (node as ts.RestTypeNode).type.kind !== ts.SyntaxKind.ArrayType || mayResolveTypeAlias(((node as ts.RestTypeNode).type as ts.ArrayTypeNode).elementType); - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - return ts.some((node as ts.UnionOrIntersectionTypeNode).types, mayResolveTypeAlias); - case ts.SyntaxKind.IndexedAccessType: - return mayResolveTypeAlias((node as ts.IndexedAccessTypeNode).objectType) || mayResolveTypeAlias((node as ts.IndexedAccessTypeNode).indexType); - case ts.SyntaxKind.ConditionalType: - return mayResolveTypeAlias((node as ts.ConditionalTypeNode).checkType) || mayResolveTypeAlias((node as ts.ConditionalTypeNode).extendsType) || - mayResolveTypeAlias((node as ts.ConditionalTypeNode).trueType) || mayResolveTypeAlias((node as ts.ConditionalTypeNode).falseType); + case SyntaxKind.TypeOperator: + return (node as TypeOperatorNode).operator !== SyntaxKind.UniqueKeyword && mayResolveTypeAlias((node as TypeOperatorNode).type); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.OptionalType: + case SyntaxKind.NamedTupleMember: + case SyntaxKind.JSDocOptionalType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocTypeExpression: + return mayResolveTypeAlias((node as ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode | NamedTupleMember).type); + case SyntaxKind.RestType: + return (node as RestTypeNode).type.kind !== SyntaxKind.ArrayType || mayResolveTypeAlias(((node as RestTypeNode).type as ArrayTypeNode).elementType); + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + return some((node as UnionOrIntersectionTypeNode).types, mayResolveTypeAlias); + case SyntaxKind.IndexedAccessType: + return mayResolveTypeAlias((node as IndexedAccessTypeNode).objectType) || mayResolveTypeAlias((node as IndexedAccessTypeNode).indexType); + case SyntaxKind.ConditionalType: + return mayResolveTypeAlias((node as ConditionalTypeNode).checkType) || mayResolveTypeAlias((node as ConditionalTypeNode).extendsType) || + mayResolveTypeAlias((node as ConditionalTypeNode).trueType) || mayResolveTypeAlias((node as ConditionalTypeNode).falseType); } return false; } - function getTypeFromArrayOrTupleTypeNode(node: ts.ArrayTypeNode | ts.TupleTypeNode): ts.Type { + function getTypeFromArrayOrTupleTypeNode(node: ArrayTypeNode | TupleTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { const target = getArrayOrTupleTargetType(node); if (target === emptyGenericType) { links.resolvedType = emptyObjectType; } - else if (!(node.kind === ts.SyntaxKind.TupleType && ts.some(node.elements, e => !!(getTupleElementFlags(e) & ts.ElementFlags.Variadic))) && isDeferredTypeReferenceNode(node)) { - links.resolvedType = node.kind === ts.SyntaxKind.TupleType && node.elements.length === 0 ? target : + else if (!(node.kind === SyntaxKind.TupleType && some(node.elements, e => !!(getTupleElementFlags(e) & ElementFlags.Variadic))) && isDeferredTypeReferenceNode(node)) { + links.resolvedType = node.kind === SyntaxKind.TupleType && node.elements.length === 0 ? target : createDeferredTypeReference(target, node, /*mapper*/ undefined); } else { - const elementTypes = node.kind === ts.SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : ts.map(node.elements, getTypeFromTypeNode); + const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : map(node.elements, getTypeFromTypeNode); links.resolvedType = createNormalizedTypeReference(target, elementTypes); } } return links.resolvedType; } - function isReadonlyTypeOperator(node: ts.Node) { - return ts.isTypeOperatorNode(node) && node.operator === ts.SyntaxKind.ReadonlyKeyword; + function isReadonlyTypeOperator(node: Node) { + return isTypeOperatorNode(node) && node.operator === SyntaxKind.ReadonlyKeyword; } - function createTupleType(elementTypes: readonly ts.Type[], elementFlags?: readonly ts.ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (ts.NamedTupleMember | ts.ParameterDeclaration)[]) { - const tupleTarget = getTupleTargetType(elementFlags || ts.map(elementTypes, _ => ts.ElementFlags.Required), readonly, namedMemberDeclarations); + function createTupleType(elementTypes: readonly Type[], elementFlags?: readonly ElementFlags[], readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]) { + const tupleTarget = getTupleTargetType(elementFlags || map(elementTypes, _ => ElementFlags.Required), readonly, namedMemberDeclarations); return tupleTarget === emptyGenericType ? emptyObjectType : elementTypes.length ? createNormalizedTypeReference(tupleTarget, elementTypes) : tupleTarget; } - function getTupleTargetType(elementFlags: readonly ts.ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (ts.NamedTupleMember | ts.ParameterDeclaration)[]): ts.GenericType { - if (elementFlags.length === 1 && elementFlags[0] & ts.ElementFlags.Rest) { + function getTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType { + if (elementFlags.length === 1 && elementFlags[0] & ElementFlags.Rest) { // [...X[]] is equivalent to just X[] return readonly ? globalReadonlyArrayType : globalArrayType; } - const key = ts.map(elementFlags, f => f & ts.ElementFlags.Required ? "#" : f & ts.ElementFlags.Optional ? "?" : f & ts.ElementFlags.Rest ? "." : "*").join() + + const key = map(elementFlags, f => f & ElementFlags.Required ? "#" : f & ElementFlags.Optional ? "?" : f & ElementFlags.Rest ? "." : "*").join() + (readonly ? "R" : "") + - (namedMemberDeclarations && namedMemberDeclarations.length ? "," + ts.map(namedMemberDeclarations, getNodeId).join(",") : ""); + (namedMemberDeclarations && namedMemberDeclarations.length ? "," + map(namedMemberDeclarations, getNodeId).join(",") : ""); let type = tupleTypes.get(key); if (!type) { tupleTypes.set(key, type = createTupleTargetType(elementFlags, readonly, namedMemberDeclarations)); @@ -14553,21 +14751,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // // Note that the generic type created by this function has no symbol associated with it. The same // is true for each of the synthesized type parameters. - function createTupleTargetType(elementFlags: readonly ts.ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (ts.NamedTupleMember | ts.ParameterDeclaration)[] | undefined): ts.TupleType { + function createTupleTargetType(elementFlags: readonly ElementFlags[], readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType { const arity = elementFlags.length; - const minLength = ts.countWhere(elementFlags, f => !!(f & (ts.ElementFlags.Required | ts.ElementFlags.Variadic))); - let typeParameters: ts.TypeParameter[] | undefined; - const properties: ts.Symbol[] = []; - let combinedFlags: ts.ElementFlags = 0; + const minLength = countWhere(elementFlags, f => !!(f & (ElementFlags.Required | ElementFlags.Variadic))); + let typeParameters: TypeParameter[] | undefined; + const properties: Symbol[] = []; + let combinedFlags: ElementFlags = 0; if (arity) { typeParameters = new Array(arity); for (let i = 0; i < arity; i++) { const typeParameter = typeParameters[i] = createTypeParameter(); const flags = elementFlags[i]; combinedFlags |= flags; - if (!(combinedFlags & ts.ElementFlags.Variable)) { - const property = createSymbol(ts.SymbolFlags.Property | (flags & ts.ElementFlags.Optional ? ts.SymbolFlags.Optional : 0), - "" + i as ts.__String, readonly ? ts.CheckFlags.Readonly : 0); + if (!(combinedFlags & ElementFlags.Variable)) { + const property = createSymbol(SymbolFlags.Property | (flags & ElementFlags.Optional ? SymbolFlags.Optional : 0), + "" + i as __String, readonly ? CheckFlags.Readonly : 0); property.tupleLabelDeclaration = namedMemberDeclarations?.[i]; property.type = typeParameter; properties.push(property); @@ -14575,8 +14773,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } const fixedLength = properties.length; - const lengthSymbol = createSymbol(ts.SymbolFlags.Property, "length" as ts.__String, readonly ? ts.CheckFlags.Readonly : 0); - if (combinedFlags & ts.ElementFlags.Variable) { + const lengthSymbol = createSymbol(SymbolFlags.Property, "length" as __String, readonly ? CheckFlags.Readonly : 0); + if (combinedFlags & ElementFlags.Variable) { lengthSymbol.type = numberType; } else { @@ -14585,46 +14783,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { lengthSymbol.type = getUnionType(literalTypes); } properties.push(lengthSymbol); - const type = createObjectType(ts.ObjectFlags.Tuple | ts.ObjectFlags.Reference) as ts.TupleType & ts.InterfaceTypeWithDeclaredMembers; + const type = createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference) as TupleType & InterfaceTypeWithDeclaredMembers; type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; - type.instantiations = new ts.Map(); - type.instantiations.set(getTypeListId(type.typeParameters), type as ts.GenericType); - type.target = type as ts.GenericType; + type.instantiations = new Map(); + type.instantiations.set(getTypeListId(type.typeParameters), type as GenericType); + type.target = type as GenericType; type.resolvedTypeArguments = type.typeParameters; type.thisType = createTypeParameter(); type.thisType.isThisType = true; type.thisType.constraint = type; type.declaredProperties = properties; - type.declaredCallSignatures = ts.emptyArray; - type.declaredConstructSignatures = ts.emptyArray; - type.declaredIndexInfos = ts.emptyArray; + type.declaredCallSignatures = emptyArray; + type.declaredConstructSignatures = emptyArray; + type.declaredIndexInfos = emptyArray; type.elementFlags = elementFlags; type.minLength = minLength; type.fixedLength = fixedLength; - type.hasRestElement = !!(combinedFlags & ts.ElementFlags.Variable); + type.hasRestElement = !!(combinedFlags & ElementFlags.Variable); type.combinedFlags = combinedFlags; type.readonly = readonly; type.labeledElementDeclarations = namedMemberDeclarations; return type; } - function createNormalizedTypeReference(target: ts.GenericType, typeArguments: readonly ts.Type[] | undefined) { - return target.objectFlags & ts.ObjectFlags.Tuple ? createNormalizedTupleType(target as ts.TupleType, typeArguments!) : createTypeReference(target, typeArguments); + function createNormalizedTypeReference(target: GenericType, typeArguments: readonly Type[] | undefined) { + return target.objectFlags & ObjectFlags.Tuple ? createNormalizedTupleType(target as TupleType, typeArguments!) : createTypeReference(target, typeArguments); } - function createNormalizedTupleType(target: ts.TupleType, elementTypes: readonly ts.Type[]): ts.Type { - if (!(target.combinedFlags & ts.ElementFlags.NonRequired)) { + function createNormalizedTupleType(target: TupleType, elementTypes: readonly Type[]): Type { + if (!(target.combinedFlags & ElementFlags.NonRequired)) { // No need to normalize when we only have regular required elements return createTypeReference(target, elementTypes); } - if (target.combinedFlags & ts.ElementFlags.Variadic) { + if (target.combinedFlags & ElementFlags.Variadic) { // Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z] - const unionIndex = ts.findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ts.ElementFlags.Variadic && t.flags & (ts.TypeFlags.Never | ts.TypeFlags.Union))); + const unionIndex = findIndex(elementTypes, (t, i) => !!(target.elementFlags[i] & ElementFlags.Variadic && t.flags & (TypeFlags.Never | TypeFlags.Union))); if (unionIndex >= 0) { - return checkCrossProductUnion(ts.map(elementTypes, (t, i) => target.elementFlags[i] & ts.ElementFlags.Variadic ? t : unknownType)) ? - mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, ts.replaceElement(elementTypes, unionIndex, t))) : + return checkCrossProductUnion(map(elementTypes, (t, i) => target.elementFlags[i] & ElementFlags.Variadic ? t : unknownType)) ? + mapType(elementTypes[unionIndex], t => createNormalizedTupleType(target, replaceElement(elementTypes, unionIndex, t))) : errorType; } } @@ -14633,34 +14831,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // (1) Zero or more required elements, followed by zero or more optional elements, followed by zero or one rest element. // (2) Zero or more required elements, followed by a rest element, followed by zero or more required elements. // In either layout, zero or more generic variadic elements may be present at any location. - const expandedTypes: ts.Type[] = []; - const expandedFlags: ts.ElementFlags[] = []; - let expandedDeclarations: (ts.NamedTupleMember | ts.ParameterDeclaration)[] | undefined = []; + const expandedTypes: Type[] = []; + const expandedFlags: ElementFlags[] = []; + let expandedDeclarations: (NamedTupleMember | ParameterDeclaration)[] | undefined = []; let lastRequiredIndex = -1; let firstRestIndex = -1; let lastOptionalOrRestIndex = -1; for (let i = 0; i < elementTypes.length; i++) { const type = elementTypes[i]; const flags = target.elementFlags[i]; - if (flags & ts.ElementFlags.Variadic) { - if (type.flags & ts.TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type)) { + if (flags & ElementFlags.Variadic) { + if (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type)) { // Generic variadic elements stay as they are. - addElement(type, ts.ElementFlags.Variadic, target.labeledElementDeclarations?.[i]); + addElement(type, ElementFlags.Variadic, target.labeledElementDeclarations?.[i]); } else if (isTupleType(type)) { const elements = getTypeArguments(type); if (elements.length + expandedTypes.length >= 10_000) { - error(currentNode, ts.isPartOfTypeNode(currentNode!) - ? ts.Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent - : ts.Diagnostics.Expression_produces_a_tuple_type_that_is_too_large_to_represent); + error(currentNode, isPartOfTypeNode(currentNode!) + ? Diagnostics.Type_produces_a_tuple_type_that_is_too_large_to_represent + : Diagnostics.Expression_produces_a_tuple_type_that_is_too_large_to_represent); return errorType; } // Spread variadic elements with tuple types into the resulting tuple. - ts.forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n])); + forEach(elements, (t, n) => addElement(t, type.target.elementFlags[n], type.target.labeledElementDeclarations?.[n])); } else { // Treat everything else as an array type and create a rest element. - addElement(isArrayLikeType(type) && getIndexTypeOfType(type, numberType) || errorType, ts.ElementFlags.Rest, target.labeledElementDeclarations?.[i]); + addElement(isArrayLikeType(type) && getIndexTypeOfType(type, numberType) || errorType, ElementFlags.Rest, target.labeledElementDeclarations?.[i]); } } else { @@ -14670,12 +14868,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Turn optional elements preceding the last required element into required elements for (let i = 0; i < lastRequiredIndex; i++) { - if (expandedFlags[i] & ts.ElementFlags.Optional) expandedFlags[i] = ts.ElementFlags.Required; + if (expandedFlags[i] & ElementFlags.Optional) expandedFlags[i] = ElementFlags.Required; } if (firstRestIndex >= 0 && firstRestIndex < lastOptionalOrRestIndex) { // Turn elements between first rest and last optional/rest into a single rest element - expandedTypes[firstRestIndex] = getUnionType(ts.sameMap(expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1), - (t, i) => expandedFlags[firstRestIndex + i] & ts.ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t)); + expandedTypes[firstRestIndex] = getUnionType(sameMap(expandedTypes.slice(firstRestIndex, lastOptionalOrRestIndex + 1), + (t, i) => expandedFlags[firstRestIndex + i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t)); expandedTypes.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); expandedFlags.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); expandedDeclarations?.splice(firstRestIndex + 1, lastOptionalOrRestIndex - firstRestIndex); @@ -14685,17 +14883,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { expandedFlags.length ? createTypeReference(tupleTarget, expandedTypes) : tupleTarget; - function addElement(type: ts.Type, flags: ts.ElementFlags, declaration: ts.NamedTupleMember | ts.ParameterDeclaration | undefined) { - if (flags & ts.ElementFlags.Required) { + function addElement(type: Type, flags: ElementFlags, declaration: NamedTupleMember | ParameterDeclaration | undefined) { + if (flags & ElementFlags.Required) { lastRequiredIndex = expandedFlags.length; } - if (flags & ts.ElementFlags.Rest && firstRestIndex < 0) { + if (flags & ElementFlags.Rest && firstRestIndex < 0) { firstRestIndex = expandedFlags.length; } - if (flags & (ts.ElementFlags.Optional | ts.ElementFlags.Rest)) { + if (flags & (ElementFlags.Optional | ElementFlags.Rest)) { lastOptionalOrRestIndex = expandedFlags.length; } - expandedTypes.push(flags & ts.ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type); + expandedTypes.push(flags & ElementFlags.Optional ? addOptionality(type, /*isProperty*/ true) : type); expandedFlags.push(flags); if (expandedDeclarations && declaration) { expandedDeclarations.push(declaration); @@ -14706,44 +14904,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function sliceTupleType(type: ts.TupleTypeReference, index: number, endSkipCount = 0) { + function sliceTupleType(type: TupleTypeReference, index: number, endSkipCount = 0) { const target = type.target; const endIndex = getTypeReferenceArity(type) - endSkipCount; - return index > target.fixedLength ? getRestArrayTypeOfTupleType(type) || createTupleType(ts.emptyArray) : + return index > target.fixedLength ? getRestArrayTypeOfTupleType(type) || createTupleType(emptyArray) : createTupleType(getTypeArguments(type).slice(index, endIndex), target.elementFlags.slice(index, endIndex), /*readonly*/ false, target.labeledElementDeclarations && target.labeledElementDeclarations.slice(index, endIndex)); } - function getKnownKeysOfTupleType(type: ts.TupleTypeReference) { - return getUnionType(ts.append(ts.arrayOf(type.target.fixedLength, i => getStringLiteralType("" + i)), + function getKnownKeysOfTupleType(type: TupleTypeReference) { + return getUnionType(append(arrayOf(type.target.fixedLength, i => getStringLiteralType("" + i)), getIndexType(type.target.readonly ? globalReadonlyArrayType : globalArrayType))); } // Return count of starting consecutive tuple elements of the given kind(s) - function getStartElementCount(type: ts.TupleType, flags: ts.ElementFlags) { - const index = ts.findIndex(type.elementFlags, f => !(f & flags)); + function getStartElementCount(type: TupleType, flags: ElementFlags) { + const index = findIndex(type.elementFlags, f => !(f & flags)); return index >= 0 ? index : type.elementFlags.length; } // Return count of ending consecutive tuple elements of the given kind(s) - function getEndElementCount(type: ts.TupleType, flags: ts.ElementFlags) { - return type.elementFlags.length - ts.findLastIndex(type.elementFlags, f => !(f & flags)) - 1; + function getEndElementCount(type: TupleType, flags: ElementFlags) { + return type.elementFlags.length - findLastIndex(type.elementFlags, f => !(f & flags)) - 1; } - function getTypeFromOptionalTypeNode(node: ts.OptionalTypeNode): ts.Type { + function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type { return addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true); } - function getTypeId(type: ts.Type): ts.TypeId { + function getTypeId(type: Type): TypeId { return type.id; } - function containsType(types: readonly ts.Type[], type: ts.Type): boolean { - return ts.binarySearch(types, type, getTypeId, ts.compareValues) >= 0; + function containsType(types: readonly Type[], type: Type): boolean { + return binarySearch(types, type, getTypeId, compareValues) >= 0; } - function insertType(types: ts.Type[], type: ts.Type): boolean { - const index = ts.binarySearch(types, type, getTypeId, ts.compareValues); + function insertType(types: Type[], type: Type): boolean { + const index = binarySearch(types, type, getTypeId, compareValues); if (index < 0) { types.splice(~index, 0, type); return true; @@ -14751,22 +14949,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function addTypeToUnion(typeSet: ts.Type[], includes: ts.TypeFlags, type: ts.Type) { + function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) { const flags = type.flags; - if (flags & ts.TypeFlags.Union) { - return addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? ts.TypeFlags.Union : 0), (type as ts.UnionType).types); + if (flags & TypeFlags.Union) { + return addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types); } // We ignore 'never' types in unions - if (!(flags & ts.TypeFlags.Never)) { - includes |= flags & ts.TypeFlags.IncludesMask; - if (flags & ts.TypeFlags.Instantiable) includes |= ts.TypeFlags.IncludesInstantiable; - if (type === wildcardType) includes |= ts.TypeFlags.IncludesWildcard; - if (!strictNullChecks && flags & ts.TypeFlags.Nullable) { - if (!(ts.getObjectFlags(type) & ts.ObjectFlags.ContainsWideningType)) includes |= ts.TypeFlags.IncludesNonWideningType; + if (!(flags & TypeFlags.Never)) { + includes |= flags & TypeFlags.IncludesMask; + if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable; + if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; + if (!strictNullChecks && flags & TypeFlags.Nullable) { + if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType; } else { const len = typeSet.length; - const index = len && type.id > typeSet[len - 1].id ? ~len : ts.binarySearch(typeSet, type, getTypeId, ts.compareValues); + const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues); if (index < 0) { typeSet.splice(~index, 0, type); } @@ -14777,14 +14975,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Add the given types to the given type set. Order is preserved, duplicates are removed, // and nested types of the given kind are flattened into the set. - function addTypesToUnion(typeSet: ts.Type[], includes: ts.TypeFlags, types: readonly ts.Type[]): ts.TypeFlags { + function addTypesToUnion(typeSet: Type[], includes: TypeFlags, types: readonly Type[]): TypeFlags { for (const type of types) { includes = addTypeToUnion(typeSet, includes, type); } return includes; } - function removeSubtypes(types: ts.Type[], hasObjectTypes: boolean): ts.Type[] | undefined { + function removeSubtypes(types: Type[], hasObjectTypes: boolean): Type[] | undefined { // [] and [T] immediately reduce to [] and [T] respectively if (types.length < 2) { return types; @@ -14799,19 +14997,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We assume that redundant primitive types have already been removed from the types array and that there // are no any and unknown types in the array. Thus, the only possible supertypes for primitive types are empty // object types, and if none of those are present we can exclude primitive types from the subtype check. - const hasEmptyObject = hasObjectTypes && ts.some(types, t => !!(t.flags & ts.TypeFlags.Object) && !isGenericMappedType(t) && isEmptyResolvedType(resolveStructuredTypeMembers(t as ts.ObjectType))); + const hasEmptyObject = hasObjectTypes && some(types, t => !!(t.flags & TypeFlags.Object) && !isGenericMappedType(t) && isEmptyResolvedType(resolveStructuredTypeMembers(t as ObjectType))); const len = types.length; let i = len; let count = 0; while (i > 0) { i--; const source = types[i]; - if (hasEmptyObject || source.flags & ts.TypeFlags.StructuredOrInstantiable) { + if (hasEmptyObject || source.flags & TypeFlags.StructuredOrInstantiable) { // Find the first property with a unit type, if any. When constituents have a property by the same name // but of a different unit type, we can quickly disqualify them from subtype checks. This helps subtype // reduction of large discriminated union types. - const keyProperty = source.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.InstantiableNonPrimitive) ? - ts.find(getPropertiesOfType(source), p => isUnitType(getTypeOfSymbol(p))) : + const keyProperty = source.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive) ? + find(getPropertiesOfType(source), p => isUnitType(getTypeOfSymbol(p))) : undefined; const keyPropertyType = keyProperty && getRegularTypeOfLiteralType(getTypeOfSymbol(keyProperty)); for (const target of types) { @@ -14823,23 +15021,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // caps union types at 1000 unique object types. const estimatedCount = (count / (len - i)) * len; if (estimatedCount > 1000000) { - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "removeSubtypes_DepthLimit", { typeIds: types.map(t => t.id) }); - error(currentNode, ts.Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + tracing?.instant(tracing.Phase.CheckTypes, "removeSubtypes_DepthLimit", { typeIds: types.map(t => t.id) }); + error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); return undefined; } } count++; - if (keyProperty && target.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.InstantiableNonPrimitive)) { + if (keyProperty && target.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) { const t = getTypeOfPropertyOfType(target, keyProperty.escapedName); if (t && isUnitType(t) && getRegularTypeOfLiteralType(t) !== keyPropertyType) { continue; } } if (isTypeRelatedTo(source, target, strictSubtypeRelation) && ( - !(ts.getObjectFlags(getTargetType(source)) & ts.ObjectFlags.Class) || - !(ts.getObjectFlags(getTargetType(target)) & ts.ObjectFlags.Class) || + !(getObjectFlags(getTargetType(source)) & ObjectFlags.Class) || + !(getObjectFlags(getTargetType(target)) & ObjectFlags.Class) || isTypeDerivedFrom(source, target))) { - ts.orderedRemoveItemAt(types, i); + orderedRemoveItemAt(types, i); break; } } @@ -14850,59 +15048,59 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return types; } - function removeRedundantLiteralTypes(types: ts.Type[], includes: ts.TypeFlags, reduceVoidUndefined: boolean) { + function removeRedundantLiteralTypes(types: Type[], includes: TypeFlags, reduceVoidUndefined: boolean) { let i = types.length; while (i > 0) { i--; const t = types[i]; const flags = t.flags; const remove = - flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) && includes & ts.TypeFlags.String || - flags & ts.TypeFlags.NumberLiteral && includes & ts.TypeFlags.Number || - flags & ts.TypeFlags.BigIntLiteral && includes & ts.TypeFlags.BigInt || - flags & ts.TypeFlags.UniqueESSymbol && includes & ts.TypeFlags.ESSymbol || - reduceVoidUndefined && flags & ts.TypeFlags.Undefined && includes & ts.TypeFlags.Void || - isFreshLiteralType(t) && containsType(types, (t as ts.LiteralType).regularType); + flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && includes & TypeFlags.String || + flags & TypeFlags.NumberLiteral && includes & TypeFlags.Number || + flags & TypeFlags.BigIntLiteral && includes & TypeFlags.BigInt || + flags & TypeFlags.UniqueESSymbol && includes & TypeFlags.ESSymbol || + reduceVoidUndefined && flags & TypeFlags.Undefined && includes & TypeFlags.Void || + isFreshLiteralType(t) && containsType(types, (t as LiteralType).regularType); if (remove) { - ts.orderedRemoveItemAt(types, i); + orderedRemoveItemAt(types, i); } } } - function removeStringLiteralsMatchedByTemplateLiterals(types: ts.Type[]) { - const templates = ts.filter(types, isPatternLiteralType) as ts.TemplateLiteralType[]; + function removeStringLiteralsMatchedByTemplateLiterals(types: Type[]) { + const templates = filter(types, isPatternLiteralType) as TemplateLiteralType[]; if (templates.length) { let i = types.length; while (i > 0) { i--; const t = types[i]; - if (t.flags & ts.TypeFlags.StringLiteral && ts.some(templates, template => isTypeMatchedByTemplateLiteralType(t, template))) { - ts.orderedRemoveItemAt(types, i); + if (t.flags & TypeFlags.StringLiteral && some(templates, template => isTypeMatchedByTemplateLiteralType(t, template))) { + orderedRemoveItemAt(types, i); } } } } - function isNamedUnionType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.Union && (type.aliasSymbol || (type as ts.UnionType).origin)); + function isNamedUnionType(type: Type) { + return !!(type.flags & TypeFlags.Union && (type.aliasSymbol || (type as UnionType).origin)); } - function addNamedUnions(namedUnions: ts.Type[], types: readonly ts.Type[]) { + function addNamedUnions(namedUnions: Type[], types: readonly Type[]) { for (const t of types) { - if (t.flags & ts.TypeFlags.Union) { - const origin = (t as ts.UnionType).origin; - if (t.aliasSymbol || origin && !(origin.flags & ts.TypeFlags.Union)) { - ts.pushIfUnique(namedUnions, t); + if (t.flags & TypeFlags.Union) { + const origin = (t as UnionType).origin; + if (t.aliasSymbol || origin && !(origin.flags & TypeFlags.Union)) { + pushIfUnique(namedUnions, t); } - else if (origin && origin.flags & ts.TypeFlags.Union) { - addNamedUnions(namedUnions, (origin as ts.UnionType).types); + else if (origin && origin.flags & TypeFlags.Union) { + addNamedUnions(namedUnions, (origin as UnionType).types); } } } } - function createOriginUnionOrIntersectionType(flags: ts.TypeFlags, types: ts.Type[]) { - const result = createOriginType(flags) as ts.UnionOrIntersectionType; + function createOriginUnionOrIntersectionType(flags: TypeFlags, types: Type[]) { + const result = createOriginType(flags) as UnionOrIntersectionType; result.types = types; return result; } @@ -14914,51 +15112,51 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // expression constructs such as array literals and the || and ?: operators). Named types can // circularly reference themselves and therefore cannot be subtype reduced during their declaration. // For example, "type Item = string | (() => Item" is a named type that circularly references itself. - function getUnionType(types: readonly ts.Type[], unionReduction: ts.UnionReduction = ts.UnionReduction.Literal, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[], origin?: ts.Type): ts.Type { + function getUnionType(types: readonly Type[], unionReduction: UnionReduction = UnionReduction.Literal, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type { if (types.length === 0) { return neverType; } if (types.length === 1) { return types[0]; } - let typeSet: ts.Type[] | undefined = []; + let typeSet: Type[] | undefined = []; const includes = addTypesToUnion(typeSet, 0, types); - if (unionReduction !== ts.UnionReduction.None) { - if (includes & ts.TypeFlags.AnyOrUnknown) { - return includes & ts.TypeFlags.Any ? - includes & ts.TypeFlags.IncludesWildcard ? wildcardType : anyType : - includes & ts.TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType : nonNullUnknownType; - } - if (exactOptionalPropertyTypes && includes & ts.TypeFlags.Undefined) { - const missingIndex = ts.binarySearch(typeSet, missingType, getTypeId, ts.compareValues); + if (unionReduction !== UnionReduction.None) { + if (includes & TypeFlags.AnyOrUnknown) { + return includes & TypeFlags.Any ? + includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : + includes & TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType : nonNullUnknownType; + } + if (exactOptionalPropertyTypes && includes & TypeFlags.Undefined) { + const missingIndex = binarySearch(typeSet, missingType, getTypeId, compareValues); if (missingIndex >= 0 && containsType(typeSet, undefinedType)) { - ts.orderedRemoveItemAt(typeSet, missingIndex); + orderedRemoveItemAt(typeSet, missingIndex); } } - if (includes & (ts.TypeFlags.Literal | ts.TypeFlags.UniqueESSymbol | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) || includes & ts.TypeFlags.Void && includes & ts.TypeFlags.Undefined) { - removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & ts.UnionReduction.Subtype)); + if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) { + removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype)); } - if (includes & ts.TypeFlags.StringLiteral && includes & ts.TypeFlags.TemplateLiteral) { + if (includes & TypeFlags.StringLiteral && includes & TypeFlags.TemplateLiteral) { removeStringLiteralsMatchedByTemplateLiterals(typeSet); } - if (unionReduction === ts.UnionReduction.Subtype) { - typeSet = removeSubtypes(typeSet, !!(includes & ts.TypeFlags.Object)); + if (unionReduction === UnionReduction.Subtype) { + typeSet = removeSubtypes(typeSet, !!(includes & TypeFlags.Object)); if (!typeSet) { return errorType; } } if (typeSet.length === 0) { - return includes & ts.TypeFlags.Null ? includes & ts.TypeFlags.IncludesNonWideningType ? nullType : nullWideningType : - includes & ts.TypeFlags.Undefined ? includes & ts.TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType : + return includes & TypeFlags.Null ? includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType : + includes & TypeFlags.Undefined ? includes & TypeFlags.IncludesNonWideningType ? undefinedType : undefinedWideningType : neverType; } } - if (!origin && includes & ts.TypeFlags.Union) { - const namedUnions: ts.Type[] = []; + if (!origin && includes & TypeFlags.Union) { + const namedUnions: Type[] = []; addNamedUnions(namedUnions, types); - const reducedTypes: ts.Type[] = []; + const reducedTypes: Type[] = []; for (const t of typeSet) { - if (!ts.some(namedUnions, union => containsType((union as ts.UnionType).types, t))) { + if (!some(namedUnions, union => containsType((union as UnionType).types, t))) { reducedTypes.push(t); } } @@ -14967,26 +15165,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // We create a denormalized origin type only when the union was created from one or more named unions // (unions with alias symbols or origins) and when there is no overlap between those named unions. - const namedTypesCount = ts.reduceLeft(namedUnions, (sum, union) => sum + (union as ts.UnionType).types.length, 0); + const namedTypesCount = reduceLeft(namedUnions, (sum, union) => sum + (union as UnionType).types.length, 0); if (namedTypesCount + reducedTypes.length === typeSet.length) { for (const t of namedUnions) { insertType(reducedTypes, t); } - origin = createOriginUnionOrIntersectionType(ts.TypeFlags.Union, reducedTypes); + origin = createOriginUnionOrIntersectionType(TypeFlags.Union, reducedTypes); } } - const objectFlags = (includes & ts.TypeFlags.NotPrimitiveUnion ? 0 : ts.ObjectFlags.PrimitiveUnion) | - (includes & ts.TypeFlags.Intersection ? ts.ObjectFlags.ContainsIntersections : 0); + const objectFlags = (includes & TypeFlags.NotPrimitiveUnion ? 0 : ObjectFlags.PrimitiveUnion) | + (includes & TypeFlags.Intersection ? ObjectFlags.ContainsIntersections : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } - function getUnionOrIntersectionTypePredicate(signatures: readonly ts.Signature[], kind: ts.TypeFlags | undefined): ts.TypePredicate | undefined { - let first: ts.TypePredicate | undefined; - const types: ts.Type[] = []; + function getUnionOrIntersectionTypePredicate(signatures: readonly Signature[], kind: TypeFlags | undefined): TypePredicate | undefined { + let first: TypePredicate | undefined; + const types: Type[] = []; for (const sig of signatures) { const pred = getTypePredicateOfSignature(sig); - if (!pred || pred.kind === ts.TypePredicateKind.AssertsThis || pred.kind === ts.TypePredicateKind.AssertsIdentifier) { - if (kind !== ts.TypeFlags.Intersection) { + if (!pred || pred.kind === TypePredicateKind.AssertsThis || pred.kind === TypePredicateKind.AssertsIdentifier) { + if (kind !== TypeFlags.Intersection) { continue; } else { @@ -15013,12 +15211,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createTypePredicate(first.kind, first.parameterName, first.parameterIndex, compositeType); } - function typePredicateKindsMatch(a: ts.TypePredicate, b: ts.TypePredicate): boolean { + function typePredicateKindsMatch(a: TypePredicate, b: TypePredicate): boolean { return a.kind === b.kind && a.parameterIndex === b.parameterIndex; } // This function assumes the constituent type list is sorted and deduplicated. - function getUnionTypeFromSortedList(types: ts.Type[], objectFlags: ts.ObjectFlags, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[], origin?: ts.Type): ts.Type { + function getUnionTypeFromSortedList(types: Type[], objectFlags: ObjectFlags, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], origin?: Type): Type { if (types.length === 0) { return neverType; } @@ -15026,94 +15224,94 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return types[0]; } const typeKey = !origin ? getTypeListId(types) : - origin.flags & ts.TypeFlags.Union ? `|${getTypeListId((origin as ts.UnionType).types)}` : - origin.flags & ts.TypeFlags.Intersection ? `&${getTypeListId((origin as ts.IntersectionType).types)}` : - `#${(origin as ts.IndexType).type.id}|${getTypeListId(types)}`; // origin type id alone is insufficient, as `keyof x` may resolve to multiple WIP values while `x` is still resolving + origin.flags & TypeFlags.Union ? `|${getTypeListId((origin as UnionType).types)}` : + origin.flags & TypeFlags.Intersection ? `&${getTypeListId((origin as IntersectionType).types)}` : + `#${(origin as IndexType).type.id}|${getTypeListId(types)}`; // origin type id alone is insufficient, as `keyof x` may resolve to multiple WIP values while `x` is still resolving const id = typeKey + getAliasId(aliasSymbol, aliasTypeArguments); let type = unionTypes.get(id); if (!type) { - type = createType(ts.TypeFlags.Union) as ts.UnionType; - type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ ts.TypeFlags.Nullable); + type = createType(TypeFlags.Union) as UnionType; + type.objectFlags = objectFlags | getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); type.types = types; type.origin = origin; type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = aliasTypeArguments; - if (types.length === 2 && types[0].flags & ts.TypeFlags.BooleanLiteral && types[1].flags & ts.TypeFlags.BooleanLiteral) { - type.flags |= ts.TypeFlags.Boolean; - (type as ts.UnionType & ts.IntrinsicType).intrinsicName = "boolean"; + if (types.length === 2 && types[0].flags & TypeFlags.BooleanLiteral && types[1].flags & TypeFlags.BooleanLiteral) { + type.flags |= TypeFlags.Boolean; + (type as UnionType & IntrinsicType).intrinsicName = "boolean"; } unionTypes.set(id, type); } return type; } - function getTypeFromUnionTypeNode(node: ts.UnionTypeNode): ts.Type { + function getTypeFromUnionTypeNode(node: UnionTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { const aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getUnionType(ts.map(node.types, getTypeFromTypeNode), ts.UnionReduction.Literal, + links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), UnionReduction.Literal, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); } return links.resolvedType; } - function addTypeToIntersection(typeSet: ts.ESMap, includes: ts.TypeFlags, type: ts.Type) { + function addTypeToIntersection(typeSet: ESMap, includes: TypeFlags, type: Type) { const flags = type.flags; - if (flags & ts.TypeFlags.Intersection) { - return addTypesToIntersection(typeSet, includes, (type as ts.IntersectionType).types); + if (flags & TypeFlags.Intersection) { + return addTypesToIntersection(typeSet, includes, (type as IntersectionType).types); } if (isEmptyAnonymousObjectType(type)) { - if (!(includes & ts.TypeFlags.IncludesEmptyObject)) { - includes |= ts.TypeFlags.IncludesEmptyObject; + if (!(includes & TypeFlags.IncludesEmptyObject)) { + includes |= TypeFlags.IncludesEmptyObject; typeSet.set(type.id.toString(), type); } } else { - if (flags & ts.TypeFlags.AnyOrUnknown) { - if (type === wildcardType) includes |= ts.TypeFlags.IncludesWildcard; + if (flags & TypeFlags.AnyOrUnknown) { + if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; } - else if (strictNullChecks || !(flags & ts.TypeFlags.Nullable)) { + else if (strictNullChecks || !(flags & TypeFlags.Nullable)) { if (exactOptionalPropertyTypes && type === missingType) { - includes |= ts.TypeFlags.IncludesMissingType; + includes |= TypeFlags.IncludesMissingType; type = undefinedType; } if (!typeSet.has(type.id.toString())) { - if (type.flags & ts.TypeFlags.Unit && includes & ts.TypeFlags.Unit) { + if (type.flags & TypeFlags.Unit && includes & TypeFlags.Unit) { // We have seen two distinct unit types which means we should reduce to an // empty intersection. Adding TypeFlags.NonPrimitive causes that to happen. - includes |= ts.TypeFlags.NonPrimitive; + includes |= TypeFlags.NonPrimitive; } typeSet.set(type.id.toString(), type); } } - includes |= flags & ts.TypeFlags.IncludesMask; + includes |= flags & TypeFlags.IncludesMask; } return includes; } // Add the given types to the given type set. Order is preserved, freshness is removed from literal // types, duplicates are removed, and nested types of the given kind are flattened into the set. - function addTypesToIntersection(typeSet: ts.ESMap, includes: ts.TypeFlags, types: readonly ts.Type[]) { + function addTypesToIntersection(typeSet: ESMap, includes: TypeFlags, types: readonly Type[]) { for (const type of types) { includes = addTypeToIntersection(typeSet, includes, getRegularTypeOfLiteralType(type)); } return includes; } - function removeRedundantSupertypes(types: ts.Type[], includes: ts.TypeFlags) { + function removeRedundantSupertypes(types: Type[], includes: TypeFlags) { let i = types.length; while (i > 0) { i--; const t = types[i]; const remove = - t.flags & ts.TypeFlags.String && includes & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) || - t.flags & ts.TypeFlags.Number && includes & ts.TypeFlags.NumberLiteral || - t.flags & ts.TypeFlags.BigInt && includes & ts.TypeFlags.BigIntLiteral || - t.flags & ts.TypeFlags.ESSymbol && includes & ts.TypeFlags.UniqueESSymbol || - t.flags & ts.TypeFlags.Void && includes & ts.TypeFlags.Undefined || - isEmptyAnonymousObjectType(t) && includes & ts.TypeFlags.DefinitelyNonNullable; + t.flags & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || + t.flags & TypeFlags.Number && includes & TypeFlags.NumberLiteral || + t.flags & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral || + t.flags & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol || + t.flags & TypeFlags.Void && includes & TypeFlags.Undefined || + isEmptyAnonymousObjectType(t) && includes & TypeFlags.DefinitelyNonNullable; if (remove) { - ts.orderedRemoveItemAt(types, i); + orderedRemoveItemAt(types, i); } } } @@ -15121,13 +15319,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Check that the given type has a match in every union. A given type is matched by // an identical type, and a literal type is additionally matched by its corresponding // primitive type. - function eachUnionContains(unionTypes: ts.UnionType[], type: ts.Type) { + function eachUnionContains(unionTypes: UnionType[], type: Type) { for (const u of unionTypes) { if (!containsType(u.types, type)) { - const primitive = type.flags & ts.TypeFlags.StringLiteral ? stringType : - type.flags & ts.TypeFlags.NumberLiteral ? numberType : - type.flags & ts.TypeFlags.BigIntLiteral ? bigintType : - type.flags & ts.TypeFlags.UniqueESSymbol ? esSymbolType : + const primitive = type.flags & TypeFlags.StringLiteral ? stringType : + type.flags & TypeFlags.NumberLiteral ? numberType : + type.flags & TypeFlags.BigIntLiteral ? bigintType : + type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : undefined; if (!primitive || !containsType(u.types, primitive)) { return false; @@ -15140,17 +15338,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Returns `true` if the intersection of the template literals and string literals is the empty set, eg `get${string}` & "setX", and should reduce to `never` */ - function extractRedundantTemplateLiterals(types: ts.Type[]): boolean { + function extractRedundantTemplateLiterals(types: Type[]): boolean { let i = types.length; - const literals = ts.filter(types, t => !!(t.flags & ts.TypeFlags.StringLiteral)); + const literals = filter(types, t => !!(t.flags & TypeFlags.StringLiteral)); while (i > 0) { i--; const t = types[i]; - if (!(t.flags & ts.TypeFlags.TemplateLiteral)) continue; + if (!(t.flags & TypeFlags.TemplateLiteral)) continue; for (const t2 of literals) { if (isTypeSubtypeOf(t2, t)) { // eg, ``get${T}` & "getX"` is just `"getX"` - ts.orderedRemoveItemAt(types, i); + orderedRemoveItemAt(types, i); break; } else if (isPatternLiteralType(t)) { @@ -15161,11 +15359,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function eachIsUnionContaining(types: ts.Type[], flag: ts.TypeFlags) { - return ts.every(types, t => !!(t.flags & ts.TypeFlags.Union) && ts.some((t as ts.UnionType).types, tt => !!(tt.flags & flag))); + function eachIsUnionContaining(types: Type[], flag: TypeFlags) { + return every(types, t => !!(t.flags & TypeFlags.Union) && some((t as UnionType).types, tt => !!(tt.flags & flag))); } - function removeFromEach(types: ts.Type[], flag: ts.TypeFlags) { + function removeFromEach(types: Type[], flag: TypeFlags) { for (let i = 0; i < types.length; i++) { types[i] = filterType(types[i], t => !(t.flags & flag)); } @@ -15174,9 +15372,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the given list of types contains more than one union of primitive types, replace the // first with a union containing an intersection of those primitive types, then remove the // other unions and return true. Otherwise, do nothing and return false. - function intersectUnionsOfPrimitiveTypes(types: ts.Type[]) { - let unionTypes: ts.UnionType[] | undefined; - const index = ts.findIndex(types, t => !!(ts.getObjectFlags(t) & ts.ObjectFlags.PrimitiveUnion)); + function intersectUnionsOfPrimitiveTypes(types: Type[]) { + let unionTypes: UnionType[] | undefined; + const index = findIndex(types, t => !!(getObjectFlags(t) & ObjectFlags.PrimitiveUnion)); if (index < 0) { return false; } @@ -15185,9 +15383,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the unionTypes array. while (i < types.length) { const t = types[i]; - if (ts.getObjectFlags(t) & ts.ObjectFlags.PrimitiveUnion) { - (unionTypes || (unionTypes = [types[index] as ts.UnionType])).push(t as ts.UnionType); - ts.orderedRemoveItemAt(types, i); + if (getObjectFlags(t) & ObjectFlags.PrimitiveUnion) { + (unionTypes || (unionTypes = [types[index] as UnionType])).push(t as UnionType); + orderedRemoveItemAt(types, i); } else { i++; @@ -15200,8 +15398,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We have more than one union of primitive types, now intersect them. For each // type in each union we check if the type is matched in every union and if so // we include it in the result. - const checked: ts.Type[] = []; - const result: ts.Type[] = []; + const checked: Type[] = []; + const result: Type[] = []; for (const u of unionTypes) { for (const t of u.types) { if (insertType(checked, t)) { @@ -15212,13 +15410,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } // Finally replace the first union with the result - types[index] = getUnionTypeFromSortedList(result, ts.ObjectFlags.PrimitiveUnion); + types[index] = getUnionTypeFromSortedList(result, ObjectFlags.PrimitiveUnion); return true; } - function createIntersectionType(types: ts.Type[], aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]) { - const result = createType(ts.TypeFlags.Intersection) as ts.IntersectionType; - result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ ts.TypeFlags.Nullable); + function createIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) { + const result = createType(TypeFlags.Intersection) as IntersectionType; + result.objectFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable); result.types = types; result.aliasSymbol = aliasSymbol; result.aliasTypeArguments = aliasTypeArguments; @@ -15235,10 +15433,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // a type alias of the form "type List = T & { next: List }" cannot be reduced during its declaration. // Also, unlike union types, the order of the constituent types is preserved in order that overload resolution // for intersections of types with signatures can be deterministic. - function getIntersectionType(types: readonly ts.Type[], aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[], noSupertypeReduction?: boolean): ts.Type { - const typeMembershipMap: ts.ESMap = new ts.Map(); + function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type { + const typeMembershipMap: ESMap = new Map(); const includes = addTypesToIntersection(typeMembershipMap, 0, types); - const typeSet: ts.Type[] = ts.arrayFrom(typeMembershipMap.values()); + const typeSet: Type[] = arrayFrom(typeMembershipMap.values()); // An intersection type is considered empty if it contains // the type never, or // more than one unit type or, @@ -15248,36 +15446,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // a symbol-like type and a type known to be non-symbol-like, or // a void-like type and a type known to be non-void-like, or // a non-primitive type and a type known to be primitive. - if (includes & ts.TypeFlags.Never) { - return ts.contains(typeSet, silentNeverType) ? silentNeverType : neverType; - } - if (strictNullChecks && includes & ts.TypeFlags.Nullable && includes & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive | ts.TypeFlags.IncludesEmptyObject) || - includes & ts.TypeFlags.NonPrimitive && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.NonPrimitive) || - includes & ts.TypeFlags.StringLike && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.StringLike) || - includes & ts.TypeFlags.NumberLike && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.NumberLike) || - includes & ts.TypeFlags.BigIntLike && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.BigIntLike) || - includes & ts.TypeFlags.ESSymbolLike && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.ESSymbolLike) || - includes & ts.TypeFlags.VoidLike && includes & (ts.TypeFlags.DisjointDomains & ~ts.TypeFlags.VoidLike)) { + if (includes & TypeFlags.Never) { + return contains(typeSet, silentNeverType) ? silentNeverType : neverType; + } + if (strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) || + includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) || + includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) || + includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) || + includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) || + includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) || + includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike)) { return neverType; } - if (includes & ts.TypeFlags.TemplateLiteral && includes & ts.TypeFlags.StringLiteral && extractRedundantTemplateLiterals(typeSet)) { + if (includes & TypeFlags.TemplateLiteral && includes & TypeFlags.StringLiteral && extractRedundantTemplateLiterals(typeSet)) { return neverType; } - if (includes & ts.TypeFlags.Any) { - return includes & ts.TypeFlags.IncludesWildcard ? wildcardType : anyType; + if (includes & TypeFlags.Any) { + return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType; } - if (!strictNullChecks && includes & ts.TypeFlags.Nullable) { - return includes & ts.TypeFlags.IncludesEmptyObject ? neverType : includes & ts.TypeFlags.Undefined ? undefinedType : nullType; + if (!strictNullChecks && includes & TypeFlags.Nullable) { + return includes & TypeFlags.IncludesEmptyObject ? neverType : includes & TypeFlags.Undefined ? undefinedType : nullType; } - if (includes & ts.TypeFlags.String && includes & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) || - includes & ts.TypeFlags.Number && includes & ts.TypeFlags.NumberLiteral || - includes & ts.TypeFlags.BigInt && includes & ts.TypeFlags.BigIntLiteral || - includes & ts.TypeFlags.ESSymbol && includes & ts.TypeFlags.UniqueESSymbol || - includes & ts.TypeFlags.Void && includes & ts.TypeFlags.Undefined || - includes & ts.TypeFlags.IncludesEmptyObject && includes & ts.TypeFlags.DefinitelyNonNullable) { + if (includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || + includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral || + includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral || + includes & TypeFlags.ESSymbol && includes & TypeFlags.UniqueESSymbol || + includes & TypeFlags.Void && includes & TypeFlags.Undefined || + includes & TypeFlags.IncludesEmptyObject && includes & TypeFlags.DefinitelyNonNullable) { if (!noSupertypeReduction) removeRedundantSupertypes(typeSet, includes); } - if (includes & ts.TypeFlags.IncludesMissingType) { + if (includes & TypeFlags.IncludesMissingType) { typeSet[typeSet.indexOf(undefinedType)] = missingType; } if (typeSet.length === 0) { @@ -15289,21 +15487,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const id = getTypeListId(typeSet) + getAliasId(aliasSymbol, aliasTypeArguments); let result = intersectionTypes.get(id); if (!result) { - if (includes & ts.TypeFlags.Union) { + if (includes & TypeFlags.Union) { if (intersectUnionsOfPrimitiveTypes(typeSet)) { // When the intersection creates a reduced set (which might mean that *all* union types have // disappeared), we restart the operation to get a new set of combined flags. Once we have // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, ts.TypeFlags.Undefined)) { - const undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, t => containsType((t as ts.UnionType).types, missingType)) ? missingType : undefinedType; - removeFromEach(typeSet, ts.TypeFlags.Undefined); - result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + else if (eachIsUnionContaining(typeSet, TypeFlags.Undefined)) { + const undefinedOrMissingType = exactOptionalPropertyTypes && some(typeSet, t => containsType((t as UnionType).types, missingType)) ? missingType : undefinedType; + removeFromEach(typeSet, TypeFlags.Undefined); + result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, ts.TypeFlags.Null)) { - removeFromEach(typeSet, ts.TypeFlags.Null); - result = getUnionType([getIntersectionType(typeSet), nullType], ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + else if (eachIsUnionContaining(typeSet, TypeFlags.Null)) { + removeFromEach(typeSet, TypeFlags.Null); + result = getUnionType([getIntersectionType(typeSet), nullType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } else { // We are attempting to construct a type of the form X & (A | B) & (C | D). Transform this into a type of @@ -15316,8 +15514,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We attach a denormalized origin type when at least one constituent of the cross-product union is an // intersection (i.e. when the intersection didn't just reduce one or more unions to smaller unions) and // the denormalized origin has fewer constituents than the union itself. - const origin = ts.some(constituents, t => !!(t.flags & ts.TypeFlags.Intersection)) && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) ? createOriginUnionOrIntersectionType(ts.TypeFlags.Intersection, typeSet) : undefined; - result = getUnionType(constituents, ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin); + const origin = some(constituents, t => !!(t.flags & TypeFlags.Intersection)) && getConstituentCountOfTypes(constituents) > getConstituentCountOfTypes(typeSet) ? createOriginUnionOrIntersectionType(TypeFlags.Intersection, typeSet) : undefined; + result = getUnionType(constituents, UnionReduction.Literal, aliasSymbol, aliasTypeArguments, origin); } } else { @@ -15328,75 +15526,75 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getCrossProductUnionSize(types: readonly ts.Type[]) { - return ts.reduceLeft(types, (n, t) => t.flags & ts.TypeFlags.Union ? n * (t as ts.UnionType).types.length : t.flags & ts.TypeFlags.Never ? 0 : n, 1); + function getCrossProductUnionSize(types: readonly Type[]) { + return reduceLeft(types, (n, t) => t.flags & TypeFlags.Union ? n * (t as UnionType).types.length : t.flags & TypeFlags.Never ? 0 : n, 1); } - function checkCrossProductUnion(types: readonly ts.Type[]) { + function checkCrossProductUnion(types: readonly Type[]) { const size = getCrossProductUnionSize(types); if (size >= 100000) { - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "checkCrossProductUnion_DepthLimit", { typeIds: types.map(t => t.id), size }); - error(currentNode, ts.Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); + tracing?.instant(tracing.Phase.CheckTypes, "checkCrossProductUnion_DepthLimit", { typeIds: types.map(t => t.id), size }); + error(currentNode, Diagnostics.Expression_produces_a_union_type_that_is_too_complex_to_represent); return false; } return true; } - function getCrossProductIntersections(types: readonly ts.Type[]) { + function getCrossProductIntersections(types: readonly Type[]) { const count = getCrossProductUnionSize(types); - const intersections: ts.Type[] = []; + const intersections: Type[] = []; for (let i = 0; i < count; i++) { const constituents = types.slice(); let n = i; for (let j = types.length - 1; j >= 0; j--) { - if (types[j].flags & ts.TypeFlags.Union) { - const sourceTypes = (types[j] as ts.UnionType).types; + if (types[j].flags & TypeFlags.Union) { + const sourceTypes = (types[j] as UnionType).types; const length = sourceTypes.length; constituents[j] = sourceTypes[n % length]; n = Math.floor(n / length); } } const t = getIntersectionType(constituents); - if (!(t.flags & ts.TypeFlags.Never)) intersections.push(t); + if (!(t.flags & TypeFlags.Never)) intersections.push(t); } return intersections; } - function getConstituentCount(type: ts.Type): number { - return !(type.flags & ts.TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 : - type.flags & ts.TypeFlags.Union && (type as ts.UnionType).origin ? getConstituentCount((type as ts.UnionType).origin!) : - getConstituentCountOfTypes((type as ts.UnionOrIntersectionType).types); + function getConstituentCount(type: Type): number { + return !(type.flags & TypeFlags.UnionOrIntersection) || type.aliasSymbol ? 1 : + type.flags & TypeFlags.Union && (type as UnionType).origin ? getConstituentCount((type as UnionType).origin!) : + getConstituentCountOfTypes((type as UnionOrIntersectionType).types); } - function getConstituentCountOfTypes(types: ts.Type[]): number { - return ts.reduceLeft(types, (n, t) => n + getConstituentCount(t), 0); + function getConstituentCountOfTypes(types: Type[]): number { + return reduceLeft(types, (n, t) => n + getConstituentCount(t), 0); } - function getTypeFromIntersectionTypeNode(node: ts.IntersectionTypeNode): ts.Type { + function getTypeFromIntersectionTypeNode(node: IntersectionTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { const aliasSymbol = getAliasSymbolForTypeNode(node); - const types = ts.map(node.types, getTypeFromTypeNode); - const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType; + const types = map(node.types, getTypeFromTypeNode); + const noSupertypeReduction = types.length === 2 && !!(types[0].flags & (TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) && types[1] === emptyTypeLiteralType; links.resolvedType = getIntersectionType(types, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol), noSupertypeReduction); } return links.resolvedType; } - function createIndexType(type: ts.InstantiableType | ts.UnionOrIntersectionType, stringsOnly: boolean) { - const result = createType(ts.TypeFlags.Index) as ts.IndexType; + function createIndexType(type: InstantiableType | UnionOrIntersectionType, stringsOnly: boolean) { + const result = createType(TypeFlags.Index) as IndexType; result.type = type; result.stringsOnly = stringsOnly; return result; } - function createOriginIndexType(type: ts.InstantiableType | ts.UnionOrIntersectionType) { - const result = createOriginType(ts.TypeFlags.Index) as ts.IndexType; + function createOriginIndexType(type: InstantiableType | UnionOrIntersectionType) { + const result = createOriginType(TypeFlags.Index) as IndexType; result.type = type; return result; } - function getIndexTypeForGenericType(type: ts.InstantiableType | ts.UnionOrIntersectionType, stringsOnly: boolean) { + function getIndexTypeForGenericType(type: InstantiableType | UnionOrIntersectionType, stringsOnly: boolean) { return stringsOnly ? type.resolvedStringIndexType || (type.resolvedStringIndexType = createIndexType(type, /*stringsOnly*/ true)) : type.resolvedIndexType || (type.resolvedIndexType = createIndexType(type, /*stringsOnly*/ false)); @@ -15409,15 +15607,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * reduction in the constraintType) when possible. * @param noIndexSignatures Indicates if _string_ index signatures should be elided. (other index signatures are always reported) */ - function getIndexTypeForMappedType(type: ts.MappedType, stringsOnly: boolean, noIndexSignatures: boolean | undefined) { + function getIndexTypeForMappedType(type: MappedType, stringsOnly: boolean, noIndexSignatures: boolean | undefined) { const typeParameter = getTypeParameterFromMappedType(type); const constraintType = getConstraintTypeFromMappedType(type); - const nameType = getNameTypeFromMappedType(type.target as ts.MappedType || type); + const nameType = getNameTypeFromMappedType(type.target as MappedType || type); if (!nameType && !noIndexSignatures) { // no mapping and no filtering required, just quickly bail to returning the constraint in the common case return constraintType; } - const keyTypes: ts.Type[] = []; + const keyTypes: Type[] = []; if (isMappedTypeWithKeyofConstraintDeclaration(type)) { // We have a { [P in keyof T]: X } @@ -15426,7 +15624,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // so we only eagerly manifest the keys if the constraint is nongeneric if (!isGenericIndexType(constraintType)) { const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' - forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, ts.TypeFlags.StringOrNumberLiteralOrUnique, stringsOnly, addMemberForKeyType); + forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType(modifiersType, TypeFlags.StringOrNumberLiteralOrUnique, stringsOnly, addMemberForKeyType); } else { // we have a generic index and a homomorphic mapping (but a distributive key remapping) - we need to defer the whole `keyof whatever` for later @@ -15442,13 +15640,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // we had to pick apart the constraintType to potentially map/filter it - compare the final resulting list with the original constraintType, // so we can return the union that preserves aliases/origin data if possible - const result = noIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (ts.TypeFlags.Any | ts.TypeFlags.String))) : getUnionType(keyTypes); - if (result.flags & ts.TypeFlags.Union && constraintType.flags & ts.TypeFlags.Union && getTypeListId((result as ts.UnionType).types) === getTypeListId((constraintType as ts.UnionType).types)){ + const result = noIndexSignatures ? filterType(getUnionType(keyTypes), t => !(t.flags & (TypeFlags.Any | TypeFlags.String))) : getUnionType(keyTypes); + if (result.flags & TypeFlags.Union && constraintType.flags & TypeFlags.Union && getTypeListId((result as UnionType).types) === getTypeListId((constraintType as UnionType).types)){ return constraintType; } return result; - function addMemberForKeyType(keyType: ts.Type) { + function addMemberForKeyType(keyType: Type) { const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; // `keyof` currently always returns `string | number` for concrete `string` index signatures - the below ternary keeps that behavior for mapped types // See `getLiteralTypeFromProperties` where there's a similar ternary to cause the same behavior. @@ -15461,35 +15659,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // want to perform the reduction when the name type of a mapped type is distributive with respect to the type variable // introduced by the 'in' clause of the mapped type. Note that non-generic types are considered to be distributive because // they're the same type regardless of what's being distributed over. - function hasDistributiveNameType(mappedType: ts.MappedType) { + function hasDistributiveNameType(mappedType: MappedType) { const typeVariable = getTypeParameterFromMappedType(mappedType); return isDistributive(getNameTypeFromMappedType(mappedType) || typeVariable); - function isDistributive(type: ts.Type): boolean { - return type.flags & (ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Primitive | ts.TypeFlags.Never | ts.TypeFlags.TypeParameter | ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive) ? true : - type.flags & ts.TypeFlags.Conditional ? (type as ts.ConditionalType).root.isDistributive && (type as ts.ConditionalType).checkType === typeVariable : - type.flags & (ts.TypeFlags.UnionOrIntersection | ts.TypeFlags.TemplateLiteral) ? ts.every((type as ts.UnionOrIntersectionType | ts.TemplateLiteralType).types, isDistributive) : - type.flags & ts.TypeFlags.IndexedAccess ? isDistributive((type as ts.IndexedAccessType).objectType) && isDistributive((type as ts.IndexedAccessType).indexType) : - type.flags & ts.TypeFlags.Substitution ? isDistributive((type as ts.SubstitutionType).baseType) && isDistributive((type as ts.SubstitutionType).constraint): - type.flags & ts.TypeFlags.StringMapping ? isDistributive((type as ts.StringMappingType).type) : + function isDistributive(type: Type): boolean { + return type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Primitive | TypeFlags.Never | TypeFlags.TypeParameter | TypeFlags.Object | TypeFlags.NonPrimitive) ? true : + type.flags & TypeFlags.Conditional ? (type as ConditionalType).root.isDistributive && (type as ConditionalType).checkType === typeVariable : + type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.TemplateLiteral) ? every((type as UnionOrIntersectionType | TemplateLiteralType).types, isDistributive) : + type.flags & TypeFlags.IndexedAccess ? isDistributive((type as IndexedAccessType).objectType) && isDistributive((type as IndexedAccessType).indexType) : + type.flags & TypeFlags.Substitution ? isDistributive((type as SubstitutionType).baseType) && isDistributive((type as SubstitutionType).constraint): + type.flags & TypeFlags.StringMapping ? isDistributive((type as StringMappingType).type) : false; } } - function getLiteralTypeFromPropertyName(name: ts.PropertyName) { - if (ts.isPrivateIdentifier(name)) { + function getLiteralTypeFromPropertyName(name: PropertyName) { + if (isPrivateIdentifier(name)) { return neverType; } - return ts.isIdentifier(name) ? getStringLiteralType(ts.unescapeLeadingUnderscores(name.escapedText)) : - getRegularTypeOfLiteralType(ts.isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); + return isIdentifier(name) ? getStringLiteralType(unescapeLeadingUnderscores(name.escapedText)) : + getRegularTypeOfLiteralType(isComputedPropertyName(name) ? checkComputedPropertyName(name) : checkExpression(name)); } - function getLiteralTypeFromProperty(prop: ts.Symbol, include: ts.TypeFlags, includeNonPublic?: boolean) { - if (includeNonPublic || !(ts.getDeclarationModifierFlagsFromSymbol(prop) & ts.ModifierFlags.NonPublicAccessibilityModifier)) { + function getLiteralTypeFromProperty(prop: Symbol, include: TypeFlags, includeNonPublic?: boolean) { + if (includeNonPublic || !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.NonPublicAccessibilityModifier)) { let type = getSymbolLinks(getLateBoundSymbol(prop)).nameType; if (!type) { - const name = ts.getNameOfDeclaration(prop.valueDeclaration) as ts.PropertyName; - type = prop.escapedName === ts.InternalSymbolName.Default ? getStringLiteralType("default") : - name && getLiteralTypeFromPropertyName(name) || (!ts.isKnownSymbol(prop) ? getStringLiteralType(ts.symbolName(prop)) : undefined); + const name = getNameOfDeclaration(prop.valueDeclaration) as PropertyName; + type = prop.escapedName === InternalSymbolName.Default ? getStringLiteralType("default") : + name && getLiteralTypeFromPropertyName(name) || (!isKnownSymbol(prop) ? getStringLiteralType(symbolName(prop)) : undefined); } if (type && type.flags & include) { return type; @@ -15498,16 +15696,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return neverType; } - function isKeyTypeIncluded(keyType: ts.Type, include: ts.TypeFlags): boolean { - return !!(keyType.flags & include || keyType.flags & ts.TypeFlags.Intersection && ts.some((keyType as ts.IntersectionType).types, t => isKeyTypeIncluded(t, include))); + function isKeyTypeIncluded(keyType: Type, include: TypeFlags): boolean { + return !!(keyType.flags & include || keyType.flags & TypeFlags.Intersection && some((keyType as IntersectionType).types, t => isKeyTypeIncluded(t, include))); } - function getLiteralTypeFromProperties(type: ts.Type, include: ts.TypeFlags, includeOrigin: boolean) { - const origin = includeOrigin && (ts.getObjectFlags(type) & (ts.ObjectFlags.ClassOrInterface | ts.ObjectFlags.Reference) || type.aliasSymbol) ? createOriginIndexType(type) : undefined; - const propertyTypes = ts.map(getPropertiesOfType(type), prop => getLiteralTypeFromProperty(prop, include)); - const indexKeyTypes = ts.map(getIndexInfosOfType(type), info => info !== enumNumberIndexInfo && isKeyTypeIncluded(info.keyType, include) ? - info.keyType === stringType && include & ts.TypeFlags.Number ? stringOrNumberType : info.keyType : neverType); - return getUnionType(ts.concatenate(propertyTypes, indexKeyTypes), ts.UnionReduction.Literal, + function getLiteralTypeFromProperties(type: Type, include: TypeFlags, includeOrigin: boolean) { + const origin = includeOrigin && (getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference) || type.aliasSymbol) ? createOriginIndexType(type) : undefined; + const propertyTypes = map(getPropertiesOfType(type), prop => getLiteralTypeFromProperty(prop, include)); + const indexKeyTypes = map(getIndexInfosOfType(type), info => info !== enumNumberIndexInfo && isKeyTypeIncluded(info.keyType, include) ? + info.keyType === stringType && include & TypeFlags.Number ? stringOrNumberType : info.keyType : neverType); + return getUnionType(concatenate(propertyTypes, indexKeyTypes), UnionReduction.Literal, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, origin); } @@ -15517,33 +15715,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * type parameters in the union with a special never type that is treated as a literal in `getReducedType`, we can cause the `getReducedType` logic * to reduce the resulting type if possible (since only intersections with conflicting literal-typed properties are reducible). */ - function isPossiblyReducibleByInstantiation(type: ts.Type): boolean { + function isPossiblyReducibleByInstantiation(type: Type): boolean { const uniqueFilled = getUniqueLiteralFilledInstantiation(type); return getReducedType(uniqueFilled) !== uniqueFilled; } - function shouldDeferIndexType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.InstantiableNonPrimitive || + function shouldDeferIndexType(type: Type) { + return !!(type.flags & TypeFlags.InstantiableNonPrimitive || isGenericTupleType(type) || isGenericMappedType(type) && !hasDistributiveNameType(type) || - type.flags & ts.TypeFlags.Union && ts.some((type as ts.UnionType).types, isPossiblyReducibleByInstantiation) || - type.flags & ts.TypeFlags.Intersection && maybeTypeOfKind(type, ts.TypeFlags.Instantiable) && ts.some((type as ts.IntersectionType).types, isEmptyAnonymousObjectType)); + type.flags & TypeFlags.Union && some((type as UnionType).types, isPossiblyReducibleByInstantiation) || + type.flags & TypeFlags.Intersection && maybeTypeOfKind(type, TypeFlags.Instantiable) && some((type as IntersectionType).types, isEmptyAnonymousObjectType)); } - function getIndexType(type: ts.Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): ts.Type { + function getIndexType(type: Type, stringsOnly = keyofStringsOnly, noIndexSignatures?: boolean): Type { type = getReducedType(type); - return shouldDeferIndexType(type) ? getIndexTypeForGenericType(type as ts.InstantiableType | ts.UnionOrIntersectionType, stringsOnly) : - type.flags & ts.TypeFlags.Union ? getIntersectionType(ts.map((type as ts.UnionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : - type.flags & ts.TypeFlags.Intersection ? getUnionType(ts.map((type as ts.IntersectionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : - ts.getObjectFlags(type) & ts.ObjectFlags.Mapped ? getIndexTypeForMappedType(type as ts.MappedType, stringsOnly, noIndexSignatures) : + return shouldDeferIndexType(type) ? getIndexTypeForGenericType(type as InstantiableType | UnionOrIntersectionType, stringsOnly) : + type.flags & TypeFlags.Union ? getIntersectionType(map((type as UnionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : + type.flags & TypeFlags.Intersection ? getUnionType(map((type as IntersectionType).types, t => getIndexType(t, stringsOnly, noIndexSignatures))) : + getObjectFlags(type) & ObjectFlags.Mapped ? getIndexTypeForMappedType(type as MappedType, stringsOnly, noIndexSignatures) : type === wildcardType ? wildcardType : - type.flags & ts.TypeFlags.Unknown ? neverType : - type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never) ? keyofConstraintType : - getLiteralTypeFromProperties(type, (noIndexSignatures ? ts.TypeFlags.StringLiteral : ts.TypeFlags.StringLike) | (stringsOnly ? 0 : ts.TypeFlags.NumberLike | ts.TypeFlags.ESSymbolLike), + type.flags & TypeFlags.Unknown ? neverType : + type.flags & (TypeFlags.Any | TypeFlags.Never) ? keyofConstraintType : + getLiteralTypeFromProperties(type, (noIndexSignatures ? TypeFlags.StringLiteral : TypeFlags.StringLike) | (stringsOnly ? 0 : TypeFlags.NumberLike | TypeFlags.ESSymbolLike), stringsOnly === keyofStringsOnly && !noIndexSignatures); } - function getExtractStringType(type: ts.Type) { + function getExtractStringType(type: Type) { if (keyofStringsOnly) { return type; } @@ -15551,54 +15749,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return extractTypeAlias ? getTypeAliasInstantiation(extractTypeAlias, [type, stringType]) : stringType; } - function getIndexTypeOrString(type: ts.Type): ts.Type { + function getIndexTypeOrString(type: Type): Type { const indexType = getExtractStringType(getIndexType(type)); - return indexType.flags & ts.TypeFlags.Never ? stringType : indexType; + return indexType.flags & TypeFlags.Never ? stringType : indexType; } - function getTypeFromTypeOperatorNode(node: ts.TypeOperatorNode): ts.Type { + function getTypeFromTypeOperatorNode(node: TypeOperatorNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { switch (node.operator) { - case ts.SyntaxKind.KeyOfKeyword: + case SyntaxKind.KeyOfKeyword: links.resolvedType = getIndexType(getTypeFromTypeNode(node.type)); break; - case ts.SyntaxKind.UniqueKeyword: - links.resolvedType = node.type.kind === ts.SyntaxKind.SymbolKeyword - ? getESSymbolLikeTypeForNode(ts.walkUpParenthesizedTypes(node.parent)) + case SyntaxKind.UniqueKeyword: + links.resolvedType = node.type.kind === SyntaxKind.SymbolKeyword + ? getESSymbolLikeTypeForNode(walkUpParenthesizedTypes(node.parent)) : errorType; break; - case ts.SyntaxKind.ReadonlyKeyword: + case SyntaxKind.ReadonlyKeyword: links.resolvedType = getTypeFromTypeNode(node.type); break; default: - throw ts.Debug.assertNever(node.operator); + throw Debug.assertNever(node.operator); } } return links.resolvedType; } - function getTypeFromTemplateTypeNode(node: ts.TemplateLiteralTypeNode) { + function getTypeFromTemplateTypeNode(node: TemplateLiteralTypeNode) { const links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getTemplateLiteralType( - [node.head.text, ...ts.map(node.templateSpans, span => span.literal.text)], - ts.map(node.templateSpans, span => getTypeFromTypeNode(span.type))); + [node.head.text, ...map(node.templateSpans, span => span.literal.text)], + map(node.templateSpans, span => getTypeFromTypeNode(span.type))); } return links.resolvedType; } - function getTemplateLiteralType(texts: readonly string[], types: readonly ts.Type[]): ts.Type { - const unionIndex = ts.findIndex(types, t => !!(t.flags & (ts.TypeFlags.Never | ts.TypeFlags.Union))); + function getTemplateLiteralType(texts: readonly string[], types: readonly Type[]): Type { + const unionIndex = findIndex(types, t => !!(t.flags & (TypeFlags.Never | TypeFlags.Union))); if (unionIndex >= 0) { return checkCrossProductUnion(types) ? - mapType(types[unionIndex], t => getTemplateLiteralType(texts, ts.replaceElement(types, unionIndex, t))) : + mapType(types[unionIndex], t => getTemplateLiteralType(texts, replaceElement(types, unionIndex, t))) : errorType; } - if (ts.contains(types, wildcardType)) { + if (contains(types, wildcardType)) { return wildcardType; } - const newTypes: ts.Type[] = []; + const newTypes: Type[] = []; const newTexts: string[] = []; let text = texts[0]; if (!addSpans(texts, types)) { @@ -15608,8 +15806,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getStringLiteralType(text); } newTexts.push(text); - if (ts.every(newTexts, t => t === "")) { - if (ts.every(newTypes, t => !!(t.flags & ts.TypeFlags.String))) { + if (every(newTexts, t => t === "")) { + if (every(newTypes, t => !!(t.flags & TypeFlags.String))) { return stringType; } // Normalize `${Mapping}` into Mapping @@ -15617,26 +15815,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return newTypes[0]; } } - const id = `${getTypeListId(newTypes)}|${ts.map(newTexts, t => t.length).join(",")}|${newTexts.join("")}`; + const id = `${getTypeListId(newTypes)}|${map(newTexts, t => t.length).join(",")}|${newTexts.join("")}`; let type = templateLiteralTypes.get(id); if (!type) { templateLiteralTypes.set(id, type = createTemplateLiteralType(newTexts, newTypes)); } return type; - function addSpans(texts: readonly string[] | string, types: readonly ts.Type[]): boolean { - const isTextsArray = ts.isArray(texts); + function addSpans(texts: readonly string[] | string, types: readonly Type[]): boolean { + const isTextsArray = isArray(texts); for (let i = 0; i < types.length; i++) { const t = types[i]; const addText = isTextsArray ? texts[i + 1] : texts; - if (t.flags & (ts.TypeFlags.Literal | ts.TypeFlags.Null | ts.TypeFlags.Undefined)) { + if (t.flags & (TypeFlags.Literal | TypeFlags.Null | TypeFlags.Undefined)) { text += getTemplateStringForType(t) || ""; text += addText; if (!isTextsArray) return true; } - else if (t.flags & ts.TypeFlags.TemplateLiteral) { - text += (t as ts.TemplateLiteralType).texts[0]; - if (!addSpans((t as ts.TemplateLiteralType).texts, (t as ts.TemplateLiteralType).types)) return false; + else if (t.flags & TypeFlags.TemplateLiteral) { + text += (t as TemplateLiteralType).texts[0]; + if (!addSpans((t as TemplateLiteralType).texts, (t as TemplateLiteralType).types)) return false; text += addText; if (!isTextsArray) return true; } @@ -15645,8 +15843,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { newTexts.push(text); text = addText; } - else if (t.flags & ts.TypeFlags.Intersection) { - const added = addSpans(texts[i + 1], (t as ts.IntersectionType).types); + else if (t.flags & TypeFlags.Intersection) { + const added = addSpans(texts[i + 1], (t as IntersectionType).types); if (!added) return false; } else if (isTextsArray) { @@ -15657,34 +15855,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTemplateStringForType(type: ts.Type) { - return type.flags & ts.TypeFlags.StringLiteral ? (type as ts.StringLiteralType).value : - type.flags & ts.TypeFlags.NumberLiteral ? "" + (type as ts.NumberLiteralType).value : - type.flags & ts.TypeFlags.BigIntLiteral ? ts.pseudoBigIntToString((type as ts.BigIntLiteralType).value) : - type.flags & (ts.TypeFlags.BooleanLiteral | ts.TypeFlags.Nullable) ? (type as ts.IntrinsicType).intrinsicName : + function getTemplateStringForType(type: Type) { + return type.flags & TypeFlags.StringLiteral ? (type as StringLiteralType).value : + type.flags & TypeFlags.NumberLiteral ? "" + (type as NumberLiteralType).value : + type.flags & TypeFlags.BigIntLiteral ? pseudoBigIntToString((type as BigIntLiteralType).value) : + type.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) ? (type as IntrinsicType).intrinsicName : undefined; } - function createTemplateLiteralType(texts: readonly string[], types: readonly ts.Type[]) { - const type = createType(ts.TypeFlags.TemplateLiteral) as ts.TemplateLiteralType; + function createTemplateLiteralType(texts: readonly string[], types: readonly Type[]) { + const type = createType(TypeFlags.TemplateLiteral) as TemplateLiteralType; type.texts = texts; type.types = types; return type; } - function getStringMappingType(symbol: ts.Symbol, type: ts.Type): ts.Type { - return type.flags & (ts.TypeFlags.Union | ts.TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) : - type.flags & ts.TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as ts.StringLiteralType).value)) : - type.flags & ts.TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as ts.TemplateLiteralType).texts, (type as ts.TemplateLiteralType).types)) : + function getStringMappingType(symbol: Symbol, type: Type): Type { + return type.flags & (TypeFlags.Union | TypeFlags.Never) ? mapType(type, t => getStringMappingType(symbol, t)) : + type.flags & TypeFlags.StringLiteral ? getStringLiteralType(applyStringMapping(symbol, (type as StringLiteralType).value)) : + type.flags & TypeFlags.TemplateLiteral ? getTemplateLiteralType(...applyTemplateStringMapping(symbol, (type as TemplateLiteralType).texts, (type as TemplateLiteralType).types)) : // Mapping> === Mapping - type.flags & ts.TypeFlags.StringMapping && symbol === type.symbol ? type : - type.flags & (ts.TypeFlags.Any | ts.TypeFlags.String | ts.TypeFlags.StringMapping) || isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) : + type.flags & TypeFlags.StringMapping && symbol === type.symbol ? type : + type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.StringMapping) || isGenericIndexType(type) ? getStringMappingTypeForGenericType(symbol, type) : // This handles Mapping<`${number}`> and Mapping<`${bigint}`> isPatternLiteralPlaceholderType(type) ? getStringMappingTypeForGenericType(symbol, getTemplateLiteralType(["", ""], [type])) : type; } - function applyStringMapping(symbol: ts.Symbol, str: string) { + function applyStringMapping(symbol: Symbol, str: string) { switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { case IntrinsicTypeKind.Uppercase: return str.toUpperCase(); case IntrinsicTypeKind.Lowercase: return str.toLowerCase(); @@ -15694,7 +15892,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return str; } - function applyTemplateStringMapping(symbol: ts.Symbol, texts: readonly string[], types: readonly ts.Type[]): [texts: readonly string[], types: readonly ts.Type[]] { + function applyTemplateStringMapping(symbol: Symbol, texts: readonly string[], types: readonly Type[]): [texts: readonly string[], types: readonly Type[]] { switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { case IntrinsicTypeKind.Uppercase: return [texts.map(t => t.toUpperCase()), types.map(t => getStringMappingType(symbol, t))]; case IntrinsicTypeKind.Lowercase: return [texts.map(t => t.toLowerCase()), types.map(t => getStringMappingType(symbol, t))]; @@ -15704,7 +15902,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return [texts, types]; } - function getStringMappingTypeForGenericType(symbol: ts.Symbol, type: ts.Type): ts.Type { + function getStringMappingTypeForGenericType(symbol: Symbol, type: Type): Type { const id = `${getSymbolId(symbol)},${getTypeId(type)}`; let result = stringMappingTypes.get(id); if (!result) { @@ -15713,14 +15911,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function createStringMappingType(symbol: ts.Symbol, type: ts.Type) { - const result = createTypeWithSymbol(ts.TypeFlags.StringMapping, symbol) as ts.StringMappingType; + function createStringMappingType(symbol: Symbol, type: Type) { + const result = createTypeWithSymbol(TypeFlags.StringMapping, symbol) as StringMappingType; result.type = type; return result; } - function createIndexedAccessType(objectType: ts.Type, indexType: ts.Type, accessFlags: ts.AccessFlags, aliasSymbol: ts.Symbol | undefined, aliasTypeArguments: readonly ts.Type[] | undefined) { - const type = createType(ts.TypeFlags.IndexedAccess) as ts.IndexedAccessType; + function createIndexedAccessType(objectType: Type, indexType: Type, accessFlags: AccessFlags, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { + const type = createType(TypeFlags.IndexedAccess) as IndexedAccessType; type.objectType = objectType; type.indexType = indexType; type.accessFlags = accessFlags; @@ -15738,67 +15936,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Should all count as literals and not print errors on access or assignment of possibly existing properties. * This mirrors the behavior of the index signature propagation, to which this behaves similarly (but doesn't affect assignability or inference). */ - function isJSLiteralType(type: ts.Type): boolean { + function isJSLiteralType(type: Type): boolean { if (noImplicitAny) { return false; // Flag is meaningless under `noImplicitAny` mode } - if (ts.getObjectFlags(type) & ts.ObjectFlags.JSLiteral) { + if (getObjectFlags(type) & ObjectFlags.JSLiteral) { return true; } - if (type.flags & ts.TypeFlags.Union) { - return ts.every((type as ts.UnionType).types, isJSLiteralType); + if (type.flags & TypeFlags.Union) { + return every((type as UnionType).types, isJSLiteralType); } - if (type.flags & ts.TypeFlags.Intersection) { - return ts.some((type as ts.IntersectionType).types, isJSLiteralType); + if (type.flags & TypeFlags.Intersection) { + return some((type as IntersectionType).types, isJSLiteralType); } - if (type.flags & ts.TypeFlags.Instantiable) { + if (type.flags & TypeFlags.Instantiable) { const constraint = getResolvedBaseConstraint(type); return constraint !== type && isJSLiteralType(constraint); } return false; } - function getPropertyNameFromIndex(indexType: ts.Type, accessNode: ts.StringLiteral | ts.Identifier | ts.PrivateIdentifier | ts.ObjectBindingPattern | ts.ArrayBindingPattern | ts.ComputedPropertyName | ts.NumericLiteral | ts.IndexedAccessTypeNode | ts.ElementAccessExpression | ts.SyntheticExpression | undefined) { + function getPropertyNameFromIndex(indexType: Type, accessNode: StringLiteral | Identifier | PrivateIdentifier | ObjectBindingPattern | ArrayBindingPattern | ComputedPropertyName | NumericLiteral | IndexedAccessTypeNode | ElementAccessExpression | SyntheticExpression | undefined) { return isTypeUsableAsPropertyName(indexType) ? getPropertyNameFromType(indexType) : - accessNode && ts.isPropertyName(accessNode) ? + accessNode && isPropertyName(accessNode) ? // late bound names are handled in the first branch, so here we only need to handle normal names - ts.getPropertyNameForPropertyNameNode(accessNode) : + getPropertyNameForPropertyNameNode(accessNode) : undefined; } - function isUncalledFunctionReference(node: ts.Node, symbol: ts.Symbol) { - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method)) { - const parent = ts.findAncestor(node.parent, n => !ts.isAccessExpression(n)) || node.parent; - if (ts.isCallLikeExpression(parent)) { - return ts.isCallOrNewExpression(parent) && ts.isIdentifier(node) && hasMatchingArgument(parent, node); + function isUncalledFunctionReference(node: Node, symbol: Symbol) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { + const parent = findAncestor(node.parent, n => !isAccessExpression(n)) || node.parent; + if (isCallLikeExpression(parent)) { + return isCallOrNewExpression(parent) && isIdentifier(node) && hasMatchingArgument(parent, node); } - return ts.every(symbol.declarations, d => !ts.isFunctionLike(d) || !!(ts.getCombinedNodeFlags(d) & ts.NodeFlags.Deprecated)); + return every(symbol.declarations, d => !isFunctionLike(d) || !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated)); } return true; } - function getPropertyTypeForIndexType(originalObjectType: ts.Type, objectType: ts.Type, indexType: ts.Type, fullIndexType: ts.Type, accessNode: ts.ElementAccessExpression | ts.IndexedAccessTypeNode | ts.PropertyName | ts.BindingName | ts.SyntheticExpression | undefined, accessFlags: ts.AccessFlags) { - const accessExpression = accessNode && accessNode.kind === ts.SyntaxKind.ElementAccessExpression ? accessNode : undefined; - const propName = accessNode && ts.isPrivateIdentifier(accessNode) ? undefined : getPropertyNameFromIndex(indexType, accessNode); + function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, fullIndexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, accessFlags: AccessFlags) { + const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined; + const propName = accessNode && isPrivateIdentifier(accessNode) ? undefined : getPropertyNameFromIndex(indexType, accessNode); if (propName !== undefined) { - if (accessFlags & ts.AccessFlags.Contextual) { + if (accessFlags & AccessFlags.Contextual) { return getTypeOfPropertyOfContextualType(objectType, propName) || anyType; } const prop = getPropertyOfType(objectType, propName); if (prop) { - if (accessFlags & ts.AccessFlags.ReportDeprecated && accessNode && prop.declarations && isDeprecatedSymbol(prop) && isUncalledFunctionReference(accessNode, prop)) { - const deprecatedNode = accessExpression?.argumentExpression ?? (ts.isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode); + if (accessFlags & AccessFlags.ReportDeprecated && accessNode && prop.declarations && isDeprecatedSymbol(prop) && isUncalledFunctionReference(accessNode, prop)) { + const deprecatedNode = accessExpression?.argumentExpression ?? (isIndexedAccessTypeNode(accessNode) ? accessNode.indexType : accessNode); addDeprecatedSuggestion(deprecatedNode, prop.declarations, propName as string); } if (accessExpression) { markPropertyAsReferenced(prop, accessExpression, isSelfTypeAccess(accessExpression.expression, objectType.symbol)); - if (isAssignmentToReadonlyEntity(accessExpression, prop, ts.getAssignmentTargetKind(accessExpression))) { - error(accessExpression.argumentExpression, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop)); + if (isAssignmentToReadonlyEntity(accessExpression, prop, getAssignmentTargetKind(accessExpression))) { + error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop)); return undefined; } - if (accessFlags & ts.AccessFlags.CacheSymbol) { + if (accessFlags & AccessFlags.CacheSymbol) { getNodeLinks(accessNode!).resolvedSymbol = prop; } if (isThisPropertyAccessInConstructor(accessExpression, prop)) { @@ -15806,69 +16004,69 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } const propType = getTypeOfSymbol(prop); - return accessExpression && ts.getAssignmentTargetKind(accessExpression) !== ts.AssignmentKind.Definite ? + return accessExpression && getAssignmentTargetKind(accessExpression) !== AssignmentKind.Definite ? getFlowTypeOfReference(accessExpression, propType) : propType; } - if (everyType(objectType, isTupleType) && ts.isNumericLiteralName(propName)) { + if (everyType(objectType, isTupleType) && isNumericLiteralName(propName)) { const index = +propName; - if (accessNode && everyType(objectType, t => !(t as ts.TupleTypeReference).target.hasRestElement) && !(accessFlags & ts.AccessFlags.NoTupleBoundsCheck)) { + if (accessNode && everyType(objectType, t => !(t as TupleTypeReference).target.hasRestElement) && !(accessFlags & AccessFlags.NoTupleBoundsCheck)) { const indexNode = getIndexNodeForAccessExpression(accessNode); if (isTupleType(objectType)) { if (index < 0) { - error(indexNode, ts.Diagnostics.A_tuple_type_cannot_be_indexed_with_a_negative_value); + error(indexNode, Diagnostics.A_tuple_type_cannot_be_indexed_with_a_negative_value); return undefinedType; } - error(indexNode, ts.Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, - typeToString(objectType), getTypeReferenceArity(objectType), ts.unescapeLeadingUnderscores(propName)); + error(indexNode, Diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, + typeToString(objectType), getTypeReferenceArity(objectType), unescapeLeadingUnderscores(propName)); } else { - error(indexNode, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(propName), typeToString(objectType)); + error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType)); } } if (index >= 0) { errorIfWritingToReadonlyIndex(getIndexInfoOfType(objectType, numberType)); return mapType(objectType, t => { - const restType = getRestTypeOfTupleType(t as ts.TupleTypeReference) || undefinedType; - return accessFlags & ts.AccessFlags.IncludeUndefined ? getUnionType([restType, undefinedType]) : restType; + const restType = getRestTypeOfTupleType(t as TupleTypeReference) || undefinedType; + return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([restType, undefinedType]) : restType; }); } } } - if (!(indexType.flags & ts.TypeFlags.Nullable) && isTypeAssignableToKind(indexType, ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.ESSymbolLike)) { - if (objectType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never)) { + if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) { + if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) { return objectType; } // If no index signature is applicable, we default to the string index signature. In effect, this means the string // index signature applies even when accessing with a symbol-like type. const indexInfo = getApplicableIndexInfo(objectType, indexType) || getIndexInfoOfType(objectType, stringType); if (indexInfo) { - if (accessFlags & ts.AccessFlags.NoIndexSignatures && indexInfo.keyType !== numberType) { + if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo.keyType !== numberType) { if (accessExpression) { - error(accessExpression, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType)); + error(accessExpression, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(originalObjectType)); } return undefined; } - if (accessNode && indexInfo.keyType === stringType && !isTypeAssignableToKind(indexType, ts.TypeFlags.String | ts.TypeFlags.Number)) { + if (accessNode && indexInfo.keyType === stringType && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { const indexNode = getIndexNodeForAccessExpression(accessNode); - error(indexNode, ts.Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); - return accessFlags & ts.AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; + error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); + return accessFlags & AccessFlags.IncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } errorIfWritingToReadonlyIndex(indexInfo); // When accessing an enum object with its own type, // e.g. E[E.A] for enum E { A }, undefined shouldn't // be included in the result type - if ((accessFlags & ts.AccessFlags.IncludeUndefined) && + if ((accessFlags & AccessFlags.IncludeUndefined) && !(objectType.symbol && - objectType.symbol.flags & (ts.SymbolFlags.RegularEnum | ts.SymbolFlags.ConstEnum) && + objectType.symbol.flags & (SymbolFlags.RegularEnum | SymbolFlags.ConstEnum) && (indexType.symbol && - indexType.flags & ts.TypeFlags.EnumLiteral && + indexType.flags & TypeFlags.EnumLiteral && getParentOfSymbol(indexType.symbol) === objectType.symbol))) { return getUnionType([indexInfo.type, undefinedType]); } return indexInfo.type; } - if (indexType.flags & ts.TypeFlags.Never) { + if (indexType.flags & TypeFlags.Never) { return neverType; } if (isJSLiteralType(objectType)) { @@ -15876,65 +16074,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (accessExpression && !isConstEnumObjectType(objectType)) { if (isObjectLiteralType(objectType)) { - if (noImplicitAny && indexType.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) { - diagnostics.add(ts.createDiagnosticForNode(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as ts.StringLiteralType).value, typeToString(objectType))); + if (noImplicitAny && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { + diagnostics.add(createDiagnosticForNode(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType))); return undefinedType; } - else if (indexType.flags & (ts.TypeFlags.Number | ts.TypeFlags.String)) { - const types = ts.map((objectType as ts.ResolvedType).properties, property => { + else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) { + const types = map((objectType as ResolvedType).properties, property => { return getTypeOfSymbol(property); }); - return getUnionType(ts.append(types, undefinedType)); + return getUnionType(append(types, undefinedType)); } } - if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & ts.SymbolFlags.BlockScoped)) { - error(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(propName), typeToString(objectType)); + if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) { + error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType)); } - else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & ts.AccessFlags.SuppressNoImplicitAnyError)) { + else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError)) { if (propName !== undefined && typeHasStaticProperty(propName, objectType)) { const typeName = typeToString(objectType); - error(accessExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName as string, typeName, typeName + "[" + ts.getTextOfNode(accessExpression.argumentExpression) + "]"); + error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName as string, typeName, typeName + "[" + getTextOfNode(accessExpression.argumentExpression) + "]"); } else if (getIndexTypeOfType(objectType, numberType)) { - error(accessExpression.argumentExpression, ts.Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); + error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number); } else { let suggestion: string | undefined; if (propName !== undefined && (suggestion = getSuggestionForNonexistentProperty(propName as string, objectType))) { if (suggestion !== undefined) { - error(accessExpression.argumentExpression, ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName as string, typeToString(objectType), suggestion); + error(accessExpression.argumentExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName as string, typeToString(objectType), suggestion); } } else { const suggestion = getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType); if (suggestion !== undefined) { - error(accessExpression, ts.Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion); + error(accessExpression, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature_Did_you_mean_to_call_1, typeToString(objectType), suggestion); } else { - let errorInfo: ts.DiagnosticMessageChain | undefined; - if (indexType.flags & ts.TypeFlags.EnumLiteral) { - errorInfo = ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics.Property_0_does_not_exist_on_type_1, "[" + typeToString(indexType) + "]", typeToString(objectType)); + let errorInfo: DiagnosticMessageChain | undefined; + if (indexType.flags & TypeFlags.EnumLiteral) { + errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + typeToString(indexType) + "]", typeToString(objectType)); } - else if (indexType.flags & ts.TypeFlags.UniqueESSymbol) { - const symbolName = getFullyQualifiedName((indexType as ts.UniqueESSymbolType).symbol, accessExpression); - errorInfo = ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics.Property_0_does_not_exist_on_type_1, "[" + symbolName + "]", typeToString(objectType)); + else if (indexType.flags & TypeFlags.UniqueESSymbol) { + const symbolName = getFullyQualifiedName((indexType as UniqueESSymbolType).symbol, accessExpression); + errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, "[" + symbolName + "]", typeToString(objectType)); } - else if (indexType.flags & ts.TypeFlags.StringLiteral) { - errorInfo = ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as ts.StringLiteralType).value, typeToString(objectType)); + else if (indexType.flags & TypeFlags.StringLiteral) { + errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType)); } - else if (indexType.flags & ts.TypeFlags.NumberLiteral) { - errorInfo = ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as ts.NumberLiteralType).value, typeToString(objectType)); + else if (indexType.flags & TypeFlags.NumberLiteral) { + errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as NumberLiteralType).value, typeToString(objectType)); } - else if (indexType.flags & (ts.TypeFlags.Number | ts.TypeFlags.String)) { - errorInfo = ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics.No_index_signature_with_a_parameter_of_type_0_was_found_on_type_1, typeToString(indexType), typeToString(objectType)); + else if (indexType.flags & (TypeFlags.Number | TypeFlags.String)) { + errorInfo = chainDiagnosticMessages(/* details */ undefined, Diagnostics.No_index_signature_with_a_parameter_of_type_0_was_found_on_type_1, typeToString(indexType), typeToString(objectType)); } - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( errorInfo, - ts.Diagnostics.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1, typeToString(fullIndexType), typeToString(objectType) + Diagnostics.Element_implicitly_has_an_any_type_because_expression_of_type_0_can_t_be_used_to_index_type_1, typeToString(fullIndexType), typeToString(objectType) ); - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(accessExpression, errorInfo)); + diagnostics.add(createDiagnosticForNodeFromMessageChain(accessExpression, errorInfo)); } } } @@ -15947,14 +16145,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (accessNode) { const indexNode = getIndexNodeForAccessExpression(accessNode); - if (indexType.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral)) { - error(indexNode, ts.Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType as ts.StringLiteralType | ts.NumberLiteralType).value, typeToString(objectType)); + if (indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { + error(indexNode, Diagnostics.Property_0_does_not_exist_on_type_1, "" + (indexType as StringLiteralType | NumberLiteralType).value, typeToString(objectType)); } - else if (indexType.flags & (ts.TypeFlags.String | ts.TypeFlags.Number)) { - error(indexNode, ts.Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); + else if (indexType.flags & (TypeFlags.String | TypeFlags.Number)) { + error(indexNode, Diagnostics.Type_0_has_no_matching_index_signature_for_type_1, typeToString(objectType), typeToString(indexType)); } else { - error(indexNode, ts.Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); + error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); } } if (isTypeAny(indexType)) { @@ -15962,81 +16160,81 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return undefined; - function errorIfWritingToReadonlyIndex(indexInfo: ts.IndexInfo | undefined): void { - if (indexInfo && indexInfo.isReadonly && accessExpression && (ts.isAssignmentTarget(accessExpression) || ts.isDeleteTarget(accessExpression))) { - error(accessExpression, ts.Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); + function errorIfWritingToReadonlyIndex(indexInfo: IndexInfo | undefined): void { + if (indexInfo && indexInfo.isReadonly && accessExpression && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) { + error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); } } } - function getIndexNodeForAccessExpression(accessNode: ts.ElementAccessExpression | ts.IndexedAccessTypeNode | ts.PropertyName | ts.BindingName | ts.SyntheticExpression) { - return accessNode.kind === ts.SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : - accessNode.kind === ts.SyntaxKind.IndexedAccessType ? accessNode.indexType : - accessNode.kind === ts.SyntaxKind.ComputedPropertyName ? accessNode.expression : + function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) { + return accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : + accessNode.kind === SyntaxKind.IndexedAccessType ? accessNode.indexType : + accessNode.kind === SyntaxKind.ComputedPropertyName ? accessNode.expression : accessNode; } - function isPatternLiteralPlaceholderType(type: ts.Type): boolean { - return !!(type.flags & (ts.TypeFlags.Any | ts.TypeFlags.String | ts.TypeFlags.Number | ts.TypeFlags.BigInt)) || isPatternLiteralType(type); + function isPatternLiteralPlaceholderType(type: Type): boolean { + return !!(type.flags & (TypeFlags.Any | TypeFlags.String | TypeFlags.Number | TypeFlags.BigInt)) || isPatternLiteralType(type); } - function isPatternLiteralType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.TemplateLiteral) && ts.every((type as ts.TemplateLiteralType).types, isPatternLiteralPlaceholderType) || - !!(type.flags & ts.TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as ts.StringMappingType).type); + function isPatternLiteralType(type: Type) { + return !!(type.flags & TypeFlags.TemplateLiteral) && every((type as TemplateLiteralType).types, isPatternLiteralPlaceholderType) || + !!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type); } - function isGenericType(type: ts.Type): boolean { + function isGenericType(type: Type): boolean { return !!getGenericObjectFlags(type); } - function isGenericObjectType(type: ts.Type): boolean { - return !!(getGenericObjectFlags(type) & ts.ObjectFlags.IsGenericObjectType); + function isGenericObjectType(type: Type): boolean { + return !!(getGenericObjectFlags(type) & ObjectFlags.IsGenericObjectType); } - function isGenericIndexType(type: ts.Type): boolean { - return !!(getGenericObjectFlags(type) & ts.ObjectFlags.IsGenericIndexType); + function isGenericIndexType(type: Type): boolean { + return !!(getGenericObjectFlags(type) & ObjectFlags.IsGenericIndexType); } - function getGenericObjectFlags(type: ts.Type): ts.ObjectFlags { - if (type.flags & ts.TypeFlags.UnionOrIntersection) { - if (!((type as ts.UnionOrIntersectionType).objectFlags & ts.ObjectFlags.IsGenericTypeComputed)) { - (type as ts.UnionOrIntersectionType).objectFlags |= ts.ObjectFlags.IsGenericTypeComputed | - ts.reduceLeft((type as ts.UnionOrIntersectionType).types, (flags, t) => flags | getGenericObjectFlags(t), 0); + function getGenericObjectFlags(type: Type): ObjectFlags { + if (type.flags & TypeFlags.UnionOrIntersection) { + if (!((type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) { + (type as UnionOrIntersectionType).objectFlags |= ObjectFlags.IsGenericTypeComputed | + reduceLeft((type as UnionOrIntersectionType).types, (flags, t) => flags | getGenericObjectFlags(t), 0); } - return (type as ts.UnionOrIntersectionType).objectFlags & ts.ObjectFlags.IsGenericType; + return (type as UnionOrIntersectionType).objectFlags & ObjectFlags.IsGenericType; } - if (type.flags & ts.TypeFlags.Substitution) { - if (!((type as ts.SubstitutionType).objectFlags & ts.ObjectFlags.IsGenericTypeComputed)) { - (type as ts.SubstitutionType).objectFlags |= ts.ObjectFlags.IsGenericTypeComputed | - getGenericObjectFlags((type as ts.SubstitutionType).baseType) | getGenericObjectFlags((type as ts.SubstitutionType).constraint); + if (type.flags & TypeFlags.Substitution) { + if (!((type as SubstitutionType).objectFlags & ObjectFlags.IsGenericTypeComputed)) { + (type as SubstitutionType).objectFlags |= ObjectFlags.IsGenericTypeComputed | + getGenericObjectFlags((type as SubstitutionType).baseType) | getGenericObjectFlags((type as SubstitutionType).constraint); } - return (type as ts.SubstitutionType).objectFlags & ts.ObjectFlags.IsGenericType; + return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType; } - return (type.flags & ts.TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ts.ObjectFlags.IsGenericObjectType : 0) | - (type.flags & (ts.TypeFlags.InstantiableNonPrimitive | ts.TypeFlags.Index | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ts.ObjectFlags.IsGenericIndexType : 0); + return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) | + (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0); } - function getSimplifiedType(type: ts.Type, writing: boolean): ts.Type { - return type.flags & ts.TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as ts.IndexedAccessType, writing) : - type.flags & ts.TypeFlags.Conditional ? getSimplifiedConditionalType(type as ts.ConditionalType, writing) : + function getSimplifiedType(type: Type, writing: boolean): Type { + return type.flags & TypeFlags.IndexedAccess ? getSimplifiedIndexedAccessType(type as IndexedAccessType, writing) : + type.flags & TypeFlags.Conditional ? getSimplifiedConditionalType(type as ConditionalType, writing) : type; } - function distributeIndexOverObjectType(objectType: ts.Type, indexType: ts.Type, writing: boolean) { + function distributeIndexOverObjectType(objectType: Type, indexType: Type, writing: boolean) { // (T | U)[K] -> T[K] | U[K] (reading) // (T | U)[K] -> T[K] & U[K] (writing) // (T & U)[K] -> T[K] & U[K] - if (objectType.flags & ts.TypeFlags.Union || objectType.flags & ts.TypeFlags.Intersection && !shouldDeferIndexType(objectType)) { - const types = ts.map((objectType as ts.UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing)); - return objectType.flags & ts.TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types); + if (objectType.flags & TypeFlags.Union || objectType.flags & TypeFlags.Intersection && !shouldDeferIndexType(objectType)) { + const types = map((objectType as UnionOrIntersectionType).types, t => getSimplifiedType(getIndexedAccessType(t, indexType), writing)); + return objectType.flags & TypeFlags.Intersection || writing ? getIntersectionType(types) : getUnionType(types); } } - function distributeObjectOverIndexType(objectType: ts.Type, indexType: ts.Type, writing: boolean) { + function distributeObjectOverIndexType(objectType: Type, indexType: Type, writing: boolean) { // T[A | B] -> T[A] | T[B] (reading) // T[A | B] -> T[A] & T[B] (writing) - if (indexType.flags & ts.TypeFlags.Union) { - const types = ts.map((indexType as ts.UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t), writing)); + if (indexType.flags & TypeFlags.Union) { + const types = map((indexType as UnionType).types, t => getSimplifiedType(getIndexedAccessType(objectType, t), writing)); return writing ? getIntersectionType(types) : getUnionType(types); } } @@ -16044,7 +16242,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Transform an indexed access to a simpler form, if possible. Return the simpler form, or return // the type itself if no transformation is possible. The writing flag indicates that the type is // the target of an assignment. - function getSimplifiedIndexedAccessType(type: ts.IndexedAccessType, writing: boolean): ts.Type { + function getSimplifiedIndexedAccessType(type: IndexedAccessType, writing: boolean): Type { const cache = writing ? "simplifiedForWriting" : "simplifiedForReading"; if (type[cache]) { return type[cache] === circularConstraintType ? type : type[cache]!; @@ -16061,7 +16259,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type[cache] = distributedOverIndex; } // Only do the inner distributions if the index can no longer be instantiated to cause index distribution again - if (!(indexType.flags & ts.TypeFlags.Instantiable)) { + if (!(indexType.flags & TypeFlags.Instantiable)) { // (T | U)[K] -> T[K] | U[K] (reading) // (T | U)[K] -> T[K] & U[K] (writing) // (T & U)[K] -> T[K] & U[K] @@ -16076,8 +16274,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // A generic tuple type indexed by a number exists only when the index type doesn't select a // fixed element. We simplify to either the combined type of all elements (when the index type // the actual number type) or to the combined type of all non-fixed elements. - if (isGenericTupleType(objectType) && indexType.flags & ts.TypeFlags.NumberLike) { - const elementType = getElementTypeOfSliceOfTupleType(objectType, indexType.flags & ts.TypeFlags.Number ? 0 : objectType.target.fixedLength, /*endSkipCount*/ 0, writing); + if (isGenericTupleType(objectType) && indexType.flags & TypeFlags.NumberLike) { + const elementType = getElementTypeOfSliceOfTupleType(objectType, indexType.flags & TypeFlags.Number ? 0 : objectType.target.fixedLength, /*endSkipCount*/ 0, writing); if (elementType) { return type[cache] = elementType; } @@ -16094,25 +16292,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type[cache] = type; } - function getSimplifiedConditionalType(type: ts.ConditionalType, writing: boolean) { + function getSimplifiedConditionalType(type: ConditionalType, writing: boolean) { const checkType = type.checkType; const extendsType = type.extendsType; const trueType = getTrueTypeFromConditionalType(type); const falseType = getFalseTypeFromConditionalType(type); // Simplifications for types of the form `T extends U ? T : never` and `T extends U ? never : T`. - if (falseType.flags & ts.TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) { - if (checkType.flags & ts.TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true + if (falseType.flags & TypeFlags.Never && getActualTypeVariable(trueType) === getActualTypeVariable(checkType)) { + if (checkType.flags & TypeFlags.Any || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true return getSimplifiedType(trueType, writing); } else if (isIntersectionEmpty(checkType, extendsType)) { // Always false return neverType; } } - else if (trueType.flags & ts.TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) { - if (!(checkType.flags & ts.TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true + else if (trueType.flags & TypeFlags.Never && getActualTypeVariable(falseType) === getActualTypeVariable(checkType)) { + if (!(checkType.flags & TypeFlags.Any) && isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(extendsType))) { // Always true return neverType; } - else if (checkType.flags & ts.TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false + else if (checkType.flags & TypeFlags.Any || isIntersectionEmpty(checkType, extendsType)) { // Always false return getSimplifiedType(falseType, writing); } } @@ -16122,25 +16320,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Invokes union simplification logic to determine if an intersection is considered empty as a union constituent */ - function isIntersectionEmpty(type1: ts.Type, type2: ts.Type) { - return !!(getUnionType([intersectTypes(type1, type2), neverType]).flags & ts.TypeFlags.Never); + function isIntersectionEmpty(type1: Type, type2: Type) { + return !!(getUnionType([intersectTypes(type1, type2), neverType]).flags & TypeFlags.Never); } - function substituteIndexedMappedType(objectType: ts.MappedType, index: ts.Type) { + function substituteIndexedMappedType(objectType: MappedType, index: Type) { const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]); const templateMapper = combineTypeMappers(objectType.mapper, mapper); - return instantiateType(getTemplateTypeFromMappedType(objectType.target as ts.MappedType || objectType), templateMapper); + return instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper); } - function getIndexedAccessType(objectType: ts.Type, indexType: ts.Type, accessFlags = ts.AccessFlags.None, accessNode?: ts.ElementAccessExpression | ts.IndexedAccessTypeNode | ts.PropertyName | ts.BindingName | ts.SyntheticExpression, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type { + function getIndexedAccessType(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { return getIndexedAccessTypeOrUndefined(objectType, indexType, accessFlags, accessNode, aliasSymbol, aliasTypeArguments) || (accessNode ? errorType : unknownType); } - function indexTypeLessThan(indexType: ts.Type, limit: number) { + function indexTypeLessThan(indexType: Type, limit: number) { return everyType(indexType, t => { - if (t.flags & ts.TypeFlags.StringOrNumberLiteral) { - const propName = getPropertyNameFromType(t as ts.StringLiteralType | ts.NumberLiteralType); - if (ts.isNumericLiteralName(propName)) { + if (t.flags & TypeFlags.StringOrNumberLiteral) { + const propName = getPropertyNameFromType(t as StringLiteralType | NumberLiteralType); + if (isNumericLiteralName(propName)) { const index = +propName; return index >= 0 && index < limit; } @@ -16149,32 +16347,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function getIndexedAccessTypeOrUndefined(objectType: ts.Type, indexType: ts.Type, accessFlags = ts.AccessFlags.None, accessNode?: ts.ElementAccessExpression | ts.IndexedAccessTypeNode | ts.PropertyName | ts.BindingName | ts.SyntheticExpression, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type | undefined { + function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessFlags = AccessFlags.None, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type | undefined { if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } // If the object type has a string index signature and no other members we know that the result will // always be the type of that index signature and we can simplify accordingly. - if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & ts.TypeFlags.Nullable) && isTypeAssignableToKind(indexType, ts.TypeFlags.String | ts.TypeFlags.Number)) { + if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { indexType = stringType; } // In noUncheckedIndexedAccess mode, indexed access operations that occur in an expression in a read position and resolve to // an index signature have 'undefined' included in their type. - if (compilerOptions.noUncheckedIndexedAccess && accessFlags & ts.AccessFlags.ExpressionPosition) accessFlags |= ts.AccessFlags.IncludeUndefined; + if (compilerOptions.noUncheckedIndexedAccess && accessFlags & AccessFlags.ExpressionPosition) accessFlags |= AccessFlags.IncludeUndefined; // If the index type is generic, or if the object type is generic and doesn't originate in an expression and // the operation isn't exclusively indexing the fixed (non-variadic) portion of a tuple type, we are performing // a higher-order index access where we cannot meaningfully access the properties of the object type. Note that // for a generic T and a non-generic K, we eagerly resolve T[K] if it originates in an expression. This is to // preserve backwards compatibility. For example, an element access 'this["foo"]' has always been resolved // eagerly using the constraint type of 'this' at the given location. - if (isGenericIndexType(indexType) || (accessNode && accessNode.kind !== ts.SyntaxKind.IndexedAccessType ? + if (isGenericIndexType(indexType) || (accessNode && accessNode.kind !== SyntaxKind.IndexedAccessType ? isGenericTupleType(objectType) && !indexTypeLessThan(indexType, objectType.target.fixedLength) : isGenericObjectType(objectType) && !(isTupleType(objectType) && indexTypeLessThan(indexType, objectType.target.fixedLength)))) { - if (objectType.flags & ts.TypeFlags.AnyOrUnknown) { + if (objectType.flags & TypeFlags.AnyOrUnknown) { return objectType; } // Defer the operation by creating an indexed access type. - const persistentAccessFlags = accessFlags & ts.AccessFlags.Persistent; + const persistentAccessFlags = accessFlags & AccessFlags.Persistent; const id = objectType.id + "," + indexType.id + "," + persistentAccessFlags + getAliasId(aliasSymbol, aliasTypeArguments); let type = indexedAccessTypes.get(id); if (!type) { @@ -16187,11 +16385,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We treat boolean as different from other unions to improve errors; // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'. const apparentObjectType = getReducedApparentType(objectType); - if (indexType.flags & ts.TypeFlags.Union && !(indexType.flags & ts.TypeFlags.Boolean)) { - const propTypes: ts.Type[] = []; + if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) { + const propTypes: Type[] = []; let wasMissingProp = false; - for (const t of (indexType as ts.UnionType).types) { - const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, indexType, accessNode, accessFlags | (wasMissingProp ? ts.AccessFlags.SuppressNoImplicitAnyError : 0)); + for (const t of (indexType as UnionType).types) { + const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, indexType, accessNode, accessFlags | (wasMissingProp ? AccessFlags.SuppressNoImplicitAnyError : 0)); if (propType) { propTypes.push(propType); } @@ -16207,28 +16405,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (wasMissingProp) { return undefined; } - return accessFlags & ts.AccessFlags.Writing + return accessFlags & AccessFlags.Writing ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) - : getUnionType(propTypes, ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + : getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, accessNode, accessFlags | ts.AccessFlags.CacheSymbol | ts.AccessFlags.ReportDeprecated); + return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, accessNode, accessFlags | AccessFlags.CacheSymbol | AccessFlags.ReportDeprecated); } - function getTypeFromIndexedAccessTypeNode(node: ts.IndexedAccessTypeNode) { + function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { const links = getNodeLinks(node); if (!links.resolvedType) { const objectType = getTypeFromTypeNode(node.objectType); const indexType = getTypeFromTypeNode(node.indexType); const potentialAlias = getAliasSymbolForTypeNode(node); - links.resolvedType = getIndexedAccessType(objectType, indexType, ts.AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias)); + links.resolvedType = getIndexedAccessType(objectType, indexType, AccessFlags.None, node, potentialAlias, getTypeArgumentsForAliasSymbol(potentialAlias)); } return links.resolvedType; } - function getTypeFromMappedTypeNode(node: ts.MappedTypeNode): ts.Type { + function getTypeFromMappedTypeNode(node: MappedTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - const type = createObjectType(ts.ObjectFlags.Mapped, node.symbol) as ts.MappedType; + const type = createObjectType(ObjectFlags.Mapped, node.symbol) as MappedType; type.declaration = node; type.aliasSymbol = getAliasSymbolForTypeNode(node); type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(type.aliasSymbol); @@ -16240,33 +16438,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function getActualTypeVariable(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Substitution) { - return (type as ts.SubstitutionType).baseType; + function getActualTypeVariable(type: Type): Type { + if (type.flags & TypeFlags.Substitution) { + return (type as SubstitutionType).baseType; } - if (type.flags & ts.TypeFlags.IndexedAccess && ( - (type as ts.IndexedAccessType).objectType.flags & ts.TypeFlags.Substitution || - (type as ts.IndexedAccessType).indexType.flags & ts.TypeFlags.Substitution)) { - return getIndexedAccessType(getActualTypeVariable((type as ts.IndexedAccessType).objectType), getActualTypeVariable((type as ts.IndexedAccessType).indexType)); + if (type.flags & TypeFlags.IndexedAccess && ( + (type as IndexedAccessType).objectType.flags & TypeFlags.Substitution || + (type as IndexedAccessType).indexType.flags & TypeFlags.Substitution)) { + return getIndexedAccessType(getActualTypeVariable((type as IndexedAccessType).objectType), getActualTypeVariable((type as IndexedAccessType).indexType)); } return type; } - function maybeCloneTypeParameter(p: ts.TypeParameter) { + function maybeCloneTypeParameter(p: TypeParameter) { const constraint = getConstraintOfTypeParameter(p); return constraint && (isGenericObjectType(constraint) || isGenericIndexType(constraint)) ? cloneTypeParameter(p) : p; } - function isTypicalNondistributiveConditional(root: ts.ConditionalRoot) { + function isTypicalNondistributiveConditional(root: ConditionalRoot) { return !root.isDistributive && isSingletonTupleType(root.node.checkType) && isSingletonTupleType(root.node.extendsType); } - function isSingletonTupleType(node: ts.TypeNode) { - return ts.isTupleTypeNode(node) && - ts.length(node.elements) === 1 && - !ts.isOptionalTypeNode(node.elements[0]) && - !ts.isRestTypeNode(node.elements[0]) && - !(ts.isNamedTupleMember(node.elements[0]) && (node.elements[0].questionToken || node.elements[0].dotDotDotToken)); + function isSingletonTupleType(node: TypeNode) { + return isTupleTypeNode(node) && + length(node.elements) === 1 && + !isOptionalTypeNode(node.elements[0]) && + !isRestTypeNode(node.elements[0]) && + !(isNamedTupleMember(node.elements[0]) && (node.elements[0].questionToken || node.elements[0].dotDotDotToken)); } /** @@ -16274,13 +16472,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * the intended comparison - we do this so we can check if the unwrapped types are generic or * not and appropriately defer condition calculation */ - function unwrapNondistributiveConditionalTuple(root: ts.ConditionalRoot, type: ts.Type) { + function unwrapNondistributiveConditionalTuple(root: ConditionalRoot, type: Type) { return isTypicalNondistributiveConditional(root) && isTupleType(type) ? getTypeArguments(type)[0] : type; } - function getConditionalType(root: ts.ConditionalRoot, mapper: ts.TypeMapper | undefined, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type { + function getConditionalType(root: ConditionalRoot, mapper: TypeMapper | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { let result; - let extraTypes: ts.Type[] | undefined; + let extraTypes: Type[] | undefined; let tailCount = 0; // We loop here for an immediately nested conditional type in the false position, effectively treating // types of the form 'A extends B ? X : C extends D ? Y : E extends F ? Z : ...' as a single construct for @@ -16289,7 +16487,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // cases we increment the tail recursion counter and stop after 1000 iterations. while (true) { if (tailCount === 1000) { - error(currentNode, ts.Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); + error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); result = errorType; break; } @@ -16300,7 +16498,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (checkType === wildcardType || extendsType === wildcardType) { return wildcardType; } - let combinedMapper: ts.TypeMapper | undefined; + let combinedMapper: TypeMapper | undefined; if (root.inferTypeParameters) { // When we're looking at making an inference for an infer type, when we get its constraint, it'll automagically be // instantiated with the context, so it doesn't need the mapper for the inference contex - however the constraint @@ -16319,9 +16517,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // * The original `mapper` used to create this conditional // * The mapper that maps the old root type parameter to the clone (`freshMapper`) // * The mapper that maps the clone to its inference result (`context.mapper`) - const freshParams = ts.sameMap(root.inferTypeParameters, maybeCloneTypeParameter); + const freshParams = sameMap(root.inferTypeParameters, maybeCloneTypeParameter); const freshMapper = freshParams !== root.inferTypeParameters ? createTypeMapper(root.inferTypeParameters, freshParams) : undefined; - const context = createInferenceContext(freshParams, /*signature*/ undefined, ts.InferenceFlags.None); + const context = createInferenceContext(freshParams, /*signature*/ undefined, InferenceFlags.None); if (freshMapper) { const freshCombinedMapper = combineTypeMappers(mapper, freshMapper); for (const p of freshParams) { @@ -16334,7 +16532,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We don't want inferences from constraints as they may cause us to eagerly resolve the // conditional type instead of deferring resolution. Also, we always want strict function // types rules (i.e. proper contravariance) for inferences. - inferTypes(context.inferences, checkType, instantiateType(extendsType, freshMapper), ts.InferencePriority.NoConstraints | ts.InferencePriority.AlwaysStrict); + inferTypes(context.inferences, checkType, instantiateType(extendsType, freshMapper), InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); } const innerMapper = combineTypeMappers(freshMapper, context.mapper); // It's possible for 'infer T' type paramteters to be given uninstantiated constraints when the @@ -16350,16 +16548,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // types with type parameters mapped to the wildcard type, the most permissive instantiations // possible (the wildcard type is assignable to and from all types). If those are not related, // then no instantiations will be and we can just return the false branch type. - if (!(inferredExtendsType.flags & ts.TypeFlags.AnyOrUnknown) && ((checkType.flags & ts.TypeFlags.Any && !isUnwrapped) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) { + if (!(inferredExtendsType.flags & TypeFlags.AnyOrUnknown) && ((checkType.flags & TypeFlags.Any && !isUnwrapped) || !isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType)))) { // Return union of trueType and falseType for 'any' since it matches anything - if (checkType.flags & ts.TypeFlags.Any && !isUnwrapped) { + if (checkType.flags & TypeFlags.Any && !isUnwrapped) { (extraTypes || (extraTypes = [])).push(instantiateType(getTypeFromTypeNode(root.node.trueType), combinedMapper || mapper)); } // If falseType is an immediately nested conditional type that isn't distributive or has an // identical checkType, switch to that type and loop. const falseType = getTypeFromTypeNode(root.node.falseType); - if (falseType.flags & ts.TypeFlags.Conditional) { - const newRoot = (falseType as ts.ConditionalType).root; + if (falseType.flags & TypeFlags.Conditional) { + const newRoot = (falseType as ConditionalType).root; if (newRoot.node.parent === root.node && (!newRoot.isDistributive || newRoot.checkType === root.checkType)) { root = newRoot; continue; @@ -16376,7 +16574,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // that has no constraint. This ensures that, for example, the type // type Foo = T extends { x: string } ? string : number // doesn't immediately resolve to 'string' instead of being deferred. - if (inferredExtendsType.flags & ts.TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { + if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { const trueType = getTypeFromTypeNode(root.node.trueType); const trueMapper = combinedMapper || mapper; if (canTailRecurse(trueType, trueMapper)) { @@ -16387,7 +16585,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } // Return a deferred type for a check that is neither definitely true nor definitely false - result = createType(ts.TypeFlags.Conditional) as ts.ConditionalType; + result = createType(TypeFlags.Conditional) as ConditionalType; result.root = root; result.checkType = instantiateType(root.checkType, mapper); result.extendsType = instantiateType(root.extendsType, mapper); @@ -16397,20 +16595,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result.aliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(root.aliasTypeArguments, mapper!); // TODO: GH#18217 break; } - return extraTypes ? getUnionType(ts.append(extraTypes, result)) : result; + return extraTypes ? getUnionType(append(extraTypes, result)) : result; // We tail-recurse for generic conditional types that (a) have not already been evaluated and cached, and // (b) are non distributive, have a check type that is unaffected by instantiation, or have a non-union check // type. Note that recursion is possible only through aliased conditional types, so we only increment the tail // recursion counter for those. - function canTailRecurse(newType: ts.Type, newMapper: ts.TypeMapper | undefined) { - if (newType.flags & ts.TypeFlags.Conditional && newMapper) { - const newRoot = (newType as ts.ConditionalType).root; + function canTailRecurse(newType: Type, newMapper: TypeMapper | undefined) { + if (newType.flags & TypeFlags.Conditional && newMapper) { + const newRoot = (newType as ConditionalType).root; if (newRoot.outerTypeParameters) { - const typeParamMapper = combineTypeMappers((newType as ts.ConditionalType).mapper, newMapper); - const typeArguments = ts.map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper)); + const typeParamMapper = combineTypeMappers((newType as ConditionalType).mapper, newMapper); + const typeArguments = map(newRoot.outerTypeParameters, t => getMappedType(t, typeParamMapper)); const newRootMapper = createTypeMapper(newRoot.outerTypeParameters, typeArguments); const newCheckType = newRoot.isDistributive ? getMappedType(newRoot.checkType, newRootMapper) : undefined; - if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (ts.TypeFlags.Union | ts.TypeFlags.Never))) { + if (!newCheckType || newCheckType === newRoot.checkType || !(newCheckType.flags & (TypeFlags.Union | TypeFlags.Never))) { root = newRoot; mapper = newRootMapper; aliasSymbol = undefined; @@ -16426,49 +16624,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTrueTypeFromConditionalType(type: ts.ConditionalType) { + function getTrueTypeFromConditionalType(type: ConditionalType) { return type.resolvedTrueType || (type.resolvedTrueType = instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.mapper)); } - function getFalseTypeFromConditionalType(type: ts.ConditionalType) { + function getFalseTypeFromConditionalType(type: ConditionalType) { return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(getTypeFromTypeNode(type.root.node.falseType), type.mapper)); } - function getInferredTrueTypeFromConditionalType(type: ts.ConditionalType) { + function getInferredTrueTypeFromConditionalType(type: ConditionalType) { return type.resolvedInferredTrueType || (type.resolvedInferredTrueType = type.combinedMapper ? instantiateType(getTypeFromTypeNode(type.root.node.trueType), type.combinedMapper) : getTrueTypeFromConditionalType(type)); } - function getInferTypeParameters(node: ts.ConditionalTypeNode): ts.TypeParameter[] | undefined { - let result: ts.TypeParameter[] | undefined; + function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] | undefined { + let result: TypeParameter[] | undefined; if (node.locals) { node.locals.forEach(symbol => { - if (symbol.flags & ts.SymbolFlags.TypeParameter) { - result = ts.append(result, getDeclaredTypeOfSymbol(symbol)); + if (symbol.flags & SymbolFlags.TypeParameter) { + result = append(result, getDeclaredTypeOfSymbol(symbol)); } }); } return result; } - function isDistributionDependent(root: ts.ConditionalRoot) { + function isDistributionDependent(root: ConditionalRoot) { return root.isDistributive && ( - isTypeParameterPossiblyReferenced(root.checkType as ts.TypeParameter, root.node.trueType) || - isTypeParameterPossiblyReferenced(root.checkType as ts.TypeParameter, root.node.falseType)); + isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.trueType) || + isTypeParameterPossiblyReferenced(root.checkType as TypeParameter, root.node.falseType)); } - function getTypeFromConditionalTypeNode(node: ts.ConditionalTypeNode): ts.Type { + function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { const checkType = getTypeFromTypeNode(node.checkType); const aliasSymbol = getAliasSymbolForTypeNode(node); const aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true); - const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : ts.filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node)); - const root: ts.ConditionalRoot = { + const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node)); + const root: ConditionalRoot = { node, checkType, extendsType: getTypeFromTypeNode(node.extendsType), - isDistributive: !!(checkType.flags & ts.TypeFlags.TypeParameter), + isDistributive: !!(checkType.flags & TypeFlags.TypeParameter), inferTypeParameters: getInferTypeParameters(node), outerTypeParameters, instantiations: undefined, @@ -16477,14 +16675,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; links.resolvedType = getConditionalType(root, /*mapper*/ undefined); if (outerTypeParameters) { - root.instantiations = new ts.Map(); + root.instantiations = new Map(); root.instantiations.set(getTypeListId(outerTypeParameters), links.resolvedType); } } return links.resolvedType; } - function getTypeFromInferTypeNode(node: ts.InferTypeNode): ts.Type { + function getTypeFromInferTypeNode(node: InferTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)); @@ -16492,54 +16690,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function getIdentifierChain(node: ts.EntityName): ts.Identifier[] { - if (ts.isIdentifier(node)) { + function getIdentifierChain(node: EntityName): Identifier[] { + if (isIdentifier(node)) { return [node]; } else { - return ts.append(getIdentifierChain(node.left), node.right); + return append(getIdentifierChain(node.left), node.right); } } - function getTypeFromImportTypeNode(node: ts.ImportTypeNode): ts.Type { + function getTypeFromImportTypeNode(node: ImportTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { if (node.isTypeOf && node.typeArguments) { // Only the non-typeof form can make use of type arguments - error(node, ts.Diagnostics.Type_arguments_cannot_be_used_here); + error(node, Diagnostics.Type_arguments_cannot_be_used_here); links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - if (!ts.isLiteralImportTypeNode(node)) { - error(node.argument, ts.Diagnostics.String_literal_expected); + if (!isLiteralImportTypeNode(node)) { + error(node.argument, Diagnostics.String_literal_expected); links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - const targetMeaning = node.isTypeOf ? ts.SymbolFlags.Value : node.flags & ts.NodeFlags.JSDoc ? ts.SymbolFlags.Value | ts.SymbolFlags.Type : ts.SymbolFlags.Type; + const targetMeaning = node.isTypeOf ? SymbolFlags.Value : node.flags & NodeFlags.JSDoc ? SymbolFlags.Value | SymbolFlags.Type : SymbolFlags.Type; // TODO: Future work: support unions/generics/whatever via a deferred import-type const innerModuleSymbol = resolveExternalModuleName(node, node.argument.literal); if (!innerModuleSymbol) { links.resolvedSymbol = unknownSymbol; return links.resolvedType = errorType; } - const isExportEquals = !!innerModuleSymbol.exports?.get(ts.InternalSymbolName.ExportEquals); + const isExportEquals = !!innerModuleSymbol.exports?.get(InternalSymbolName.ExportEquals); const moduleSymbol = resolveExternalModuleSymbol(innerModuleSymbol, /*dontResolveAlias*/ false); - if (!ts.nodeIsMissing(node.qualifier)) { - const nameStack: ts.Identifier[] = getIdentifierChain(node.qualifier!); + if (!nodeIsMissing(node.qualifier)) { + const nameStack: Identifier[] = getIdentifierChain(node.qualifier!); let currentNamespace = moduleSymbol; - let current: ts.Identifier | undefined; + let current: Identifier | undefined; while (current = nameStack.shift()) { - const meaning = nameStack.length ? ts.SymbolFlags.Namespace : targetMeaning; + const meaning = nameStack.length ? SymbolFlags.Namespace : targetMeaning; // typeof a.b.c is normally resolved using `checkExpression` which in turn defers to `checkQualifiedName` // That, in turn, ultimately uses `getPropertyOfType` on the type of the symbol, which differs slightly from // the `exports` lookup process that only looks up namespace members which is used for most type references const mergedResolvedSymbol = getMergedSymbol(resolveSymbol(currentNamespace)); - const symbolFromVariable = node.isTypeOf || ts.isInJSFile(node) && isExportEquals + const symbolFromVariable = node.isTypeOf || isInJSFile(node) && isExportEquals ? getPropertyOfType(getTypeOfSymbol(mergedResolvedSymbol), current.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ true) : undefined; const symbolFromModule = node.isTypeOf ? undefined : getSymbol(getExportsOfSymbol(mergedResolvedSymbol), current.escapedText, meaning); const next = symbolFromModule ?? symbolFromVariable; if (!next) { - error(current, ts.Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), ts.declarationNameToString(current)); + error(current, Diagnostics.Namespace_0_has_no_exported_member_1, getFullyQualifiedName(currentNamespace), declarationNameToString(current)); return links.resolvedType = errorType; } getNodeLinks(current).resolvedSymbol = next; @@ -16553,9 +16751,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { links.resolvedType = resolveImportSymbolType(node, links, moduleSymbol, targetMeaning); } else { - const errorMessage = targetMeaning === ts.SymbolFlags.Value - ? ts.Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here - : ts.Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0; + const errorMessage = targetMeaning === SymbolFlags.Value + ? Diagnostics.Module_0_does_not_refer_to_a_value_but_is_used_as_a_value_here + : Diagnostics.Module_0_does_not_refer_to_a_type_but_is_used_as_a_type_here_Did_you_mean_typeof_import_0; error(node, errorMessage, node.argument.literal.text); @@ -16567,10 +16765,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function resolveImportSymbolType(node: ts.ImportTypeNode, links: ts.NodeLinks, symbol: ts.Symbol, meaning: ts.SymbolFlags) { + function resolveImportSymbolType(node: ImportTypeNode, links: NodeLinks, symbol: Symbol, meaning: SymbolFlags) { const resolvedSymbol = resolveSymbol(symbol); links.resolvedSymbol = resolvedSymbol; - if (meaning === ts.SymbolFlags.Value) { + if (meaning === SymbolFlags.Value) { return getTypeOfSymbol(symbol); // intentionally doesn't use resolved symbol so type is cached as expected on the alias } else { @@ -16578,7 +16776,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: ts.TypeNode): ts.Type { + function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers @@ -16587,10 +16785,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { links.resolvedType = emptyTypeLiteralType; } else { - let type = createObjectType(ts.ObjectFlags.Anonymous, node.symbol); + let type = createObjectType(ObjectFlags.Anonymous, node.symbol); type.aliasSymbol = aliasSymbol; type.aliasTypeArguments = getTypeArgumentsForAliasSymbol(aliasSymbol); - if (ts.isJSDocTypeLiteral(node) && node.isArrayType) { + if (isJSDocTypeLiteral(node) && node.isArrayType) { type = createArrayType(type); } links.resolvedType = type; @@ -16599,54 +16797,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function getAliasSymbolForTypeNode(node: ts.Node) { + function getAliasSymbolForTypeNode(node: Node) { let host = node.parent; - while (ts.isParenthesizedTypeNode(host) || ts.isJSDocTypeExpression(host) || ts.isTypeOperatorNode(host) && host.operator === ts.SyntaxKind.ReadonlyKeyword) { + while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) { host = host.parent; } - return ts.isTypeAlias(host) ? getSymbolOfNode(host) : undefined; + return isTypeAlias(host) ? getSymbolOfNode(host) : undefined; } - function getTypeArgumentsForAliasSymbol(symbol: ts.Symbol | undefined) { + function getTypeArgumentsForAliasSymbol(symbol: Symbol | undefined) { return symbol ? getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol) : undefined; } - function isNonGenericObjectType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.Object) && !isGenericMappedType(type); + function isNonGenericObjectType(type: Type) { + return !!(type.flags & TypeFlags.Object) && !isGenericMappedType(type); } - function isEmptyObjectTypeOrSpreadsIntoEmptyObject(type: ts.Type) { - return isEmptyObjectType(type) || !!(type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.BooleanLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.StringLike | ts.TypeFlags.EnumLike | ts.TypeFlags.NonPrimitive | ts.TypeFlags.Index)); + function isEmptyObjectTypeOrSpreadsIntoEmptyObject(type: Type) { + return isEmptyObjectType(type) || !!(type.flags & (TypeFlags.Null | TypeFlags.Undefined | TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)); } - function tryMergeUnionOfObjectTypeAndEmptyObject(type: ts.Type, readonly: boolean): ts.Type { - if (!(type.flags & ts.TypeFlags.Union)) { + function tryMergeUnionOfObjectTypeAndEmptyObject(type: Type, readonly: boolean): Type { + if (!(type.flags & TypeFlags.Union)) { return type; } - if (ts.every((type as ts.UnionType).types, isEmptyObjectTypeOrSpreadsIntoEmptyObject)) { - return ts.find((type as ts.UnionType).types, isEmptyObjectType) || emptyObjectType; + if (every((type as UnionType).types, isEmptyObjectTypeOrSpreadsIntoEmptyObject)) { + return find((type as UnionType).types, isEmptyObjectType) || emptyObjectType; } - const firstType = ts.find((type as ts.UnionType).types, t => !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t)); + const firstType = find((type as UnionType).types, t => !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t)); if (!firstType) { return type; } - const secondType = ts.find((type as ts.UnionType).types, t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t)); + const secondType = find((type as UnionType).types, t => t !== firstType && !isEmptyObjectTypeOrSpreadsIntoEmptyObject(t)); if (secondType) { return type; } return getAnonymousPartialType(firstType); - function getAnonymousPartialType(type: ts.Type) { + function getAnonymousPartialType(type: Type) { // gets the type as if it had been spread, but where everything in the spread is made optional - const members = ts.createSymbolTable(); + const members = createSymbolTable(); for (const prop of getPropertiesOfType(type)) { - if (ts.getDeclarationModifierFlagsFromSymbol(prop) & (ts.ModifierFlags.Private | ts.ModifierFlags.Protected)) { + if (getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) { // do nothing, skip privates } else if (isSpreadableProperty(prop)) { - const isSetonlyAccessor = prop.flags & ts.SymbolFlags.SetAccessor && !(prop.flags & ts.SymbolFlags.GetAccessor); - const flags = ts.SymbolFlags.Property | ts.SymbolFlags.Optional; - const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? ts.CheckFlags.Readonly : 0)); + const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); + const flags = SymbolFlags.Property | SymbolFlags.Optional; + const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true); result.declarations = prop.declarations; result.nameType = getSymbolLinks(prop).nameType; @@ -16654,8 +16852,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { members.set(prop.escapedName, result); } } - const spread = createAnonymousType(type.symbol, members, ts.emptyArray, ts.emptyArray, getIndexInfosOfType(type)); - spread.objectFlags |= ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral; + const spread = createAnonymousType(type.symbol, members, emptyArray, emptyArray, getIndexInfosOfType(type)); + spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; return spread; } } @@ -16665,32 +16863,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * this function should be called in a left folding style, with left = previous result of getSpreadType * and right = the new element to be spread. */ - function getSpreadType(left: ts.Type, right: ts.Type, symbol: ts.Symbol | undefined, objectFlags: ts.ObjectFlags, readonly: boolean): ts.Type { - if (left.flags & ts.TypeFlags.Any || right.flags & ts.TypeFlags.Any) { + function getSpreadType(left: Type, right: Type, symbol: Symbol | undefined, objectFlags: ObjectFlags, readonly: boolean): Type { + if (left.flags & TypeFlags.Any || right.flags & TypeFlags.Any) { return anyType; } - if (left.flags & ts.TypeFlags.Unknown || right.flags & ts.TypeFlags.Unknown) { + if (left.flags & TypeFlags.Unknown || right.flags & TypeFlags.Unknown) { return unknownType; } - if (left.flags & ts.TypeFlags.Never) { + if (left.flags & TypeFlags.Never) { return right; } - if (right.flags & ts.TypeFlags.Never) { + if (right.flags & TypeFlags.Never) { return left; } left = tryMergeUnionOfObjectTypeAndEmptyObject(left, readonly); - if (left.flags & ts.TypeFlags.Union) { + if (left.flags & TypeFlags.Union) { return checkCrossProductUnion([left, right]) ? mapType(left, t => getSpreadType(t, right, symbol, objectFlags, readonly)) : errorType; } right = tryMergeUnionOfObjectTypeAndEmptyObject(right, readonly); - if (right.flags & ts.TypeFlags.Union) { + if (right.flags & TypeFlags.Union) { return checkCrossProductUnion([left, right]) ? mapType(right, t => getSpreadType(left, t, symbol, objectFlags, readonly)) : errorType; } - if (right.flags & (ts.TypeFlags.BooleanLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.StringLike | ts.TypeFlags.EnumLike | ts.TypeFlags.NonPrimitive | ts.TypeFlags.Index)) { + if (right.flags & (TypeFlags.BooleanLike | TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.EnumLike | TypeFlags.NonPrimitive | TypeFlags.Index)) { return left; } @@ -16701,22 +16899,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When the left type is an intersection, we may need to merge the last constituent of the // intersection with the right type. For example when the left type is 'T & { a: string }' // and the right type is '{ b: string }' we produce 'T & { a: string, b: string }'. - if (left.flags & ts.TypeFlags.Intersection) { - const types = (left as ts.IntersectionType).types; + if (left.flags & TypeFlags.Intersection) { + const types = (left as IntersectionType).types; const lastLeft = types[types.length - 1]; if (isNonGenericObjectType(lastLeft) && isNonGenericObjectType(right)) { - return getIntersectionType(ts.concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)])); + return getIntersectionType(concatenate(types.slice(0, types.length - 1), [getSpreadType(lastLeft, right, symbol, objectFlags, readonly)])); } } return getIntersectionType([left, right]); } - const members = ts.createSymbolTable(); - const skippedPrivateMembers = new ts.Set(); + const members = createSymbolTable(); + const skippedPrivateMembers = new Set<__String>(); const indexInfos = left === emptyObjectType ? getIndexInfosOfType(right) : getUnionIndexInfos([left, right]); for (const rightProp of getPropertiesOfType(right)) { - if (ts.getDeclarationModifierFlagsFromSymbol(rightProp) & (ts.ModifierFlags.Private | ts.ModifierFlags.Protected)) { + if (getDeclarationModifierFlagsFromSymbol(rightProp) & (ModifierFlags.Private | ModifierFlags.Protected)) { skippedPrivateMembers.add(rightProp.escapedName); } else if (isSpreadableProperty(rightProp)) { @@ -16731,11 +16929,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (members.has(leftProp.escapedName)) { const rightProp = members.get(leftProp.escapedName)!; const rightType = getTypeOfSymbol(rightProp); - if (rightProp.flags & ts.SymbolFlags.Optional) { - const declarations = ts.concatenate(leftProp.declarations, rightProp.declarations); - const flags = ts.SymbolFlags.Property | (leftProp.flags & ts.SymbolFlags.Optional); + if (rightProp.flags & SymbolFlags.Optional) { + const declarations = concatenate(leftProp.declarations, rightProp.declarations); + const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional); const result = createSymbol(flags, leftProp.escapedName); - result.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType)], ts.UnionReduction.Subtype); + result.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType)], UnionReduction.Subtype); result.leftSpread = leftProp; result.rightSpread = rightProp; result.declarations = declarations; @@ -16748,25 +16946,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - const spread = createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, ts.sameMap(indexInfos, info => getIndexInfoWithReadonly(info, readonly))); - spread.objectFlags |= ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral | ts.ObjectFlags.ContainsSpread | objectFlags; + const spread = createAnonymousType(symbol, members, emptyArray, emptyArray, sameMap(indexInfos, info => getIndexInfoWithReadonly(info, readonly))); + spread.objectFlags |= ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral | ObjectFlags.ContainsSpread | objectFlags; return spread; } /** We approximate own properties as non-methods plus methods that are inside the object literal */ - function isSpreadableProperty(prop: ts.Symbol): boolean { - return !ts.some(prop.declarations, ts.isPrivateIdentifierClassElementDeclaration) && - (!(prop.flags & (ts.SymbolFlags.Method | ts.SymbolFlags.GetAccessor | ts.SymbolFlags.SetAccessor)) || - !prop.declarations?.some(decl => ts.isClassLike(decl.parent))); + function isSpreadableProperty(prop: Symbol): boolean { + return !some(prop.declarations, isPrivateIdentifierClassElementDeclaration) && + (!(prop.flags & (SymbolFlags.Method | SymbolFlags.GetAccessor | SymbolFlags.SetAccessor)) || + !prop.declarations?.some(decl => isClassLike(decl.parent))); } - function getSpreadSymbol(prop: ts.Symbol, readonly: boolean) { - const isSetonlyAccessor = prop.flags & ts.SymbolFlags.SetAccessor && !(prop.flags & ts.SymbolFlags.GetAccessor); + function getSpreadSymbol(prop: Symbol, readonly: boolean) { + const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); if (!isSetonlyAccessor && readonly === isReadonlySymbol(prop)) { return prop; } - const flags = ts.SymbolFlags.Property | (prop.flags & ts.SymbolFlags.Optional); - const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? ts.CheckFlags.Readonly : 0)); + const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional); + const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop); result.declarations = prop.declarations; result.nameType = getSymbolLinks(prop).nameType; @@ -16774,68 +16972,68 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getIndexInfoWithReadonly(info: ts.IndexInfo, readonly: boolean) { + function getIndexInfoWithReadonly(info: IndexInfo, readonly: boolean) { return info.isReadonly !== readonly ? createIndexInfo(info.keyType, info.type, readonly, info.declaration) : info; } - function createLiteralType(flags: ts.TypeFlags, value: string | number | ts.PseudoBigInt, symbol?: ts.Symbol, regularType?: ts.LiteralType) { - const type = createTypeWithSymbol(flags, symbol!) as ts.LiteralType; + function createLiteralType(flags: TypeFlags, value: string | number | PseudoBigInt, symbol?: Symbol, regularType?: LiteralType) { + const type = createTypeWithSymbol(flags, symbol!) as LiteralType; type.value = value; type.regularType = regularType || type; return type; } - function getFreshTypeOfLiteralType(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Literal) { - if (!(type as ts.LiteralType).freshType) { - const freshType = createLiteralType(type.flags, (type as ts.LiteralType).value, (type as ts.LiteralType).symbol, type as ts.LiteralType); + function getFreshTypeOfLiteralType(type: Type): Type { + if (type.flags & TypeFlags.Literal) { + if (!(type as LiteralType).freshType) { + const freshType = createLiteralType(type.flags, (type as LiteralType).value, (type as LiteralType).symbol, type as LiteralType); freshType.freshType = freshType; - (type as ts.LiteralType).freshType = freshType; + (type as LiteralType).freshType = freshType; } - return (type as ts.LiteralType).freshType; + return (type as LiteralType).freshType; } return type; } - function getRegularTypeOfLiteralType(type: ts.Type): ts.Type { - return type.flags & ts.TypeFlags.Literal ? (type as ts.LiteralType).regularType : - type.flags & ts.TypeFlags.Union ? ((type as ts.UnionType).regularType || ((type as ts.UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as ts.UnionType)) : + function getRegularTypeOfLiteralType(type: Type): Type { + return type.flags & TypeFlags.Literal ? (type as LiteralType).regularType : + type.flags & TypeFlags.Union ? ((type as UnionType).regularType || ((type as UnionType).regularType = mapType(type, getRegularTypeOfLiteralType) as UnionType)) : type; } - function isFreshLiteralType(type: ts.Type) { - return !!(type.flags & ts.TypeFlags.Literal) && (type as ts.LiteralType).freshType === type; + function isFreshLiteralType(type: Type) { + return !!(type.flags & TypeFlags.Literal) && (type as LiteralType).freshType === type; } - function getStringLiteralType(value: string): ts.StringLiteralType { + function getStringLiteralType(value: string): StringLiteralType { let type; return stringLiteralTypes.get(value) || - (stringLiteralTypes.set(value, type = createLiteralType(ts.TypeFlags.StringLiteral, value) as ts.StringLiteralType), type); + (stringLiteralTypes.set(value, type = createLiteralType(TypeFlags.StringLiteral, value) as StringLiteralType), type); } - function getNumberLiteralType(value: number): ts.NumberLiteralType { + function getNumberLiteralType(value: number): NumberLiteralType { let type; return numberLiteralTypes.get(value) || - (numberLiteralTypes.set(value, type = createLiteralType(ts.TypeFlags.NumberLiteral, value) as ts.NumberLiteralType), type); + (numberLiteralTypes.set(value, type = createLiteralType(TypeFlags.NumberLiteral, value) as NumberLiteralType), type); } - function getBigIntLiteralType(value: ts.PseudoBigInt): ts.BigIntLiteralType { + function getBigIntLiteralType(value: PseudoBigInt): BigIntLiteralType { let type; - const key = ts.pseudoBigIntToString(value); + const key = pseudoBigIntToString(value); return bigIntLiteralTypes.get(key) || - (bigIntLiteralTypes.set(key, type = createLiteralType(ts.TypeFlags.BigIntLiteral, value) as ts.BigIntLiteralType), type); + (bigIntLiteralTypes.set(key, type = createLiteralType(TypeFlags.BigIntLiteral, value) as BigIntLiteralType), type); } - function getEnumLiteralType(value: string | number, enumId: number, symbol: ts.Symbol): ts.LiteralType { + function getEnumLiteralType(value: string | number, enumId: number, symbol: Symbol): LiteralType { let type; const key = `${enumId}${typeof value === "string" ? "@" : "#"}${value}`; - const flags = ts.TypeFlags.EnumLiteral | (typeof value === "string" ? ts.TypeFlags.StringLiteral : ts.TypeFlags.NumberLiteral); + const flags = TypeFlags.EnumLiteral | (typeof value === "string" ? TypeFlags.StringLiteral : TypeFlags.NumberLiteral); return enumLiteralTypes.get(key) || (enumLiteralTypes.set(key, type = createLiteralType(flags, value, symbol)), type); } - function getTypeFromLiteralTypeNode(node: ts.LiteralTypeNode): ts.Type { - if (node.literal.kind === ts.SyntaxKind.NullKeyword) { + function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { + if (node.literal.kind === SyntaxKind.NullKeyword) { return nullType; } const links = getNodeLinks(node); @@ -16845,15 +17043,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function createUniqueESSymbolType(symbol: ts.Symbol) { - const type = createTypeWithSymbol(ts.TypeFlags.UniqueESSymbol, symbol) as ts.UniqueESSymbolType; - type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as ts.__String; + function createUniqueESSymbolType(symbol: Symbol) { + const type = createTypeWithSymbol(TypeFlags.UniqueESSymbol, symbol) as UniqueESSymbolType; + type.escapedName = `__@${type.symbol.escapedName}@${getSymbolId(type.symbol)}` as __String; return type; } - function getESSymbolLikeTypeForNode(node: ts.Node) { - if (ts.isValidESSymbolDeclaration(node)) { - const symbol = ts.isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as ts.BinaryExpression).left) : getSymbolOfNode(node); + function getESSymbolLikeTypeForNode(node: Node) { + if (isValidESSymbolDeclaration(node)) { + const symbol = isCommonJsExportPropertyAssignment(node) ? getSymbolOfNode((node as BinaryExpression).left) : getSymbolOfNode(node); if (symbol) { const links = getSymbolLinks(symbol); return links.uniqueESSymbolType || (links.uniqueESSymbolType = createUniqueESSymbolType(symbol)); @@ -16862,35 +17060,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return esSymbolType; } - function getThisType(node: ts.Node): ts.Type { - const container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); + function getThisType(node: Node): Type { + const container = getThisContainer(node, /*includeArrowFunctions*/ false); const parent = container && container.parent; - if (parent && (ts.isClassLike(parent) || parent.kind === ts.SyntaxKind.InterfaceDeclaration)) { - if (!ts.isStatic(container) && - (!ts.isConstructorDeclaration(container) || ts.isNodeDescendantOf(node, container.body))) { - return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ts.ClassLikeDeclaration | ts.InterfaceDeclaration)).thisType!; + if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { + if (!isStatic(container) && + (!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body))) { + return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!; } } // inside x.prototype = { ... } - if (parent && ts.isObjectLiteralExpression(parent) && ts.isBinaryExpression(parent.parent) && ts.getAssignmentDeclarationKind(parent.parent) === ts.AssignmentDeclarationKind.Prototype) { + if (parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent.parent.left)!.parent!).thisType!; } // /** @return {this} */ // x.prototype.m = function() { ... } - const host = node.flags & ts.NodeFlags.JSDoc ? ts.getHostSignatureFromJSDoc(node) : undefined; - if (host && ts.isFunctionExpression(host) && ts.isBinaryExpression(host.parent) && ts.getAssignmentDeclarationKind(host.parent) === ts.AssignmentDeclarationKind.PrototypeProperty) { + const host = node.flags & NodeFlags.JSDoc ? getHostSignatureFromJSDoc(node) : undefined; + if (host && isFunctionExpression(host) && isBinaryExpression(host.parent) && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(host.parent.left)!.parent!).thisType!; } // inside constructor function C() { ... } - if (isJSConstructor(container) && ts.isNodeDescendantOf(node, container.body)) { + if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) { return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(container)).thisType!; } - error(node, ts.Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface); + error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface); return errorType; } - function getTypeFromThisTypeNode(node: ts.ThisExpression | ts.ThisTypeNode): ts.Type { + function getTypeFromThisTypeNode(node: ThisExpression | ThisTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { links.resolvedType = getThisType(node); @@ -16898,134 +17096,134 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function getTypeFromRestTypeNode(node: ts.RestTypeNode | ts.NamedTupleMember) { + function getTypeFromRestTypeNode(node: RestTypeNode | NamedTupleMember) { return getTypeFromTypeNode(getArrayElementTypeNode(node.type) || node.type); } - function getArrayElementTypeNode(node: ts.TypeNode): ts.TypeNode | undefined { + function getArrayElementTypeNode(node: TypeNode): TypeNode | undefined { switch (node.kind) { - case ts.SyntaxKind.ParenthesizedType: - return getArrayElementTypeNode((node as ts.ParenthesizedTypeNode).type); - case ts.SyntaxKind.TupleType: - if ((node as ts.TupleTypeNode).elements.length === 1) { - node = (node as ts.TupleTypeNode).elements[0]; - if (node.kind === ts.SyntaxKind.RestType || node.kind === ts.SyntaxKind.NamedTupleMember && (node as ts.NamedTupleMember).dotDotDotToken) { - return getArrayElementTypeNode((node as ts.RestTypeNode | ts.NamedTupleMember).type); + case SyntaxKind.ParenthesizedType: + return getArrayElementTypeNode((node as ParenthesizedTypeNode).type); + case SyntaxKind.TupleType: + if ((node as TupleTypeNode).elements.length === 1) { + node = (node as TupleTypeNode).elements[0]; + if (node.kind === SyntaxKind.RestType || node.kind === SyntaxKind.NamedTupleMember && (node as NamedTupleMember).dotDotDotToken) { + return getArrayElementTypeNode((node as RestTypeNode | NamedTupleMember).type); } } break; - case ts.SyntaxKind.ArrayType: - return (node as ts.ArrayTypeNode).elementType; + case SyntaxKind.ArrayType: + return (node as ArrayTypeNode).elementType; } return undefined; } - function getTypeFromNamedTupleTypeNode(node: ts.NamedTupleMember): ts.Type { + function getTypeFromNamedTupleTypeNode(node: NamedTupleMember): Type { const links = getNodeLinks(node); return links.resolvedType || (links.resolvedType = node.dotDotDotToken ? getTypeFromRestTypeNode(node) : addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken)); } - function getTypeFromTypeNode(node: ts.TypeNode): ts.Type { + function getTypeFromTypeNode(node: TypeNode): Type { return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node); } - function getTypeFromTypeNodeWorker(node: ts.TypeNode): ts.Type { + function getTypeFromTypeNodeWorker(node: TypeNode): Type { switch (node.kind) { - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.JSDocAllType: - case ts.SyntaxKind.JSDocUnknownType: + case SyntaxKind.AnyKeyword: + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: return anyType; - case ts.SyntaxKind.UnknownKeyword: + case SyntaxKind.UnknownKeyword: return unknownType; - case ts.SyntaxKind.StringKeyword: + case SyntaxKind.StringKeyword: return stringType; - case ts.SyntaxKind.NumberKeyword: + case SyntaxKind.NumberKeyword: return numberType; - case ts.SyntaxKind.BigIntKeyword: + case SyntaxKind.BigIntKeyword: return bigintType; - case ts.SyntaxKind.BooleanKeyword: + case SyntaxKind.BooleanKeyword: return booleanType; - case ts.SyntaxKind.SymbolKeyword: + case SyntaxKind.SymbolKeyword: return esSymbolType; - case ts.SyntaxKind.VoidKeyword: + case SyntaxKind.VoidKeyword: return voidType; - case ts.SyntaxKind.UndefinedKeyword: + case SyntaxKind.UndefinedKeyword: return undefinedType; - case ts.SyntaxKind.NullKeyword as ts.TypeNodeSyntaxKind: + case SyntaxKind.NullKeyword as TypeNodeSyntaxKind: // TODO(rbuckton): `NullKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service. return nullType; - case ts.SyntaxKind.NeverKeyword: + case SyntaxKind.NeverKeyword: return neverType; - case ts.SyntaxKind.ObjectKeyword: - return node.flags & ts.NodeFlags.JavaScriptFile && !noImplicitAny ? anyType : nonPrimitiveType; - case ts.SyntaxKind.IntrinsicKeyword: + case SyntaxKind.ObjectKeyword: + return node.flags & NodeFlags.JavaScriptFile && !noImplicitAny ? anyType : nonPrimitiveType; + case SyntaxKind.IntrinsicKeyword: return intrinsicMarkerType; - case ts.SyntaxKind.ThisType: - case ts.SyntaxKind.ThisKeyword as ts.TypeNodeSyntaxKind: + case SyntaxKind.ThisType: + case SyntaxKind.ThisKeyword as TypeNodeSyntaxKind: // TODO(rbuckton): `ThisKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service and because of `isPartOfTypeNode`. - return getTypeFromThisTypeNode(node as ts.ThisExpression | ts.ThisTypeNode); - case ts.SyntaxKind.LiteralType: - return getTypeFromLiteralTypeNode(node as ts.LiteralTypeNode); - case ts.SyntaxKind.TypeReference: - return getTypeFromTypeReference(node as ts.TypeReferenceNode); - case ts.SyntaxKind.TypePredicate: - return (node as ts.TypePredicateNode).assertsModifier ? voidType : booleanType; - case ts.SyntaxKind.ExpressionWithTypeArguments: - return getTypeFromTypeReference(node as ts.ExpressionWithTypeArguments); - case ts.SyntaxKind.TypeQuery: - return getTypeFromTypeQueryNode(node as ts.TypeQueryNode); - case ts.SyntaxKind.ArrayType: - case ts.SyntaxKind.TupleType: - return getTypeFromArrayOrTupleTypeNode(node as ts.ArrayTypeNode | ts.TupleTypeNode); - case ts.SyntaxKind.OptionalType: - return getTypeFromOptionalTypeNode(node as ts.OptionalTypeNode); - case ts.SyntaxKind.UnionType: - return getTypeFromUnionTypeNode(node as ts.UnionTypeNode); - case ts.SyntaxKind.IntersectionType: - return getTypeFromIntersectionTypeNode(node as ts.IntersectionTypeNode); - case ts.SyntaxKind.JSDocNullableType: - return getTypeFromJSDocNullableTypeNode(node as ts.JSDocNullableType); - case ts.SyntaxKind.JSDocOptionalType: - return addOptionality(getTypeFromTypeNode((node as ts.JSDocOptionalType).type)); - case ts.SyntaxKind.NamedTupleMember: - return getTypeFromNamedTupleTypeNode(node as ts.NamedTupleMember); - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.JSDocNonNullableType: - case ts.SyntaxKind.JSDocTypeExpression: - return getTypeFromTypeNode((node as ts.ParenthesizedTypeNode | ts.JSDocTypeReferencingNode | ts.JSDocTypeExpression | ts.NamedTupleMember).type); - case ts.SyntaxKind.RestType: - return getTypeFromRestTypeNode(node as ts.RestTypeNode); - case ts.SyntaxKind.JSDocVariadicType: - return getTypeFromJSDocVariadicType(node as ts.JSDocVariadicType); - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.JSDocTypeLiteral: - case ts.SyntaxKind.JSDocFunctionType: - case ts.SyntaxKind.JSDocSignature: + return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode); + case SyntaxKind.LiteralType: + return getTypeFromLiteralTypeNode(node as LiteralTypeNode); + case SyntaxKind.TypeReference: + return getTypeFromTypeReference(node as TypeReferenceNode); + case SyntaxKind.TypePredicate: + return (node as TypePredicateNode).assertsModifier ? voidType : booleanType; + case SyntaxKind.ExpressionWithTypeArguments: + return getTypeFromTypeReference(node as ExpressionWithTypeArguments); + case SyntaxKind.TypeQuery: + return getTypeFromTypeQueryNode(node as TypeQueryNode); + case SyntaxKind.ArrayType: + case SyntaxKind.TupleType: + return getTypeFromArrayOrTupleTypeNode(node as ArrayTypeNode | TupleTypeNode); + case SyntaxKind.OptionalType: + return getTypeFromOptionalTypeNode(node as OptionalTypeNode); + case SyntaxKind.UnionType: + return getTypeFromUnionTypeNode(node as UnionTypeNode); + case SyntaxKind.IntersectionType: + return getTypeFromIntersectionTypeNode(node as IntersectionTypeNode); + case SyntaxKind.JSDocNullableType: + return getTypeFromJSDocNullableTypeNode(node as JSDocNullableType); + case SyntaxKind.JSDocOptionalType: + return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type)); + case SyntaxKind.NamedTupleMember: + return getTypeFromNamedTupleTypeNode(node as NamedTupleMember); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocTypeExpression: + return getTypeFromTypeNode((node as ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember).type); + case SyntaxKind.RestType: + return getTypeFromRestTypeNode(node as RestTypeNode); + case SyntaxKind.JSDocVariadicType: + return getTypeFromJSDocVariadicType(node as JSDocVariadicType); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocSignature: return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); - case ts.SyntaxKind.TypeOperator: - return getTypeFromTypeOperatorNode(node as ts.TypeOperatorNode); - case ts.SyntaxKind.IndexedAccessType: - return getTypeFromIndexedAccessTypeNode(node as ts.IndexedAccessTypeNode); - case ts.SyntaxKind.MappedType: - return getTypeFromMappedTypeNode(node as ts.MappedTypeNode); - case ts.SyntaxKind.ConditionalType: - return getTypeFromConditionalTypeNode(node as ts.ConditionalTypeNode); - case ts.SyntaxKind.InferType: - return getTypeFromInferTypeNode(node as ts.InferTypeNode); - case ts.SyntaxKind.TemplateLiteralType: - return getTypeFromTemplateTypeNode(node as ts.TemplateLiteralTypeNode); - case ts.SyntaxKind.ImportType: - return getTypeFromImportTypeNode(node as ts.ImportTypeNode); + case SyntaxKind.TypeOperator: + return getTypeFromTypeOperatorNode(node as TypeOperatorNode); + case SyntaxKind.IndexedAccessType: + return getTypeFromIndexedAccessTypeNode(node as IndexedAccessTypeNode); + case SyntaxKind.MappedType: + return getTypeFromMappedTypeNode(node as MappedTypeNode); + case SyntaxKind.ConditionalType: + return getTypeFromConditionalTypeNode(node as ConditionalTypeNode); + case SyntaxKind.InferType: + return getTypeFromInferTypeNode(node as InferTypeNode); + case SyntaxKind.TemplateLiteralType: + return getTypeFromTemplateTypeNode(node as TemplateLiteralTypeNode); + case SyntaxKind.ImportType: + return getTypeFromImportTypeNode(node as ImportTypeNode); // This function assumes that an identifier, qualified name, or property access expression is a type expression // Callers should first ensure this by calling `isPartOfTypeNode` // TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s. - case ts.SyntaxKind.Identifier as ts.TypeNodeSyntaxKind: - case ts.SyntaxKind.QualifiedName as ts.TypeNodeSyntaxKind: - case ts.SyntaxKind.PropertyAccessExpression as ts.TypeNodeSyntaxKind: + case SyntaxKind.Identifier as TypeNodeSyntaxKind: + case SyntaxKind.QualifiedName as TypeNodeSyntaxKind: + case SyntaxKind.PropertyAccessExpression as TypeNodeSyntaxKind: const symbol = getSymbolAtLocation(node); return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; default: @@ -17033,9 +17231,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function instantiateList(items: readonly T[], mapper: ts.TypeMapper, instantiator: (item: T, mapper: ts.TypeMapper) => T): readonly T[]; - function instantiateList(items: readonly T[] | undefined, mapper: ts.TypeMapper, instantiator: (item: T, mapper: ts.TypeMapper) => T): readonly T[] | undefined; - function instantiateList(items: readonly T[] | undefined, mapper: ts.TypeMapper, instantiator: (item: T, mapper: ts.TypeMapper) => T): readonly T[] | undefined { + function instantiateList(items: readonly T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[]; + function instantiateList(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined; + function instantiateList(items: readonly T[] | undefined, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): readonly T[] | undefined { if (items && items.length) { for (let i = 0; i < items.length; i++) { const item = items[i]; @@ -17053,29 +17251,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return items; } - function instantiateTypes(types: readonly ts.Type[], mapper: ts.TypeMapper): readonly ts.Type[]; - function instantiateTypes(types: readonly ts.Type[] | undefined, mapper: ts.TypeMapper): readonly ts.Type[] | undefined; - function instantiateTypes(types: readonly ts.Type[] | undefined, mapper: ts.TypeMapper): readonly ts.Type[] | undefined { - return instantiateList(types, mapper, instantiateType); + function instantiateTypes(types: readonly Type[], mapper: TypeMapper): readonly Type[]; + function instantiateTypes(types: readonly Type[] | undefined, mapper: TypeMapper): readonly Type[] | undefined; + function instantiateTypes(types: readonly Type[] | undefined, mapper: TypeMapper): readonly Type[] | undefined { + return instantiateList(types, mapper, instantiateType); } - function instantiateSignatures(signatures: readonly ts.Signature[], mapper: ts.TypeMapper): readonly ts.Signature[] { - return instantiateList(signatures, mapper, instantiateSignature); + function instantiateSignatures(signatures: readonly Signature[], mapper: TypeMapper): readonly Signature[] { + return instantiateList(signatures, mapper, instantiateSignature); } - function instantiateIndexInfos(indexInfos: readonly ts.IndexInfo[], mapper: ts.TypeMapper): readonly ts.IndexInfo[] { - return instantiateList(indexInfos, mapper, instantiateIndexInfo); + function instantiateIndexInfos(indexInfos: readonly IndexInfo[], mapper: TypeMapper): readonly IndexInfo[] { + return instantiateList(indexInfos, mapper, instantiateIndexInfo); } - function createTypeMapper(sources: readonly ts.TypeParameter[], targets: readonly ts.Type[] | undefined): ts.TypeMapper { + function createTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper { return sources.length === 1 ? makeUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) : makeArrayTypeMapper(sources, targets); } - function getMappedType(type: ts.Type, mapper: ts.TypeMapper): ts.Type { + function getMappedType(type: Type, mapper: TypeMapper): Type { switch (mapper.kind) { - case ts.TypeMapKind.Simple: + case TypeMapKind.Simple: return type === mapper.source ? mapper.target : type; - case ts.TypeMapKind.Array: { + case TypeMapKind.Array: { const sources = mapper.sources; const targets = mapper.targets; for (let i = 0; i < sources.length; i++) { @@ -17085,7 +17283,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return type; } - case ts.TypeMapKind.Deferred: { + case TypeMapKind.Deferred: { const sources = mapper.sources; const targets = mapper.targets; for (let i = 0; i < sources.length; i++) { @@ -17095,36 +17293,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return type; } - case ts.TypeMapKind.Function: + case TypeMapKind.Function: return mapper.func(type); - case ts.TypeMapKind.Composite: - case ts.TypeMapKind.Merged: + case TypeMapKind.Composite: + case TypeMapKind.Merged: const t1 = getMappedType(type, mapper.mapper1); - return t1 !== type && mapper.kind === ts.TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2); + return t1 !== type && mapper.kind === TypeMapKind.Composite ? instantiateType(t1, mapper.mapper2) : getMappedType(t1, mapper.mapper2); } } - function makeUnaryTypeMapper(source: ts.Type, target: ts.Type): ts.TypeMapper { - return ts.Debug.attachDebugPrototypeIfDebug({ kind: ts.TypeMapKind.Simple, source, target }); + function makeUnaryTypeMapper(source: Type, target: Type): TypeMapper { + return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Simple, source, target }); } - function makeArrayTypeMapper(sources: readonly ts.TypeParameter[], targets: readonly ts.Type[] | undefined): ts.TypeMapper { - return ts.Debug.attachDebugPrototypeIfDebug({ kind: ts.TypeMapKind.Array, sources, targets }); + function makeArrayTypeMapper(sources: readonly TypeParameter[], targets: readonly Type[] | undefined): TypeMapper { + return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Array, sources, targets }); } - function makeFunctionTypeMapper(func: (t: ts.Type) => ts.Type, debugInfo: () => string): ts.TypeMapper { - return ts.Debug.attachDebugPrototypeIfDebug({ kind: ts.TypeMapKind.Function, func, debugInfo: ts.Debug.isDebugging ? debugInfo : undefined }); + function makeFunctionTypeMapper(func: (t: Type) => Type, debugInfo: () => string): TypeMapper { + return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Function, func, debugInfo: Debug.isDebugging ? debugInfo : undefined }); } - function makeDeferredTypeMapper(sources: readonly ts.TypeParameter[], targets: (() => ts.Type)[]) { - return ts.Debug.attachDebugPrototypeIfDebug({ kind: ts.TypeMapKind.Deferred, sources, targets }); + function makeDeferredTypeMapper(sources: readonly TypeParameter[], targets: (() => Type)[]) { + return Debug.attachDebugPrototypeIfDebug({ kind: TypeMapKind.Deferred, sources, targets }); } - function makeCompositeTypeMapper(kind: ts.TypeMapKind.Composite | ts.TypeMapKind.Merged, mapper1: ts.TypeMapper, mapper2: ts.TypeMapper): ts.TypeMapper { - return ts.Debug.attachDebugPrototypeIfDebug({ kind, mapper1, mapper2 }); + function makeCompositeTypeMapper(kind: TypeMapKind.Composite | TypeMapKind.Merged, mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper { + return Debug.attachDebugPrototypeIfDebug({ kind, mapper1, mapper2 }); } - function createTypeEraser(sources: readonly ts.TypeParameter[]): ts.TypeMapper { + function createTypeEraser(sources: readonly TypeParameter[]): TypeMapper { return createTypeMapper(sources, /*targets*/ undefined); } @@ -17132,52 +17330,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Maps forward-references to later types parameters to the empty object type. * This is used during inference when instantiating type parameter defaults. */ - function createBackreferenceMapper(context: ts.InferenceContext, index: number): ts.TypeMapper { + function createBackreferenceMapper(context: InferenceContext, index: number): TypeMapper { const forwardInferences = context.inferences.slice(index); - return createTypeMapper(ts.map(forwardInferences, i => i.typeParameter), ts.map(forwardInferences, () => unknownType)); + return createTypeMapper(map(forwardInferences, i => i.typeParameter), map(forwardInferences, () => unknownType)); } - function combineTypeMappers(mapper1: ts.TypeMapper | undefined, mapper2: ts.TypeMapper): ts.TypeMapper { - return mapper1 ? makeCompositeTypeMapper(ts.TypeMapKind.Composite, mapper1, mapper2) : mapper2; + function combineTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper { + return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Composite, mapper1, mapper2) : mapper2; } - function mergeTypeMappers(mapper1: ts.TypeMapper | undefined, mapper2: ts.TypeMapper): ts.TypeMapper { - return mapper1 ? makeCompositeTypeMapper(ts.TypeMapKind.Merged, mapper1, mapper2) : mapper2; + function mergeTypeMappers(mapper1: TypeMapper | undefined, mapper2: TypeMapper): TypeMapper { + return mapper1 ? makeCompositeTypeMapper(TypeMapKind.Merged, mapper1, mapper2) : mapper2; } - function prependTypeMapping(source: ts.Type, target: ts.Type, mapper: ts.TypeMapper | undefined) { - return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(ts.TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper); + function prependTypeMapping(source: Type, target: Type, mapper: TypeMapper | undefined) { + return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, makeUnaryTypeMapper(source, target), mapper); } - function appendTypeMapping(mapper: ts.TypeMapper | undefined, source: ts.Type, target: ts.Type) { - return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(ts.TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target)); + function appendTypeMapping(mapper: TypeMapper | undefined, source: Type, target: Type) { + return !mapper ? makeUnaryTypeMapper(source, target) : makeCompositeTypeMapper(TypeMapKind.Merged, mapper, makeUnaryTypeMapper(source, target)); } - function getRestrictiveTypeParameter(tp: ts.TypeParameter) { + function getRestrictiveTypeParameter(tp: TypeParameter) { return !tp.constraint && !getConstraintDeclaration(tp) || tp.constraint === noConstraintType ? tp : tp.restrictiveInstantiation || ( tp.restrictiveInstantiation = createTypeParameter(tp.symbol), - (tp.restrictiveInstantiation as ts.TypeParameter).constraint = noConstraintType, + (tp.restrictiveInstantiation as TypeParameter).constraint = noConstraintType, tp.restrictiveInstantiation ); } - function cloneTypeParameter(typeParameter: ts.TypeParameter): ts.TypeParameter { + function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter { const result = createTypeParameter(typeParameter.symbol); result.target = typeParameter; return result; } - function instantiateTypePredicate(predicate: ts.TypePredicate, mapper: ts.TypeMapper): ts.TypePredicate { + function instantiateTypePredicate(predicate: TypePredicate, mapper: TypeMapper): TypePredicate { return createTypePredicate(predicate.kind, predicate.parameterName, predicate.parameterIndex, instantiateType(predicate.type, mapper)); } - function instantiateSignature(signature: ts.Signature, mapper: ts.TypeMapper, eraseTypeParameters?: boolean): ts.Signature { - let freshTypeParameters: ts.TypeParameter[] | undefined; + function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature { + let freshTypeParameters: TypeParameter[] | undefined; if (signature.typeParameters && !eraseTypeParameters) { // First create a fresh set of type parameters, then include a mapping from the old to the // new type parameters in the mapper function. Finally store this mapper in the new type // parameters such that we can use it when instantiating constraints. - freshTypeParameters = ts.map(signature.typeParameters, cloneTypeParameter); + freshTypeParameters = map(signature.typeParameters, cloneTypeParameter); mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper); for (const tp of freshTypeParameters) { tp.mapper = mapper; @@ -17192,20 +17390,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, signature.minArgumentCount, - signature.flags & ts.SignatureFlags.PropagatingFlags); + signature.flags & SignatureFlags.PropagatingFlags); result.target = signature; result.mapper = mapper; return result; } - function instantiateSymbol(symbol: ts.Symbol, mapper: ts.TypeMapper): ts.Symbol { + function instantiateSymbol(symbol: Symbol, mapper: TypeMapper): Symbol { const links = getSymbolLinks(symbol); if (links.type && !couldContainTypeVariables(links.type)) { // If the type of the symbol is already resolved, and if that type could not possibly // be affected by instantiation, simply return the symbol itself. return symbol; } - if (ts.getCheckFlags(symbol) & ts.CheckFlags.Instantiated) { + if (getCheckFlags(symbol) & CheckFlags.Instantiated) { // If symbol being instantiated is itself a instantiation, fetch the original target and combine the // type mappers. This ensures that original type identities are properly preserved and that aliases // always reference a non-aliases. @@ -17214,7 +17412,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and // also transient so that we can just store data on it directly. - const result = createSymbol(symbol.flags, symbol.escapedName, ts.CheckFlags.Instantiated | ts.getCheckFlags(symbol) & (ts.CheckFlags.Readonly | ts.CheckFlags.Late | ts.CheckFlags.OptionalParameter | ts.CheckFlags.RestParameter)); + const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter)); result.declarations = symbol.declarations; result.parent = symbol.parent; result.target = symbol; @@ -17228,13 +17426,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getObjectTypeInstantiation(type: ts.AnonymousType | ts.DeferredTypeReference, mapper: ts.TypeMapper, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]) { - const declaration = type.objectFlags & ts.ObjectFlags.Reference ? (type as ts.TypeReference).node! : - type.objectFlags & ts.ObjectFlags.InstantiationExpressionType ? (type as ts.InstantiationExpressionType).node : + function getObjectTypeInstantiation(type: AnonymousType | DeferredTypeReference, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]) { + const declaration = type.objectFlags & ObjectFlags.Reference ? (type as TypeReference).node! : + type.objectFlags & ObjectFlags.InstantiationExpressionType ? (type as InstantiationExpressionType).node : type.symbol.declarations![0]; const links = getNodeLinks(declaration); - const target = type.objectFlags & ts.ObjectFlags.Reference ? links.resolvedType! as ts.DeferredTypeReference : - type.objectFlags & ts.ObjectFlags.Instantiated ? type.target! : type; + const target = type.objectFlags & ObjectFlags.Reference ? links.resolvedType! as DeferredTypeReference : + type.objectFlags & ObjectFlags.Instantiated ? type.target! : type; let typeParameters = links.outerTypeParameters; if (!typeParameters) { // The first time an anonymous type is instantiated we compute and store a list of the type @@ -17243,13 +17441,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // set of type parameters to those that are possibly referenced in the literal. let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true); if (isJSConstructor(declaration)) { - const templateTagParameters = getTypeParametersFromDeclaration(declaration as ts.DeclarationWithTypeParameters); - outerTypeParameters = ts.addRange(outerTypeParameters, templateTagParameters); + const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters); + outerTypeParameters = addRange(outerTypeParameters, templateTagParameters); } - typeParameters = outerTypeParameters || ts.emptyArray; - const allDeclarations = type.objectFlags & (ts.ObjectFlags.Reference | ts.ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!; - typeParameters = (target.objectFlags & (ts.ObjectFlags.Reference | ts.ObjectFlags.InstantiationExpressionType) || target.symbol.flags & ts.SymbolFlags.Method || target.symbol.flags & ts.SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ? - ts.filter(typeParameters, tp => ts.some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) : + typeParameters = outerTypeParameters || emptyArray; + const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!; + typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ? + filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) : typeParameters; links.outerTypeParameters = typeParameters; } @@ -17258,19 +17456,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // mapper to the type parameters to produce the effective list of type arguments, and compute the // instantiation cache key from the type IDs of the type arguments. const combinedMapper = combineTypeMappers(type.mapper, mapper); - const typeArguments = ts.map(typeParameters, t => getMappedType(t, combinedMapper)); + const typeArguments = map(typeParameters, t => getMappedType(t, combinedMapper)); const newAliasSymbol = aliasSymbol || type.aliasSymbol; const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); const id = getTypeListId(typeArguments) + getAliasId(newAliasSymbol, newAliasTypeArguments); if (!target.instantiations) { - target.instantiations = new ts.Map(); + target.instantiations = new Map(); target.instantiations.set(getTypeListId(typeParameters) + getAliasId(target.aliasSymbol, target.aliasTypeArguments), target); } let result = target.instantiations.get(id); if (!result) { const newMapper = createTypeMapper(typeParameters, typeArguments); - result = target.objectFlags & ts.ObjectFlags.Reference ? createDeferredTypeReference((type as ts.DeferredTypeReference).target, (type as ts.DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) : - target.objectFlags & ts.ObjectFlags.Mapped ? instantiateMappedType(target as ts.MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) : + result = target.objectFlags & ObjectFlags.Reference ? createDeferredTypeReference((type as DeferredTypeReference).target, (type as DeferredTypeReference).node, newMapper, newAliasSymbol, newAliasTypeArguments) : + target.objectFlags & ObjectFlags.Mapped ? instantiateMappedType(target as MappedType, newMapper, newAliasSymbol, newAliasTypeArguments) : instantiateAnonymousType(target, newMapper, newAliasSymbol, newAliasTypeArguments); target.instantiations.set(id, result); } @@ -17279,12 +17477,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function maybeTypeParameterReference(node: ts.Node) { - return !(node.parent.kind === ts.SyntaxKind.TypeReference && (node.parent as ts.TypeReferenceNode).typeArguments && node === (node.parent as ts.TypeReferenceNode).typeName || - node.parent.kind === ts.SyntaxKind.ImportType && (node.parent as ts.ImportTypeNode).typeArguments && node === (node.parent as ts.ImportTypeNode).qualifier); + function maybeTypeParameterReference(node: Node) { + return !(node.parent.kind === SyntaxKind.TypeReference && (node.parent as TypeReferenceNode).typeArguments && node === (node.parent as TypeReferenceNode).typeName || + node.parent.kind === SyntaxKind.ImportType && (node.parent as ImportTypeNode).typeArguments && node === (node.parent as ImportTypeNode).qualifier); } - function isTypeParameterPossiblyReferenced(tp: ts.TypeParameter, node: ts.Node) { + function isTypeParameterPossiblyReferenced(tp: TypeParameter, node: Node) { // If the type parameter doesn't have exactly one declaration, if there are intervening statement blocks // between the node and the type parameter declaration, if the node contains actual references to the // type parameter, or if the node contains type queries that we can't prove couldn't contain references to the type parameter, @@ -17292,27 +17490,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (tp.symbol && tp.symbol.declarations && tp.symbol.declarations.length === 1) { const container = tp.symbol.declarations[0].parent; for (let n = node; n !== container; n = n.parent) { - if (!n || n.kind === ts.SyntaxKind.Block || n.kind === ts.SyntaxKind.ConditionalType && ts.forEachChild((n as ts.ConditionalTypeNode).extendsType, containsReference)) { + if (!n || n.kind === SyntaxKind.Block || n.kind === SyntaxKind.ConditionalType && forEachChild((n as ConditionalTypeNode).extendsType, containsReference)) { return true; } } return containsReference(node); } return true; - function containsReference(node: ts.Node): boolean { + function containsReference(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ThisType: + case SyntaxKind.ThisType: return !!tp.isThisType; - case ts.SyntaxKind.Identifier: - return !tp.isThisType && ts.isPartOfTypeNode(node) && maybeTypeParameterReference(node) && - getTypeFromTypeNodeWorker(node as ts.TypeNode) === tp; // use worker because we're looking for === equality - case ts.SyntaxKind.TypeQuery: - const entityName = (node as ts.TypeQueryNode).exprName; - const firstIdentifier = ts.getFirstIdentifier(entityName); + case SyntaxKind.Identifier: + return !tp.isThisType && isPartOfTypeNode(node) && maybeTypeParameterReference(node) && + getTypeFromTypeNodeWorker(node as TypeNode) === tp; // use worker because we're looking for === equality + case SyntaxKind.TypeQuery: + const entityName = (node as TypeQueryNode).exprName; + const firstIdentifier = getFirstIdentifier(entityName); const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier); const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called - let tpScope: ts.Node; - if (tpDeclaration.kind === ts.SyntaxKind.TypeParameter) { // Type parameter is a regular type parameter, e.g. foo + let tpScope: Node; + if (tpDeclaration.kind === SyntaxKind.TypeParameter) { // Type parameter is a regular type parameter, e.g. foo tpScope = tpDeclaration.parent; } else if (tp.isThisType) { @@ -17326,33 +17524,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (firstIdentifierSymbol.declarations) { - return ts.some(firstIdentifierSymbol.declarations, idDecl => ts.isNodeDescendantOf(idDecl, tpScope)) || - ts.some((node as ts.TypeQueryNode).typeArguments, containsReference); + return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) || + some((node as TypeQueryNode).typeArguments, containsReference); } return true; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - return !(node as ts.FunctionLikeDeclaration).type && !!(node as ts.FunctionLikeDeclaration).body || - ts.some((node as ts.FunctionLikeDeclaration).typeParameters, containsReference) || - ts.some((node as ts.FunctionLikeDeclaration).parameters, containsReference) || - !!(node as ts.FunctionLikeDeclaration).type && containsReference((node as ts.FunctionLikeDeclaration).type!); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return !(node as FunctionLikeDeclaration).type && !!(node as FunctionLikeDeclaration).body || + some((node as FunctionLikeDeclaration).typeParameters, containsReference) || + some((node as FunctionLikeDeclaration).parameters, containsReference) || + !!(node as FunctionLikeDeclaration).type && containsReference((node as FunctionLikeDeclaration).type!); } - return !!ts.forEachChild(node, containsReference); + return !!forEachChild(node, containsReference); } } - function getHomomorphicTypeVariable(type: ts.MappedType) { + function getHomomorphicTypeVariable(type: MappedType) { const constraintType = getConstraintTypeFromMappedType(type); - if (constraintType.flags & ts.TypeFlags.Index) { - const typeVariable = getActualTypeVariable((constraintType as ts.IndexType).type); - if (typeVariable.flags & ts.TypeFlags.TypeParameter) { - return typeVariable as ts.TypeParameter; + if (constraintType.flags & TypeFlags.Index) { + const typeVariable = getActualTypeVariable((constraintType as IndexType).type); + if (typeVariable.flags & TypeFlags.TypeParameter) { + return typeVariable as TypeParameter; } } return undefined; } - function instantiateMappedType(type: ts.MappedType, mapper: ts.TypeMapper, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type { + function instantiateMappedType(type: MappedType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { // For a homomorphic mapped type { [P in keyof T]: X }, where T is some type variable, the mapping // operation depends on T as follows: // * If T is a primitive type no mapping is performed and the result is simply T. @@ -17368,10 +17566,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const mappedTypeVariable = instantiateType(typeVariable, mapper); if (typeVariable !== mappedTypeVariable) { return mapTypeWithAlias(getReducedType(mappedTypeVariable), t => { - if (t.flags & (ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.InstantiableNonPrimitive | ts.TypeFlags.Object | ts.TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { + if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { if (!type.declaration.nameType) { let constraint; - if (isArrayType(t) || t.flags & ts.TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 && + if (isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); } @@ -17396,64 +17594,64 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return modifiers & MappedTypeModifiers.IncludeReadonly ? true : modifiers & MappedTypeModifiers.ExcludeReadonly ? false : state; } - function instantiateMappedGenericTupleType(tupleType: ts.TupleTypeReference, mappedType: ts.MappedType, typeVariable: ts.TypeVariable, mapper: ts.TypeMapper) { + function instantiateMappedGenericTupleType(tupleType: TupleTypeReference, mappedType: MappedType, typeVariable: TypeVariable, mapper: TypeMapper) { // When a tuple type is generic (i.e. when it contains variadic elements), we want to eagerly map the // non-generic elements and defer mapping the generic elements. In order to facilitate this, we transform // M<[A, B?, ...T, ...C[]] into [...M<[A]>, ...M<[B?]>, ...M, ...M] and then rely on tuple type // normalization to resolve the non-generic parts of the resulting tuple. const elementFlags = tupleType.target.elementFlags; - const elementTypes = ts.map(getTypeArguments(tupleType), (t, i) => { - const singleton = elementFlags[i] & ts.ElementFlags.Variadic ? t : - elementFlags[i] & ts.ElementFlags.Rest ? createArrayType(t) : + const elementTypes = map(getTypeArguments(tupleType), (t, i) => { + const singleton = elementFlags[i] & ElementFlags.Variadic ? t : + elementFlags[i] & ElementFlags.Rest ? createArrayType(t) : createTupleType([t], [elementFlags[i]]); // The singleton is never a generic tuple type, so it is safe to recurse here. return instantiateMappedType(mappedType, prependTypeMapping(typeVariable, singleton, mapper)); }); const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, getMappedTypeModifiers(mappedType)); - return createTupleType(elementTypes, ts.map(elementTypes, _ => ts.ElementFlags.Variadic), newReadonly); + return createTupleType(elementTypes, map(elementTypes, _ => ElementFlags.Variadic), newReadonly); } - function instantiateMappedArrayType(arrayType: ts.Type, mappedType: ts.MappedType, mapper: ts.TypeMapper) { + function instantiateMappedArrayType(arrayType: Type, mappedType: MappedType, mapper: TypeMapper) { const elementType = instantiateMappedTypeTemplate(mappedType, numberType, /*isOptional*/ true, mapper); return isErrorType(elementType) ? errorType : createArrayType(elementType, getModifiedReadonlyState(isReadonlyArrayType(arrayType), getMappedTypeModifiers(mappedType))); } - function instantiateMappedTupleType(tupleType: ts.TupleTypeReference, mappedType: ts.MappedType, mapper: ts.TypeMapper) { + function instantiateMappedTupleType(tupleType: TupleTypeReference, mappedType: MappedType, mapper: TypeMapper) { const elementFlags = tupleType.target.elementFlags; - const elementTypes = ts.map(getTypeArguments(tupleType), (_, i) => - instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ts.ElementFlags.Optional), mapper)); + const elementTypes = map(getTypeArguments(tupleType), (_, i) => + instantiateMappedTypeTemplate(mappedType, getStringLiteralType("" + i), !!(elementFlags[i] & ElementFlags.Optional), mapper)); const modifiers = getMappedTypeModifiers(mappedType); - const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? ts.map(elementFlags, f => f & ts.ElementFlags.Required ? ts.ElementFlags.Optional : f) : - modifiers & MappedTypeModifiers.ExcludeOptional ? ts.map(elementFlags, f => f & ts.ElementFlags.Optional ? ts.ElementFlags.Required : f) : + const newTupleModifiers = modifiers & MappedTypeModifiers.IncludeOptional ? map(elementFlags, f => f & ElementFlags.Required ? ElementFlags.Optional : f) : + modifiers & MappedTypeModifiers.ExcludeOptional ? map(elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : elementFlags; const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers); - return ts.contains(elementTypes, errorType) ? errorType : + return contains(elementTypes, errorType) ? errorType : createTupleType(elementTypes, newTupleModifiers, newReadonly, tupleType.target.labeledElementDeclarations); } - function instantiateMappedTypeTemplate(type: ts.MappedType, key: ts.Type, isOptional: boolean, mapper: ts.TypeMapper) { + function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) { const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key); - const propType = instantiateType(getTemplateTypeFromMappedType(type.target as ts.MappedType || type), templateMapper); + const propType = instantiateType(getTemplateTypeFromMappedType(type.target as MappedType || type), templateMapper); const modifiers = getMappedTypeModifiers(type); - return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, ts.TypeFlags.Undefined | ts.TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : + return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) : strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : propType; } - function instantiateAnonymousType(type: ts.AnonymousType, mapper: ts.TypeMapper, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.AnonymousType { - const result = createObjectType(type.objectFlags | ts.ObjectFlags.Instantiated, type.symbol) as ts.AnonymousType; - if (type.objectFlags & ts.ObjectFlags.Mapped) { - (result as ts.MappedType).declaration = (type as ts.MappedType).declaration; + function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): AnonymousType { + const result = createObjectType(type.objectFlags | ObjectFlags.Instantiated, type.symbol) as AnonymousType; + if (type.objectFlags & ObjectFlags.Mapped) { + (result as MappedType).declaration = (type as MappedType).declaration; // C.f. instantiateSignature - const origTypeParameter = getTypeParameterFromMappedType(type as ts.MappedType); + const origTypeParameter = getTypeParameterFromMappedType(type as MappedType); const freshTypeParameter = cloneTypeParameter(origTypeParameter); - (result as ts.MappedType).typeParameter = freshTypeParameter; + (result as MappedType).typeParameter = freshTypeParameter; mapper = combineTypeMappers(makeUnaryTypeMapper(origTypeParameter, freshTypeParameter), mapper); freshTypeParameter.mapper = mapper; } - if (type.objectFlags & ts.ObjectFlags.InstantiationExpressionType) { - (result as ts.InstantiationExpressionType).node = (type as ts.InstantiationExpressionType).node; + if (type.objectFlags & ObjectFlags.InstantiationExpressionType) { + (result as InstantiationExpressionType).node = (type as InstantiationExpressionType).node; } result.target = type; result.mapper = mapper; @@ -17463,13 +17661,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getConditionalTypeInstantiation(type: ts.ConditionalType, mapper: ts.TypeMapper, aliasSymbol?: ts.Symbol, aliasTypeArguments?: readonly ts.Type[]): ts.Type { + function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { const root = type.root; if (root.outerTypeParameters) { // We are instantiating a conditional type that has one or more type parameters in scope. Apply the // mapper to the type parameters to produce the effective list of type arguments, and compute the // instantiation cache key from the type IDs of the type arguments. - const typeArguments = ts.map(root.outerTypeParameters, t => getMappedType(t, mapper)); + const typeArguments = map(root.outerTypeParameters, t => getMappedType(t, mapper)); const id = getTypeListId(typeArguments) + getAliasId(aliasSymbol, aliasTypeArguments); let result = root.instantiations!.get(id); if (!result) { @@ -17479,7 +17677,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Distributive conditional types are distributed over union types. For example, when the // distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the // result is (A extends U ? X : Y) | (B extends U ? X : Y). - result = distributionType && checkType !== distributionType && distributionType.flags & (ts.TypeFlags.Union | ts.TypeFlags.Never) ? + result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ? mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) : getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments); root.instantiations!.set(id, result); @@ -17489,13 +17687,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function instantiateType(type: ts.Type, mapper: ts.TypeMapper | undefined): ts.Type; - function instantiateType(type: ts.Type | undefined, mapper: ts.TypeMapper | undefined): ts.Type | undefined; - function instantiateType(type: ts.Type | undefined, mapper: ts.TypeMapper | undefined): ts.Type | undefined { + function instantiateType(type: Type, mapper: TypeMapper | undefined): Type; + function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined; + function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined { return type && mapper ? instantiateTypeWithAlias(type, mapper, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined) : type; } - function instantiateTypeWithAlias(type: ts.Type, mapper: ts.TypeMapper, aliasSymbol: ts.Symbol | undefined, aliasTypeArguments: readonly ts.Type[] | undefined): ts.Type { + function instantiateTypeWithAlias(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type { if (!couldContainTypeVariables(type)) { return type; } @@ -17503,8 +17701,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We have reached 100 recursive type instantiations, or 5M type instantiations caused by the same statement // or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types // that perpetually generate new type identities, so we stop the recursion here by yielding the error type. - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount }); - error(currentNode, ts.Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); + tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount }); + error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); return errorType; } totalInstantiationCount++; @@ -17515,86 +17713,86 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function instantiateTypeWorker(type: ts.Type, mapper: ts.TypeMapper, aliasSymbol: ts.Symbol | undefined, aliasTypeArguments: readonly ts.Type[] | undefined): ts.Type { + function instantiateTypeWorker(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type { const flags = type.flags; - if (flags & ts.TypeFlags.TypeParameter) { + if (flags & TypeFlags.TypeParameter) { return getMappedType(type, mapper); } - if (flags & ts.TypeFlags.Object) { - const objectFlags = (type as ts.ObjectType).objectFlags; - if (objectFlags & (ts.ObjectFlags.Reference | ts.ObjectFlags.Anonymous | ts.ObjectFlags.Mapped)) { - if (objectFlags & ts.ObjectFlags.Reference && !(type as ts.TypeReference).node) { - const resolvedTypeArguments = (type as ts.TypeReference).resolvedTypeArguments; + if (flags & TypeFlags.Object) { + const objectFlags = (type as ObjectType).objectFlags; + if (objectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous | ObjectFlags.Mapped)) { + if (objectFlags & ObjectFlags.Reference && !(type as TypeReference).node) { + const resolvedTypeArguments = (type as TypeReference).resolvedTypeArguments; const newTypeArguments = instantiateTypes(resolvedTypeArguments, mapper); - return newTypeArguments !== resolvedTypeArguments ? createNormalizedTypeReference((type as ts.TypeReference).target, newTypeArguments) : type; + return newTypeArguments !== resolvedTypeArguments ? createNormalizedTypeReference((type as TypeReference).target, newTypeArguments) : type; } - if (objectFlags & ts.ObjectFlags.ReverseMapped) { - return instantiateReverseMappedType(type as ts.ReverseMappedType, mapper); + if (objectFlags & ObjectFlags.ReverseMapped) { + return instantiateReverseMappedType(type as ReverseMappedType, mapper); } - return getObjectTypeInstantiation(type as ts.TypeReference | ts.AnonymousType | ts.MappedType, mapper, aliasSymbol, aliasTypeArguments); + return getObjectTypeInstantiation(type as TypeReference | AnonymousType | MappedType, mapper, aliasSymbol, aliasTypeArguments); } return type; } - if (flags & ts.TypeFlags.UnionOrIntersection) { - const origin = type.flags & ts.TypeFlags.Union ? (type as ts.UnionType).origin : undefined; - const types = origin && origin.flags & ts.TypeFlags.UnionOrIntersection ? (origin as ts.UnionOrIntersectionType).types : (type as ts.UnionOrIntersectionType).types; + if (flags & TypeFlags.UnionOrIntersection) { + const origin = type.flags & TypeFlags.Union ? (type as UnionType).origin : undefined; + const types = origin && origin.flags & TypeFlags.UnionOrIntersection ? (origin as UnionOrIntersectionType).types : (type as UnionOrIntersectionType).types; const newTypes = instantiateTypes(types, mapper); if (newTypes === types && aliasSymbol === type.aliasSymbol) { return type; } const newAliasSymbol = aliasSymbol || type.aliasSymbol; const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); - return flags & ts.TypeFlags.Intersection || origin && origin.flags & ts.TypeFlags.Intersection ? + return flags & TypeFlags.Intersection || origin && origin.flags & TypeFlags.Intersection ? getIntersectionType(newTypes, newAliasSymbol, newAliasTypeArguments) : - getUnionType(newTypes, ts.UnionReduction.Literal, newAliasSymbol, newAliasTypeArguments); + getUnionType(newTypes, UnionReduction.Literal, newAliasSymbol, newAliasTypeArguments); } - if (flags & ts.TypeFlags.Index) { - return getIndexType(instantiateType((type as ts.IndexType).type, mapper)); + if (flags & TypeFlags.Index) { + return getIndexType(instantiateType((type as IndexType).type, mapper)); } - if (flags & ts.TypeFlags.TemplateLiteral) { - return getTemplateLiteralType((type as ts.TemplateLiteralType).texts, instantiateTypes((type as ts.TemplateLiteralType).types, mapper)); + if (flags & TypeFlags.TemplateLiteral) { + return getTemplateLiteralType((type as TemplateLiteralType).texts, instantiateTypes((type as TemplateLiteralType).types, mapper)); } - if (flags & ts.TypeFlags.StringMapping) { - return getStringMappingType((type as ts.StringMappingType).symbol, instantiateType((type as ts.StringMappingType).type, mapper)); + if (flags & TypeFlags.StringMapping) { + return getStringMappingType((type as StringMappingType).symbol, instantiateType((type as StringMappingType).type, mapper)); } - if (flags & ts.TypeFlags.IndexedAccess) { + if (flags & TypeFlags.IndexedAccess) { const newAliasSymbol = aliasSymbol || type.aliasSymbol; const newAliasTypeArguments = aliasSymbol ? aliasTypeArguments : instantiateTypes(type.aliasTypeArguments, mapper); - return getIndexedAccessType(instantiateType((type as ts.IndexedAccessType).objectType, mapper), instantiateType((type as ts.IndexedAccessType).indexType, mapper), (type as ts.IndexedAccessType).accessFlags, /*accessNode*/ undefined, newAliasSymbol, newAliasTypeArguments); + return getIndexedAccessType(instantiateType((type as IndexedAccessType).objectType, mapper), instantiateType((type as IndexedAccessType).indexType, mapper), (type as IndexedAccessType).accessFlags, /*accessNode*/ undefined, newAliasSymbol, newAliasTypeArguments); } - if (flags & ts.TypeFlags.Conditional) { - return getConditionalTypeInstantiation(type as ts.ConditionalType, combineTypeMappers((type as ts.ConditionalType).mapper, mapper), aliasSymbol, aliasTypeArguments); + if (flags & TypeFlags.Conditional) { + return getConditionalTypeInstantiation(type as ConditionalType, combineTypeMappers((type as ConditionalType).mapper, mapper), aliasSymbol, aliasTypeArguments); } - if (flags & ts.TypeFlags.Substitution) { - const newBaseType = instantiateType((type as ts.SubstitutionType).baseType, mapper); - const newConstraint = instantiateType((type as ts.SubstitutionType).constraint, mapper); + if (flags & TypeFlags.Substitution) { + const newBaseType = instantiateType((type as SubstitutionType).baseType, mapper); + const newConstraint = instantiateType((type as SubstitutionType).constraint, mapper); // A substitution type originates in the true branch of a conditional type and can be resolved // to just the base type in the same cases as the conditional type resolves to its true branch // (because the base type is then known to satisfy the constraint). - if (newBaseType.flags & ts.TypeFlags.TypeVariable && isGenericType(newConstraint)) { + if (newBaseType.flags & TypeFlags.TypeVariable && isGenericType(newConstraint)) { return getSubstitutionType(newBaseType, newConstraint); } - if (newConstraint.flags & ts.TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(newBaseType), getRestrictiveInstantiation(newConstraint))) { + if (newConstraint.flags & TypeFlags.AnyOrUnknown || isTypeAssignableTo(getRestrictiveInstantiation(newBaseType), getRestrictiveInstantiation(newConstraint))) { return newBaseType; } - return newBaseType.flags & ts.TypeFlags.TypeVariable ? getSubstitutionType(newBaseType, newConstraint) : getIntersectionType([newConstraint, newBaseType]); + return newBaseType.flags & TypeFlags.TypeVariable ? getSubstitutionType(newBaseType, newConstraint) : getIntersectionType([newConstraint, newBaseType]); } return type; } - function instantiateReverseMappedType(type: ts.ReverseMappedType, mapper: ts.TypeMapper) { + function instantiateReverseMappedType(type: ReverseMappedType, mapper: TypeMapper) { const innerMappedType = instantiateType(type.mappedType, mapper); - if (!(ts.getObjectFlags(innerMappedType) & ts.ObjectFlags.Mapped)) { + if (!(getObjectFlags(innerMappedType) & ObjectFlags.Mapped)) { return type; } const innerIndexType = instantiateType(type.constraintType, mapper); - if (!(innerIndexType.flags & ts.TypeFlags.Index)) { + if (!(innerIndexType.flags & TypeFlags.Index)) { return type; } const instantiated = inferTypeForHomomorphicMappedType( instantiateType(type.source, mapper), - innerMappedType as ts.MappedType, - innerIndexType as ts.IndexType + innerMappedType as MappedType, + innerIndexType as IndexType ); if (instantiated) { return instantiated; @@ -17602,18 +17800,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; // Nested invocation of `inferTypeForHomomorphicMappedType` or the `source` instantiated into something unmappable } - function getUniqueLiteralFilledInstantiation(type: ts.Type) { - return type.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Never) ? type : + function getUniqueLiteralFilledInstantiation(type: Type) { + return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type : type.uniqueLiteralFilledInstantiation || (type.uniqueLiteralFilledInstantiation = instantiateType(type, uniqueLiteralMapper)); } - function getPermissiveInstantiation(type: ts.Type) { - return type.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Never) ? type : + function getPermissiveInstantiation(type: Type) { + return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type : type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper)); } - function getRestrictiveInstantiation(type: ts.Type) { - if (type.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Never)) { + function getRestrictiveInstantiation(type: Type) { + if (type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never)) { return type; } if (type.restrictiveInstantiation) { @@ -17629,44 +17827,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.restrictiveInstantiation; } - function instantiateIndexInfo(info: ts.IndexInfo, mapper: ts.TypeMapper) { + function instantiateIndexInfo(info: IndexInfo, mapper: TypeMapper) { return createIndexInfo(info.keyType, instantiateType(info.type, mapper), info.isReadonly, info.declaration); } // Returns true if the given expression contains (at any level of nesting) a function or arrow expression // that is subject to contextual typing. - function isContextSensitive(node: ts.Expression | ts.MethodDeclaration | ts.ObjectLiteralElementLike | ts.JsxAttributeLike | ts.JsxChild): boolean { - ts.Debug.assert(node.kind !== ts.SyntaxKind.MethodDeclaration || ts.isObjectLiteralMethod(node)); + function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElementLike | JsxAttributeLike | JsxChild): boolean { + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); switch (node.kind) { - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type - return isContextSensitiveFunctionLikeDeclaration(node as ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration); - case ts.SyntaxKind.ObjectLiteralExpression: - return ts.some((node as ts.ObjectLiteralExpression).properties, isContextSensitive); - case ts.SyntaxKind.ArrayLiteralExpression: - return ts.some((node as ts.ArrayLiteralExpression).elements, isContextSensitive); - case ts.SyntaxKind.ConditionalExpression: - return isContextSensitive((node as ts.ConditionalExpression).whenTrue) || - isContextSensitive((node as ts.ConditionalExpression).whenFalse); - case ts.SyntaxKind.BinaryExpression: - return ((node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.BarBarToken || (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) && - (isContextSensitive((node as ts.BinaryExpression).left) || isContextSensitive((node as ts.BinaryExpression).right)); - case ts.SyntaxKind.PropertyAssignment: - return isContextSensitive((node as ts.PropertyAssignment).initializer); - case ts.SyntaxKind.ParenthesizedExpression: - return isContextSensitive((node as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.JsxAttributes: - return ts.some((node as ts.JsxAttributes).properties, isContextSensitive) || ts.isJsxOpeningElement(node.parent) && ts.some(node.parent.parent.children, isContextSensitive); - case ts.SyntaxKind.JsxAttribute: { + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionDeclaration: // Function declarations can have context when annotated with a jsdoc @type + return isContextSensitiveFunctionLikeDeclaration(node as FunctionExpression | ArrowFunction | MethodDeclaration); + case SyntaxKind.ObjectLiteralExpression: + return some((node as ObjectLiteralExpression).properties, isContextSensitive); + case SyntaxKind.ArrayLiteralExpression: + return some((node as ArrayLiteralExpression).elements, isContextSensitive); + case SyntaxKind.ConditionalExpression: + return isContextSensitive((node as ConditionalExpression).whenTrue) || + isContextSensitive((node as ConditionalExpression).whenFalse); + case SyntaxKind.BinaryExpression: + return ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken || (node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken) && + (isContextSensitive((node as BinaryExpression).left) || isContextSensitive((node as BinaryExpression).right)); + case SyntaxKind.PropertyAssignment: + return isContextSensitive((node as PropertyAssignment).initializer); + case SyntaxKind.ParenthesizedExpression: + return isContextSensitive((node as ParenthesizedExpression).expression); + case SyntaxKind.JsxAttributes: + return some((node as JsxAttributes).properties, isContextSensitive) || isJsxOpeningElement(node.parent) && some(node.parent.parent.children, isContextSensitive); + case SyntaxKind.JsxAttribute: { // If there is no initializer, JSX attribute has a boolean value of true which is not context sensitive. - const { initializer } = node as ts.JsxAttribute; + const { initializer } = node as JsxAttribute; return !!initializer && isContextSensitive(initializer); } - case ts.SyntaxKind.JsxExpression: { + case SyntaxKind.JsxExpression: { // It is possible to that node.expression is undefined (e.g
) - const { expression } = node as ts.JsxExpression; + const { expression } = node as JsxExpression; return !!expression && isContextSensitive(expression); } } @@ -17674,62 +17872,62 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isContextSensitiveFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration): boolean { - return ts.hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node); + function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration): boolean { + return hasContextSensitiveParameters(node) || hasContextSensitiveReturnExpression(node); } - function hasContextSensitiveReturnExpression(node: ts.FunctionLikeDeclaration) { + function hasContextSensitiveReturnExpression(node: FunctionLikeDeclaration) { // TODO(anhans): A block should be context-sensitive if it has a context-sensitive return value. - return !node.typeParameters && !ts.getEffectiveReturnTypeNode(node) && !!node.body && node.body.kind !== ts.SyntaxKind.Block && isContextSensitive(node.body); + return !node.typeParameters && !getEffectiveReturnTypeNode(node) && !!node.body && node.body.kind !== SyntaxKind.Block && isContextSensitive(node.body); } - function isContextSensitiveFunctionOrObjectLiteralMethod(func: ts.Node): func is ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration { - return (ts.isFunctionExpressionOrArrowFunction(func) || ts.isObjectLiteralMethod(func)) && + function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { + return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func); } - function getTypeWithoutSignatures(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function getTypeWithoutSignatures(type: Type): Type { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); if (resolved.constructSignatures.length || resolved.callSignatures.length) { - const result = createObjectType(ts.ObjectFlags.Anonymous, type.symbol); + const result = createObjectType(ObjectFlags.Anonymous, type.symbol); result.members = resolved.members; result.properties = resolved.properties; - result.callSignatures = ts.emptyArray; - result.constructSignatures = ts.emptyArray; - result.indexInfos = ts.emptyArray; + result.callSignatures = emptyArray; + result.constructSignatures = emptyArray; + result.indexInfos = emptyArray; return result; } } - else if (type.flags & ts.TypeFlags.Intersection) { - return getIntersectionType(ts.map((type as ts.IntersectionType).types, getTypeWithoutSignatures)); + else if (type.flags & TypeFlags.Intersection) { + return getIntersectionType(map((type as IntersectionType).types, getTypeWithoutSignatures)); } return type; } // TYPE CHECKING - function isTypeIdenticalTo(source: ts.Type, target: ts.Type): boolean { + function isTypeIdenticalTo(source: Type, target: Type): boolean { return isTypeRelatedTo(source, target, identityRelation); } - function compareTypesIdentical(source: ts.Type, target: ts.Type): ts.Ternary { - return isTypeRelatedTo(source, target, identityRelation) ? ts.Ternary.True : ts.Ternary.False; + function compareTypesIdentical(source: Type, target: Type): Ternary { + return isTypeRelatedTo(source, target, identityRelation) ? Ternary.True : Ternary.False; } - function compareTypesAssignable(source: ts.Type, target: ts.Type): ts.Ternary { - return isTypeRelatedTo(source, target, assignableRelation) ? ts.Ternary.True : ts.Ternary.False; + function compareTypesAssignable(source: Type, target: Type): Ternary { + return isTypeRelatedTo(source, target, assignableRelation) ? Ternary.True : Ternary.False; } - function compareTypesSubtypeOf(source: ts.Type, target: ts.Type): ts.Ternary { - return isTypeRelatedTo(source, target, subtypeRelation) ? ts.Ternary.True : ts.Ternary.False; + function compareTypesSubtypeOf(source: Type, target: Type): Ternary { + return isTypeRelatedTo(source, target, subtypeRelation) ? Ternary.True : Ternary.False; } - function isTypeSubtypeOf(source: ts.Type, target: ts.Type): boolean { + function isTypeSubtypeOf(source: Type, target: Type): boolean { return isTypeRelatedTo(source, target, subtypeRelation); } - function isTypeAssignableTo(source: ts.Type, target: ts.Type): boolean { + function isTypeAssignableTo(source: Type, target: Type): boolean { return isTypeRelatedTo(source, target, assignableRelation); } @@ -17741,12 +17939,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // T occurs directly or indirectly in an 'extends' clause of S. // Note that this check ignores type parameters and only considers the // inheritance hierarchy. - function isTypeDerivedFrom(source: ts.Type, target: ts.Type): boolean { - return source.flags & ts.TypeFlags.Union ? ts.every((source as ts.UnionType).types, t => isTypeDerivedFrom(t, target)) : - target.flags & ts.TypeFlags.Union ? ts.some((target as ts.UnionType).types, t => isTypeDerivedFrom(source, t)) : - source.flags & ts.TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) : - target === globalObjectType ? !!(source.flags & (ts.TypeFlags.Object | ts.TypeFlags.NonPrimitive)) : - target === globalFunctionType ? !!(source.flags & ts.TypeFlags.Object) && isFunctionObjectType(source as ts.ObjectType) : + function isTypeDerivedFrom(source: Type, target: Type): boolean { + return source.flags & TypeFlags.Union ? every((source as UnionType).types, t => isTypeDerivedFrom(t, target)) : + target.flags & TypeFlags.Union ? some((target as UnionType).types, t => isTypeDerivedFrom(source, t)) : + source.flags & TypeFlags.InstantiableNonPrimitive ? isTypeDerivedFrom(getBaseConstraintOfType(source) || unknownType, target) : + target === globalObjectType ? !!(source.flags & (TypeFlags.Object | TypeFlags.NonPrimitive)) : + target === globalFunctionType ? !!(source.flags & TypeFlags.Object) && isFunctionObjectType(source as ObjectType) : hasBaseType(source, getTargetType(target)) || (isArrayType(target) && !isReadonlyArrayType(target) && isTypeDerivedFrom(source, globalReadonlyArrayType)); } @@ -17760,15 +17958,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * - the types of `case` clause expressions and their respective `switch` expressions. * - the type of an expression in a type assertion with the type being asserted. */ - function isTypeComparableTo(source: ts.Type, target: ts.Type): boolean { + function isTypeComparableTo(source: Type, target: Type): boolean { return isTypeRelatedTo(source, target, comparableRelation); } - function areTypesComparable(type1: ts.Type, type2: ts.Type): boolean { + function areTypesComparable(type1: Type, type2: Type): boolean { return isTypeComparableTo(type1, type2) || isTypeComparableTo(type2, type1); } - function checkTypeAssignableTo(source: ts.Type, target: ts.Type, errorNode: ts.Node | undefined, headMessage?: ts.DiagnosticMessage, containingMessageChain?: () => ts.DiagnosticMessageChain | undefined, errorOutputObject?: { errors?: ts.Diagnostic[] }): boolean { + function checkTypeAssignableTo(source: Type, target: Type, errorNode: Node | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined, errorOutputObject?: { errors?: Diagnostic[] }): boolean { return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain, errorOutputObject); } @@ -17776,19 +17974,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Like `checkTypeAssignableTo`, but if it would issue an error, instead performs structural comparisons of the types using the given expression node to * attempt to issue more specific errors on, for example, specific object literal properties or tuple members. */ - function checkTypeAssignableToAndOptionallyElaborate(source: ts.Type, target: ts.Type, errorNode: ts.Node | undefined, expr: ts.Expression | undefined, headMessage?: ts.DiagnosticMessage, containingMessageChain?: () => ts.DiagnosticMessageChain | undefined): boolean { + function checkTypeAssignableToAndOptionallyElaborate(source: Type, target: Type, errorNode: Node | undefined, expr: Expression | undefined, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { return checkTypeRelatedToAndOptionallyElaborate(source, target, assignableRelation, errorNode, expr, headMessage, containingMessageChain, /*errorOutputContainer*/ undefined); } function checkTypeRelatedToAndOptionallyElaborate( - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - errorNode: ts.Node | undefined, - expr: ts.Expression | undefined, - headMessage: ts.DiagnosticMessage | undefined, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + source: Type, + target: Type, + relation: ESMap, + errorNode: Node | undefined, + expr: Expression | undefined, + headMessage: DiagnosticMessage | undefined, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ): boolean { if (isTypeRelatedTo(source, target, relation)) return true; if (!errorNode || !elaborateError(expr, source, target, relation, headMessage, containingMessageChain, errorOutputContainer)) { @@ -17797,18 +17995,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isOrHasGenericConditional(type: ts.Type): boolean { - return !!(type.flags & ts.TypeFlags.Conditional || (type.flags & ts.TypeFlags.Intersection && ts.some((type as ts.IntersectionType).types, isOrHasGenericConditional))); + function isOrHasGenericConditional(type: Type): boolean { + return !!(type.flags & TypeFlags.Conditional || (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isOrHasGenericConditional))); } function elaborateError( - node: ts.Expression | undefined, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - headMessage: ts.DiagnosticMessage | undefined, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: Expression | undefined, + source: Type, + target: Type, + relation: ESMap, + headMessage: DiagnosticMessage | undefined, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ): boolean { if (!node || isOrHasGenericConditional(target)) return false; if (!checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined) @@ -17816,50 +18014,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } switch (node.kind) { - case ts.SyntaxKind.JsxExpression: - case ts.SyntaxKind.ParenthesizedExpression: - return elaborateError((node as ts.ParenthesizedExpression | ts.JsxExpression).expression, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); - case ts.SyntaxKind.BinaryExpression: - switch ((node as ts.BinaryExpression).operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.CommaToken: - return elaborateError((node as ts.BinaryExpression).right, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); + case SyntaxKind.JsxExpression: + case SyntaxKind.ParenthesizedExpression: + return elaborateError((node as ParenthesizedExpression | JsxExpression).expression, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); + case SyntaxKind.BinaryExpression: + switch ((node as BinaryExpression).operatorToken.kind) { + case SyntaxKind.EqualsToken: + case SyntaxKind.CommaToken: + return elaborateError((node as BinaryExpression).right, source, target, relation, headMessage, containingMessageChain, errorOutputContainer); } break; - case ts.SyntaxKind.ObjectLiteralExpression: - return elaborateObjectLiteral(node as ts.ObjectLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); - case ts.SyntaxKind.ArrayLiteralExpression: - return elaborateArrayLiteral(node as ts.ArrayLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); - case ts.SyntaxKind.JsxAttributes: - return elaborateJsxComponents(node as ts.JsxAttributes, source, target, relation, containingMessageChain, errorOutputContainer); - case ts.SyntaxKind.ArrowFunction: - return elaborateArrowFunction(node as ts.ArrowFunction, source, target, relation, containingMessageChain, errorOutputContainer); + case SyntaxKind.ObjectLiteralExpression: + return elaborateObjectLiteral(node as ObjectLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); + case SyntaxKind.ArrayLiteralExpression: + return elaborateArrayLiteral(node as ArrayLiteralExpression, source, target, relation, containingMessageChain, errorOutputContainer); + case SyntaxKind.JsxAttributes: + return elaborateJsxComponents(node as JsxAttributes, source, target, relation, containingMessageChain, errorOutputContainer); + case SyntaxKind.ArrowFunction: + return elaborateArrowFunction(node as ArrowFunction, source, target, relation, containingMessageChain, errorOutputContainer); } return false; } function elaborateDidYouMeanToCallOrConstruct( - node: ts.Expression, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - headMessage: ts.DiagnosticMessage | undefined, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: Expression, + source: Type, + target: Type, + relation: ESMap, + headMessage: DiagnosticMessage | undefined, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ): boolean { - const callSignatures = getSignaturesOfType(source, ts.SignatureKind.Call); - const constructSignatures = getSignaturesOfType(source, ts.SignatureKind.Construct); + const callSignatures = getSignaturesOfType(source, SignatureKind.Call); + const constructSignatures = getSignaturesOfType(source, SignatureKind.Construct); for (const signatures of [constructSignatures, callSignatures]) { - if (ts.some(signatures, s => { + if (some(signatures, s => { const returnType = getReturnTypeOfSignature(s); - return !(returnType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never)) && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined); + return !(returnType.flags & (TypeFlags.Any | TypeFlags.Never)) && checkTypeRelatedTo(returnType, target, relation, /*errorNode*/ undefined); })) { - const resultObj: { errors?: ts.Diagnostic[] } = errorOutputContainer || {}; + const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {}; checkTypeAssignableTo(source, target, node, headMessage, containingMessageChain, resultObj); const diagnostic = resultObj.errors![resultObj.errors!.length - 1]; - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode( + addRelatedInfo(diagnostic, createDiagnosticForNode( node, - signatures === constructSignatures ? ts.Diagnostics.Did_you_mean_to_use_new_with_this_expression : ts.Diagnostics.Did_you_mean_to_call_this_expression + signatures === constructSignatures ? Diagnostics.Did_you_mean_to_use_new_with_this_expression : Diagnostics.Did_you_mean_to_call_this_expression )); return true; } @@ -17868,55 +18066,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function elaborateArrowFunction( - node: ts.ArrowFunction, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: ArrowFunction, + source: Type, + target: Type, + relation: ESMap, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ): boolean { // Don't elaborate blocks - if (ts.isBlock(node.body)) { + if (isBlock(node.body)) { return false; } // Or functions with annotated parameter types - if (ts.some(node.parameters, ts.hasType)) { + if (some(node.parameters, ts.hasType)) { return false; } const sourceSig = getSingleCallSignature(source); if (!sourceSig) { return false; } - const targetSignatures = getSignaturesOfType(target, ts.SignatureKind.Call); - if (!ts.length(targetSignatures)) { + const targetSignatures = getSignaturesOfType(target, SignatureKind.Call); + if (!length(targetSignatures)) { return false; } const returnExpression = node.body; const sourceReturn = getReturnTypeOfSignature(sourceSig); - const targetReturn = getUnionType(ts.map(targetSignatures, getReturnTypeOfSignature)); + const targetReturn = getUnionType(map(targetSignatures, getReturnTypeOfSignature)); if (!checkTypeRelatedTo(sourceReturn, targetReturn, relation, /*errorNode*/ undefined)) { const elaborated = returnExpression && elaborateError(returnExpression, sourceReturn, targetReturn, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer); if (elaborated) { return elaborated; } - const resultObj: { errors?: ts.Diagnostic[] } = errorOutputContainer || {}; + const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {}; checkTypeRelatedTo(sourceReturn, targetReturn, relation, returnExpression, /*message*/ undefined, containingMessageChain, resultObj); if (resultObj.errors) { - if (target.symbol && ts.length(target.symbol.declarations)) { - ts.addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], ts.createDiagnosticForNode( + if (target.symbol && length(target.symbol.declarations)) { + addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], createDiagnosticForNode( target.symbol.declarations![0], - ts.Diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature, + Diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature, )); } - if ((ts.getFunctionFlags(node) & ts.FunctionFlags.Async) === 0 + if ((getFunctionFlags(node) & FunctionFlags.Async) === 0 // exclude cases where source itself is promisy - this way we don't make a suggestion when relating // an IPromise and a Promise that are slightly different - && !getTypeOfPropertyOfType(sourceReturn, "then" as ts.__String) + && !getTypeOfPropertyOfType(sourceReturn, "then" as __String) && checkTypeRelatedTo(createPromiseType(sourceReturn), targetReturn, relation, /*errorNode*/ undefined) ) { - ts.addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], ts.createDiagnosticForNode( + addRelatedInfo(resultObj.errors[resultObj.errors.length - 1], createDiagnosticForNode( node, - ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async + Diagnostics.Did_you_mean_to_mark_this_function_as_async )); } return true; @@ -17925,20 +18123,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function getBestMatchIndexedAccessTypeOrUndefined(source: ts.Type, target: ts.Type, nameType: ts.Type) { + function getBestMatchIndexedAccessTypeOrUndefined(source: Type, target: Type, nameType: Type) { const idx = getIndexedAccessTypeOrUndefined(target, nameType); if (idx) { return idx; } - if (target.flags & ts.TypeFlags.Union) { - const best = getBestMatchingType(source, target as ts.UnionType); + if (target.flags & TypeFlags.Union) { + const best = getBestMatchingType(source, target as UnionType); if (best) { return getIndexedAccessTypeOrUndefined(best, nameType); } } } - function checkExpressionForMutableLocationWithContextualType(next: ts.Expression, sourcePropType: ts.Type) { + function checkExpressionForMutableLocationWithContextualType(next: Expression, sourcePropType: Type) { next.contextualType = sourcePropType; try { return checkExpressionForMutableLocation(next, CheckMode.Contextual, sourcePropType); @@ -17948,7 +18146,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - type ElaborationIterator = IterableIterator<{ errorNode: ts.Node, innerExpression: ts.Expression | undefined, nameType: ts.Type, errorMessage?: ts.DiagnosticMessage | undefined }>; + type ElaborationIterator = IterableIterator<{ errorNode: Node, innerExpression: Expression | undefined, nameType: Type, errorMessage?: DiagnosticMessage | undefined }>; /** * For every element returned from the iterator, checks that element to issue an error on a property of that element's type * If that element would issue an error, we first attempt to dive into that element's inner expression and issue a more specific error by recuring into `elaborateError` @@ -17956,18 +18154,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { */ function elaborateElementwise( iterator: ElaborationIterator, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + source: Type, + target: Type, + relation: ESMap, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ) { // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span let reportedError = false; for (let status = iterator.next(); !status.done; status = iterator.next()) { const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; let targetPropType = getBestMatchIndexedAccessTypeOrUndefined(source, target, nameType); - if (!targetPropType || targetPropType.flags & ts.TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables + if (!targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables let sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType); if (!sourcePropType) continue; const propName = getPropertyNameFromIndex(nameType, /*accessNode*/ undefined); @@ -17976,17 +18174,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { reportedError = true; if (!elaborated) { // Issue error on the prop itself, since the prop couldn't elaborate the error - const resultObj: { errors?: ts.Diagnostic[] } = errorOutputContainer || {}; + const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {}; // Use the expression type, if available const specificSource = next ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; if (exactOptionalPropertyTypes && isExactOptionalPropertyMismatch(specificSource, targetPropType)) { - const diag = ts.createDiagnosticForNode(prop, ts.Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType)); + const diag = createDiagnosticForNode(prop, Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType)); diagnostics.add(diag); resultObj.errors = [diag]; } else { - const targetIsOptional = !!(propName && (getPropertyOfType(target, propName) || unknownSymbol).flags & ts.SymbolFlags.Optional); - const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & ts.SymbolFlags.Optional); + const targetIsOptional = !!(propName && (getPropertyOfType(target, propName) || unknownSymbol).flags & SymbolFlags.Optional); + const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional); targetPropType = removeMissingType(targetPropType, targetIsOptional); sourcePropType = removeMissingType(sourcePropType, targetIsOptional && sourceIsOptional); const result = checkTypeRelatedTo(specificSource, targetPropType, relation, prop, errorMessage, containingMessageChain, resultObj); @@ -18003,19 +18201,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let issuedElaboration = false; if (!targetProp) { const indexInfo = getApplicableIndexInfo(target, nameType); - if (indexInfo && indexInfo.declaration && !ts.getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) { + if (indexInfo && indexInfo.declaration && !getSourceFileOfNode(indexInfo.declaration).hasNoDefaultLib) { issuedElaboration = true; - ts.addRelatedInfo(reportedDiag, ts.createDiagnosticForNode(indexInfo.declaration, ts.Diagnostics.The_expected_type_comes_from_this_index_signature)); + addRelatedInfo(reportedDiag, createDiagnosticForNode(indexInfo.declaration, Diagnostics.The_expected_type_comes_from_this_index_signature)); } } - if (!issuedElaboration && (targetProp && ts.length(targetProp.declarations) || target.symbol && ts.length(target.symbol.declarations))) { - const targetNode = targetProp && ts.length(targetProp.declarations) ? targetProp.declarations![0] : target.symbol.declarations![0]; - if (!ts.getSourceFileOfNode(targetNode).hasNoDefaultLib) { - ts.addRelatedInfo(reportedDiag, ts.createDiagnosticForNode( + if (!issuedElaboration && (targetProp && length(targetProp.declarations) || target.symbol && length(target.symbol.declarations))) { + const targetNode = targetProp && length(targetProp.declarations) ? targetProp.declarations![0] : target.symbol.declarations![0]; + if (!getSourceFileOfNode(targetNode).hasNoDefaultLib) { + addRelatedInfo(reportedDiag, createDiagnosticForNode( targetNode, - ts.Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, - propertyName && !(nameType.flags & ts.TypeFlags.UniqueESSymbol) ? ts.unescapeLeadingUnderscores(propertyName) : typeToString(nameType), + Diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, + propertyName && !(nameType.flags & TypeFlags.UniqueESSymbol) ? unescapeLeadingUnderscores(propertyName) : typeToString(nameType), typeToString(target) )); } @@ -18027,16 +18225,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return reportedError; } - function *generateJsxAttributes(node: ts.JsxAttributes): ElaborationIterator { - if (!ts.length(node.properties)) return; + function *generateJsxAttributes(node: JsxAttributes): ElaborationIterator { + if (!length(node.properties)) return; for (const prop of node.properties) { - if (ts.isJsxSpreadAttribute(prop) || isHyphenatedJsxName(ts.idText(prop.name))) continue; - yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: getStringLiteralType(ts.idText(prop.name)) }; + if (isJsxSpreadAttribute(prop) || isHyphenatedJsxName(idText(prop.name))) continue; + yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: getStringLiteralType(idText(prop.name)) }; } } - function *generateJsxChildren(node: ts.JsxElement, getInvalidTextDiagnostic: () => ts.DiagnosticMessage): ElaborationIterator { - if (!ts.length(node.children)) return; + function *generateJsxChildren(node: JsxElement, getInvalidTextDiagnostic: () => DiagnosticMessage): ElaborationIterator { + if (!length(node.children)) return; let memberOffset = 0; for (let i = 0; i < node.children.length; i++) { const child = node.children[i]; @@ -18051,48 +18249,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getElaborationElementForJsxChild(child: ts.JsxChild, nameType: ts.LiteralType, getInvalidTextDiagnostic: () => ts.DiagnosticMessage) { + function getElaborationElementForJsxChild(child: JsxChild, nameType: LiteralType, getInvalidTextDiagnostic: () => DiagnosticMessage) { switch (child.kind) { - case ts.SyntaxKind.JsxExpression: + case SyntaxKind.JsxExpression: // child is of the type of the expression return { errorNode: child, innerExpression: child.expression, nameType }; - case ts.SyntaxKind.JsxText: + case SyntaxKind.JsxText: if (child.containsOnlyTriviaWhiteSpaces) { break; // Whitespace only jsx text isn't real jsx text } // child is a string return { errorNode: child, innerExpression: undefined, nameType, errorMessage: getInvalidTextDiagnostic() }; - case ts.SyntaxKind.JsxElement: - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxFragment: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxFragment: // child is of type JSX.Element return { errorNode: child, innerExpression: child, nameType }; default: - return ts.Debug.assertNever(child, "Found invalid jsx child"); + return Debug.assertNever(child, "Found invalid jsx child"); } } function elaborateJsxComponents( - node: ts.JsxAttributes, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: JsxAttributes, + source: Type, + target: Type, + relation: ESMap, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ) { let result = elaborateElementwise(generateJsxAttributes(node), source, target, relation, containingMessageChain, errorOutputContainer); - let invalidTextDiagnostic: ts.DiagnosticMessage | undefined; - if (ts.isJsxOpeningElement(node.parent) && ts.isJsxElement(node.parent.parent)) { + let invalidTextDiagnostic: DiagnosticMessage | undefined; + if (isJsxOpeningElement(node.parent) && isJsxElement(node.parent.parent)) { const containingElement = node.parent.parent; const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); - const childrenPropName = childPropName === undefined ? "children" : ts.unescapeLeadingUnderscores(childPropName); + const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName); const childrenNameType = getStringLiteralType(childrenPropName); const childrenTargetType = getIndexedAccessType(target, childrenNameType); - const validChildren = ts.getSemanticJsxChildren(containingElement.children); - if (!ts.length(validChildren)) { + const validChildren = getSemanticJsxChildren(containingElement.children); + if (!length(validChildren)) { return result; } - const moreThanOneRealChildren = ts.length(validChildren) > 1; + const moreThanOneRealChildren = length(validChildren) > 1; const arrayLikeTargetParts = filterType(childrenTargetType, isArrayOrTupleLikeType); const nonArrayLikeTargetParts = filterType(childrenTargetType, t => !isArrayOrTupleLikeType(t)); if (moreThanOneRealChildren) { @@ -18106,7 +18304,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result = true; const diag = error( containingElement.openingElement.tagName, - ts.Diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, + Diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, childrenPropName, typeToString(childrenTargetType) ); @@ -18135,7 +18333,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { result = true; const diag = error( containingElement.openingElement.tagName, - ts.Diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, + Diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, childrenPropName, typeToString(childrenTargetType) ); @@ -18149,39 +18347,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function getInvalidTextualChildDiagnostic() { if (!invalidTextDiagnostic) { - const tagNameText = ts.getTextOfNode(node.parent.tagName); + const tagNameText = getTextOfNode(node.parent.tagName); const childPropName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); - const childrenPropName = childPropName === undefined ? "children" : ts.unescapeLeadingUnderscores(childPropName); + const childrenPropName = childPropName === undefined ? "children" : unescapeLeadingUnderscores(childPropName); const childrenTargetType = getIndexedAccessType(target, getStringLiteralType(childrenPropName)); - const diagnostic = ts.Diagnostics._0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2; - invalidTextDiagnostic = { ...diagnostic, key: "!!ALREADY FORMATTED!!", message: ts.formatMessage(/*_dummy*/ undefined, diagnostic, tagNameText, childrenPropName, typeToString(childrenTargetType)) }; + const diagnostic = Diagnostics._0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2; + invalidTextDiagnostic = { ...diagnostic, key: "!!ALREADY FORMATTED!!", message: formatMessage(/*_dummy*/ undefined, diagnostic, tagNameText, childrenPropName, typeToString(childrenTargetType)) }; } return invalidTextDiagnostic; } } - function *generateLimitedTupleElements(node: ts.ArrayLiteralExpression, target: ts.Type): ElaborationIterator { - const len = ts.length(node.elements); + function *generateLimitedTupleElements(node: ArrayLiteralExpression, target: Type): ElaborationIterator { + const len = length(node.elements); if (!len) return; for (let i = 0; i < len; i++) { // Skip elements which do not exist in the target - a length error on the tuple overall is likely better than an error on a mismatched index signature - if (isTupleLikeType(target) && !getPropertyOfType(target, ("" + i) as ts.__String)) continue; + if (isTupleLikeType(target) && !getPropertyOfType(target, ("" + i) as __String)) continue; const elem = node.elements[i]; - if (ts.isOmittedExpression(elem)) continue; + if (isOmittedExpression(elem)) continue; const nameType = getNumberLiteralType(i); yield { errorNode: elem, innerExpression: elem, nameType }; } } function elaborateArrayLiteral( - node: ts.ArrayLiteralExpression, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: ArrayLiteralExpression, + source: Type, + target: Type, + relation: ESMap, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ) { - if (target.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.Never)) return false; + if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false; if (isTupleLikeType(source)) { return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation, containingMessageChain, errorOutputContainer); } @@ -18202,39 +18400,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function *generateObjectLiteralElements(node: ts.ObjectLiteralExpression): ElaborationIterator { - if (!ts.length(node.properties)) return; + function *generateObjectLiteralElements(node: ObjectLiteralExpression): ElaborationIterator { + if (!length(node.properties)) return; for (const prop of node.properties) { - if (ts.isSpreadAssignment(prop)) continue; - const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), ts.TypeFlags.StringOrNumberLiteralOrUnique); - if (!type || (type.flags & ts.TypeFlags.Never)) { + if (isSpreadAssignment(prop)) continue; + const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique); + if (!type || (type.flags & TypeFlags.Never)) { continue; } switch (prop.kind) { - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ShorthandPropertyAssignment: yield { errorNode: prop.name, innerExpression: undefined, nameType: type }; break; - case ts.SyntaxKind.PropertyAssignment: - yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: type, errorMessage: ts.isComputedNonLiteralName(prop.name) ? ts.Diagnostics.Type_of_computed_property_s_value_is_0_which_is_not_assignable_to_type_1 : undefined }; + case SyntaxKind.PropertyAssignment: + yield { errorNode: prop.name, innerExpression: prop.initializer, nameType: type, errorMessage: isComputedNonLiteralName(prop.name) ? Diagnostics.Type_of_computed_property_s_value_is_0_which_is_not_assignable_to_type_1 : undefined }; break; default: - ts.Debug.assertNever(prop); + Debug.assertNever(prop); } } } function elaborateObjectLiteral( - node: ts.ObjectLiteralExpression, - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } | undefined + node: ObjectLiteralExpression, + source: Type, + target: Type, + relation: ESMap, + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } | undefined ) { - if (target.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.Never)) return false; + if (target.flags & (TypeFlags.Primitive | TypeFlags.Never)) return false; return elaborateElementwise(generateObjectLiteralElements(node), source, target, relation, containingMessageChain, errorOutputContainer); } @@ -18242,23 +18440,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * This is *not* a bi-directional relationship. * If one needs to check both directions for comparability, use a second call to this function or 'isTypeComparableTo'. */ - function checkTypeComparableTo(source: ts.Type, target: ts.Type, errorNode: ts.Node, headMessage?: ts.DiagnosticMessage, containingMessageChain?: () => ts.DiagnosticMessageChain | undefined): boolean { + function checkTypeComparableTo(source: Type, target: Type, errorNode: Node, headMessage?: DiagnosticMessage, containingMessageChain?: () => DiagnosticMessageChain | undefined): boolean { return checkTypeRelatedTo(source, target, comparableRelation, errorNode, headMessage, containingMessageChain); } - function isSignatureAssignableTo(source: ts.Signature, - target: ts.Signature, + function isSignatureAssignableTo(source: Signature, + target: Signature, ignoreReturnTypes: boolean): boolean { return compareSignaturesRelated(source, target, ignoreReturnTypes ? SignatureCheckMode.IgnoreReturnTypes : 0, /*reportErrors*/ false, - /*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== ts.Ternary.False; + /*errorReporter*/ undefined, /*errorReporter*/ undefined, compareTypesAssignable, /*reportUnreliableMarkers*/ undefined) !== Ternary.False; } - type ErrorReporter = (message: ts.DiagnosticMessage, arg0?: string, arg1?: string) => void; + type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void; /** * Returns true if `s` is `(...args: any[]) => any` or `(this: any, ...args: any[]) => any` */ - function isAnySignature(s: ts.Signature) { + function isAnySignature(s: Signature) { return !s.typeParameters && (!s.thisParameter || isTypeAny(getTypeOfParameter(s.thisParameter))) && s.parameters.length === 1 && signatureHasRestParameter(s) && (getTypeOfParameter(s.parameters[0]) === anyArrayType || isTypeAny(getTypeOfParameter(s.parameters[0]))) && isTypeAny(getReturnTypeOfSignature(s)); @@ -18267,28 +18465,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesRelated(source: ts.Signature, - target: ts.Signature, + function compareSignaturesRelated(source: Signature, + target: Signature, checkMode: SignatureCheckMode, reportErrors: boolean, errorReporter: ErrorReporter | undefined, - incompatibleErrorReporter: ((source: ts.Type, target: ts.Type) => void) | undefined, - compareTypes: ts.TypeComparer, - reportUnreliableMarkers: ts.TypeMapper | undefined): ts.Ternary { + incompatibleErrorReporter: ((source: Type, target: Type) => void) | undefined, + compareTypes: TypeComparer, + reportUnreliableMarkers: TypeMapper | undefined): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return ts.Ternary.True; + return Ternary.True; } if (isAnySignature(target)) { - return ts.Ternary.True; + return Ternary.True; } const targetCount = getParameterCount(target); const sourceHasMoreParameters = !hasEffectiveRestParameter(target) && (checkMode & SignatureCheckMode.StrictArity ? hasEffectiveRestParameter(source) || getParameterCount(source) > targetCount : getMinArgumentCount(source) > targetCount); if (sourceHasMoreParameters) { - return ts.Ternary.False; + return Ternary.False; } if (source.typeParameters && source.typeParameters !== target.typeParameters) { @@ -18303,10 +18501,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { void instantiateType(sourceRestType || targetRestType, reportUnreliableMarkers); } - const kind = target.declaration ? target.declaration.kind : ts.SyntaxKind.Unknown; - const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== ts.SyntaxKind.MethodDeclaration && - kind !== ts.SyntaxKind.MethodSignature && kind !== ts.SyntaxKind.Constructor; - let result = ts.Ternary.True; + const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; + const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && + kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; + let result = Ternary.True; const sourceThisType = getThisTypeOfSignature(source); if (sourceThisType && sourceThisType !== voidType) { @@ -18317,9 +18515,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { || compareTypes(targetThisType, sourceThisType, reportErrors); if (!related) { if (reportErrors) { - errorReporter!(ts.Diagnostics.The_this_types_of_each_signature_are_incompatible); + errorReporter!(Diagnostics.The_this_types_of_each_signature_are_incompatible); } - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -18349,15 +18547,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); // With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && compareTypes(sourceType, targetType, /*reportErrors*/ false)) { - related = ts.Ternary.False; + related = Ternary.False; } if (!related) { if (reportErrors) { - errorReporter!(ts.Diagnostics.Types_of_parameters_0_and_1_are_incompatible, - ts.unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), - ts.unescapeLeadingUnderscores(getParameterNameAtPosition(target, i))); + errorReporter!(Diagnostics.Types_of_parameters_0_and_1_are_incompatible, + unescapeLeadingUnderscores(getParameterNameAtPosition(source, i)), + unescapeLeadingUnderscores(getParameterNameAtPosition(target, i))); } - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -18383,11 +18581,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (sourceTypePredicate) { result &= compareTypePredicateRelatedTo(sourceTypePredicate, targetTypePredicate, reportErrors, errorReporter, compareTypes); } - else if (ts.isIdentifierTypePredicate(targetTypePredicate)) { + else if (isIdentifierTypePredicate(targetTypePredicate)) { if (reportErrors) { - errorReporter!(ts.Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); + errorReporter!(Diagnostics.Signature_0_must_be_a_type_predicate, signatureToString(source)); } - return ts.Ternary.False; + return Ternary.False; } } else { @@ -18407,39 +18605,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function compareTypePredicateRelatedTo( - source: ts.TypePredicate, - target: ts.TypePredicate, + source: TypePredicate, + target: TypePredicate, reportErrors: boolean, errorReporter: ErrorReporter | undefined, - compareTypes: (s: ts.Type, t: ts.Type, reportErrors?: boolean) => ts.Ternary): ts.Ternary { + compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary { if (source.kind !== target.kind) { if (reportErrors) { - errorReporter!(ts.Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); - errorReporter!(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard); + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return ts.Ternary.False; + return Ternary.False; } - if (source.kind === ts.TypePredicateKind.Identifier || source.kind === ts.TypePredicateKind.AssertsIdentifier) { - if (source.parameterIndex !== (target as ts.IdentifierTypePredicate).parameterIndex) { + if (source.kind === TypePredicateKind.Identifier || source.kind === TypePredicateKind.AssertsIdentifier) { + if (source.parameterIndex !== (target as IdentifierTypePredicate).parameterIndex) { if (reportErrors) { - errorReporter!(ts.Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as ts.IdentifierTypePredicate).parameterName); - errorReporter!(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as IdentifierTypePredicate).parameterName); + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } - return ts.Ternary.False; + return Ternary.False; } } - const related = source.type === target.type ? ts.Ternary.True : + const related = source.type === target.type ? Ternary.True : source.type && target.type ? compareTypes(source.type, target.type, reportErrors) : - ts.Ternary.False; - if (related === ts.Ternary.False && reportErrors) { - errorReporter!(ts.Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); + Ternary.False; + if (related === Ternary.False && reportErrors) { + errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target)); } return related; } - function isImplementationCompatibleWithOverload(implementation: ts.Signature, overload: ts.Signature): boolean { + function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean { const erasedSource = getErasedSignature(implementation); const erasedTarget = getErasedSignature(overload); @@ -18456,7 +18654,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isEmptyResolvedType(t: ts.ResolvedType) { + function isEmptyResolvedType(t: ResolvedType) { return t !== anyFunctionType && t.properties.length === 0 && t.callSignatures.length === 0 && @@ -18464,174 +18662,174 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { t.indexInfos.length === 0; } - function isEmptyObjectType(type: ts.Type): boolean { - return type.flags & ts.TypeFlags.Object ? !isGenericMappedType(type) && isEmptyResolvedType(resolveStructuredTypeMembers(type as ts.ObjectType)) : - type.flags & ts.TypeFlags.NonPrimitive ? true : - type.flags & ts.TypeFlags.Union ? ts.some((type as ts.UnionType).types, isEmptyObjectType) : - type.flags & ts.TypeFlags.Intersection ? ts.every((type as ts.UnionType).types, isEmptyObjectType) : + function isEmptyObjectType(type: Type): boolean { + return type.flags & TypeFlags.Object ? !isGenericMappedType(type) && isEmptyResolvedType(resolveStructuredTypeMembers(type as ObjectType)) : + type.flags & TypeFlags.NonPrimitive ? true : + type.flags & TypeFlags.Union ? some((type as UnionType).types, isEmptyObjectType) : + type.flags & TypeFlags.Intersection ? every((type as UnionType).types, isEmptyObjectType) : false; } - function isEmptyAnonymousObjectType(type: ts.Type) { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous && ( - (type as ts.ResolvedType).members && isEmptyResolvedType(type as ts.ResolvedType) || - type.symbol && type.symbol.flags & ts.SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0)); + function isEmptyAnonymousObjectType(type: Type) { + return !!(getObjectFlags(type) & ObjectFlags.Anonymous && ( + (type as ResolvedType).members && isEmptyResolvedType(type as ResolvedType) || + type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && getMembersOfSymbol(type.symbol).size === 0)); } - function isUnknownLikeUnionType(type: ts.Type) { - if (strictNullChecks && type.flags & ts.TypeFlags.Union) { - if (!((type as ts.UnionType).objectFlags & ts.ObjectFlags.IsUnknownLikeUnionComputed)) { - const types = (type as ts.UnionType).types; - (type as ts.UnionType).objectFlags |= ts.ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & ts.TypeFlags.Undefined && - types[1].flags & ts.TypeFlags.Null && ts.some(types, isEmptyAnonymousObjectType) ? ts.ObjectFlags.IsUnknownLikeUnion : 0); + function isUnknownLikeUnionType(type: Type) { + if (strictNullChecks && type.flags & TypeFlags.Union) { + if (!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnionComputed)) { + const types = (type as UnionType).types; + (type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & TypeFlags.Undefined && + types[1].flags & TypeFlags.Null && some(types, isEmptyAnonymousObjectType) ? ObjectFlags.IsUnknownLikeUnion : 0); } - return !!((type as ts.UnionType).objectFlags & ts.ObjectFlags.IsUnknownLikeUnion); + return !!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnion); } return false; } - function containsUndefinedType(type: ts.Type) { - return !!((type.flags & ts.TypeFlags.Union ? (type as ts.UnionType).types[0] : type).flags & ts.TypeFlags.Undefined); + function containsUndefinedType(type: Type) { + return !!((type.flags & TypeFlags.Union ? (type as UnionType).types[0] : type).flags & TypeFlags.Undefined); } - function isStringIndexSignatureOnlyType(type: ts.Type): boolean { - return type.flags & ts.TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) || - type.flags & ts.TypeFlags.UnionOrIntersection && ts.every((type as ts.UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) || + function isStringIndexSignatureOnlyType(type: Type): boolean { + return type.flags & TypeFlags.Object && !isGenericMappedType(type) && getPropertiesOfType(type).length === 0 && getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, stringType) || + type.flags & TypeFlags.UnionOrIntersection && every((type as UnionOrIntersectionType).types, isStringIndexSignatureOnlyType) || false; } - function isEnumTypeRelatedTo(source: ts.Symbol, target: ts.Symbol, errorReporter?: ErrorReporter) { - const sourceSymbol = source.flags & ts.SymbolFlags.EnumMember ? getParentOfSymbol(source)! : source; - const targetSymbol = target.flags & ts.SymbolFlags.EnumMember ? getParentOfSymbol(target)! : target; + function isEnumTypeRelatedTo(source: Symbol, target: Symbol, errorReporter?: ErrorReporter) { + const sourceSymbol = source.flags & SymbolFlags.EnumMember ? getParentOfSymbol(source)! : source; + const targetSymbol = target.flags & SymbolFlags.EnumMember ? getParentOfSymbol(target)! : target; if (sourceSymbol === targetSymbol) { return true; } - if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & ts.SymbolFlags.RegularEnum) || !(targetSymbol.flags & ts.SymbolFlags.RegularEnum)) { + if (sourceSymbol.escapedName !== targetSymbol.escapedName || !(sourceSymbol.flags & SymbolFlags.RegularEnum) || !(targetSymbol.flags & SymbolFlags.RegularEnum)) { return false; } const id = getSymbolId(sourceSymbol) + "," + getSymbolId(targetSymbol); const entry = enumRelation.get(id); - if (entry !== undefined && !(!(entry & ts.RelationComparisonResult.Reported) && entry & ts.RelationComparisonResult.Failed && errorReporter)) { - return !!(entry & ts.RelationComparisonResult.Succeeded); + if (entry !== undefined && !(!(entry & RelationComparisonResult.Reported) && entry & RelationComparisonResult.Failed && errorReporter)) { + return !!(entry & RelationComparisonResult.Succeeded); } const targetEnumType = getTypeOfSymbol(targetSymbol); for (const property of getPropertiesOfType(getTypeOfSymbol(sourceSymbol))) { - if (property.flags & ts.SymbolFlags.EnumMember) { + if (property.flags & SymbolFlags.EnumMember) { const targetProperty = getPropertyOfType(targetEnumType, property.escapedName); - if (!targetProperty || !(targetProperty.flags & ts.SymbolFlags.EnumMember)) { + if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) { if (errorReporter) { - errorReporter(ts.Diagnostics.Property_0_is_missing_in_type_1, ts.symbolName(property), - typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.UseFullyQualifiedType)); - enumRelation.set(id, ts.RelationComparisonResult.Failed | ts.RelationComparisonResult.Reported); + errorReporter(Diagnostics.Property_0_is_missing_in_type_1, symbolName(property), + typeToString(getDeclaredTypeOfSymbol(targetSymbol), /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType)); + enumRelation.set(id, RelationComparisonResult.Failed | RelationComparisonResult.Reported); } else { - enumRelation.set(id, ts.RelationComparisonResult.Failed); + enumRelation.set(id, RelationComparisonResult.Failed); } return false; } } } - enumRelation.set(id, ts.RelationComparisonResult.Succeeded); + enumRelation.set(id, RelationComparisonResult.Succeeded); return true; } - function isSimpleTypeRelatedTo(source: ts.Type, target: ts.Type, relation: ts.ESMap, errorReporter?: ErrorReporter) { + function isSimpleTypeRelatedTo(source: Type, target: Type, relation: ESMap, errorReporter?: ErrorReporter) { const s = source.flags; const t = target.flags; - if (t & ts.TypeFlags.AnyOrUnknown || s & ts.TypeFlags.Never || source === wildcardType) return true; - if (t & ts.TypeFlags.Never) return false; - if (s & ts.TypeFlags.StringLike && t & ts.TypeFlags.String) return true; - if (s & ts.TypeFlags.StringLiteral && s & ts.TypeFlags.EnumLiteral && - t & ts.TypeFlags.StringLiteral && !(t & ts.TypeFlags.EnumLiteral) && - (source as ts.StringLiteralType).value === (target as ts.StringLiteralType).value) return true; - if (s & ts.TypeFlags.NumberLike && t & ts.TypeFlags.Number) return true; - if (s & ts.TypeFlags.NumberLiteral && s & ts.TypeFlags.EnumLiteral && - t & ts.TypeFlags.NumberLiteral && !(t & ts.TypeFlags.EnumLiteral) && - (source as ts.NumberLiteralType).value === (target as ts.NumberLiteralType).value) return true; - if (s & ts.TypeFlags.BigIntLike && t & ts.TypeFlags.BigInt) return true; - if (s & ts.TypeFlags.BooleanLike && t & ts.TypeFlags.Boolean) return true; - if (s & ts.TypeFlags.ESSymbolLike && t & ts.TypeFlags.ESSymbol) return true; - if (s & ts.TypeFlags.Enum && t & ts.TypeFlags.Enum && source.symbol.escapedName === target.symbol.escapedName && + if (t & TypeFlags.AnyOrUnknown || s & TypeFlags.Never || source === wildcardType) return true; + if (t & TypeFlags.Never) return false; + if (s & TypeFlags.StringLike && t & TypeFlags.String) return true; + if (s & TypeFlags.StringLiteral && s & TypeFlags.EnumLiteral && + t & TypeFlags.StringLiteral && !(t & TypeFlags.EnumLiteral) && + (source as StringLiteralType).value === (target as StringLiteralType).value) return true; + if (s & TypeFlags.NumberLike && t & TypeFlags.Number) return true; + if (s & TypeFlags.NumberLiteral && s & TypeFlags.EnumLiteral && + t & TypeFlags.NumberLiteral && !(t & TypeFlags.EnumLiteral) && + (source as NumberLiteralType).value === (target as NumberLiteralType).value) return true; + if (s & TypeFlags.BigIntLike && t & TypeFlags.BigInt) return true; + if (s & TypeFlags.BooleanLike && t & TypeFlags.Boolean) return true; + if (s & TypeFlags.ESSymbolLike && t & TypeFlags.ESSymbol) return true; + if (s & TypeFlags.Enum && t & TypeFlags.Enum && source.symbol.escapedName === target.symbol.escapedName && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & ts.TypeFlags.EnumLiteral && t & ts.TypeFlags.EnumLiteral) { - if (s & ts.TypeFlags.Union && t & ts.TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; - if (s & ts.TypeFlags.Literal && t & ts.TypeFlags.Literal && (source as ts.LiteralType).value === (target as ts.LiteralType).value && + if (s & TypeFlags.EnumLiteral && t & TypeFlags.EnumLiteral) { + if (s & TypeFlags.Union && t & TypeFlags.Union && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; + if (s & TypeFlags.Literal && t & TypeFlags.Literal && (source as LiteralType).value === (target as LiteralType).value && isEnumTypeRelatedTo(source.symbol, target.symbol, errorReporter)) return true; } // In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`. // Since unions and intersections may reduce to `never`, we exclude them here. - if (s & ts.TypeFlags.Undefined && (!strictNullChecks && !(t & ts.TypeFlags.UnionOrIntersection) || t & (ts.TypeFlags.Undefined | ts.TypeFlags.Void))) return true; - if (s & ts.TypeFlags.Null && (!strictNullChecks && !(t & ts.TypeFlags.UnionOrIntersection) || t & ts.TypeFlags.Null)) return true; - if (s & ts.TypeFlags.Object && t & ts.TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(ts.getObjectFlags(source) & ts.ObjectFlags.FreshLiteral))) return true; + if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; + if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true; + if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) return true; if (relation === assignableRelation || relation === comparableRelation) { - if (s & ts.TypeFlags.Any) return true; + if (s & TypeFlags.Any) return true; // Type number or any numeric literal type is assignable to any numeric enum type or any // numeric enum literal type. This rule exists for backwards compatibility reasons because // bit-flag enum types sometimes look like literal enum types with numeric literal values. - if (s & (ts.TypeFlags.Number | ts.TypeFlags.NumberLiteral) && !(s & ts.TypeFlags.EnumLiteral) && ( - t & ts.TypeFlags.Enum || relation === assignableRelation && t & ts.TypeFlags.NumberLiteral && t & ts.TypeFlags.EnumLiteral)) return true; + if (s & (TypeFlags.Number | TypeFlags.NumberLiteral) && !(s & TypeFlags.EnumLiteral) && ( + t & TypeFlags.Enum || relation === assignableRelation && t & TypeFlags.NumberLiteral && t & TypeFlags.EnumLiteral)) return true; // Anything is assignable to a union containing undefined, null, and {} if (isUnknownLikeUnionType(target)) return true; } return false; } - function isTypeRelatedTo(source: ts.Type, target: ts.Type, relation: ts.ESMap) { + function isTypeRelatedTo(source: Type, target: Type, relation: ESMap) { if (isFreshLiteralType(source)) { - source = (source as ts.FreshableType).regularType; + source = (source as FreshableType).regularType; } if (isFreshLiteralType(target)) { - target = (target as ts.FreshableType).regularType; + target = (target as FreshableType).regularType; } if (source === target) { return true; } if (relation !== identityRelation) { - if (relation === comparableRelation && !(target.flags & ts.TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) { + if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) { return true; } } - else if (!((source.flags | target.flags) & (ts.TypeFlags.UnionOrIntersection | ts.TypeFlags.IndexedAccess | ts.TypeFlags.Conditional | ts.TypeFlags.Substitution))) { + else if (!((source.flags | target.flags) & (TypeFlags.UnionOrIntersection | TypeFlags.IndexedAccess | TypeFlags.Conditional | TypeFlags.Substitution))) { // We have excluded types that may simplify to other forms, so types must have identical flags if (source.flags !== target.flags) return false; - if (source.flags & ts.TypeFlags.Singleton) return true; + if (source.flags & TypeFlags.Singleton) return true; } - if (source.flags & ts.TypeFlags.Object && target.flags & ts.TypeFlags.Object) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation, /*ignoreConstraints*/ false)); if (related !== undefined) { - return !!(related & ts.RelationComparisonResult.Succeeded); + return !!(related & RelationComparisonResult.Succeeded); } } - if (source.flags & ts.TypeFlags.StructuredOrInstantiable || target.flags & ts.TypeFlags.StructuredOrInstantiable) { + if (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable) { return checkTypeRelatedTo(source, target, relation, /*errorNode*/ undefined); } return false; } - function isIgnoredJsxProperty(source: ts.Type, sourceProp: ts.Symbol) { - return ts.getObjectFlags(source) & ts.ObjectFlags.JsxAttributes && isHyphenatedJsxName(sourceProp.escapedName); + function isIgnoredJsxProperty(source: Type, sourceProp: Symbol) { + return getObjectFlags(source) & ObjectFlags.JsxAttributes && isHyphenatedJsxName(sourceProp.escapedName); } - function getNormalizedType(type: ts.Type, writing: boolean): ts.Type { + function getNormalizedType(type: Type, writing: boolean): Type { while (true) { - const t = isFreshLiteralType(type) ? (type as ts.FreshableType).regularType : - ts.getObjectFlags(type) & ts.ObjectFlags.Reference ? (type as ts.TypeReference).node ? createTypeReference((type as ts.TypeReference).target, getTypeArguments(type as ts.TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type : - type.flags & ts.TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as ts.UnionOrIntersectionType, writing) : - type.flags & ts.TypeFlags.Substitution ? writing ? (type as ts.SubstitutionType).baseType : getSubstitutionIntersection(type as ts.SubstitutionType) : - type.flags & ts.TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : + const t = isFreshLiteralType(type) ? (type as FreshableType).regularType : + getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).node ? createTypeReference((type as TypeReference).target, getTypeArguments(type as TypeReference)) : getSingleBaseForNonAugmentingSubtype(type) || type : + type.flags & TypeFlags.UnionOrIntersection ? getNormalizedUnionOrIntersectionType(type as UnionOrIntersectionType, writing) : + type.flags & TypeFlags.Substitution ? writing ? (type as SubstitutionType).baseType : getSubstitutionIntersection(type as SubstitutionType) : + type.flags & TypeFlags.Simplifiable ? getSimplifiedType(type, writing) : type; if (t === type) return t; type = t; } } - function getNormalizedUnionOrIntersectionType(type: ts.UnionOrIntersectionType, writing: boolean) { + function getNormalizedUnionOrIntersectionType(type: UnionOrIntersectionType, writing: boolean) { const reduced = getReducedType(type); if (reduced !== type) { return reduced; } - if (type.flags & ts.TypeFlags.Intersection && ts.some((type as ts.IntersectionType).types, isEmptyAnonymousObjectType)) { - const normalizedTypes = ts.sameMap(type.types, t => getNormalizedType(t, writing)); + if (type.flags & TypeFlags.Intersection && some((type as IntersectionType).types, isEmptyAnonymousObjectType)) { + const normalizedTypes = sameMap(type.types, t => getNormalizedType(t, writing)); if (normalizedTypes !== type.types) { return getIntersectionType(normalizedTypes); } @@ -18651,39 +18849,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param errorOutputContainer Return the diagnostic. Do not log if 'skipLogging' is truthy. */ function checkTypeRelatedTo( - source: ts.Type, - target: ts.Type, - relation: ts.ESMap, - errorNode: ts.Node | undefined, - headMessage?: ts.DiagnosticMessage, - containingMessageChain?: () => ts.DiagnosticMessageChain | undefined, - errorOutputContainer?: { errors?: ts.Diagnostic[], skipLogging?: boolean }, + source: Type, + target: Type, + relation: ESMap, + errorNode: Node | undefined, + headMessage?: DiagnosticMessage, + containingMessageChain?: () => DiagnosticMessageChain | undefined, + errorOutputContainer?: { errors?: Diagnostic[], skipLogging?: boolean }, ): boolean { - let errorInfo: ts.DiagnosticMessageChain | undefined; - let relatedInfo: [ts.DiagnosticRelatedInformation, ...ts.DiagnosticRelatedInformation[]] | undefined; + let errorInfo: DiagnosticMessageChain | undefined; + let relatedInfo: [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined; let maybeKeys: string[]; - let sourceStack: ts.Type[]; - let targetStack: ts.Type[]; + let sourceStack: Type[]; + let targetStack: Type[]; let maybeCount = 0; let sourceDepth = 0; let targetDepth = 0; let expandingFlags = ExpandingFlags.None; let overflow = false; let overrideNextErrorInfo = 0; // How many `reportRelationError` calls should be skipped in the elaboration pyramid - let lastSkippedInfo: [ts.Type, ts.Type] | undefined; - let incompatibleStack: [ts.DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] | undefined; + let lastSkippedInfo: [Type, Type] | undefined; + let incompatibleStack: [DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] | undefined; let inPropertyCheck = false; - ts.Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); + Debug.assert(relation !== identityRelation || !errorNode, "no error reporting in identity checking"); const result = isRelatedTo(source, target, RecursionFlags.Both, /*reportErrors*/ !!errorNode, headMessage); if (incompatibleStack) { reportIncompatibleStack(); } if (overflow) { - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth: sourceDepth, targetDepth }); - const diag = error(errorNode || currentNode, ts.Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); + tracing?.instant(tracing.Phase.CheckTypes, "checkTypeRelatedTo_DepthLimit", { sourceId: source.id, targetId: target.id, depth: sourceDepth, targetDepth }); + const diag = error(errorNode || currentNode, Diagnostics.Excessive_stack_depth_comparing_types_0_and_1, typeToString(source), typeToString(target)); if (errorOutputContainer) { (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag); } @@ -18692,27 +18890,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (containingMessageChain) { const chain = containingMessageChain(); if (chain) { - ts.concatenateDiagnosticMessageChains(chain, errorInfo); + concatenateDiagnosticMessageChains(chain, errorInfo); errorInfo = chain; } } - let relatedInformation: ts.DiagnosticRelatedInformation[] | undefined; + let relatedInformation: DiagnosticRelatedInformation[] | undefined; // Check if we should issue an extra diagnostic to produce a quickfix for a slightly incorrect import statement if (headMessage && errorNode && !result && source.symbol) { const links = getSymbolLinks(source.symbol); - if (links.originatingImport && !ts.isImportCall(links.originatingImport)) { + if (links.originatingImport && !isImportCall(links.originatingImport)) { const helpfulRetry = checkTypeRelatedTo(getTypeOfSymbol(links.target!), target, relation, /*errorNode*/ undefined); if (helpfulRetry) { // Likely an incorrect import. Issue a helpful diagnostic to produce a quickfix to change the import - const diag = ts.createDiagnosticForNode(links.originatingImport, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead); - relatedInformation = ts.append(relatedInformation, diag); // Cause the error to appear with the error that triggered it + const diag = createDiagnosticForNode(links.originatingImport, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead); + relatedInformation = append(relatedInformation, diag); // Cause the error to appear with the error that triggered it } } } - const diag = ts.createDiagnosticForNodeFromMessageChain(errorNode!, errorInfo, relatedInformation); + const diag = createDiagnosticForNodeFromMessageChain(errorNode!, errorInfo, relatedInformation); if (relatedInfo) { - ts.addRelatedInfo(diag, ...relatedInfo); + addRelatedInfo(diag, ...relatedInfo); } if (errorOutputContainer) { (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag); @@ -18721,12 +18919,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { diagnostics.add(diag); } } - if (errorNode && errorOutputContainer && errorOutputContainer.skipLogging && result === ts.Ternary.False) { - ts.Debug.assert(!!errorOutputContainer.errors, "missed opportunity to interact with error."); + if (errorNode && errorOutputContainer && errorOutputContainer.skipLogging && result === Ternary.False) { + Debug.assert(!!errorOutputContainer.errors, "missed opportunity to interact with error."); } - return result !== ts.Ternary.False; + return result !== Ternary.False; function resetErrorInfo(saved: ReturnType) { errorInfo = saved.errorInfo; @@ -18742,11 +18940,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { lastSkippedInfo, incompatibleStack: incompatibleStack?.slice(), overrideNextErrorInfo, - relatedInfo: relatedInfo?.slice() as [ts.DiagnosticRelatedInformation, ...ts.DiagnosticRelatedInformation[]] | undefined, + relatedInfo: relatedInfo?.slice() as [DiagnosticRelatedInformation, ...DiagnosticRelatedInformation[]] | undefined, }; } - function reportIncompatibleError(message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number) { + function reportIncompatibleError(message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number) { overrideNextErrorInfo++; // Suppress the next relation error lastSkippedInfo = undefined; // Reset skipped info cache (incompatibleStack ||= []).push([message, arg0, arg1, arg2, arg3]); @@ -18768,11 +18966,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The first error will be the innermost, while the last will be the outermost - so by popping off the end, // we can build from left to right let path = ""; - const secondaryRootErrors: [ts.DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] = []; + const secondaryRootErrors: [DiagnosticMessage, (string | number)?, (string | number)?, (string | number)?, (string | number)?][] = []; while (stack.length) { const [msg, ...args] = stack.pop()!; switch (msg.code) { - case ts.Diagnostics.Types_of_property_0_are_incompatible.code: { + case Diagnostics.Types_of_property_0_are_incompatible.code: { // Parenthesize a `new` if there is one if (path.indexOf("new ") === 0) { path = `(${path})`; @@ -18783,7 +18981,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { path = `${str}`; } // Otherwise write a dotted name if possible - else if (ts.isIdentifierText(str, ts.getEmitScriptTarget(compilerOptions))) { + else if (isIdentifierText(str, getEmitScriptTarget(compilerOptions))) { path = `${path}.${str}`; } // Failing that, check if the name is already a computed name @@ -18796,51 +18994,51 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } break; } - case ts.Diagnostics.Call_signature_return_types_0_and_1_are_incompatible.code: - case ts.Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code: - case ts.Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: - case ts.Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: { + case Diagnostics.Call_signature_return_types_0_and_1_are_incompatible.code: + case Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code: + case Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: + case Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code: { if (path.length === 0) { // Don't flatten signature compatability errors at the start of a chain - instead prefer // to unify (the with no arguments bit is excessive for printback) and print them back let mappedMsg = msg; - if (msg.code === ts.Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { - mappedMsg = ts.Diagnostics.Call_signature_return_types_0_and_1_are_incompatible; + if (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { + mappedMsg = Diagnostics.Call_signature_return_types_0_and_1_are_incompatible; } - else if (msg.code === ts.Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { - mappedMsg = ts.Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible; + else if (msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) { + mappedMsg = Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible; } secondaryRootErrors.unshift([mappedMsg, args[0], args[1]]); } else { - const prefix = (msg.code === ts.Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code || - msg.code === ts.Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) + const prefix = (msg.code === Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible.code || + msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) ? "new " : ""; - const params = (msg.code === ts.Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code || - msg.code === ts.Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) + const params = (msg.code === Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code || + msg.code === Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1.code) ? "" : "..."; path = `${prefix}${path}(${params})`; } break; } - case ts.Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target.code: { - secondaryRootErrors.unshift([ts.Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, args[0], args[1]]); + case Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target.code: { + secondaryRootErrors.unshift([Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, args[0], args[1]]); break; } - case ts.Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target.code: { - secondaryRootErrors.unshift([ts.Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, args[0], args[1], args[2]]); + case Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target.code: { + secondaryRootErrors.unshift([Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, args[0], args[1], args[2]]); break; } default: - return ts.Debug.fail(`Unhandled Diagnostic: ${msg.code}`); + return Debug.fail(`Unhandled Diagnostic: ${msg.code}`); } } if (path) { reportError(path[path.length - 1] === ")" - ? ts.Diagnostics.The_types_returned_by_0_are_incompatible_between_these_types - : ts.Diagnostics.The_types_of_0_are_incompatible_between_these_types, + ? Diagnostics.The_types_returned_by_0_are_incompatible_between_these_types + : Diagnostics.The_types_of_0_are_incompatible_between_these_types, path ); } @@ -18860,15 +19058,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function reportError(message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { - ts.Debug.assert(!!errorNode); + function reportError(message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): void { + Debug.assert(!!errorNode); if (incompatibleStack) reportIncompatibleStack(); if (message.elidedInCompatabilityPyramid) return; - errorInfo = ts.chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2, arg3); + errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2, arg3); } - function associateRelatedInfo(info: ts.DiagnosticRelatedInformation) { - ts.Debug.assert(!!errorInfo); + function associateRelatedInfo(info: DiagnosticRelatedInformation) { + Debug.assert(!!errorInfo); if (!relatedInfo) { relatedInfo = [info]; } @@ -18877,7 +19075,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function reportRelationError(message: ts.DiagnosticMessage | undefined, source: ts.Type, target: ts.Type) { + function reportRelationError(message: DiagnosticMessage | undefined, source: Type, target: Type) { if (incompatibleStack) reportIncompatibleStack(); const [sourceType, targetType] = getTypeNamesForErrorDisplay(source, target); let generalizedSource = source; @@ -18885,16 +19083,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isLiteralType(source) && !typeCouldHaveTopLevelSingletonTypes(target)) { generalizedSource = getBaseTypeOfLiteralType(source); - ts.Debug.assert(!isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable"); + Debug.assert(!isTypeAssignableTo(generalizedSource, target), "generalized source shouldn't be assignable"); generalizedSourceType = getTypeNameForErrorDisplay(generalizedSource); } - if (target.flags & ts.TypeFlags.TypeParameter && target !== markerSuperTypeForCheck && target !== markerSubTypeForCheck) { + if (target.flags & TypeFlags.TypeParameter && target !== markerSuperTypeForCheck && target !== markerSubTypeForCheck) { const constraint = getBaseConstraintOfType(target); let needsOriginalSource; if (constraint && (isTypeAssignableTo(generalizedSource, constraint) || (needsOriginalSource = isTypeAssignableTo(source, constraint)))) { reportError( - ts.Diagnostics._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2, + Diagnostics._0_is_assignable_to_the_constraint_of_type_1_but_1_could_be_instantiated_with_a_different_subtype_of_constraint_2, needsOriginalSource ? sourceType : generalizedSourceType, targetType, typeToString(constraint), @@ -18903,7 +19101,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { errorInfo = undefined; reportError( - ts.Diagnostics._0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1, + Diagnostics._0_could_be_instantiated_with_an_arbitrary_type_which_could_be_unrelated_to_1, targetType, generalizedSourceType ); @@ -18912,35 +19110,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!message) { if (relation === comparableRelation) { - message = ts.Diagnostics.Type_0_is_not_comparable_to_type_1; + message = Diagnostics.Type_0_is_not_comparable_to_type_1; } else if (sourceType === targetType) { - message = ts.Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated; + message = Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated; } else if (exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) { - message = ts.Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; + message = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } else { - if (source.flags & ts.TypeFlags.StringLiteral && target.flags & ts.TypeFlags.Union) { - const suggestedType = getSuggestedTypeForNonexistentStringLiteralType(source as ts.StringLiteralType, target as ts.UnionType); + if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.Union) { + const suggestedType = getSuggestedTypeForNonexistentStringLiteralType(source as StringLiteralType, target as UnionType); if (suggestedType) { - reportError(ts.Diagnostics.Type_0_is_not_assignable_to_type_1_Did_you_mean_2, generalizedSourceType, targetType, typeToString(suggestedType)); + reportError(Diagnostics.Type_0_is_not_assignable_to_type_1_Did_you_mean_2, generalizedSourceType, targetType, typeToString(suggestedType)); return; } } - message = ts.Diagnostics.Type_0_is_not_assignable_to_type_1; + message = Diagnostics.Type_0_is_not_assignable_to_type_1; } } - else if (message === ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 + else if (message === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 && exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) { - message = ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; + message = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } reportError(message, generalizedSourceType, targetType); } - function tryElaborateErrorsForPrimitivesAndObjects(source: ts.Type, target: ts.Type) { + function tryElaborateErrorsForPrimitivesAndObjects(source: Type, target: Type) { const sourceType = symbolValueDeclarationIsContextSensitive(source.symbol) ? typeToString(source, source.symbol.valueDeclaration) : typeToString(source); const targetType = symbolValueDeclarationIsContextSensitive(target.symbol) ? typeToString(target, target.symbol.valueDeclaration) : typeToString(target); @@ -18948,7 +19146,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { (globalNumberType === source && numberType === target) || (globalBooleanType === source && booleanType === target) || (getGlobalESSymbolType() === source && esSymbolType === target)) { - reportError(ts.Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); + reportError(Diagnostics._0_is_a_primitive_but_1_is_a_wrapper_object_Prefer_using_0_when_possible, targetType, sourceType); } } @@ -18958,7 +19156,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * any other elaborations when relating the `source` and * `target` types. */ - function tryElaborateArrayLikeErrors(source: ts.Type, target: ts.Type, reportErrors: boolean): boolean { + function tryElaborateArrayLikeErrors(source: Type, target: Type, reportErrors: boolean): boolean { /** * The spec for elaboration is: * - If the source is a readonly tuple and the target is a mutable array or tuple, elaborate on mutability and skip property elaborations. @@ -18969,7 +19167,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isTupleType(source)) { if (source.target.readonly && isMutableArrayOrTuple(target)) { if (reportErrors) { - reportError(ts.Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); + reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); } return false; } @@ -18977,7 +19175,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (isReadonlyArrayType(source) && isMutableArrayOrTuple(target)) { if (reportErrors) { - reportError(ts.Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); + reportError(Diagnostics.The_type_0_is_readonly_and_cannot_be_assigned_to_the_mutable_type_1, typeToString(source), typeToString(target)); } return false; } @@ -18987,7 +19185,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function isRelatedToWorker(source: ts.Type, target: ts.Type, reportErrors: boolean) { + function isRelatedToWorker(source: Type, target: Type, reportErrors: boolean) { return isRelatedTo(source, target, RecursionFlags.Both, reportErrors); } @@ -18997,17 +19195,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * Ternary.Maybe if they are related with assumptions of other relationships, or * * Ternary.False if they are not related. */ - function isRelatedTo(originalSource: ts.Type, originalTarget: ts.Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: ts.DiagnosticMessage, intersectionState = IntersectionState.None): ts.Ternary { + function isRelatedTo(originalSource: Type, originalTarget: Type, recursionFlags: RecursionFlags = RecursionFlags.Both, reportErrors = false, headMessage?: DiagnosticMessage, intersectionState = IntersectionState.None): Ternary { // Before normalization: if `source` is type an object type, and `target` is primitive, // skip all the checks we don't need and just return `isSimpleTypeRelatedTo` result - if (originalSource.flags & ts.TypeFlags.Object && originalTarget.flags & ts.TypeFlags.Primitive) { + if (originalSource.flags & TypeFlags.Object && originalTarget.flags & TypeFlags.Primitive) { if (isSimpleTypeRelatedTo(originalSource, originalTarget, relation, reportErrors ? reportError : undefined)) { - return ts.Ternary.True; + return Ternary.True; } if (reportErrors) { reportErrorResults(originalSource, originalTarget, originalSource, originalTarget, headMessage); } - return ts.Ternary.False; + return Ternary.False; } // Normalize the source and target types: Turn fresh literal types into regular literal types, @@ -19017,11 +19215,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const source = getNormalizedType(originalSource, /*writing*/ false); let target = getNormalizedType(originalTarget, /*writing*/ true); - if (source === target) return ts.Ternary.True; + if (source === target) return Ternary.True; if (relation === identityRelation) { - if (source.flags !== target.flags) return ts.Ternary.False; - if (source.flags & ts.TypeFlags.Singleton) return ts.Ternary.True; + if (source.flags !== target.flags) return Ternary.False; + if (source.flags & TypeFlags.Singleton) return Ternary.True; traceUnionsOrIntersectionsTooLarge(source, target); return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None, recursionFlags); } @@ -19031,64 +19229,64 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // as we break down the _target_ union first, _then_ get the source constraint - so for every // member of the target, we attempt to find a match in the source. This avoids that in cases where // the target is exactly the constraint. - if (source.flags & ts.TypeFlags.TypeParameter && getConstraintOfType(source) === target) { - return ts.Ternary.True; + if (source.flags & TypeFlags.TypeParameter && getConstraintOfType(source) === target) { + return Ternary.True; } // See if we're relating a definitely non-nullable type to a union that includes null and/or undefined // plus a single non-nullable type. If so, remove null and/or undefined from the target type. - if (source.flags & ts.TypeFlags.DefinitelyNonNullable && target.flags & ts.TypeFlags.Union) { - const types = (target as ts.UnionType).types; - const candidate = types.length === 2 && types[0].flags & ts.TypeFlags.Nullable ? types[1] : - types.length === 3 && types[0].flags & ts.TypeFlags.Nullable && types[1].flags & ts.TypeFlags.Nullable ? types[2] : + if (source.flags & TypeFlags.DefinitelyNonNullable && target.flags & TypeFlags.Union) { + const types = (target as UnionType).types; + const candidate = types.length === 2 && types[0].flags & TypeFlags.Nullable ? types[1] : + types.length === 3 && types[0].flags & TypeFlags.Nullable && types[1].flags & TypeFlags.Nullable ? types[2] : undefined; - if (candidate && !(candidate.flags & ts.TypeFlags.Nullable)) { + if (candidate && !(candidate.flags & TypeFlags.Nullable)) { target = getNormalizedType(candidate, /*writing*/ true); - if (source === target) return ts.Ternary.True; + if (source === target) return Ternary.True; } } - if (relation === comparableRelation && !(target.flags & ts.TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || - isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return ts.Ternary.True; + if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || + isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True; - if (source.flags & ts.TypeFlags.StructuredOrInstantiable || target.flags & ts.TypeFlags.StructuredOrInstantiable) { - const isPerformingExcessPropertyChecks = !(intersectionState & IntersectionState.Target) && (isObjectLiteralType(source) && ts.getObjectFlags(source) & ts.ObjectFlags.FreshLiteral); + if (source.flags & TypeFlags.StructuredOrInstantiable || target.flags & TypeFlags.StructuredOrInstantiable) { + const isPerformingExcessPropertyChecks = !(intersectionState & IntersectionState.Target) && (isObjectLiteralType(source) && getObjectFlags(source) & ObjectFlags.FreshLiteral); if (isPerformingExcessPropertyChecks) { - if (hasExcessProperties(source as ts.FreshObjectLiteralType, target, reportErrors)) { + if (hasExcessProperties(source as FreshObjectLiteralType, target, reportErrors)) { if (reportErrors) { reportRelationError(headMessage, source, originalTarget.aliasSymbol ? originalTarget : target); } - return ts.Ternary.False; + return Ternary.False; } } const isPerformingCommonPropertyChecks = (relation !== comparableRelation || isUnitType(source)) && !(intersectionState & IntersectionState.Target) && - source.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.Object | ts.TypeFlags.Intersection) && source !== globalObjectType && - target.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) && isWeakType(target) && + source.flags & (TypeFlags.Primitive | TypeFlags.Object | TypeFlags.Intersection) && source !== globalObjectType && + target.flags & (TypeFlags.Object | TypeFlags.Intersection) && isWeakType(target) && (getPropertiesOfType(source).length > 0 || typeHasCallOrConstructSignatures(source)); - const isComparingJsxAttributes = !!(ts.getObjectFlags(source) & ts.ObjectFlags.JsxAttributes); + const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); if (isPerformingCommonPropertyChecks && !hasCommonProperties(source, target, isComparingJsxAttributes)) { if (reportErrors) { const sourceString = typeToString(originalSource.aliasSymbol ? originalSource : source); const targetString = typeToString(originalTarget.aliasSymbol ? originalTarget : target); - const calls = getSignaturesOfType(source, ts.SignatureKind.Call); - const constructs = getSignaturesOfType(source, ts.SignatureKind.Construct); + const calls = getSignaturesOfType(source, SignatureKind.Call); + const constructs = getSignaturesOfType(source, SignatureKind.Construct); if (calls.length > 0 && isRelatedTo(getReturnTypeOfSignature(calls[0]), target, RecursionFlags.Source, /*reportErrors*/ false) || constructs.length > 0 && isRelatedTo(getReturnTypeOfSignature(constructs[0]), target, RecursionFlags.Source, /*reportErrors*/ false)) { - reportError(ts.Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, sourceString, targetString); + reportError(Diagnostics.Value_of_type_0_has_no_properties_in_common_with_type_1_Did_you_mean_to_call_it, sourceString, targetString); } else { - reportError(ts.Diagnostics.Type_0_has_no_properties_in_common_with_type_1, sourceString, targetString); + reportError(Diagnostics.Type_0_has_no_properties_in_common_with_type_1, sourceString, targetString); } } - return ts.Ternary.False; + return Ternary.False; } traceUnionsOrIntersectionsTooLarge(source, target); - const skipCaching = source.flags & ts.TypeFlags.Union && (source as ts.UnionType).types.length < 4 && !(target.flags & ts.TypeFlags.Union) || - target.flags & ts.TypeFlags.Union && (target as ts.UnionType).types.length < 4 && !(source.flags & ts.TypeFlags.StructuredOrInstantiable); + const skipCaching = source.flags & TypeFlags.Union && (source as UnionType).types.length < 4 && !(target.flags & TypeFlags.Union) || + target.flags & TypeFlags.Union && (target as UnionType).types.length < 4 && !(source.flags & TypeFlags.StructuredOrInstantiable); const result = skipCaching ? unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState) : recursiveTypeRelatedTo(source, target, reportErrors, intersectionState, recursionFlags); @@ -19100,10 +19298,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (reportErrors) { reportErrorResults(originalSource, originalTarget, source, target, headMessage); } - return ts.Ternary.False; + return Ternary.False; } - function reportErrorResults(originalSource: ts.Type, originalTarget: ts.Type, source: ts.Type, target: ts.Type, headMessage: ts.DiagnosticMessage | undefined) { + function reportErrorResults(originalSource: Type, originalTarget: Type, source: Type, target: Type, headMessage: DiagnosticMessage | undefined) { const sourceHasBase = !!getSingleBaseForNonAugmentingSubtype(originalSource); const targetHasBase = !!getSingleBaseForNonAugmentingSubtype(originalTarget); source = (originalSource.aliasSymbol || sourceHasBase) ? originalSource : source; @@ -19112,25 +19310,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (maybeSuppress) { overrideNextErrorInfo--; } - if (source.flags & ts.TypeFlags.Object && target.flags & ts.TypeFlags.Object) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) { const currentError = errorInfo; tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ true); if (errorInfo !== currentError) { maybeSuppress = !!errorInfo; } } - if (source.flags & ts.TypeFlags.Object && target.flags & ts.TypeFlags.Primitive) { + if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Primitive) { tryElaborateErrorsForPrimitivesAndObjects(source, target); } - else if (source.symbol && source.flags & ts.TypeFlags.Object && globalObjectType === source) { - reportError(ts.Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); + else if (source.symbol && source.flags & TypeFlags.Object && globalObjectType === source) { + reportError(Diagnostics.The_Object_type_is_assignable_to_very_few_other_types_Did_you_mean_to_use_the_any_type_instead); } - else if (ts.getObjectFlags(source) & ts.ObjectFlags.JsxAttributes && target.flags & ts.TypeFlags.Intersection) { - const targetTypes = (target as ts.IntersectionType).types; + else if (getObjectFlags(source) & ObjectFlags.JsxAttributes && target.flags & TypeFlags.Intersection) { + const targetTypes = (target as IntersectionType).types; const intrinsicAttributes = getJsxType(JsxNames.IntrinsicAttributes, errorNode); const intrinsicClassAttributes = getJsxType(JsxNames.IntrinsicClassAttributes, errorNode); if (!isErrorType(intrinsicAttributes) && !isErrorType(intrinsicClassAttributes) && - (ts.contains(targetTypes, intrinsicAttributes) || ts.contains(targetTypes, intrinsicClassAttributes))) { + (contains(targetTypes, intrinsicAttributes) || contains(targetTypes, intrinsicClassAttributes))) { // do not report top error return; } @@ -19144,26 +19342,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } reportRelationError(headMessage, source, target); - if (source.flags & ts.TypeFlags.TypeParameter && source.symbol?.declarations?.[0] && !getConstraintOfType(source as ts.TypeVariable)) { - const syntheticParam = cloneTypeParameter(source as ts.TypeParameter); + if (source.flags & TypeFlags.TypeParameter && source.symbol?.declarations?.[0] && !getConstraintOfType(source as TypeVariable)) { + const syntheticParam = cloneTypeParameter(source as TypeParameter); syntheticParam.constraint = instantiateType(target, makeUnaryTypeMapper(source, syntheticParam)); if (hasNonCircularBaseConstraint(syntheticParam)) { const targetConstraintString = typeToString(target, source.symbol.declarations[0]); - associateRelatedInfo(ts.createDiagnosticForNode(source.symbol.declarations[0], ts.Diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)); + associateRelatedInfo(createDiagnosticForNode(source.symbol.declarations[0], Diagnostics.This_type_parameter_might_need_an_extends_0_constraint, targetConstraintString)); } } } - function traceUnionsOrIntersectionsTooLarge(source: ts.Type, target: ts.Type): void { - if (!ts.tracing) { + function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void { + if (!tracing) { return; } - if ((source.flags & ts.TypeFlags.UnionOrIntersection) && (target.flags & ts.TypeFlags.UnionOrIntersection)) { - const sourceUnionOrIntersection = source as ts.UnionOrIntersectionType; - const targetUnionOrIntersection = target as ts.UnionOrIntersectionType; + if ((source.flags & TypeFlags.UnionOrIntersection) && (target.flags & TypeFlags.UnionOrIntersection)) { + const sourceUnionOrIntersection = source as UnionOrIntersectionType; + const targetUnionOrIntersection = target as UnionOrIntersectionType; - if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ts.ObjectFlags.PrimitiveUnion) { + if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ObjectFlags.PrimitiveUnion) { // There's a fast path for comparing primitive unions return; } @@ -19171,7 +19369,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const sourceSize = sourceUnionOrIntersection.types.length; const targetSize = targetUnionOrIntersection.types.length; if (sourceSize * targetSize > 1E6) { - ts.tracing.instant(ts.tracing.Phase.CheckTypes, "traceUnionsOrIntersectionsTooLarge_DepthLimit", { + tracing.instant(tracing.Phase.CheckTypes, "traceUnionsOrIntersectionsTooLarge_DepthLimit", { sourceId: source.id, sourceSize, targetId: target.id, @@ -19183,30 +19381,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeOfPropertyInTypes(types: ts.Type[], name: ts.__String) { - const appendPropType = (propTypes: ts.Type[] | undefined, type: ts.Type) => { + function getTypeOfPropertyInTypes(types: Type[], name: __String) { + const appendPropType = (propTypes: Type[] | undefined, type: Type) => { type = getApparentType(type); - const prop = type.flags & ts.TypeFlags.UnionOrIntersection ? getPropertyOfUnionOrIntersectionType(type as ts.UnionOrIntersectionType, name) : getPropertyOfObjectType(type, name); + const prop = type.flags & TypeFlags.UnionOrIntersection ? getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name) : getPropertyOfObjectType(type, name); const propType = prop && getTypeOfSymbol(prop) || getApplicableIndexInfoForName(type, name)?.type || undefinedType; - return ts.append(propTypes, propType); + return append(propTypes, propType); }; - return getUnionType(ts.reduceLeft(types, appendPropType, /*initial*/ undefined) || ts.emptyArray); + return getUnionType(reduceLeft(types, appendPropType, /*initial*/ undefined) || emptyArray); } - function hasExcessProperties(source: ts.FreshObjectLiteralType, target: ts.Type, reportErrors: boolean): boolean { - if (!isExcessPropertyCheckTarget(target) || !noImplicitAny && ts.getObjectFlags(target) & ts.ObjectFlags.JSLiteral) { + function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { + if (!isExcessPropertyCheckTarget(target) || !noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral) { return false; // Disable excess property checks on JS literals to simulate having an implicit "index signature" - but only outside of noImplicitAny } - const isComparingJsxAttributes = !!(ts.getObjectFlags(source) & ts.ObjectFlags.JsxAttributes); + const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); if ((relation === assignableRelation || relation === comparableRelation) && (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { return false; } let reducedTarget = target; - let checkTypes: ts.Type[] | undefined; - if (target.flags & ts.TypeFlags.Union) { - reducedTarget = findMatchingDiscriminantType(source, target as ts.UnionType, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target as ts.UnionType); - checkTypes = reducedTarget.flags & ts.TypeFlags.Union ? (reducedTarget as ts.UnionType).types : [reducedTarget]; + let checkTypes: Type[] | undefined; + if (target.flags & TypeFlags.Union) { + reducedTarget = findMatchingDiscriminantType(source, target as UnionType, isRelatedTo) || filterPrimitivesIfContainsNonPrimitive(target as UnionType); + checkTypes = reducedTarget.flags & TypeFlags.Union ? (reducedTarget as UnionType).types : [reducedTarget]; } for (const prop of getPropertiesOfType(source)) { if (shouldCheckAsExcessProperty(prop, source.symbol) && !isIgnoredJsxProperty(source, prop)) { @@ -19218,11 +19416,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We know *exactly* where things went wrong when comparing the types. // Use this property as the error node as this will be more helpful in // reasoning about what went wrong. - if (!errorNode) return ts.Debug.fail(); - if (ts.isJsxAttributes(errorNode) || ts.isJsxOpeningLikeElement(errorNode) || ts.isJsxOpeningLikeElement(errorNode.parent)) { + if (!errorNode) return Debug.fail(); + if (isJsxAttributes(errorNode) || isJsxOpeningLikeElement(errorNode) || isJsxOpeningLikeElement(errorNode.parent)) { // JsxAttributes has an object-literal flag and undergo same type-assignablity check as normal object-literal. // However, using an object-literal error message will be very confusing to the users so we give different a message. - if (prop.valueDeclaration && ts.isJsxAttribute(prop.valueDeclaration) && ts.getSourceFileOfNode(errorNode) === ts.getSourceFileOfNode(prop.valueDeclaration.name)) { + if (prop.valueDeclaration && isJsxAttribute(prop.valueDeclaration) && getSourceFileOfNode(errorNode) === getSourceFileOfNode(prop.valueDeclaration.name)) { // Note that extraneous children (as in `extra`) don't pass this check, // since `children` is a SyntaxKind.PropertySignature instead of a SyntaxKind.JsxAttribute. errorNode = prop.valueDeclaration.name; @@ -19231,33 +19429,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const suggestionSymbol = getSuggestedSymbolForNonexistentJSXAttribute(propName, errorTarget); const suggestion = suggestionSymbol ? symbolToString(suggestionSymbol) : undefined; if (suggestion) { - reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName, typeToString(errorTarget), suggestion); + reportError(Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName, typeToString(errorTarget), suggestion); } else { - reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, propName, typeToString(errorTarget)); + reportError(Diagnostics.Property_0_does_not_exist_on_type_1, propName, typeToString(errorTarget)); } } else { // use the property's value declaration if the property is assigned inside the literal itself - const objectLiteralDeclaration = source.symbol?.declarations && ts.firstOrUndefined(source.symbol.declarations); + const objectLiteralDeclaration = source.symbol?.declarations && firstOrUndefined(source.symbol.declarations); let suggestion: string | undefined; - if (prop.valueDeclaration && ts.findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration) && ts.getSourceFileOfNode(objectLiteralDeclaration) === ts.getSourceFileOfNode(errorNode)) { - const propDeclaration = prop.valueDeclaration as ts.ObjectLiteralElementLike; - ts.Debug.assertNode(propDeclaration, ts.isObjectLiteralElementLike); + if (prop.valueDeclaration && findAncestor(prop.valueDeclaration, d => d === objectLiteralDeclaration) && getSourceFileOfNode(objectLiteralDeclaration) === getSourceFileOfNode(errorNode)) { + const propDeclaration = prop.valueDeclaration as ObjectLiteralElementLike; + Debug.assertNode(propDeclaration, isObjectLiteralElementLike); errorNode = propDeclaration; const name = propDeclaration.name!; - if (ts.isIdentifier(name)) { + if (isIdentifier(name)) { suggestion = getSuggestionForNonexistentProperty(name, errorTarget); } } if (suggestion !== undefined) { - reportError(ts.Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2, + reportError(Diagnostics.Object_literal_may_only_specify_known_properties_but_0_does_not_exist_in_type_1_Did_you_mean_to_write_2, symbolToString(prop), typeToString(errorTarget), suggestion); } else { - reportError(ts.Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(errorTarget)); } } @@ -19266,7 +19464,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (checkTypes && !isRelatedTo(getTypeOfSymbol(prop), getTypeOfPropertyInTypes(checkTypes, prop.escapedName), RecursionFlags.Both, reportErrors)) { if (reportErrors) { - reportIncompatibleError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(prop)); + reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(prop)); } return true; } @@ -19275,38 +19473,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function shouldCheckAsExcessProperty(prop: ts.Symbol, container: ts.Symbol) { + function shouldCheckAsExcessProperty(prop: Symbol, container: Symbol) { return prop.valueDeclaration && container.valueDeclaration && prop.valueDeclaration.parent === container.valueDeclaration; } - function unionOrIntersectionRelatedTo(source: ts.Type, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function unionOrIntersectionRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { // Note that these checks are specifically ordered to produce correct results. In particular, // we need to deconstruct unions before intersections (because unions are always at the top), // and we need to handle "each" relations before "some" relations for the same kind of type. - if (source.flags & ts.TypeFlags.Union) { + if (source.flags & TypeFlags.Union) { return relation === comparableRelation ? - someTypeRelatedToType(source as ts.UnionType, target, reportErrors && !(source.flags & ts.TypeFlags.Primitive), intersectionState) : - eachTypeRelatedToType(source as ts.UnionType, target, reportErrors && !(source.flags & ts.TypeFlags.Primitive), intersectionState); + someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState) : + eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState); } - if (target.flags & ts.TypeFlags.Union) { - return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as ts.UnionType, reportErrors && !(source.flags & ts.TypeFlags.Primitive) && !(target.flags & ts.TypeFlags.Primitive)); + if (target.flags & TypeFlags.Union) { + return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); } - if (target.flags & ts.TypeFlags.Intersection) { - return typeRelatedToEachType(source, target as ts.IntersectionType, reportErrors, IntersectionState.Target); + if (target.flags & TypeFlags.Intersection) { + return typeRelatedToEachType(source, target as IntersectionType, reportErrors, IntersectionState.Target); } // Source is an intersection. For the comparable relation, if the target is a primitive type we hoist the // constraints of all non-primitive types in the source into a new intersection. We do this because the // intersection may further constrain the constraints of the non-primitive types. For example, given a type // parameter 'T extends 1 | 2', the intersection 'T & 1' should be reduced to '1' such that it doesn't // appear to be comparable to '2'. - if (relation === comparableRelation && target.flags & ts.TypeFlags.Primitive) { - const constraints = ts.sameMap((source as ts.IntersectionType).types, t => t.flags & ts.TypeFlags.Instantiable ? getBaseConstraintOfType(t) || unknownType : t); - if (constraints !== (source as ts.IntersectionType).types) { + if (relation === comparableRelation && target.flags & TypeFlags.Primitive) { + const constraints = sameMap((source as IntersectionType).types, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(t) || unknownType : t); + if (constraints !== (source as IntersectionType).types) { source = getIntersectionType(constraints); - if (source.flags & ts.TypeFlags.Never) { - return ts.Ternary.False; + if (source.flags & TypeFlags.Never) { + return Ternary.False; } - if (!(source.flags & ts.TypeFlags.Intersection)) { + if (!(source.flags & TypeFlags.Intersection)) { return isRelatedTo(source, target, RecursionFlags.Source, /*reportErrors*/ false) || isRelatedTo(target, source, RecursionFlags.Source, /*reportErrors*/ false); } @@ -19316,29 +19514,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Don't report errors though. Elaborating on whether a source constituent is related to the target is // not actually useful and leads to some confusing error messages. Instead, we rely on the caller // checking whether the full intersection viewed as an object is related to the target. - return someTypeRelatedToType(source as ts.IntersectionType, target, /*reportErrors*/ false, IntersectionState.Source); + return someTypeRelatedToType(source as IntersectionType, target, /*reportErrors*/ false, IntersectionState.Source); } - function eachTypeRelatedToSomeType(source: ts.UnionOrIntersectionType, target: ts.UnionOrIntersectionType): ts.Ternary { - let result = ts.Ternary.True; + function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary { + let result = Ternary.True; const sourceTypes = source.types; for (const sourceType of sourceTypes) { const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function typeRelatedToSomeType(source: ts.Type, target: ts.UnionOrIntersectionType, reportErrors: boolean): ts.Ternary { + function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { const targetTypes = target.types; - if (target.flags & ts.TypeFlags.Union) { + if (target.flags & TypeFlags.Union) { if (containsType(targetTypes, source)) { - return ts.Ternary.True; + return Ternary.True; } - const match = getMatchingUnionConstituentForType(target as ts.UnionType, source); + const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false); if (related) { @@ -19359,26 +19557,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true); } } - return ts.Ternary.False; + return Ternary.False; } - function typeRelatedToEachType(source: ts.Type, target: ts.IntersectionType, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { - let result = ts.Ternary.True; + function typeRelatedToEachType(source: Type, target: IntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + let result = Ternary.True; const targetTypes = target.types; for (const targetType of targetTypes) { const related = isRelatedTo(source, targetType, RecursionFlags.Target, reportErrors, /*headMessage*/ undefined, intersectionState); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function someTypeRelatedToType(source: ts.UnionOrIntersectionType, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { const sourceTypes = source.types; - if (source.flags & ts.TypeFlags.Union && containsType(sourceTypes, target)) { - return ts.Ternary.True; + if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) { + return Ternary.True; } const len = sourceTypes.length; for (let i = 0; i < len; i++) { @@ -19387,34 +19585,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return related; } } - return ts.Ternary.False; + return Ternary.False; } - function getUndefinedStrippedTargetIfNeeded(source: ts.Type, target: ts.Type) { + function getUndefinedStrippedTargetIfNeeded(source: Type, target: Type) { // As a builtin type, `undefined` is a very low type ID - making it almsot always first, making this a very fast check to see // if we need to strip `undefined` from the target - if (source.flags & ts.TypeFlags.Union && target.flags & ts.TypeFlags.Union && - !((source as ts.UnionType).types[0].flags & ts.TypeFlags.Undefined) && (target as ts.UnionType).types[0].flags & ts.TypeFlags.Undefined) { - return extractTypesOfKind(target, ~ts.TypeFlags.Undefined); + if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && + !((source as UnionType).types[0].flags & TypeFlags.Undefined) && (target as UnionType).types[0].flags & TypeFlags.Undefined) { + return extractTypesOfKind(target, ~TypeFlags.Undefined); } return target; } - function eachTypeRelatedToType(source: ts.UnionOrIntersectionType, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { - let result = ts.Ternary.True; + function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + let result = Ternary.True; const sourceTypes = source.types; // We strip `undefined` from the target if the `source` trivially doesn't contain it for our correspondence-checking fastpath // since `undefined` is frequently added by optionality and would otherwise spoil a potentially useful correspondence - const undefinedStrippedTarget = getUndefinedStrippedTargetIfNeeded(source, target as ts.UnionType); + const undefinedStrippedTarget = getUndefinedStrippedTargetIfNeeded(source, target as UnionType); for (let i = 0; i < sourceTypes.length; i++) { const sourceType = sourceTypes[i]; - if (undefinedStrippedTarget.flags & ts.TypeFlags.Union && sourceTypes.length >= (undefinedStrippedTarget as ts.UnionType).types.length && sourceTypes.length % (undefinedStrippedTarget as ts.UnionType).types.length === 0) { + if (undefinedStrippedTarget.flags & TypeFlags.Union && sourceTypes.length >= (undefinedStrippedTarget as UnionType).types.length && sourceTypes.length % (undefinedStrippedTarget as UnionType).types.length === 0) { // many unions are mappings of one another; in such cases, simply comparing members at the same index can shortcut the comparison // such unions will have identical lengths, and their corresponding elements will match up. Another common scenario is where a large // union has a union of objects intersected with it. In such cases, if the input was, eg `("a" | "b" | "c") & (string | boolean | {} | {whatever})`, // the result will have the structure `"a" | "b" | "c" | "a" & {} | "b" & {} | "c" & {} | "a" & {whatever} | "b" & {whatever} | "c" & {whatever}` // - the resulting union has a length which is a multiple of the original union, and the elements correspond modulo the length of the original union - const related = isRelatedTo(sourceType, (undefinedStrippedTarget as ts.UnionType).types[i % (undefinedStrippedTarget as ts.UnionType).types.length], RecursionFlags.Both, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); + const related = isRelatedTo(sourceType, (undefinedStrippedTarget as UnionType).types[i % (undefinedStrippedTarget as UnionType).types.length], RecursionFlags.Both, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); if (related) { result &= related; continue; @@ -19422,43 +19620,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const related = isRelatedTo(sourceType, target, RecursionFlags.Source, reportErrors, /*headMessage*/ undefined, intersectionState); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function typeArgumentsRelatedTo(sources: readonly ts.Type[] = ts.emptyArray, targets: readonly ts.Type[] = ts.emptyArray, variances: readonly ts.VarianceFlags[] = ts.emptyArray, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function typeArgumentsRelatedTo(sources: readonly Type[] = emptyArray, targets: readonly Type[] = emptyArray, variances: readonly VarianceFlags[] = emptyArray, reportErrors: boolean, intersectionState: IntersectionState): Ternary { if (sources.length !== targets.length && relation === identityRelation) { - return ts.Ternary.False; + return Ternary.False; } const length = sources.length <= targets.length ? sources.length : targets.length; - let result = ts.Ternary.True; + let result = Ternary.True; for (let i = 0; i < length; i++) { // When variance information isn't available we default to covariance. This happens // in the process of computing variance information for recursive types and when // comparing 'this' type arguments. - const varianceFlags = i < variances.length ? variances[i] : ts.VarianceFlags.Covariant; - const variance = varianceFlags & ts.VarianceFlags.VarianceMask; + const varianceFlags = i < variances.length ? variances[i] : VarianceFlags.Covariant; + const variance = varianceFlags & VarianceFlags.VarianceMask; // We ignore arguments for independent type parameters (because they're never witnessed). - if (variance !== ts.VarianceFlags.Independent) { + if (variance !== VarianceFlags.Independent) { const s = sources[i]; const t = targets[i]; - let related = ts.Ternary.True; - if (varianceFlags & ts.VarianceFlags.Unmeasurable) { + let related = Ternary.True; + if (varianceFlags & VarianceFlags.Unmeasurable) { // Even an `Unmeasurable` variance works out without a structural check if the source and target are _identical_. // We can't simply assume invariance, because `Unmeasurable` marks nonlinear relations, for example, a relation tained by // the `-?` modifier in a mapped type (where, no matter how the inputs are related, the outputs still might not be) related = relation === identityRelation ? isRelatedTo(s, t, RecursionFlags.Both, /*reportErrors*/ false) : compareTypesIdentical(s, t); } - else if (variance === ts.VarianceFlags.Covariant) { + else if (variance === VarianceFlags.Covariant) { related = isRelatedTo(s, t, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); } - else if (variance === ts.VarianceFlags.Contravariant) { + else if (variance === VarianceFlags.Contravariant) { related = isRelatedTo(t, s, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); } - else if (variance === ts.VarianceFlags.Bivariant) { + else if (variance === VarianceFlags.Bivariant) { // In the bivariant case we first compare contravariantly without reporting // errors. Then, if that doesn't succeed, we compare covariantly with error // reporting. Thus, error elaboration will be based on the the covariant check, @@ -19478,7 +19676,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -19491,29 +19689,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are // equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion // and issue an error. Otherwise, actually compare the structure of the two types. - function recursiveTypeRelatedTo(source: ts.Type, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState, recursionFlags: RecursionFlags): ts.Ternary { + function recursiveTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, recursionFlags: RecursionFlags): Ternary { if (overflow) { - return ts.Ternary.False; + return Ternary.False; } const id = getRelationKey(source, target, intersectionState, relation, /*ingnoreConstraints*/ false); const entry = relation.get(id); if (entry !== undefined) { - if (reportErrors && entry & ts.RelationComparisonResult.Failed && !(entry & ts.RelationComparisonResult.Reported)) { + if (reportErrors && entry & RelationComparisonResult.Failed && !(entry & RelationComparisonResult.Reported)) { // We are elaborating errors and the cached result is an unreported failure. The result will be reported // as a failure, and should be updated as a reported failure by the bottom of this function. } else { if (outofbandVarianceMarkerHandler) { // We're in the middle of variance checking - integrate any unmeasurable/unreliable flags from this cached component - const saved = entry & ts.RelationComparisonResult.ReportsMask; - if (saved & ts.RelationComparisonResult.ReportsUnmeasurable) { + const saved = entry & RelationComparisonResult.ReportsMask; + if (saved & RelationComparisonResult.ReportsUnmeasurable) { instantiateType(source, reportUnmeasurableMapper); } - if (saved & ts.RelationComparisonResult.ReportsUnreliable) { + if (saved & RelationComparisonResult.ReportsUnreliable) { instantiateType(source, reportUnreliableMapper); } } - return entry & ts.RelationComparisonResult.Succeeded ? ts.Ternary.True : ts.Ternary.False; + return entry & RelationComparisonResult.Succeeded ? Ternary.True : Ternary.False; } } if (!maybeKeys) { @@ -19529,12 +19727,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = 0; i < maybeCount; i++) { // If source and target are already being compared, consider them related with assumptions if (id === maybeKeys[i] || broadestEquivalentId && broadestEquivalentId === maybeKeys[i]) { - return ts.Ternary.Maybe; + return Ternary.Maybe; } } if (sourceDepth === 100 || targetDepth === 100) { overflow = true; - return ts.Ternary.False; + return Ternary.False; } } const maybeStart = maybeCount; @@ -19552,18 +19750,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!(expandingFlags & ExpandingFlags.Target) && isDeeplyNestedType(target, targetStack, targetDepth)) expandingFlags |= ExpandingFlags.Target; } let originalHandler: typeof outofbandVarianceMarkerHandler; - let propagatingVarianceFlags: ts.RelationComparisonResult = 0; + let propagatingVarianceFlags: RelationComparisonResult = 0; if (outofbandVarianceMarkerHandler) { originalHandler = outofbandVarianceMarkerHandler; outofbandVarianceMarkerHandler = onlyUnreliable => { - propagatingVarianceFlags |= onlyUnreliable ? ts.RelationComparisonResult.ReportsUnreliable : ts.RelationComparisonResult.ReportsUnmeasurable; + propagatingVarianceFlags |= onlyUnreliable ? RelationComparisonResult.ReportsUnreliable : RelationComparisonResult.ReportsUnmeasurable; return originalHandler!(onlyUnreliable); }; } - let result: ts.Ternary; + let result: Ternary; if (expandingFlags === ExpandingFlags.Both) { - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "recursiveTypeRelatedTo_DepthLimit", { + tracing?.instant(tracing.Phase.CheckTypes, "recursiveTypeRelatedTo_DepthLimit", { sourceId: source.id, sourceIdStack: sourceStack.map(t => t.id), targetId: target.id, @@ -19571,12 +19769,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { depth: sourceDepth, targetDepth }); - result = ts.Ternary.Maybe; + result = Ternary.Maybe; } else { - ts.tracing?.push(ts.tracing.Phase.CheckTypes, "structuredTypeRelatedTo", { sourceId: source.id, targetId: target.id }); + tracing?.push(tracing.Phase.CheckTypes, "structuredTypeRelatedTo", { sourceId: source.id, targetId: target.id }); result = structuredTypeRelatedTo(source, target, reportErrors, intersectionState); - ts.tracing?.pop(); + tracing?.pop(); } if (outofbandVarianceMarkerHandler) { @@ -19590,12 +19788,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } expandingFlags = saveExpandingFlags; if (result) { - if (result === ts.Ternary.True || (sourceDepth === 0 && targetDepth === 0)) { - if (result === ts.Ternary.True || result === ts.Ternary.Maybe) { + if (result === Ternary.True || (sourceDepth === 0 && targetDepth === 0)) { + if (result === Ternary.True || result === Ternary.Maybe) { // If result is definitely true, record all maybe keys as having succeeded. Also, record Ternary.Maybe // results as having succeeded once we reach depth 0, but never record Ternary.Unknown results. for (let i = maybeStart; i < maybeCount; i++) { - relation.set(maybeKeys[i], ts.RelationComparisonResult.Succeeded | propagatingVarianceFlags); + relation.set(maybeKeys[i], RelationComparisonResult.Succeeded | propagatingVarianceFlags); } } maybeCount = maybeStart; @@ -19604,13 +19802,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // A false result goes straight into global cache (when something is false under // assumptions it will also be false without assumptions) - relation.set(id, (reportErrors ? ts.RelationComparisonResult.Reported : 0) | ts.RelationComparisonResult.Failed | propagatingVarianceFlags); + relation.set(id, (reportErrors ? RelationComparisonResult.Reported : 0) | RelationComparisonResult.Failed | propagatingVarianceFlags); maybeCount = maybeStart; } return result; } - function structuredTypeRelatedTo(source: ts.Type, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { const saveErrorInfo = captureErrorCalculationState(); let result = structuredTypeRelatedToWorker(source, target, reportErrors, intersectionState, saveErrorInfo); if (relation !== identityRelation) { @@ -19627,8 +19825,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // needs to have its constraint hoisted into an intersection with said type parameter, this way // the type param can be compared with itself in the target (with the influence of its constraint to match other parts) // For example, if `T extends 1 | 2` and `U extends 2 | 3` and we compare `T & U` to `T & U & (1 | 2 | 3)` - if (!result && (source.flags & ts.TypeFlags.Intersection || source.flags & ts.TypeFlags.TypeParameter && target.flags & ts.TypeFlags.Union)) { - const constraint = getEffectiveConstraintOfIntersection(source.flags & ts.TypeFlags.Intersection ? (source as ts.IntersectionType).types: [source], !!(target.flags & ts.TypeFlags.Union)); + if (!result && (source.flags & TypeFlags.Intersection || source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.Union)) { + const constraint = getEffectiveConstraintOfIntersection(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types: [source], !!(target.flags & TypeFlags.Union)); if (constraint && everyType(constraint, c => c !== source)) { // Skip comparison if expansion contains the source itself // TODO: Stack errors so we get a pyramid for the "normal" comparison above, _and_ a second for this result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); @@ -19650,8 +19848,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We suppress recursive intersection property checks because they can generate lots of work when relating // recursive intersections that are structurally similar but not exactly identical. See #37854. if (result && !inPropertyCheck && ( - target.flags & ts.TypeFlags.Intersection && !isGenericObjectType(target) && source.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) || - isNonGenericObjectType(target) && !isArrayOrTupleType(target) && source.flags & ts.TypeFlags.Intersection && getApparentType(source).flags & ts.TypeFlags.StructuredType && !ts.some((source as ts.IntersectionType).types, t => !!(ts.getObjectFlags(t) & ts.ObjectFlags.NonInferrableType)))) { + target.flags & TypeFlags.Intersection && !isGenericObjectType(target) && source.flags & (TypeFlags.Object | TypeFlags.Intersection) || + isNonGenericObjectType(target) && !isArrayOrTupleType(target) && source.flags & TypeFlags.Intersection && getApparentType(source).flags & TypeFlags.StructuredType && !some((source as IntersectionType).types, t => !!(getObjectFlags(t) & ObjectFlags.NonInferrableType)))) { inPropertyCheck = true; result &= propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None); inPropertyCheck = false; @@ -19663,37 +19861,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function structuredTypeRelatedToWorker(source: ts.Type, target: ts.Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): ts.Ternary { - let result: ts.Ternary; - let originalErrorInfo: ts.DiagnosticMessageChain | undefined; + function structuredTypeRelatedToWorker(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState, saveErrorInfo: ReturnType): Ternary { + let result: Ternary; + let originalErrorInfo: DiagnosticMessageChain | undefined; let varianceCheckFailed = false; let sourceFlags = source.flags; const targetFlags = target.flags; if (relation === identityRelation) { // We've already checked that source.flags and target.flags are identical - if (sourceFlags & ts.TypeFlags.UnionOrIntersection) { - let result = eachTypeRelatedToSomeType(source as ts.UnionOrIntersectionType, target as ts.UnionOrIntersectionType); + if (sourceFlags & TypeFlags.UnionOrIntersection) { + let result = eachTypeRelatedToSomeType(source as UnionOrIntersectionType, target as UnionOrIntersectionType); if (result) { - result &= eachTypeRelatedToSomeType(target as ts.UnionOrIntersectionType, source as ts.UnionOrIntersectionType); + result &= eachTypeRelatedToSomeType(target as UnionOrIntersectionType, source as UnionOrIntersectionType); } return result; } - if (sourceFlags & ts.TypeFlags.Index) { - return isRelatedTo((source as ts.IndexType).type, (target as ts.IndexType).type, RecursionFlags.Both, /*reportErrors*/ false); + if (sourceFlags & TypeFlags.Index) { + return isRelatedTo((source as IndexType).type, (target as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false); } - if (sourceFlags & ts.TypeFlags.IndexedAccess) { - if (result = isRelatedTo((source as ts.IndexedAccessType).objectType, (target as ts.IndexedAccessType).objectType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as ts.IndexedAccessType).indexType, (target as ts.IndexedAccessType).indexType, RecursionFlags.Both, /*reportErrors*/ false)) { + if (sourceFlags & TypeFlags.IndexedAccess) { + if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, /*reportErrors*/ false)) { return result; } } } - if (sourceFlags & ts.TypeFlags.Conditional) { - if ((source as ts.ConditionalType).root.isDistributive === (target as ts.ConditionalType).root.isDistributive) { - if (result = isRelatedTo((source as ts.ConditionalType).checkType, (target as ts.ConditionalType).checkType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as ts.ConditionalType).extendsType, (target as ts.ConditionalType).extendsType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getTrueTypeFromConditionalType(source as ts.ConditionalType), getTrueTypeFromConditionalType(target as ts.ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo(getFalseTypeFromConditionalType(source as ts.ConditionalType), getFalseTypeFromConditionalType(target as ts.ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { + if (sourceFlags & TypeFlags.Conditional) { + if ((source as ConditionalType).root.isDistributive === (target as ConditionalType).root.isDistributive) { + if (result = isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source as ConditionalType).extendsType, (target as ConditionalType).extendsType, RecursionFlags.Both, /*reportErrors*/ false)) { + if (result &= isRelatedTo(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { + if (result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, /*reportErrors*/ false)) { return result; } } @@ -19701,18 +19899,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - if (sourceFlags & ts.TypeFlags.Substitution) { - if (result = isRelatedTo((source as ts.SubstitutionType).baseType, (target as ts.SubstitutionType).baseType, RecursionFlags.Both, /*reportErrors*/ false)) { - if (result &= isRelatedTo((source as ts.SubstitutionType).constraint, (target as ts.SubstitutionType).constraint, RecursionFlags.Both, /*reportErrors*/ false)) { + if (sourceFlags & TypeFlags.Substitution) { + if (result = isRelatedTo((source as SubstitutionType).baseType, (target as SubstitutionType).baseType, RecursionFlags.Both, /*reportErrors*/ false)) { + if (result &= isRelatedTo((source as SubstitutionType).constraint, (target as SubstitutionType).constraint, RecursionFlags.Both, /*reportErrors*/ false)) { return result; } } } - if (!(sourceFlags & ts.TypeFlags.Object)) { - return ts.Ternary.False; + if (!(sourceFlags & TypeFlags.Object)) { + return Ternary.False; } } - else if (sourceFlags & ts.TypeFlags.UnionOrIntersection || targetFlags & ts.TypeFlags.UnionOrIntersection) { + else if (sourceFlags & TypeFlags.UnionOrIntersection || targetFlags & TypeFlags.UnionOrIntersection) { if (result = unionOrIntersectionRelatedTo(source, target, reportErrors, intersectionState)) { return result; } @@ -19722,21 +19920,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Source is an intersection, target is an object (e.g. { a } & { b } <=> { a, b }). // Source is an intersection, target is a union (e.g. { a } & { b: boolean } <=> { a, b: true } | { a, b: false }). // Source is an intersection, target instantiable (e.g. string & { tag } <=> T["a"] constrained to string & { tag }). - if (!(sourceFlags & ts.TypeFlags.Instantiable || - sourceFlags & ts.TypeFlags.Object && targetFlags & ts.TypeFlags.Union || - sourceFlags & ts.TypeFlags.Intersection && targetFlags & (ts.TypeFlags.Object | ts.TypeFlags.Union | ts.TypeFlags.Instantiable))) { - return ts.Ternary.False; + if (!(sourceFlags & TypeFlags.Instantiable || + sourceFlags & TypeFlags.Object && targetFlags & TypeFlags.Union || + sourceFlags & TypeFlags.Intersection && targetFlags & (TypeFlags.Object | TypeFlags.Union | TypeFlags.Instantiable))) { + return Ternary.False; } } // We limit alias variance probing to only object and conditional types since their alias behavior // is more predictable than other, interned types, which may or may not have an alias depending on // the order in which things were checked. - if (sourceFlags & (ts.TypeFlags.Object | ts.TypeFlags.Conditional) && source.aliasSymbol && source.aliasTypeArguments && + if (sourceFlags & (TypeFlags.Object | TypeFlags.Conditional) && source.aliasSymbol && source.aliasTypeArguments && source.aliasSymbol === target.aliasSymbol && !(isMarkerType(source) || isMarkerType(target))) { const variances = getAliasVariances(source.aliasSymbol); - if (variances === ts.emptyArray) { - return ts.Ternary.Unknown; + if (variances === emptyArray) { + return Ternary.Unknown; } const varianceResult = relateVariances(source.aliasTypeArguments, target.aliasTypeArguments, variances, intersectionState); if (varianceResult !== undefined) { @@ -19751,38 +19949,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - if (targetFlags & ts.TypeFlags.TypeParameter) { + if (targetFlags & TypeFlags.TypeParameter) { // A source type { [P in Q]: X } is related to a target type T if keyof T is related to Q and X is related to T[Q]. - if (ts.getObjectFlags(source) & ts.ObjectFlags.Mapped && !(source as ts.MappedType).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source as ts.MappedType), RecursionFlags.Both)) { + if (getObjectFlags(source) & ObjectFlags.Mapped && !(source as MappedType).declaration.nameType && isRelatedTo(getIndexType(target), getConstraintTypeFromMappedType(source as MappedType), RecursionFlags.Both)) { - if (!(getMappedTypeModifiers(source as ts.MappedType) & MappedTypeModifiers.IncludeOptional)) { - const templateType = getTemplateTypeFromMappedType(source as ts.MappedType); - const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source as ts.MappedType)); + if (!(getMappedTypeModifiers(source as MappedType) & MappedTypeModifiers.IncludeOptional)) { + const templateType = getTemplateTypeFromMappedType(source as MappedType); + const indexedAccessType = getIndexedAccessType(target, getTypeParameterFromMappedType(source as MappedType)); if (result = isRelatedTo(templateType, indexedAccessType, RecursionFlags.Both, reportErrors)) { return result; } } } - if (relation === comparableRelation && sourceFlags & ts.TypeFlags.TypeParameter) { + if (relation === comparableRelation && sourceFlags & TypeFlags.TypeParameter) { // This is a carve-out in comparability to essentially forbid comparing a type parameter // with another type parameter unless one extends the other. (Remember: comparability is mostly bidirectional!) let constraint = getConstraintOfTypeParameter(source); if (constraint && hasNonCircularBaseConstraint(source)) { - while (constraint && someType(constraint, c => !!(c.flags & ts.TypeFlags.TypeParameter))) { + while (constraint && someType(constraint, c => !!(c.flags & TypeFlags.TypeParameter))) { if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false)) { return result; } constraint = getConstraintOfTypeParameter(constraint); } } - return ts.Ternary.False; + return Ternary.False; } } - else if (targetFlags & ts.TypeFlags.Index) { - const targetType = (target as ts.IndexType).type; + else if (targetFlags & TypeFlags.Index) { + const targetType = (target as IndexType).type; // A keyof S is related to a keyof T if T is related to S. - if (sourceFlags & ts.TypeFlags.Index) { - if (result = isRelatedTo(targetType, (source as ts.IndexType).type, RecursionFlags.Both, /*reportErrors*/ false)) { + if (sourceFlags & TypeFlags.Index) { + if (result = isRelatedTo(targetType, (source as IndexType).type, RecursionFlags.Both, /*reportErrors*/ false)) { return result; } } @@ -19802,8 +20000,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // false positives. For example, given 'T extends { [K in keyof T]: string }', // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when // related to other types. - if (isRelatedTo(source, getIndexType(constraint, (target as ts.IndexType).stringsOnly), RecursionFlags.Target, reportErrors) === ts.Ternary.True) { - return ts.Ternary.True; + if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), RecursionFlags.Target, reportErrors) === Ternary.True) { + return Ternary.True; } } else if (isGenericMappedType(targetType)) { @@ -19818,10 +20016,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // we need to get the apparent mappings and union them with the generic mappings, since some properties may be // missing from the `constraintType` which will otherwise be mapped in the object const modifiersType = getApparentType(getModifiersTypeFromMappedType(targetType)); - const mappedKeys: ts.Type[] = []; + const mappedKeys: Type[] = []; forEachMappedTypePropertyKeyTypeAndIndexSignatureKeyType( modifiersType, - ts.TypeFlags.StringOrNumberLiteralOrUnique, + TypeFlags.StringOrNumberLiteralOrUnique, /*stringsOnly*/ false, t => void mappedKeys.push(instantiateType(nameType, appendTypeMapping(targetType.mapper, getTypeParameterFromMappedType(targetType), t))) ); @@ -19831,18 +20029,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { targetKeys = nameType || constraintType; } - if (isRelatedTo(source, targetKeys, RecursionFlags.Target, reportErrors) === ts.Ternary.True) { - return ts.Ternary.True; + if (isRelatedTo(source, targetKeys, RecursionFlags.Target, reportErrors) === Ternary.True) { + return Ternary.True; } } } } - else if (targetFlags & ts.TypeFlags.IndexedAccess) { - if (sourceFlags & ts.TypeFlags.IndexedAccess) { + else if (targetFlags & TypeFlags.IndexedAccess) { + if (sourceFlags & TypeFlags.IndexedAccess) { // Relate components directly before falling back to constraint relationships // A type S[K] is related to a type T[J] if S is related to T and K is related to J. - if (result = isRelatedTo((source as ts.IndexedAccessType).objectType, (target as ts.IndexedAccessType).objectType, RecursionFlags.Both, reportErrors)) { - result &= isRelatedTo((source as ts.IndexedAccessType).indexType, (target as ts.IndexedAccessType).indexType, RecursionFlags.Both, reportErrors); + if (result = isRelatedTo((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType, RecursionFlags.Both, reportErrors)) { + result &= isRelatedTo((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType, RecursionFlags.Both, reportErrors); } if (result) { return result; @@ -19854,12 +20052,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // A type S is related to a type T[K] if S is related to C, where C is the base // constraint of T[K] for writing. if (relation === assignableRelation || relation === comparableRelation) { - const objectType = (target as ts.IndexedAccessType).objectType; - const indexType = (target as ts.IndexedAccessType).indexType; + const objectType = (target as IndexedAccessType).objectType; + const indexType = (target as IndexedAccessType).indexType; const baseObjectType = getBaseConstraintOfType(objectType) || objectType; const baseIndexType = getBaseConstraintOfType(indexType) || indexType; if (!isGenericObjectType(baseObjectType) && !isGenericIndexType(baseIndexType)) { - const accessFlags = ts.AccessFlags.Writing | (baseObjectType !== objectType ? ts.AccessFlags.NoIndexSignatures : 0); + const accessFlags = AccessFlags.Writing | (baseObjectType !== objectType ? AccessFlags.NoIndexSignatures : 0); const constraint = getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType, accessFlags); if (constraint) { if (reportErrors && originalErrorInfo) { @@ -19888,9 +20086,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!(modifiers & MappedTypeModifiers.ExcludeOptional)) { // If the mapped type has shape `{ [P in Q]: T[P] }`, // source `S` is related to target if `T` = `S`, i.e. `S` is related to `{ [P in Q]: S[P] }`. - if (!keysRemapped && templateType.flags & ts.TypeFlags.IndexedAccess && (templateType as ts.IndexedAccessType).objectType === source && - (templateType as ts.IndexedAccessType).indexType === getTypeParameterFromMappedType(target)) { - return ts.Ternary.True; + if (!keysRemapped && templateType.flags & TypeFlags.IndexedAccess && (templateType as IndexedAccessType).objectType === source && + (templateType as IndexedAccessType).indexType === getTypeParameterFromMappedType(target)) { + return Ternary.True; } if (!isGenericMappedType(source)) { // If target has shape `{ [P in Q as R]: T}`, then its keys have type `R`. @@ -19905,16 +20103,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // A source type `S` is related to a target type `{ [P in Q]?: T }` if some constituent `Q'` of `Q` is related to `keyof S` and `S[Q']` is related to `T`. // A source type `S` is related to a target type `{ [P in Q as R]?: T }` if some constituent `R'` of `R` is related to `keyof S` and `S[R']` is related to `T`. if (includeOptional - ? !(filteredByApplicability!.flags & ts.TypeFlags.Never) + ? !(filteredByApplicability!.flags & TypeFlags.Never) : isRelatedTo(targetKeys, sourceKeys, RecursionFlags.Both)) { const templateType = getTemplateTypeFromMappedType(target); const typeParameter = getTypeParameterFromMappedType(target); // Fastpath: When the template type has the form `Obj[P]` where `P` is the mapped type parameter, directly compare source `S` with `Obj` // to avoid creating the (potentially very large) number of new intermediate types made by manufacturing `S[P]`. - const nonNullComponent = extractTypesOfKind(templateType, ~ts.TypeFlags.Nullable); - if (!keysRemapped && nonNullComponent.flags & ts.TypeFlags.IndexedAccess && (nonNullComponent as ts.IndexedAccessType).indexType === typeParameter) { - if (result = isRelatedTo(source, (nonNullComponent as ts.IndexedAccessType).objectType, RecursionFlags.Target, reportErrors)) { + const nonNullComponent = extractTypesOfKind(templateType, ~TypeFlags.Nullable); + if (!keysRemapped && nonNullComponent.flags & TypeFlags.IndexedAccess && (nonNullComponent as IndexedAccessType).indexType === typeParameter) { + if (result = isRelatedTo(source, (nonNullComponent as IndexedAccessType).objectType, RecursionFlags.Target, reportErrors)) { return result; } } @@ -19945,13 +20143,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (targetFlags & ts.TypeFlags.Conditional) { + else if (targetFlags & TypeFlags.Conditional) { // If we reach 10 levels of nesting for the same conditional type, assume it is an infinitely expanding recursive // conditional type and bail out with a Ternary.Maybe result. if (isDeeplyNestedType(target, targetStack, targetDepth, 10)) { - return ts.Ternary.Maybe; + return Ternary.Maybe; } - const c = target as ts.ConditionalType; + const c = target as ConditionalType; // We check for a relationship to a conditional type target only when the conditional type has no // 'infer' positions and is not distributive or is distributive but doesn't reference the check type // parameter in either of the result types. @@ -19960,78 +20158,78 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const skipTrue = !isTypeAssignableTo(getPermissiveInstantiation(c.checkType), getPermissiveInstantiation(c.extendsType)); const skipFalse = !skipTrue && isTypeAssignableTo(getRestrictiveInstantiation(c.checkType), getRestrictiveInstantiation(c.extendsType)); // TODO: Find a nice way to include potential conditional type breakdowns in error output, if they seem good (they usually don't) - if (result = skipTrue ? ts.Ternary.True : isRelatedTo(source, getTrueTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { - result &= skipFalse ? ts.Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); + if (result = skipTrue ? Ternary.True : isRelatedTo(source, getTrueTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { + result &= skipFalse ? Ternary.True : isRelatedTo(source, getFalseTypeFromConditionalType(c), RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); if (result) { return result; } } } } - else if (targetFlags & ts.TypeFlags.TemplateLiteral) { - if (sourceFlags & ts.TypeFlags.TemplateLiteral) { + else if (targetFlags & TypeFlags.TemplateLiteral) { + if (sourceFlags & TypeFlags.TemplateLiteral) { if (relation === comparableRelation) { - return templateLiteralTypesDefinitelyUnrelated(source as ts.TemplateLiteralType, target as ts.TemplateLiteralType) ? ts.Ternary.False : ts.Ternary.True; + return templateLiteralTypesDefinitelyUnrelated(source as TemplateLiteralType, target as TemplateLiteralType) ? Ternary.False : Ternary.True; } // Report unreliable variance for type variables referenced in template literal type placeholders. // For example, `foo-${number}` is related to `foo-${string}` even though number isn't related to string. instantiateType(source, reportUnreliableMapper); } - if (isTypeMatchedByTemplateLiteralType(source, target as ts.TemplateLiteralType)) { - return ts.Ternary.True; + if (isTypeMatchedByTemplateLiteralType(source, target as TemplateLiteralType)) { + return Ternary.True; } } - else if (target.flags & ts.TypeFlags.StringMapping) { - if (!(source.flags & ts.TypeFlags.StringMapping)) { + else if (target.flags & TypeFlags.StringMapping) { + if (!(source.flags & TypeFlags.StringMapping)) { if (isMemberOfStringMapping(source, target)) { - return ts.Ternary.True; + return Ternary.True; } } } - if (sourceFlags & ts.TypeFlags.TypeVariable) { + if (sourceFlags & TypeFlags.TypeVariable) { // IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch - if (!(sourceFlags & ts.TypeFlags.IndexedAccess && targetFlags & ts.TypeFlags.IndexedAccess)) { - const constraint = getConstraintOfType(source as ts.TypeVariable) || unknownType; + if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) { + const constraint = getConstraintOfType(source as TypeVariable) || unknownType; // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { return result; } // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example - else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & ts.TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { + else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { return result; } if (isMappedTypeGenericIndexedAccess(source)) { // For an indexed access type { [P in K]: E}[X], above we have already explored an instantiation of E with X // substituted for P. We also want to explore type { [P in K]: E }[C], where C is the constraint of X. - const indexConstraint = getConstraintOfType((source as ts.IndexedAccessType).indexType); + const indexConstraint = getConstraintOfType((source as IndexedAccessType).indexType); if (indexConstraint) { - if (result = isRelatedTo(getIndexedAccessType((source as ts.IndexedAccessType).objectType, indexConstraint), target, RecursionFlags.Source, reportErrors)) { + if (result = isRelatedTo(getIndexedAccessType((source as IndexedAccessType).objectType, indexConstraint), target, RecursionFlags.Source, reportErrors)) { return result; } } } } } - else if (sourceFlags & ts.TypeFlags.Index) { + else if (sourceFlags & TypeFlags.Index) { if (result = isRelatedTo(keyofConstraintType, target, RecursionFlags.Source, reportErrors)) { return result; } } - else if (sourceFlags & ts.TypeFlags.TemplateLiteral && !(targetFlags & ts.TypeFlags.Object)) { - if (!(targetFlags & ts.TypeFlags.TemplateLiteral)) { + else if (sourceFlags & TypeFlags.TemplateLiteral && !(targetFlags & TypeFlags.Object)) { + if (!(targetFlags & TypeFlags.TemplateLiteral)) { const constraint = getBaseConstraintOfType(source); if (constraint && constraint !== source && (result = isRelatedTo(constraint, target, RecursionFlags.Source, reportErrors))) { return result; } } } - else if (sourceFlags & ts.TypeFlags.StringMapping) { - if (targetFlags & ts.TypeFlags.StringMapping) { - if ((source as ts.StringMappingType).symbol !== (target as ts.StringMappingType).symbol) { - return ts.Ternary.False; + else if (sourceFlags & TypeFlags.StringMapping) { + if (targetFlags & TypeFlags.StringMapping) { + if ((source as StringMappingType).symbol !== (target as StringMappingType).symbol) { + return Ternary.False; } - if (result = isRelatedTo((source as ts.StringMappingType).type, (target as ts.StringMappingType).type, RecursionFlags.Both, reportErrors)) { + if (result = isRelatedTo((source as StringMappingType).type, (target as StringMappingType).type, RecursionFlags.Both, reportErrors)) { return result; } } @@ -20042,30 +20240,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (sourceFlags & ts.TypeFlags.Conditional) { + else if (sourceFlags & TypeFlags.Conditional) { // If we reach 10 levels of nesting for the same conditional type, assume it is an infinitely expanding recursive // conditional type and bail out with a Ternary.Maybe result. if (isDeeplyNestedType(source, sourceStack, sourceDepth, 10)) { - return ts.Ternary.Maybe; + return Ternary.Maybe; } - if (targetFlags & ts.TypeFlags.Conditional) { + if (targetFlags & TypeFlags.Conditional) { // Two conditional types 'T1 extends U1 ? X1 : Y1' and 'T2 extends U2 ? X2 : Y2' are related if // one of T1 and T2 is related to the other, U1 and U2 are identical types, X1 is related to X2, // and Y1 is related to Y2. - const sourceParams = (source as ts.ConditionalType).root.inferTypeParameters; - let sourceExtends = (source as ts.ConditionalType).extendsType; - let mapper: ts.TypeMapper | undefined; + const sourceParams = (source as ConditionalType).root.inferTypeParameters; + let sourceExtends = (source as ConditionalType).extendsType; + let mapper: TypeMapper | undefined; if (sourceParams) { // If the source has infer type parameters, we instantiate them in the context of the target - const ctx = createInferenceContext(sourceParams, /*signature*/ undefined, ts.InferenceFlags.None, isRelatedToWorker); - inferTypes(ctx.inferences, (target as ts.ConditionalType).extendsType, sourceExtends, ts.InferencePriority.NoConstraints | ts.InferencePriority.AlwaysStrict); + const ctx = createInferenceContext(sourceParams, /*signature*/ undefined, InferenceFlags.None, isRelatedToWorker); + inferTypes(ctx.inferences, (target as ConditionalType).extendsType, sourceExtends, InferencePriority.NoConstraints | InferencePriority.AlwaysStrict); sourceExtends = instantiateType(sourceExtends, ctx.mapper); mapper = ctx.mapper; } - if (isTypeIdenticalTo(sourceExtends, (target as ts.ConditionalType).extendsType) && - (isRelatedTo((source as ts.ConditionalType).checkType, (target as ts.ConditionalType).checkType, RecursionFlags.Both) || isRelatedTo((target as ts.ConditionalType).checkType, (source as ts.ConditionalType).checkType, RecursionFlags.Both))) { - if (result = isRelatedTo(instantiateType(getTrueTypeFromConditionalType(source as ts.ConditionalType), mapper), getTrueTypeFromConditionalType(target as ts.ConditionalType), RecursionFlags.Both, reportErrors)) { - result &= isRelatedTo(getFalseTypeFromConditionalType(source as ts.ConditionalType), getFalseTypeFromConditionalType(target as ts.ConditionalType), RecursionFlags.Both, reportErrors); + if (isTypeIdenticalTo(sourceExtends, (target as ConditionalType).extendsType) && + (isRelatedTo((source as ConditionalType).checkType, (target as ConditionalType).checkType, RecursionFlags.Both) || isRelatedTo((target as ConditionalType).checkType, (source as ConditionalType).checkType, RecursionFlags.Both))) { + if (result = isRelatedTo(instantiateType(getTrueTypeFromConditionalType(source as ConditionalType), mapper), getTrueTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors)) { + result &= isRelatedTo(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target as ConditionalType), RecursionFlags.Both, reportErrors); } if (result) { return result; @@ -20075,7 +20273,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // conditionals aren't related to one another via distributive constraint as it is much too inaccurate and allows way // more assignments than are desirable (since it maps the source check type to its constraint, it loses information) - const distributiveConstraint = hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ts.ConditionalType) : undefined; + const distributiveConstraint = hasNonCircularBaseConstraint(source) ? getConstraintOfDistributiveConditionalType(source as ConditionalType) : undefined; if (distributiveConstraint) { if (result = isRelatedTo(distributiveConstraint, target, RecursionFlags.Source, reportErrors)) { return result; @@ -20085,7 +20283,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // conditionals _can_ be related to one another via normal constraint, as, eg, `A extends B ? O : never` should be assignable to `O` // when `O` is a conditional (`never` is trivially assignable to `O`, as is `O`!). - const defaultConstraint = getDefaultConstraintOfConditionalType(source as ts.ConditionalType); + const defaultConstraint = getDefaultConstraintOfConditionalType(source as ConditionalType); if (defaultConstraint) { if (result = isRelatedTo(defaultConstraint, target, RecursionFlags.Source, reportErrors)) { return result; @@ -20095,7 +20293,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // An empty object type is related to any mapped type that includes a '?' modifier. if (relation !== subtypeRelation && relation !== strictSubtypeRelation && isPartialMappedType(target) && isEmptyObjectType(source)) { - return ts.Ternary.True; + return Ternary.True; } if (isGenericMappedType(target)) { if (isGenericMappedType(source)) { @@ -20103,34 +20301,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } } - return ts.Ternary.False; + return Ternary.False; } - const sourceIsPrimitive = !!(sourceFlags & ts.TypeFlags.Primitive); + const sourceIsPrimitive = !!(sourceFlags & TypeFlags.Primitive); if (relation !== identityRelation) { source = getApparentType(source); sourceFlags = source.flags; } else if (isGenericMappedType(source)) { - return ts.Ternary.False; + return Ternary.False; } - if (ts.getObjectFlags(source) & ts.ObjectFlags.Reference && ts.getObjectFlags(target) & ts.ObjectFlags.Reference && (source as ts.TypeReference).target === (target as ts.TypeReference).target && + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target && !isTupleType(source) && !(isMarkerType(source) || isMarkerType(target))) { // When strictNullChecks is disabled, the element type of the empty array literal is undefinedWideningType, // and an empty array literal wouldn't be assignable to a `never[]` without this check. if (isEmptyArrayLiteralType(source)) { - return ts.Ternary.True; + return Ternary.True; } // We have type references to the same generic type, and the type references are not marker // type references (which are intended by be compared structurally). Obtain the variance // information for the type parameters and relate the type arguments accordingly. - const variances = getVariances((source as ts.TypeReference).target); + const variances = getVariances((source as TypeReference).target); // We return Ternary.Maybe for a recursive invocation of getVariances (signalled by emptyArray). This // effectively means we measure variance only from type parameter occurrences that aren't nested in // recursive instantiations of the generic type. - if (variances === ts.emptyArray) { - return ts.Ternary.Unknown; + if (variances === emptyArray) { + return Ternary.Unknown; } - const varianceResult = relateVariances(getTypeArguments(source as ts.TypeReference), getTypeArguments(target as ts.TypeReference), variances, intersectionState); + const varianceResult = relateVariances(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), variances, intersectionState); if (varianceResult !== undefined) { return varianceResult; } @@ -20142,27 +20340,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // By flags alone, we know that the `target` is a readonly array while the source is a normal array or tuple // or `target` is an array and source is a tuple - in both cases the types cannot be identical, by construction - return ts.Ternary.False; + return Ternary.False; } } // Consider a fresh empty object literal type "closed" under the subtype relationship - this way `{} <- {[idx: string]: any} <- fresh({})` // and not `{} <- fresh({}) <- {[idx: string]: any}` - else if ((relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyObjectType(target) && ts.getObjectFlags(target) & ts.ObjectFlags.FreshLiteral && !isEmptyObjectType(source)) { - return ts.Ternary.False; + else if ((relation === subtypeRelation || relation === strictSubtypeRelation) && isEmptyObjectType(target) && getObjectFlags(target) & ObjectFlags.FreshLiteral && !isEmptyObjectType(source)) { + return Ternary.False; } // Even if relationship doesn't hold for unions, intersections, or generic type references, // it may hold in a structural comparison. // In a check of the form X = A & B, we will have previously checked if A relates to X or B relates // to X. Failing both of those we want to check if the aggregation of A and B's members structurally // relates to X. Thus, we include intersection types on the source side here. - if (sourceFlags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) && targetFlags & ts.TypeFlags.Object) { + if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Object) { // Report structural errors only if we haven't reported any errors yet const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo.errorInfo && !sourceIsPrimitive; result = propertiesRelatedTo(source, target, reportStructuralErrors, /*excludedProperties*/ undefined, intersectionState); if (result) { - result &= signaturesRelatedTo(source, target, ts.SignatureKind.Call, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportStructuralErrors); if (result) { - result &= signaturesRelatedTo(source, target, ts.SignatureKind.Construct, reportStructuralErrors); + result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportStructuralErrors); if (result) { result &= indexSignaturesRelatedTo(source, target, sourceIsPrimitive, reportStructuralErrors, intersectionState); } @@ -20179,28 +20377,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // there exists a constituent of T for every combination of the discriminants of S // with respect to T. We do not report errors here, as we will use the existing // error result from checking each constituent of the union. - if (sourceFlags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection) && targetFlags & ts.TypeFlags.Union) { - const objectOnlyTarget = extractTypesOfKind(target, ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.Substitution); - if (objectOnlyTarget.flags & ts.TypeFlags.Union) { - const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as ts.UnionType); + if (sourceFlags & (TypeFlags.Object | TypeFlags.Intersection) && targetFlags & TypeFlags.Union) { + const objectOnlyTarget = extractTypesOfKind(target, TypeFlags.Object | TypeFlags.Intersection | TypeFlags.Substitution); + if (objectOnlyTarget.flags & TypeFlags.Union) { + const result = typeRelatedToDiscriminatedType(source, objectOnlyTarget as UnionType); if (result) { return result; } } } } - return ts.Ternary.False; + return Ternary.False; - function countMessageChainBreadth(info: ts.DiagnosticMessageChain[] | undefined): number { + function countMessageChainBreadth(info: DiagnosticMessageChain[] | undefined): number { if (!info) return 0; - return ts.reduceLeft(info, (value, chain) => value + 1 + countMessageChainBreadth(chain.next), 0); + return reduceLeft(info, (value, chain) => value + 1 + countMessageChainBreadth(chain.next), 0); } - function relateVariances(sourceTypeArguments: readonly ts.Type[] | undefined, targetTypeArguments: readonly ts.Type[] | undefined, variances: ts.VarianceFlags[], intersectionState: IntersectionState) { + function relateVariances(sourceTypeArguments: readonly Type[] | undefined, targetTypeArguments: readonly Type[] | undefined, variances: VarianceFlags[], intersectionState: IntersectionState) { if (result = typeArgumentsRelatedTo(sourceTypeArguments, targetTypeArguments, variances, reportErrors, intersectionState)) { return result; } - if (ts.some(variances, v => !!(v & ts.VarianceFlags.AllowsStructuralFallback))) { + if (some(variances, v => !!(v & VarianceFlags.AllowsStructuralFallback))) { // If some type parameter was `Unmeasurable` or `Unreliable`, and we couldn't pass by assuming it was identical, then we // have to allow a structural fallback check // We elide the variance-based error elaborations, since those might not be too helpful, since we'll potentially @@ -20218,7 +20416,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // (in which case any type argument is permitted on the source side). In those cases we proceed // with a structural comparison. Otherwise, we know for certain the instantiations aren't // related and we can return here. - if (variances !== ts.emptyArray && !allowStructuralFallback) { + if (variances !== emptyArray && !allowStructuralFallback) { // In some cases generic types that are covariant in regular type checking mode become // invariant in --strictFunctionTypes mode because one or more type parameters are used in // both co- and contravariant positions. In order to make it easier to diagnose *why* such @@ -20227,8 +20425,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // reveal the reason). // We can switch on `reportErrors` here, since varianceCheckFailed guarantees we return `False`, // we can return `False` early here to skip calculating the structural error message we don't need. - if (varianceCheckFailed && !(reportErrors && ts.some(variances, v => (v & ts.VarianceFlags.VarianceMask) === ts.VarianceFlags.Invariant))) { - return ts.Ternary.False; + if (varianceCheckFailed && !(reportErrors && some(variances, v => (v & VarianceFlags.VarianceMask) === VarianceFlags.Invariant))) { + return Ternary.False; } // We remember the original error information so we can restore it in case the structural // comparison unexpectedly succeeds. This can happen when the structural comparison result @@ -20242,11 +20440,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is // related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice // that S and T are contra-variant whereas X and Y are co-variant. - function mappedTypeRelatedTo(source: ts.MappedType, target: ts.MappedType, reportErrors: boolean): ts.Ternary { + function mappedTypeRelatedTo(source: MappedType, target: MappedType, reportErrors: boolean): Ternary { const modifiersRelated = relation === comparableRelation || (relation === identityRelation ? getMappedTypeModifiers(source) === getMappedTypeModifiers(target) : getCombinedMappedTypeOptionality(source) <= getCombinedMappedTypeOptionality(target)); if (modifiersRelated) { - let result: ts.Ternary; + let result: Ternary; const targetConstraint = getConstraintTypeFromMappedType(target); const sourceConstraint = instantiateType(getConstraintTypeFromMappedType(source), getCombinedMappedTypeOptionality(source) < 0 ? reportUnmeasurableMapper : reportUnreliableMapper); if (result = isRelatedTo(targetConstraint, sourceConstraint, RecursionFlags.Both, reportErrors)) { @@ -20256,10 +20454,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return ts.Ternary.False; + return Ternary.False; } - function typeRelatedToDiscriminatedType(source: ts.Type, target: ts.UnionType) { + function typeRelatedToDiscriminatedType(source: Type, target: UnionType) { // 1. Generate the combinations of discriminant properties & types 'source' can satisfy. // a. If the number of combinations is above a set limit, the comparison is too complex. // 2. Filter 'target' to the subset of types whose discriminants exist in the matrix. @@ -20272,7 +20470,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const sourceProperties = getPropertiesOfType(source); const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); - if (!sourcePropertiesFiltered) return ts.Ternary.False; + if (!sourcePropertiesFiltered) return Ternary.False; // Though we could compute the number of combinations as we generate // the matrix, this would incur additional memory overhead due to @@ -20284,27 +20482,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { numCombinations *= countTypes(getNonMissingTypeOfSymbol(sourceProperty)); if (numCombinations > 25) { // We've reached the complexity limit. - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations }); - return ts.Ternary.False; + tracing?.instant(tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations }); + return Ternary.False; } } // Compute the set of types for each discriminant property. - const sourceDiscriminantTypes: ts.Type[][] = new Array(sourcePropertiesFiltered.length); - const excludedProperties = new ts.Set(); + const sourceDiscriminantTypes: Type[][] = new Array(sourcePropertiesFiltered.length); + const excludedProperties = new Set<__String>(); for (let i = 0; i < sourcePropertiesFiltered.length; i++) { const sourceProperty = sourcePropertiesFiltered[i]; const sourcePropertyType = getNonMissingTypeOfSymbol(sourceProperty); - sourceDiscriminantTypes[i] = sourcePropertyType.flags & ts.TypeFlags.Union - ? (sourcePropertyType as ts.UnionType).types + sourceDiscriminantTypes[i] = sourcePropertyType.flags & TypeFlags.Union + ? (sourcePropertyType as UnionType).types : [sourcePropertyType]; excludedProperties.add(sourceProperty.escapedName); } // Match each combination of the cartesian product of discriminant properties to one or more // constituents of 'target'. If any combination does not have a match then 'source' is not relatable. - const discriminantCombinations = ts.cartesianProduct(sourceDiscriminantTypes); - const matchingTypes: ts.Type[] = []; + const discriminantCombinations = cartesianProduct(sourceDiscriminantTypes); + const matchingTypes: Type[] = []; for (const combination of discriminantCombinations) { let hasMatch = false; outer: for (const type of target.types) { @@ -20321,23 +20519,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { continue outer; } } - ts.pushIfUnique(matchingTypes, type, ts.equateValues); + pushIfUnique(matchingTypes, type, equateValues); hasMatch = true; } if (!hasMatch) { // We failed to match any type for this combination. - return ts.Ternary.False; + return Ternary.False; } } // Compare the remaining non-discriminant properties of each match. - let result = ts.Ternary.True; + let result = Ternary.True; for (const type of matchingTypes) { result &= propertiesRelatedTo(source, type, /*reportErrors*/ false, excludedProperties, IntersectionState.None); if (result) { - result &= signaturesRelatedTo(source, type, ts.SignatureKind.Call, /*reportStructuralErrors*/ false); + result &= signaturesRelatedTo(source, type, SignatureKind.Call, /*reportStructuralErrors*/ false); if (result) { - result &= signaturesRelatedTo(source, type, ts.SignatureKind.Construct, /*reportStructuralErrors*/ false); + result &= signaturesRelatedTo(source, type, SignatureKind.Construct, /*reportStructuralErrors*/ false); if (result && !(isTupleType(source) && isTupleType(type))) { // Comparing numeric index types when both `source` and `type` are tuples is unnecessary as the // element types should be sufficiently covered by `propertiesRelatedTo`. It also causes problems @@ -20354,9 +20552,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function excludeProperties(properties: ts.Symbol[], excludedProperties: ts.Set | undefined) { + function excludeProperties(properties: Symbol[], excludedProperties: Set<__String> | undefined) { if (!excludedProperties || properties.length === 0) return properties; - let result: ts.Symbol[] | undefined; + let result: Symbol[] | undefined; for (let i = 0; i < properties.length; i++) { if (!excludedProperties.has(properties[i].escapedName)) { if (result) { @@ -20370,46 +20568,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result || properties; } - function isPropertySymbolTypeRelated(sourceProp: ts.Symbol, targetProp: ts.Symbol, getTypeOfSourceProperty: (sym: ts.Symbol) => ts.Type, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { - const targetIsOptional = strictNullChecks && !!(ts.getCheckFlags(targetProp) & ts.CheckFlags.Partial); + function isPropertySymbolTypeRelated(sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary { + const targetIsOptional = strictNullChecks && !!(getCheckFlags(targetProp) & CheckFlags.Partial); const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional); const effectiveSource = getTypeOfSourceProperty(sourceProp); return isRelatedTo(effectiveSource, effectiveTarget, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); } - function propertyRelatedTo(source: ts.Type, target: ts.Type, sourceProp: ts.Symbol, targetProp: ts.Symbol, getTypeOfSourceProperty: (sym: ts.Symbol) => ts.Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): ts.Ternary { - const sourcePropFlags = ts.getDeclarationModifierFlagsFromSymbol(sourceProp); - const targetPropFlags = ts.getDeclarationModifierFlagsFromSymbol(targetProp); - if (sourcePropFlags & ts.ModifierFlags.Private || targetPropFlags & ts.ModifierFlags.Private) { + function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary { + const sourcePropFlags = getDeclarationModifierFlagsFromSymbol(sourceProp); + const targetPropFlags = getDeclarationModifierFlagsFromSymbol(targetProp); + if (sourcePropFlags & ModifierFlags.Private || targetPropFlags & ModifierFlags.Private) { if (sourceProp.valueDeclaration !== targetProp.valueDeclaration) { if (reportErrors) { - if (sourcePropFlags & ts.ModifierFlags.Private && targetPropFlags & ts.ModifierFlags.Private) { - reportError(ts.Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); + if (sourcePropFlags & ModifierFlags.Private && targetPropFlags & ModifierFlags.Private) { + reportError(Diagnostics.Types_have_separate_declarations_of_a_private_property_0, symbolToString(targetProp)); } else { - reportError(ts.Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), - typeToString(sourcePropFlags & ts.ModifierFlags.Private ? source : target), - typeToString(sourcePropFlags & ts.ModifierFlags.Private ? target : source)); + reportError(Diagnostics.Property_0_is_private_in_type_1_but_not_in_type_2, symbolToString(targetProp), + typeToString(sourcePropFlags & ModifierFlags.Private ? source : target), + typeToString(sourcePropFlags & ModifierFlags.Private ? target : source)); } } - return ts.Ternary.False; + return Ternary.False; } } - else if (targetPropFlags & ts.ModifierFlags.Protected) { + else if (targetPropFlags & ModifierFlags.Protected) { if (!isValidOverrideOf(sourceProp, targetProp)) { if (reportErrors) { - reportError(ts.Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), + reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, symbolToString(targetProp), typeToString(getDeclaringClass(sourceProp) || source), typeToString(getDeclaringClass(targetProp) || target)); } - return ts.Ternary.False; + return Ternary.False; } } - else if (sourcePropFlags & ts.ModifierFlags.Protected) { + else if (sourcePropFlags & ModifierFlags.Protected) { if (reportErrors) { - reportError(ts.Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, + reportError(Diagnostics.Property_0_is_protected_in_type_1_but_public_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return ts.Ternary.False; + return Ternary.False; } // Ensure {readonly a: whatever} is not a subtype of {a: whatever}, @@ -20422,18 +20620,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { relation === strictSubtypeRelation && isReadonlySymbol(sourceProp) && !isReadonlySymbol(targetProp) ) { - return ts.Ternary.False; + return Ternary.False; } // If the target comes from a partial union prop, allow `undefined` in the target type const related = isPropertySymbolTypeRelated(sourceProp, targetProp, getTypeOfSourceProperty, reportErrors, intersectionState); if (!related) { if (reportErrors) { - reportIncompatibleError(ts.Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp)); + reportIncompatibleError(Diagnostics.Types_of_property_0_are_incompatible, symbolToString(targetProp)); } - return ts.Ternary.False; + return Ternary.False; } // When checking for comparability, be more lenient with optional properties. - if (!skipOptional && sourceProp.flags & ts.SymbolFlags.Optional && targetProp.flags & ts.SymbolFlags.ClassMember && !(targetProp.flags & ts.SymbolFlags.Optional)) { + if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && targetProp.flags & SymbolFlags.ClassMember && !(targetProp.flags & SymbolFlags.Optional)) { // TypeScript 1.0 spec (April 2014): 3.8.3 // S is a subtype of a type T, and T is a supertype of S if ... // S' and T are object types and, for each member M in T.. @@ -20442,45 +20640,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // (M - property in T) // (N - property in S) if (reportErrors) { - reportError(ts.Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, + reportError(Diagnostics.Property_0_is_optional_in_type_1_but_required_in_type_2, symbolToString(targetProp), typeToString(source), typeToString(target)); } - return ts.Ternary.False; + return Ternary.False; } return related; } - function reportUnmatchedProperty(source: ts.Type, target: ts.Type, unmatchedProperty: ts.Symbol, requireOptionalProperties: boolean) { + function reportUnmatchedProperty(source: Type, target: Type, unmatchedProperty: Symbol, requireOptionalProperties: boolean) { let shouldSkipElaboration = false; // give specific error in case where private names have the same description if (unmatchedProperty.valueDeclaration - && ts.isNamedDeclaration(unmatchedProperty.valueDeclaration) - && ts.isPrivateIdentifier(unmatchedProperty.valueDeclaration.name) + && isNamedDeclaration(unmatchedProperty.valueDeclaration) + && isPrivateIdentifier(unmatchedProperty.valueDeclaration.name) && source.symbol - && source.symbol.flags & ts.SymbolFlags.Class) { + && source.symbol.flags & SymbolFlags.Class) { const privateIdentifierDescription = unmatchedProperty.valueDeclaration.name.escapedText; - const symbolTableKey = ts.getSymbolNameForPrivateIdentifier(source.symbol, privateIdentifierDescription); + const symbolTableKey = getSymbolNameForPrivateIdentifier(source.symbol, privateIdentifierDescription); if (symbolTableKey && getPropertyOfType(source, symbolTableKey)) { - const sourceName = ts.factory.getDeclarationName(source.symbol.valueDeclaration); - const targetName = ts.factory.getDeclarationName(target.symbol.valueDeclaration); + const sourceName = factory.getDeclarationName(source.symbol.valueDeclaration); + const targetName = factory.getDeclarationName(target.symbol.valueDeclaration); reportError( - ts.Diagnostics.Property_0_in_type_1_refers_to_a_different_member_that_cannot_be_accessed_from_within_type_2, + Diagnostics.Property_0_in_type_1_refers_to_a_different_member_that_cannot_be_accessed_from_within_type_2, diagnosticName(privateIdentifierDescription), diagnosticName(sourceName.escapedText === "" ? anon : sourceName), diagnosticName(targetName.escapedText === "" ? anon : targetName)); return; } } - const props = ts.arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); - if (!headMessage || (headMessage.code !== ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code && - headMessage.code !== ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { + const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && + headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { shouldSkipElaboration = true; // Retain top-level error for interface implementing issues, otherwise omit it } if (props.length === 1) { - const propName = symbolToString(unmatchedProperty, /*enclosingDeclaration*/ undefined, ts.SymbolFlags.None, ts.SymbolFormatFlags.AllowAnyNodeKind | ts.SymbolFormatFlags.WriteComputedProps); - reportError(ts.Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target)); - if (ts.length(unmatchedProperty.declarations)) { - associateRelatedInfo(ts.createDiagnosticForNode(unmatchedProperty.declarations![0], ts.Diagnostics._0_is_declared_here, propName)); + const propName = symbolToString(unmatchedProperty, /*enclosingDeclaration*/ undefined, SymbolFlags.None, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteComputedProps); + reportError(Diagnostics.Property_0_is_missing_in_type_1_but_required_in_type_2, propName, ...getTypeNamesForErrorDisplay(source, target)); + if (length(unmatchedProperty.declarations)) { + associateRelatedInfo(createDiagnosticForNode(unmatchedProperty.declarations![0], Diagnostics._0_is_declared_here, propName)); } if (shouldSkipElaboration && errorInfo) { overrideNextErrorInfo++; @@ -20488,10 +20686,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else if (tryElaborateArrayLikeErrors(source, target, /*reportErrors*/ false)) { if (props.length > 5) { // arbitrary cutoff for too-long list form - reportError(ts.Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), ts.map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2_and_3_more, typeToString(source), typeToString(target), map(props.slice(0, 4), p => symbolToString(p)).join(", "), props.length - 4); } else { - reportError(ts.Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), ts.map(props, p => symbolToString(p)).join(", ")); + reportError(Diagnostics.Type_0_is_missing_the_following_properties_from_type_1_Colon_2, typeToString(source), typeToString(target), map(props, p => symbolToString(p)).join(", ")); } if (shouldSkipElaboration && errorInfo) { overrideNextErrorInfo++; @@ -20500,53 +20698,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // No array like or unmatched property error - just issue top level error (errorInfo = undefined) } - function propertiesRelatedTo(source: ts.Type, target: ts.Type, reportErrors: boolean, excludedProperties: ts.Set | undefined, intersectionState: IntersectionState): ts.Ternary { + function propertiesRelatedTo(source: Type, target: Type, reportErrors: boolean, excludedProperties: Set<__String> | undefined, intersectionState: IntersectionState): Ternary { if (relation === identityRelation) { return propertiesIdenticalTo(source, target, excludedProperties); } - let result = ts.Ternary.True; + let result = Ternary.True; if (isTupleType(target)) { if (isArrayOrTupleType(source)) { if (!target.target.readonly && (isReadonlyArrayType(source) || isTupleType(source) && source.target.readonly)) { - return ts.Ternary.False; + return Ternary.False; } const sourceArity = getTypeReferenceArity(source); const targetArity = getTypeReferenceArity(target); - const sourceRestFlag = isTupleType(source) ? source.target.combinedFlags & ts.ElementFlags.Rest : ts.ElementFlags.Rest; - const targetRestFlag = target.target.combinedFlags & ts.ElementFlags.Rest; + const sourceRestFlag = isTupleType(source) ? source.target.combinedFlags & ElementFlags.Rest : ElementFlags.Rest; + const targetRestFlag = target.target.combinedFlags & ElementFlags.Rest; const sourceMinLength = isTupleType(source) ? source.target.minLength : 0; const targetMinLength = target.target.minLength; if (!sourceRestFlag && sourceArity < targetMinLength) { if (reportErrors) { - reportError(ts.Diagnostics.Source_has_0_element_s_but_target_requires_1, sourceArity, targetMinLength); + reportError(Diagnostics.Source_has_0_element_s_but_target_requires_1, sourceArity, targetMinLength); } - return ts.Ternary.False; + return Ternary.False; } if (!targetRestFlag && targetArity < sourceMinLength) { if (reportErrors) { - reportError(ts.Diagnostics.Source_has_0_element_s_but_target_allows_only_1, sourceMinLength, targetArity); + reportError(Diagnostics.Source_has_0_element_s_but_target_allows_only_1, sourceMinLength, targetArity); } - return ts.Ternary.False; + return Ternary.False; } if (!targetRestFlag && (sourceRestFlag || targetArity < sourceArity)) { if (reportErrors) { if (sourceMinLength < targetMinLength) { - reportError(ts.Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength); + reportError(Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength); } else { - reportError(ts.Diagnostics.Target_allows_only_0_element_s_but_source_may_have_more, targetArity); + reportError(Diagnostics.Target_allows_only_0_element_s_but_source_may_have_more, targetArity); } } - return ts.Ternary.False; + return Ternary.False; } const sourceTypeArguments = getTypeArguments(source); const targetTypeArguments = getTypeArguments(target); - const targetStartCount = getStartElementCount(target.target, ts.ElementFlags.NonRest); - const targetEndCount = getEndElementCount(target.target, ts.ElementFlags.NonRest); + const targetStartCount = getStartElementCount(target.target, ElementFlags.NonRest); + const targetEndCount = getEndElementCount(target.target, ElementFlags.NonRest); const targetHasRestElement = target.target.hasRestElement; let canExcludeDiscriminants = !!excludedProperties; for (let sourcePosition = 0; sourcePosition < sourceArity; sourcePosition++) { - const sourceFlags = isTupleType(source) ? source.target.elementFlags[sourcePosition] : ts.ElementFlags.Rest; + const sourceFlags = isTupleType(source) ? source.target.elementFlags[sourcePosition] : ElementFlags.Rest; const sourcePositionFromEnd = sourceArity - 1 - sourcePosition; const targetPosition = targetHasRestElement && sourcePosition >= targetStartCount @@ -20555,57 +20753,57 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const targetFlags = target.target.elementFlags[targetPosition]; - if (targetFlags & ts.ElementFlags.Variadic && !(sourceFlags & ts.ElementFlags.Variadic)) { + if (targetFlags & ElementFlags.Variadic && !(sourceFlags & ElementFlags.Variadic)) { if (reportErrors) { - reportError(ts.Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, targetPosition); + reportError(Diagnostics.Source_provides_no_match_for_variadic_element_at_position_0_in_target, targetPosition); } - return ts.Ternary.False; + return Ternary.False; } - if (sourceFlags & ts.ElementFlags.Variadic && !(targetFlags & ts.ElementFlags.Variable)) { + if (sourceFlags & ElementFlags.Variadic && !(targetFlags & ElementFlags.Variable)) { if (reportErrors) { - reportError(ts.Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourcePosition, targetPosition); + reportError(Diagnostics.Variadic_element_at_position_0_in_source_does_not_match_element_at_position_1_in_target, sourcePosition, targetPosition); } - return ts.Ternary.False; + return Ternary.False; } - if (targetFlags & ts.ElementFlags.Required && !(sourceFlags & ts.ElementFlags.Required)) { + if (targetFlags & ElementFlags.Required && !(sourceFlags & ElementFlags.Required)) { if (reportErrors) { - reportError(ts.Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, targetPosition); + reportError(Diagnostics.Source_provides_no_match_for_required_element_at_position_0_in_target, targetPosition); } - return ts.Ternary.False; + return Ternary.False; } // We can only exclude discriminant properties if we have not yet encountered a variable-length element. if (canExcludeDiscriminants) { - if (sourceFlags & ts.ElementFlags.Variable || targetFlags & ts.ElementFlags.Variable) { + if (sourceFlags & ElementFlags.Variable || targetFlags & ElementFlags.Variable) { canExcludeDiscriminants = false; } - if (canExcludeDiscriminants && excludedProperties?.has(("" + sourcePosition) as ts.__String)) { + if (canExcludeDiscriminants && excludedProperties?.has(("" + sourcePosition) as __String)) { continue; } } - const sourceType = removeMissingType(sourceTypeArguments[sourcePosition], !!(sourceFlags & targetFlags & ts.ElementFlags.Optional)); + const sourceType = removeMissingType(sourceTypeArguments[sourcePosition], !!(sourceFlags & targetFlags & ElementFlags.Optional)); const targetType = targetTypeArguments[targetPosition]; - const targetCheckType = sourceFlags & ts.ElementFlags.Variadic && targetFlags & ts.ElementFlags.Rest ? createArrayType(targetType) : - removeMissingType(targetType, !!(targetFlags & ts.ElementFlags.Optional)); + const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : + removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional)); const related = isRelatedTo(sourceType, targetCheckType, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); if (!related) { if (reportErrors && (targetArity > 1 || sourceArity > 1)) { if (targetHasRestElement && sourcePosition >= targetStartCount && sourcePositionFromEnd >= targetEndCount && targetStartCount !== sourceArity - targetEndCount - 1) { - reportIncompatibleError(ts.Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, targetStartCount, sourceArity - targetEndCount - 1, targetPosition); + reportIncompatibleError(Diagnostics.Type_at_positions_0_through_1_in_source_is_not_compatible_with_type_at_position_2_in_target, targetStartCount, sourceArity - targetEndCount - 1, targetPosition); } else { - reportIncompatibleError(ts.Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourcePosition, targetPosition); + reportIncompatibleError(Diagnostics.Type_at_position_0_in_source_is_not_compatible_with_type_at_position_1_in_target, sourcePosition, targetPosition); } } - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - if (target.target.combinedFlags & ts.ElementFlags.Variable) { - return ts.Ternary.False; + if (target.target.combinedFlags & ElementFlags.Variable) { + return Ternary.False; } } const requireOptionalProperties = (relation === subtypeRelation || relation === strictSubtypeRelation) && !isObjectLiteralType(source) && !isEmptyArrayLiteralType(source) && !isTupleType(source); @@ -20614,17 +20812,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (reportErrors && shouldReportUnmatchedPropertyError(source, target)) { reportUnmatchedProperty(source, target, unmatchedProperty, requireOptionalProperties); } - return ts.Ternary.False; + return Ternary.False; } if (isObjectLiteralType(target)) { for (const sourceProp of excludeProperties(getPropertiesOfType(source), excludedProperties)) { if (!getPropertyOfObjectType(target, sourceProp.escapedName)) { const sourceType = getTypeOfSymbol(sourceProp); - if (!(sourceType.flags & ts.TypeFlags.Undefined)) { + if (!(sourceType.flags & TypeFlags.Undefined)) { if (reportErrors) { - reportError(ts.Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target)); + reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target)); } - return ts.Ternary.False; + return Ternary.False; } } } @@ -20635,12 +20833,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const numericNamesOnly = isTupleType(source) && isTupleType(target); for (const targetProp of excludeProperties(properties, excludedProperties)) { const name = targetProp.escapedName; - if (!(targetProp.flags & ts.SymbolFlags.Prototype) && (!numericNamesOnly || ts.isNumericLiteralName(name) || name === "length")) { + if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) { const sourceProp = getPropertyOfType(source, name); if (sourceProp && sourceProp !== targetProp) { const related = propertyRelatedTo(source, target, sourceProp, targetProp, getNonMissingTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -20649,70 +20847,70 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function propertiesIdenticalTo(source: ts.Type, target: ts.Type, excludedProperties: ts.Set | undefined): ts.Ternary { - if (!(source.flags & ts.TypeFlags.Object && target.flags & ts.TypeFlags.Object)) { - return ts.Ternary.False; + function propertiesIdenticalTo(source: Type, target: Type, excludedProperties: Set<__String> | undefined): Ternary { + if (!(source.flags & TypeFlags.Object && target.flags & TypeFlags.Object)) { + return Ternary.False; } const sourceProperties = excludeProperties(getPropertiesOfObjectType(source), excludedProperties); const targetProperties = excludeProperties(getPropertiesOfObjectType(target), excludedProperties); if (sourceProperties.length !== targetProperties.length) { - return ts.Ternary.False; + return Ternary.False; } - let result = ts.Ternary.True; + let result = Ternary.True; for (const sourceProp of sourceProperties) { const targetProp = getPropertyOfObjectType(target, sourceProp.escapedName); if (!targetProp) { - return ts.Ternary.False; + return Ternary.False; } const related = compareProperties(sourceProp, targetProp, isRelatedTo); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function signaturesRelatedTo(source: ts.Type, target: ts.Type, kind: ts.SignatureKind, reportErrors: boolean): ts.Ternary { + function signaturesRelatedTo(source: Type, target: Type, kind: SignatureKind, reportErrors: boolean): Ternary { if (relation === identityRelation) { return signaturesIdenticalTo(source, target, kind); } if (target === anyFunctionType || source === anyFunctionType) { - return ts.Ternary.True; + return Ternary.True; } const sourceIsJSConstructor = source.symbol && isJSConstructor(source.symbol.valueDeclaration); const targetIsJSConstructor = target.symbol && isJSConstructor(target.symbol.valueDeclaration); - const sourceSignatures = getSignaturesOfType(source, (sourceIsJSConstructor && kind === ts.SignatureKind.Construct) ? - ts.SignatureKind.Call : kind); - const targetSignatures = getSignaturesOfType(target, (targetIsJSConstructor && kind === ts.SignatureKind.Construct) ? - ts.SignatureKind.Call : kind); + const sourceSignatures = getSignaturesOfType(source, (sourceIsJSConstructor && kind === SignatureKind.Construct) ? + SignatureKind.Call : kind); + const targetSignatures = getSignaturesOfType(target, (targetIsJSConstructor && kind === SignatureKind.Construct) ? + SignatureKind.Call : kind); - if (kind === ts.SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) { - const sourceIsAbstract = !!(sourceSignatures[0].flags & ts.SignatureFlags.Abstract); - const targetIsAbstract = !!(targetSignatures[0].flags & ts.SignatureFlags.Abstract); + if (kind === SignatureKind.Construct && sourceSignatures.length && targetSignatures.length) { + const sourceIsAbstract = !!(sourceSignatures[0].flags & SignatureFlags.Abstract); + const targetIsAbstract = !!(targetSignatures[0].flags & SignatureFlags.Abstract); if (sourceIsAbstract && !targetIsAbstract) { // An abstract constructor type is not assignable to a non-abstract constructor type // as it would otherwise be possible to new an abstract class. Note that the assignability // check we perform for an extends clause excludes construct signatures from the target, // so this check never proceeds. if (reportErrors) { - reportError(ts.Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); + reportError(Diagnostics.Cannot_assign_an_abstract_constructor_type_to_a_non_abstract_constructor_type); } - return ts.Ternary.False; + return Ternary.False; } if (!constructorVisibilitiesAreCompatible(sourceSignatures[0], targetSignatures[0], reportErrors)) { - return ts.Ternary.False; + return Ternary.False; } } - let result = ts.Ternary.True; - const incompatibleReporter = kind === ts.SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn; - const sourceObjectFlags = ts.getObjectFlags(source); - const targetObjectFlags = ts.getObjectFlags(target); - if (sourceObjectFlags & ts.ObjectFlags.Instantiated && targetObjectFlags & ts.ObjectFlags.Instantiated && source.symbol === target.symbol || - sourceObjectFlags & ts.ObjectFlags.Reference && targetObjectFlags & ts.ObjectFlags.Reference && (source as ts.TypeReference).target === (target as ts.TypeReference).target) { + let result = Ternary.True; + const incompatibleReporter = kind === SignatureKind.Construct ? reportIncompatibleConstructSignatureReturn : reportIncompatibleCallSignatureReturn; + const sourceObjectFlags = getObjectFlags(source); + const targetObjectFlags = getObjectFlags(target); + if (sourceObjectFlags & ObjectFlags.Instantiated && targetObjectFlags & ObjectFlags.Instantiated && source.symbol === target.symbol || + sourceObjectFlags & ObjectFlags.Reference && targetObjectFlags & ObjectFlags.Reference && (source as TypeReference).target === (target as TypeReference).target) { // We have instantiations of the same anonymous type (which typically will be the type of a // method). Simply do a pairwise comparison of the signatures in the two signature lists instead // of the much more expensive N * M comparison matrix we explore below. We erase type parameters @@ -20720,7 +20918,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = 0; i < targetSignatures.length; i++) { const related = signatureRelatedTo(sourceSignatures[i], targetSignatures[i], /*erase*/ true, reportErrors, incompatibleReporter(sourceSignatures[i], targetSignatures[i])); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -20732,15 +20930,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // this regardless of the number of signatures, but the potential costs are prohibitive due // to the quadratic nature of the logic below. const eraseGenerics = relation === comparableRelation || !!compilerOptions.noStrictGenericChecks; - const sourceSignature = ts.first(sourceSignatures); - const targetSignature = ts.first(targetSignatures); + const sourceSignature = first(sourceSignatures); + const targetSignature = first(targetSignatures); result = signatureRelatedTo(sourceSignature, targetSignature, eraseGenerics, reportErrors, incompatibleReporter(sourceSignature, targetSignature)); - if (!result && reportErrors && kind === ts.SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags) && - (targetSignature.declaration?.kind === ts.SyntaxKind.Constructor || sourceSignature.declaration?.kind === ts.SyntaxKind.Constructor)) { - const constructSignatureToString = (signature: ts.Signature) => - signatureToString(signature, /*enclosingDeclaration*/ undefined, ts.TypeFormatFlags.WriteArrowStyleSignature, kind); - reportError(ts.Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature)); - reportError(ts.Diagnostics.Types_of_construct_signatures_are_incompatible); + if (!result && reportErrors && kind === SignatureKind.Construct && (sourceObjectFlags & targetObjectFlags) && + (targetSignature.declaration?.kind === SyntaxKind.Constructor || sourceSignature.declaration?.kind === SyntaxKind.Constructor)) { + const constructSignatureToString = (signature: Signature) => + signatureToString(signature, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrowStyleSignature, kind); + reportError(Diagnostics.Type_0_is_not_assignable_to_type_1, constructSignatureToString(sourceSignature), constructSignatureToString(targetSignature)); + reportError(Diagnostics.Types_of_construct_signatures_are_incompatible); return result; } } @@ -20759,23 +20957,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { shouldElaborateErrors = false; } if (shouldElaborateErrors) { - reportError(ts.Diagnostics.Type_0_provides_no_match_for_the_signature_1, + reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1, typeToString(source), signatureToString(t, /*enclosingDeclaration*/ undefined, /*flags*/ undefined, kind)); } - return ts.Ternary.False; + return Ternary.False; } } return result; } - function shouldReportUnmatchedPropertyError(source: ts.Type, target: ts.Type): boolean { - const typeCallSignatures = getSignaturesOfStructuredType(source, ts.SignatureKind.Call); - const typeConstructSignatures = getSignaturesOfStructuredType(source, ts.SignatureKind.Construct); + function shouldReportUnmatchedPropertyError(source: Type, target: Type): boolean { + const typeCallSignatures = getSignaturesOfStructuredType(source, SignatureKind.Call); + const typeConstructSignatures = getSignaturesOfStructuredType(source, SignatureKind.Construct); const typeProperties = getPropertiesOfObjectType(source); if ((typeCallSignatures.length || typeConstructSignatures.length) && !typeProperties.length) { - if ((getSignaturesOfType(target, ts.SignatureKind.Call).length && typeCallSignatures.length) || - (getSignaturesOfType(target, ts.SignatureKind.Construct).length && typeConstructSignatures.length)) { + if ((getSignaturesOfType(target, SignatureKind.Call).length && typeCallSignatures.length) || + (getSignaturesOfType(target, SignatureKind.Construct).length && typeConstructSignatures.length)) { return true; // target has similar signature kinds to source, still focus on the unmatched property } return false; @@ -20783,65 +20981,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function reportIncompatibleCallSignatureReturn(siga: ts.Signature, sigb: ts.Signature) { + function reportIncompatibleCallSignatureReturn(siga: Signature, sigb: Signature) { if (siga.parameters.length === 0 && sigb.parameters.length === 0) { - return (source: ts.Type, target: ts.Type) => reportIncompatibleError(ts.Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); } - return (source: ts.Type, target: ts.Type) => reportIncompatibleError(ts.Diagnostics.Call_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Call_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); } - function reportIncompatibleConstructSignatureReturn(siga: ts.Signature, sigb: ts.Signature) { + function reportIncompatibleConstructSignatureReturn(siga: Signature, sigb: Signature) { if (siga.parameters.length === 0 && sigb.parameters.length === 0) { - return (source: ts.Type, target: ts.Type) => reportIncompatibleError(ts.Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signatures_with_no_arguments_have_incompatible_return_types_0_and_1, typeToString(source), typeToString(target)); } - return (source: ts.Type, target: ts.Type) => reportIncompatibleError(ts.Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); + return (source: Type, target: Type) => reportIncompatibleError(Diagnostics.Construct_signature_return_types_0_and_1_are_incompatible, typeToString(source), typeToString(target)); } /** * See signatureAssignableTo, compareSignaturesIdentical */ - function signatureRelatedTo(source: ts.Signature, target: ts.Signature, erase: boolean, reportErrors: boolean, incompatibleReporter: (source: ts.Type, target: ts.Type) => void): ts.Ternary { + function signatureRelatedTo(source: Signature, target: Signature, erase: boolean, reportErrors: boolean, incompatibleReporter: (source: Type, target: Type) => void): Ternary { return compareSignaturesRelated(erase ? getErasedSignature(source) : source, erase ? getErasedSignature(target) : target, relation === strictSubtypeRelation ? SignatureCheckMode.StrictArity : 0, reportErrors, reportError, incompatibleReporter, isRelatedToWorker, reportUnreliableMapper); } - function signaturesIdenticalTo(source: ts.Type, target: ts.Type, kind: ts.SignatureKind): ts.Ternary { + function signaturesIdenticalTo(source: Type, target: Type, kind: SignatureKind): Ternary { const sourceSignatures = getSignaturesOfType(source, kind); const targetSignatures = getSignaturesOfType(target, kind); if (sourceSignatures.length !== targetSignatures.length) { - return ts.Ternary.False; + return Ternary.False; } - let result = ts.Ternary.True; + let result = Ternary.True; for (let i = 0; i < sourceSignatures.length; i++) { const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreThisTypes*/ false, /*ignoreReturnTypes*/ false, isRelatedTo); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function membersRelatedToIndexInfo(source: ts.Type, targetInfo: ts.IndexInfo, reportErrors: boolean): ts.Ternary { - let result = ts.Ternary.True; + function membersRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean): Ternary { + let result = Ternary.True; const keyType = targetInfo.keyType; - const props = source.flags & ts.TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(source as ts.IntersectionType) : getPropertiesOfObjectType(source); + const props = source.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType(source as IntersectionType) : getPropertiesOfObjectType(source); for (const prop of props) { // Skip over ignored JSX and symbol-named members if (isIgnoredJsxProperty(source, prop)) { continue; } - if (isApplicableIndexType(getLiteralTypeFromProperty(prop, ts.TypeFlags.StringOrNumberLiteralOrUnique), keyType)) { + if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), keyType)) { const propType = getNonMissingTypeOfSymbol(prop); - const type = exactOptionalPropertyTypes || propType.flags & ts.TypeFlags.Undefined || keyType === numberType || !(prop.flags & ts.SymbolFlags.Optional) + const type = exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional) ? propType : getTypeWithFacts(propType, TypeFacts.NEUndefined); const related = isRelatedTo(type, targetInfo.type, RecursionFlags.Both, reportErrors); if (!related) { if (reportErrors) { - reportError(ts.Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop)); + reportError(Diagnostics.Property_0_is_incompatible_with_index_signature, symbolToString(prop)); } - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -20850,7 +21048,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isApplicableIndexType(info.keyType, keyType)) { const related = indexInfoRelatedTo(info, targetInfo, reportErrors); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -20858,39 +21056,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function indexInfoRelatedTo(sourceInfo: ts.IndexInfo, targetInfo: ts.IndexInfo, reportErrors: boolean) { + function indexInfoRelatedTo(sourceInfo: IndexInfo, targetInfo: IndexInfo, reportErrors: boolean) { const related = isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both, reportErrors); if (!related && reportErrors) { if (sourceInfo.keyType === targetInfo.keyType) { - reportError(ts.Diagnostics._0_index_signatures_are_incompatible, typeToString(sourceInfo.keyType)); + reportError(Diagnostics._0_index_signatures_are_incompatible, typeToString(sourceInfo.keyType)); } else { - reportError(ts.Diagnostics._0_and_1_index_signatures_are_incompatible, typeToString(sourceInfo.keyType), typeToString(targetInfo.keyType)); + reportError(Diagnostics._0_and_1_index_signatures_are_incompatible, typeToString(sourceInfo.keyType), typeToString(targetInfo.keyType)); } } return related; } - function indexSignaturesRelatedTo(source: ts.Type, target: ts.Type, sourceIsPrimitive: boolean, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function indexSignaturesRelatedTo(source: Type, target: Type, sourceIsPrimitive: boolean, reportErrors: boolean, intersectionState: IntersectionState): Ternary { if (relation === identityRelation) { return indexSignaturesIdenticalTo(source, target); } const indexInfos = getIndexInfosOfType(target); - const targetHasStringIndex = ts.some(indexInfos, info => info.keyType === stringType); - let result = ts.Ternary.True; + const targetHasStringIndex = some(indexInfos, info => info.keyType === stringType); + let result = Ternary.True; for (const targetInfo of indexInfos) { - const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & ts.TypeFlags.Any ? ts.Ternary.True : + const related = !sourceIsPrimitive && targetHasStringIndex && targetInfo.type.flags & TypeFlags.Any ? Ternary.True : isGenericMappedType(source) && targetHasStringIndex ? isRelatedTo(getTemplateTypeFromMappedType(source), targetInfo.type, RecursionFlags.Both, reportErrors) : typeRelatedToIndexInfo(source, targetInfo, reportErrors, intersectionState); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } return result; } - function typeRelatedToIndexInfo(source: ts.Type, targetInfo: ts.IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): ts.Ternary { + function typeRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): Ternary { const sourceInfo = getApplicableIndexInfo(source, targetInfo.keyType); if (sourceInfo) { return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors); @@ -20900,94 +21098,94 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return membersRelatedToIndexInfo(source, targetInfo, reportErrors); } if (reportErrors) { - reportError(ts.Diagnostics.Index_signature_for_type_0_is_missing_in_type_1, typeToString(targetInfo.keyType), typeToString(source)); + reportError(Diagnostics.Index_signature_for_type_0_is_missing_in_type_1, typeToString(targetInfo.keyType), typeToString(source)); } - return ts.Ternary.False; + return Ternary.False; } - function indexSignaturesIdenticalTo(source: ts.Type, target: ts.Type): ts.Ternary { + function indexSignaturesIdenticalTo(source: Type, target: Type): Ternary { const sourceInfos = getIndexInfosOfType(source); const targetInfos = getIndexInfosOfType(target); if (sourceInfos.length !== targetInfos.length) { - return ts.Ternary.False; + return Ternary.False; } for (const targetInfo of targetInfos) { const sourceInfo = getIndexInfoOfType(source, targetInfo.keyType); if (!(sourceInfo && isRelatedTo(sourceInfo.type, targetInfo.type, RecursionFlags.Both) && sourceInfo.isReadonly === targetInfo.isReadonly)) { - return ts.Ternary.False; + return Ternary.False; } } - return ts.Ternary.True; + return Ternary.True; } - function constructorVisibilitiesAreCompatible(sourceSignature: ts.Signature, targetSignature: ts.Signature, reportErrors: boolean) { + function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) { if (!sourceSignature.declaration || !targetSignature.declaration) { return true; } - const sourceAccessibility = ts.getSelectedEffectiveModifierFlags(sourceSignature.declaration, ts.ModifierFlags.NonPublicAccessibilityModifier); - const targetAccessibility = ts.getSelectedEffectiveModifierFlags(targetSignature.declaration, ts.ModifierFlags.NonPublicAccessibilityModifier); + const sourceAccessibility = getSelectedEffectiveModifierFlags(sourceSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier); + const targetAccessibility = getSelectedEffectiveModifierFlags(targetSignature.declaration, ModifierFlags.NonPublicAccessibilityModifier); // A public, protected and private signature is assignable to a private signature. - if (targetAccessibility === ts.ModifierFlags.Private) { + if (targetAccessibility === ModifierFlags.Private) { return true; } // A public and protected signature is assignable to a protected signature. - if (targetAccessibility === ts.ModifierFlags.Protected && sourceAccessibility !== ts.ModifierFlags.Private) { + if (targetAccessibility === ModifierFlags.Protected && sourceAccessibility !== ModifierFlags.Private) { return true; } // Only a public signature is assignable to public signature. - if (targetAccessibility !== ts.ModifierFlags.Protected && !sourceAccessibility) { + if (targetAccessibility !== ModifierFlags.Protected && !sourceAccessibility) { return true; } if (reportErrors) { - reportError(ts.Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility)); + reportError(Diagnostics.Cannot_assign_a_0_constructor_type_to_a_1_constructor_type, visibilityToString(sourceAccessibility), visibilityToString(targetAccessibility)); } return false; } } - function typeCouldHaveTopLevelSingletonTypes(type: ts.Type): boolean { + function typeCouldHaveTopLevelSingletonTypes(type: Type): boolean { // Okay, yes, 'boolean' is a union of 'true | false', but that's not useful // in error reporting scenarios. If you need to use this function but that detail matters, // feel free to add a flag. - if (type.flags & ts.TypeFlags.Boolean) { + if (type.flags & TypeFlags.Boolean) { return false; } - if (type.flags & ts.TypeFlags.UnionOrIntersection) { - return !!ts.forEach((type as ts.IntersectionType).types, typeCouldHaveTopLevelSingletonTypes); + if (type.flags & TypeFlags.UnionOrIntersection) { + return !!forEach((type as IntersectionType).types, typeCouldHaveTopLevelSingletonTypes); } - if (type.flags & ts.TypeFlags.Instantiable) { + if (type.flags & TypeFlags.Instantiable) { const constraint = getConstraintOfType(type); if (constraint && constraint !== type) { return typeCouldHaveTopLevelSingletonTypes(constraint); } } - return isUnitType(type) || !!(type.flags & ts.TypeFlags.TemplateLiteral) || !!(type.flags & ts.TypeFlags.StringMapping); + return isUnitType(type) || !!(type.flags & TypeFlags.TemplateLiteral) || !!(type.flags & TypeFlags.StringMapping); } - function getExactOptionalUnassignableProperties(source: ts.Type, target: ts.Type) { - if (isTupleType(source) && isTupleType(target)) return ts.emptyArray; + function getExactOptionalUnassignableProperties(source: Type, target: Type) { + if (isTupleType(source) && isTupleType(target)) return emptyArray; return getPropertiesOfType(target) .filter(targetProp => isExactOptionalPropertyMismatch(getTypeOfPropertyOfType(source, targetProp.escapedName), getTypeOfSymbol(targetProp))); } - function isExactOptionalPropertyMismatch(source: ts.Type | undefined, target: ts.Type | undefined) { - return !!source && !!target && maybeTypeOfKind(source, ts.TypeFlags.Undefined) && !!containsMissingType(target); + function isExactOptionalPropertyMismatch(source: Type | undefined, target: Type | undefined) { + return !!source && !!target && maybeTypeOfKind(source, TypeFlags.Undefined) && !!containsMissingType(target); } - function getExactOptionalProperties(type: ts.Type) { + function getExactOptionalProperties(type: Type) { return getPropertiesOfType(type).filter(targetProp => containsMissingType(getTypeOfSymbol(targetProp))); } - function getBestMatchingType(source: ts.Type, target: ts.UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) { + function getBestMatchingType(source: Type, target: UnionOrIntersectionType, isRelatedTo = compareTypesAssignable) { return findMatchingDiscriminantType(source, target, isRelatedTo, /*skipPartial*/ true) || findMatchingTypeReferenceOrTypeAliasReference(source, target) || findBestTypeForObjectLiteral(source, target) || @@ -20995,15 +21193,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { findMostOverlappyType(source, target); } - function discriminateTypeByDiscriminableItems(target: ts.UnionType, discriminators: [() => ts.Type, ts.__String][], related: (source: ts.Type, target: ts.Type) => boolean | ts.Ternary, defaultValue?: undefined, skipPartial?: boolean): ts.Type | undefined; - function discriminateTypeByDiscriminableItems(target: ts.UnionType, discriminators: [() => ts.Type, ts.__String][], related: (source: ts.Type, target: ts.Type) => boolean | ts.Ternary, defaultValue: ts.Type, skipPartial?: boolean): ts.Type; - function discriminateTypeByDiscriminableItems(target: ts.UnionType, discriminators: [() => ts.Type, ts.__String][], related: (source: ts.Type, target: ts.Type) => boolean | ts.Ternary, defaultValue?: ts.Type, skipPartial?: boolean) { + function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: undefined, skipPartial?: boolean): Type | undefined; + function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue: Type, skipPartial?: boolean): Type; + function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: Type, skipPartial?: boolean) { // undefined=unknown, true=discriminated, false=not discriminated // The state of each type progresses from left to right. Discriminated types stop at 'true'. const discriminable = target.types.map(_ => undefined) as (boolean | undefined)[]; for (const [getDiscriminatingType, propertyName] of discriminators) { const targetProp = getUnionOrIntersectionProperty(target, propertyName); - if (skipPartial && targetProp && ts.getCheckFlags(targetProp) & ts.CheckFlags.ReadPartial) { + if (skipPartial && targetProp && getCheckFlags(targetProp) & CheckFlags.ReadPartial) { continue; } let i = 0; @@ -21037,19 +21235,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * A type is 'weak' if it is an object type with at least one optional property * and no required properties, call/construct signatures or index signatures */ - function isWeakType(type: ts.Type): boolean { - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function isWeakType(type: Type): boolean { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); return resolved.callSignatures.length === 0 && resolved.constructSignatures.length === 0 && resolved.indexInfos.length === 0 && - resolved.properties.length > 0 && ts.every(resolved.properties, p => !!(p.flags & ts.SymbolFlags.Optional)); + resolved.properties.length > 0 && every(resolved.properties, p => !!(p.flags & SymbolFlags.Optional)); } - if (type.flags & ts.TypeFlags.Intersection) { - return ts.every((type as ts.IntersectionType).types, isWeakType); + if (type.flags & TypeFlags.Intersection) { + return every((type as IntersectionType).types, isWeakType); } return false; } - function hasCommonProperties(source: ts.Type, target: ts.Type, isComparingJsxAttributes: boolean) { + function hasCommonProperties(source: Type, target: Type, isComparingJsxAttributes: boolean) { for (const prop of getPropertiesOfType(source)) { if (isKnownProperty(target, prop.escapedName, isComparingJsxAttributes)) { return true; @@ -21058,14 +21256,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function getVariances(type: ts.GenericType): ts.VarianceFlags[] { + function getVariances(type: GenericType): VarianceFlags[] { // Arrays and tuples are known to be covariant, no need to spend time computing this. - return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ts.ObjectFlags.Tuple ? + return type === globalArrayType || type === globalReadonlyArrayType || type.objectFlags & ObjectFlags.Tuple ? arrayVariances : getVariancesWorker(type.symbol, type.typeParameters); } - function getAliasVariances(symbol: ts.Symbol) { + function getAliasVariances(symbol: Symbol) { return getVariancesWorker(symbol, getSymbolLinks(symbol).typeParameters); } @@ -21074,17 +21272,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // generic type are structurally compared. We infer the variance information by comparing // instantiations of the generic type for type arguments with known relations. The function // returns the emptyArray singleton when invoked recursively for the given generic type. - function getVariancesWorker(symbol: ts.Symbol, typeParameters: readonly ts.TypeParameter[] = ts.emptyArray): ts.VarianceFlags[] { + function getVariancesWorker(symbol: Symbol, typeParameters: readonly TypeParameter[] = emptyArray): VarianceFlags[] { const links = getSymbolLinks(symbol); if (!links.variances) { - ts.tracing?.push(ts.tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) }); - links.variances = ts.emptyArray; + tracing?.push(tracing.Phase.CheckTypes, "getVariancesWorker", { arity: typeParameters.length, id: getTypeId(getDeclaredTypeOfSymbol(symbol)) }); + links.variances = emptyArray; const variances = []; for (const tp of typeParameters) { const modifiers = getVarianceModifiers(tp); - let variance = modifiers & ts.ModifierFlags.Out ? - modifiers & ts.ModifierFlags.In ? ts.VarianceFlags.Invariant : ts.VarianceFlags.Covariant : - modifiers & ts.ModifierFlags.In ? ts.VarianceFlags.Contravariant : undefined; + let variance = modifiers & ModifierFlags.Out ? + modifiers & ModifierFlags.In ? VarianceFlags.Invariant : VarianceFlags.Covariant : + modifiers & ModifierFlags.In ? VarianceFlags.Contravariant : undefined; if (variance === undefined) { let unmeasurable = false; let unreliable = false; @@ -21095,90 +21293,90 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // invariance, covariance, contravariance or bivariance. const typeWithSuper = createMarkerType(symbol, tp, markerSuperType); const typeWithSub = createMarkerType(symbol, tp, markerSubType); - variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? ts.VarianceFlags.Covariant : 0) | - (isTypeAssignableTo(typeWithSuper, typeWithSub) ? ts.VarianceFlags.Contravariant : 0); + variance = (isTypeAssignableTo(typeWithSub, typeWithSuper) ? VarianceFlags.Covariant : 0) | + (isTypeAssignableTo(typeWithSuper, typeWithSub) ? VarianceFlags.Contravariant : 0); // If the instantiations appear to be related bivariantly it may be because the // type parameter is independent (i.e. it isn't witnessed anywhere in the generic // type). To determine this we compare instantiations where the type parameter is // replaced with marker types that are known to be unrelated. - if (variance === ts.VarianceFlags.Bivariant && isTypeAssignableTo(createMarkerType(symbol, tp, markerOtherType), typeWithSuper)) { - variance = ts.VarianceFlags.Independent; + if (variance === VarianceFlags.Bivariant && isTypeAssignableTo(createMarkerType(symbol, tp, markerOtherType), typeWithSuper)) { + variance = VarianceFlags.Independent; } outofbandVarianceMarkerHandler = oldHandler; if (unmeasurable || unreliable) { if (unmeasurable) { - variance |= ts.VarianceFlags.Unmeasurable; + variance |= VarianceFlags.Unmeasurable; } if (unreliable) { - variance |= ts.VarianceFlags.Unreliable; + variance |= VarianceFlags.Unreliable; } } } variances.push(variance); } links.variances = variances; - ts.tracing?.pop({ variances: variances.map(ts.Debug.formatVariance) }); + tracing?.pop({ variances: variances.map(Debug.formatVariance) }); } return links.variances; } - function createMarkerType(symbol: ts.Symbol, source: ts.TypeParameter, target: ts.Type) { + function createMarkerType(symbol: Symbol, source: TypeParameter, target: Type) { const mapper = makeUnaryTypeMapper(source, target); const type = getDeclaredTypeOfSymbol(symbol); if (isErrorType(type)) { return type; } - const result = symbol.flags & ts.SymbolFlags.TypeAlias ? + const result = symbol.flags & SymbolFlags.TypeAlias ? getTypeAliasInstantiation(symbol, instantiateTypes(getSymbolLinks(symbol).typeParameters!, mapper)) : - createTypeReference(type as ts.GenericType, instantiateTypes((type as ts.GenericType).typeParameters, mapper)); + createTypeReference(type as GenericType, instantiateTypes((type as GenericType).typeParameters, mapper)); markerTypes.add(getTypeId(result)); return result; } - function isMarkerType(type: ts.Type) { + function isMarkerType(type: Type) { return markerTypes.has(getTypeId(type)); } - function getVarianceModifiers(tp: ts.TypeParameter): ts.ModifierFlags { - return (ts.some(tp.symbol?.declarations, d => ts.hasSyntacticModifier(d, ts.ModifierFlags.In)) ? ts.ModifierFlags.In : 0) | - (ts.some(tp.symbol?.declarations, d => ts.hasSyntacticModifier(d, ts.ModifierFlags.Out)) ? ts.ModifierFlags.Out: 0); + function getVarianceModifiers(tp: TypeParameter): ModifierFlags { + return (some(tp.symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.In)) ? ModifierFlags.In : 0) | + (some(tp.symbol?.declarations, d => hasSyntacticModifier(d, ModifierFlags.Out)) ? ModifierFlags.Out: 0); } // Return true if the given type reference has a 'void' type argument for a covariant type parameter. // See comment at call in recursiveTypeRelatedTo for when this case matters. - function hasCovariantVoidArgument(typeArguments: readonly ts.Type[], variances: ts.VarianceFlags[]): boolean { + function hasCovariantVoidArgument(typeArguments: readonly Type[], variances: VarianceFlags[]): boolean { for (let i = 0; i < variances.length; i++) { - if ((variances[i] & ts.VarianceFlags.VarianceMask) === ts.VarianceFlags.Covariant && typeArguments[i].flags & ts.TypeFlags.Void) { + if ((variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Covariant && typeArguments[i].flags & TypeFlags.Void) { return true; } } return false; } - function isUnconstrainedTypeParameter(type: ts.Type) { - return type.flags & ts.TypeFlags.TypeParameter && !getConstraintOfTypeParameter(type as ts.TypeParameter); + function isUnconstrainedTypeParameter(type: Type) { + return type.flags & TypeFlags.TypeParameter && !getConstraintOfTypeParameter(type as TypeParameter); } - function isNonDeferredTypeReference(type: ts.Type): type is ts.TypeReference { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference) && !(type as ts.TypeReference).node; + function isNonDeferredTypeReference(type: Type): type is TypeReference { + return !!(getObjectFlags(type) & ObjectFlags.Reference) && !(type as TypeReference).node; } - function isTypeReferenceWithGenericArguments(type: ts.Type): boolean { - return isNonDeferredTypeReference(type) && ts.some(getTypeArguments(type), t => !!(t.flags & ts.TypeFlags.TypeParameter) || isTypeReferenceWithGenericArguments(t)); + function isTypeReferenceWithGenericArguments(type: Type): boolean { + return isNonDeferredTypeReference(type) && some(getTypeArguments(type), t => !!(t.flags & TypeFlags.TypeParameter) || isTypeReferenceWithGenericArguments(t)); } - function getGenericTypeReferenceRelationKey(source: ts.TypeReference, target: ts.TypeReference, postFix: string, ignoreConstraints: boolean) { - const typeParameters: ts.Type[] = []; + function getGenericTypeReferenceRelationKey(source: TypeReference, target: TypeReference, postFix: string, ignoreConstraints: boolean) { + const typeParameters: Type[] = []; let constraintMarker = ""; const sourceId = getTypeReferenceId(source, 0); const targetId = getTypeReferenceId(target, 0); return `${constraintMarker}${sourceId},${targetId}${postFix}`; // getTypeReferenceId(A) returns "111=0-12=1" // where A.id=111 and number.id=12 - function getTypeReferenceId(type: ts.TypeReference, depth = 0) { + function getTypeReferenceId(type: TypeReference, depth = 0) { let result = "" + type.target.id; for (const t of getTypeArguments(type)) { - if (t.flags & ts.TypeFlags.TypeParameter) { + if (t.flags & TypeFlags.TypeParameter) { if (ignoreConstraints || isUnconstrainedTypeParameter(t)) { let index = typeParameters.indexOf(t); if (index < 0) { @@ -21193,7 +21391,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { constraintMarker = "*"; } else if (depth < 4 && isTypeReferenceWithGenericArguments(t)) { - result += "<" + getTypeReferenceId(t as ts.TypeReference, depth + 1) + ">"; + result += "<" + getTypeReferenceId(t as TypeReference, depth + 1) + ">"; continue; } result += "-" + t.id; @@ -21206,7 +21404,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * To improve caching, the relation key for two generic types uses the target's id plus ids of the type parameters. * For other cases, the types ids are used. */ - function getRelationKey(source: ts.Type, target: ts.Type, intersectionState: IntersectionState, relation: ts.ESMap, ignoreConstraints: boolean) { + function getRelationKey(source: Type, target: Type, intersectionState: IntersectionState, relation: ESMap, ignoreConstraints: boolean) { if (relation === identityRelation && source.id > target.id) { const temp = source; source = target; @@ -21214,15 +21412,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const postFix = intersectionState ? ":" + intersectionState : ""; return isTypeReferenceWithGenericArguments(source) && isTypeReferenceWithGenericArguments(target) ? - getGenericTypeReferenceRelationKey(source as ts.TypeReference, target as ts.TypeReference, postFix, ignoreConstraints) : + getGenericTypeReferenceRelationKey(source as TypeReference, target as TypeReference, postFix, ignoreConstraints) : `${source.id},${target.id}${postFix}`; } // Invoke the callback for each underlying property symbol of the given symbol and return the first // value that isn't undefined. - function forEachProperty(prop: ts.Symbol, callback: (p: ts.Symbol) => T): T | undefined { - if (ts.getCheckFlags(prop) & ts.CheckFlags.Synthetic) { - for (const t of (prop as ts.TransientSymbol).containingType!.types) { + function forEachProperty(prop: Symbol, callback: (p: Symbol) => T): T | undefined { + if (getCheckFlags(prop) & CheckFlags.Synthetic) { + for (const t of (prop as TransientSymbol).containingType!.types) { const p = getPropertyOfType(t, prop.escapedName); const result = p && forEachProperty(p, callback); if (result) { @@ -21235,12 +21433,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Return the declaring class type of a property or undefined if property not declared in class - function getDeclaringClass(prop: ts.Symbol) { - return prop.parent && prop.parent.flags & ts.SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) as ts.InterfaceType : undefined; + function getDeclaringClass(prop: Symbol) { + return prop.parent && prop.parent.flags & SymbolFlags.Class ? getDeclaredTypeOfSymbol(getParentOfSymbol(prop)!) as InterfaceType : undefined; } // Return the inherited type of the given property or undefined if property doesn't exist in a base class. - function getTypeOfPropertyInBaseClass(property: ts.Symbol) { + function getTypeOfPropertyInBaseClass(property: Symbol) { const classType = getDeclaringClass(property); const baseClassType = classType && getBaseTypes(classType)[0]; return baseClassType && getTypeOfPropertyOfType(baseClassType, property.escapedName); @@ -21248,7 +21446,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if some underlying source property is declared in a class that derives // from the given base class. - function isPropertyInClassDerivedFrom(prop: ts.Symbol, baseClass: ts.Type | undefined) { + function isPropertyInClassDerivedFrom(prop: Symbol, baseClass: Type | undefined) { return forEachProperty(prop, sp => { const sourceClass = getDeclaringClass(sp); return sourceClass ? hasBaseType(sourceClass, baseClass) : false; @@ -21256,15 +21454,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Return true if source property is a valid override of protected parts of target property. - function isValidOverrideOf(sourceProp: ts.Symbol, targetProp: ts.Symbol) { - return !forEachProperty(targetProp, tp => ts.getDeclarationModifierFlagsFromSymbol(tp) & ts.ModifierFlags.Protected ? + function isValidOverrideOf(sourceProp: Symbol, targetProp: Symbol) { + return !forEachProperty(targetProp, tp => getDeclarationModifierFlagsFromSymbol(tp) & ModifierFlags.Protected ? !isPropertyInClassDerivedFrom(sourceProp, getDeclaringClass(tp)) : false); } // Return true if the given class derives from each of the declaring classes of the protected // constituents of the given property. - function isClassDerivedFromDeclaringClasses(checkClass: T, prop: ts.Symbol, writing: boolean) { - return forEachProperty(prop, p => ts.getDeclarationModifierFlagsFromSymbol(p, writing) & ts.ModifierFlags.Protected ? + function isClassDerivedFromDeclaringClasses(checkClass: T, prop: Symbol, writing: boolean) { + return forEachProperty(prop, p => getDeclarationModifierFlagsFromSymbol(p, writing) & ModifierFlags.Protected ? !hasBaseType(checkClass, getDeclaringClass(p)) : false) ? undefined : checkClass; } @@ -21280,7 +21478,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // `type A = null extends T ? [A>] : [T]` // has expanded into `[A>>>>>]`. In such cases we need // to terminate the expansion, and we do so here. - function isDeeplyNestedType(type: ts.Type, stack: ts.Type[], depth: number, maxDepth = 3): boolean { + function isDeeplyNestedType(type: Type, stack: Type[], depth: number, maxDepth = 3): boolean { if (depth >= maxDepth) { const identity = getRecursionIdentity(type); let count = 0; @@ -21309,16 +21507,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // instantiations of that type have the same recursion identity. The default recursion identity is the object // identity of the type, meaning that every type is unique. Generally, types with constituents that could circularly // reference the type have a recursion identity that differs from the object identity. - function getRecursionIdentity(type: ts.Type): object { + function getRecursionIdentity(type: Type): object { // Object and array literals are known not to contain recursive references and don't need a recursion identity. - if (type.flags & ts.TypeFlags.Object && !isObjectOrArrayLiteralType(type)) { - if (ts.getObjectFlags(type) && ts.ObjectFlags.Reference && (type as ts.TypeReference).node) { + if (type.flags & TypeFlags.Object && !isObjectOrArrayLiteralType(type)) { + if (getObjectFlags(type) && ObjectFlags.Reference && (type as TypeReference).node) { // Deferred type references are tracked through their associated AST node. This gives us finer // granularity than using their associated target because each manifest type reference has a // unique AST node. - return (type as ts.TypeReference).node!; + return (type as TypeReference).node!; } - if (type.symbol && !(ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous && type.symbol.flags & ts.SymbolFlags.Class)) { + if (type.symbol && !(getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol.flags & SymbolFlags.Class)) { // We track all object types that have an associated symbol (representing the origin of the type), but // exclude the static side of classes from this check since it shares its symbol with the instance side. return type.symbol; @@ -21328,56 +21526,56 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type.target; } } - if (type.flags & ts.TypeFlags.TypeParameter) { + if (type.flags & TypeFlags.TypeParameter) { return type.symbol; } - if (type.flags & ts.TypeFlags.IndexedAccess) { + if (type.flags & TypeFlags.IndexedAccess) { // Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P][Q] it is A do { - type = (type as ts.IndexedAccessType).objectType; - } while (type.flags & ts.TypeFlags.IndexedAccess); + type = (type as IndexedAccessType).objectType; + } while (type.flags & TypeFlags.IndexedAccess); return type; } - if (type.flags & ts.TypeFlags.Conditional) { + if (type.flags & TypeFlags.Conditional) { // The root object represents the origin of the conditional type - return (type as ts.ConditionalType).root; + return (type as ConditionalType).root; } return type; } - function isPropertyIdenticalTo(sourceProp: ts.Symbol, targetProp: ts.Symbol): boolean { - return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== ts.Ternary.False; + function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean { + return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False; } - function compareProperties(sourceProp: ts.Symbol, targetProp: ts.Symbol, compareTypes: (source: ts.Type, target: ts.Type) => ts.Ternary): ts.Ternary { + function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary { // Two members are considered identical when // - they are public properties with identical names, optionality, and types, // - they are private or protected properties originating in the same declaration and having identical types if (sourceProp === targetProp) { - return ts.Ternary.True; + return Ternary.True; } - const sourcePropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(sourceProp) & ts.ModifierFlags.NonPublicAccessibilityModifier; - const targetPropAccessibility = ts.getDeclarationModifierFlagsFromSymbol(targetProp) & ts.ModifierFlags.NonPublicAccessibilityModifier; + const sourcePropAccessibility = getDeclarationModifierFlagsFromSymbol(sourceProp) & ModifierFlags.NonPublicAccessibilityModifier; + const targetPropAccessibility = getDeclarationModifierFlagsFromSymbol(targetProp) & ModifierFlags.NonPublicAccessibilityModifier; if (sourcePropAccessibility !== targetPropAccessibility) { - return ts.Ternary.False; + return Ternary.False; } if (sourcePropAccessibility) { if (getTargetSymbol(sourceProp) !== getTargetSymbol(targetProp)) { - return ts.Ternary.False; + return Ternary.False; } } else { - if ((sourceProp.flags & ts.SymbolFlags.Optional) !== (targetProp.flags & ts.SymbolFlags.Optional)) { - return ts.Ternary.False; + if ((sourceProp.flags & SymbolFlags.Optional) !== (targetProp.flags & SymbolFlags.Optional)) { + return Ternary.False; } } if (isReadonlySymbol(sourceProp) !== isReadonlySymbol(targetProp)) { - return ts.Ternary.False; + return Ternary.False; } return compareTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } - function isMatchingSignature(source: ts.Signature, target: ts.Signature, partialMatch: boolean) { + function isMatchingSignature(source: Signature, target: Signature, partialMatch: boolean) { const sourceParameterCount = getParameterCount(source); const targetParameterCount = getParameterCount(target); const sourceMinArgumentCount = getMinArgumentCount(source); @@ -21402,17 +21600,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * See signatureRelatedTo, compareSignaturesIdentical */ - function compareSignaturesIdentical(source: ts.Signature, target: ts.Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: ts.Type, t: ts.Type) => ts.Ternary): ts.Ternary { + function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreThisTypes: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary { // TODO (drosen): De-duplicate code between related functions. if (source === target) { - return ts.Ternary.True; + return Ternary.True; } if (!(isMatchingSignature(source, target, partialMatch))) { - return ts.Ternary.False; + return Ternary.False; } // Check that the two signatures have the same number of type parameters. - if (ts.length(source.typeParameters) !== ts.length(target.typeParameters)) { - return ts.Ternary.False; + if (length(source.typeParameters) !== length(target.typeParameters)) { + return Ternary.False; } // Check that type parameter constraints and defaults match. If they do, instantiate the source // signature with the type parameters of the target signature and continue the comparison. @@ -21423,12 +21621,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const t = target.typeParameters[i]; if (!(s === t || compareTypes(instantiateType(getConstraintFromTypeParameter(s), mapper) || unknownType, getConstraintFromTypeParameter(t) || unknownType) && compareTypes(instantiateType(getDefaultFromTypeParameter(s), mapper) || unknownType, getDefaultFromTypeParameter(t) || unknownType))) { - return ts.Ternary.False; + return Ternary.False; } } source = instantiateSignature(source, mapper, /*eraseTypeParameters*/ true); } - let result = ts.Ternary.True; + let result = Ternary.True; if (!ignoreThisTypes) { const sourceThisType = getThisTypeOfSignature(source); if (sourceThisType) { @@ -21436,7 +21634,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (targetThisType) { const related = compareTypes(sourceThisType, targetThisType); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -21448,7 +21646,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const t = getTypeAtPosition(target, i); const related = compareTypes(t, s); if (!related) { - return ts.Ternary.False; + return Ternary.False; } result &= related; } @@ -21462,17 +21660,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function compareTypePredicatesIdentical(source: ts.TypePredicate | undefined, target: ts.TypePredicate | undefined, compareTypes: (s: ts.Type, t: ts.Type) => ts.Ternary): ts.Ternary { - return !(source && target && typePredicateKindsMatch(source, target)) ? ts.Ternary.False : - source.type === target.type ? ts.Ternary.True : + function compareTypePredicatesIdentical(source: TypePredicate | undefined, target: TypePredicate | undefined, compareTypes: (s: Type, t: Type) => Ternary): Ternary { + return !(source && target && typePredicateKindsMatch(source, target)) ? Ternary.False : + source.type === target.type ? Ternary.True : source.type && target.type ? compareTypes(source.type, target.type) : - ts.Ternary.False; + Ternary.False; } - function literalTypesWithSameBaseType(types: ts.Type[]): boolean { - let commonBaseType: ts.Type | undefined; + function literalTypesWithSameBaseType(types: Type[]): boolean { + let commonBaseType: Type | undefined; for (const t of types) { - if (!(t.flags & ts.TypeFlags.Never)) { + if (!(t.flags & TypeFlags.Never)) { const baseType = getBaseTypeOfLiteralType(t); commonBaseType ??= baseType; if (baseType === t || baseType !== commonBaseType) { @@ -21483,71 +21681,71 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function getCombinedTypeFlags(types: ts.Type[]): ts.TypeFlags { - return ts.reduceLeft(types, (flags, t) => flags | (t.flags & ts.TypeFlags.Union ? getCombinedTypeFlags((t as ts.UnionType).types) : t.flags), 0); + function getCombinedTypeFlags(types: Type[]): TypeFlags { + return reduceLeft(types, (flags, t) => flags | (t.flags & TypeFlags.Union ? getCombinedTypeFlags((t as UnionType).types) : t.flags), 0); } - function getCommonSupertype(types: ts.Type[]): ts.Type { + function getCommonSupertype(types: Type[]): Type { if (types.length === 1) { return types[0]; } // Remove nullable types from each of the candidates. - const primaryTypes = strictNullChecks ? ts.sameMap(types, t => filterType(t, u => !(u.flags & ts.TypeFlags.Nullable))) : types; + const primaryTypes = strictNullChecks ? sameMap(types, t => filterType(t, u => !(u.flags & TypeFlags.Nullable))) : types; // When the candidate types are all literal types with the same base type, return a union // of those literal types. Otherwise, return the leftmost type for which no type to the // right is a supertype. const superTypeOrUnion = literalTypesWithSameBaseType(primaryTypes) ? getUnionType(primaryTypes) : - ts.reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; + reduceLeft(primaryTypes, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; // Add any nullable types that occurred in the candidates back to the result. - return primaryTypes === types ? superTypeOrUnion : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & ts.TypeFlags.Nullable); + return primaryTypes === types ? superTypeOrUnion : getNullableType(superTypeOrUnion, getCombinedTypeFlags(types) & TypeFlags.Nullable); } // Return the leftmost type for which no type to the right is a subtype. - function getCommonSubtype(types: ts.Type[]) { - return ts.reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s)!; + function getCommonSubtype(types: Type[]) { + return reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s)!; } - function isArrayType(type: ts.Type): type is ts.TypeReference { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference) && ((type as ts.TypeReference).target === globalArrayType || (type as ts.TypeReference).target === globalReadonlyArrayType); + function isArrayType(type: Type): type is TypeReference { + return !!(getObjectFlags(type) & ObjectFlags.Reference) && ((type as TypeReference).target === globalArrayType || (type as TypeReference).target === globalReadonlyArrayType); } - function isReadonlyArrayType(type: ts.Type): boolean { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference) && (type as ts.TypeReference).target === globalReadonlyArrayType; + function isReadonlyArrayType(type: Type): boolean { + return !!(getObjectFlags(type) & ObjectFlags.Reference) && (type as TypeReference).target === globalReadonlyArrayType; } - function isArrayOrTupleType(type: ts.Type): type is ts.TypeReference { + function isArrayOrTupleType(type: Type): type is TypeReference { return isArrayType(type) || isTupleType(type); } - function isMutableArrayOrTuple(type: ts.Type): boolean { + function isMutableArrayOrTuple(type: Type): boolean { return isArrayType(type) && !isReadonlyArrayType(type) || isTupleType(type) && !type.target.readonly; } - function getElementTypeOfArrayType(type: ts.Type): ts.Type | undefined { + function getElementTypeOfArrayType(type: Type): Type | undefined { return isArrayType(type) ? getTypeArguments(type)[0] : undefined; } - function isArrayLikeType(type: ts.Type): boolean { + function isArrayLikeType(type: Type): boolean { // A type is array-like if it is a reference to the global Array or global ReadonlyArray type, // or if it is not the undefined or null type and if it is assignable to ReadonlyArray - return isArrayType(type) || !(type.flags & ts.TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); + return isArrayType(type) || !(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType); } - function getSingleBaseForNonAugmentingSubtype(type: ts.Type) { - if (!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference) || !(ts.getObjectFlags((type as ts.TypeReference).target) & ts.ObjectFlags.ClassOrInterface)) { + function getSingleBaseForNonAugmentingSubtype(type: Type) { + if (!(getObjectFlags(type) & ObjectFlags.Reference) || !(getObjectFlags((type as TypeReference).target) & ObjectFlags.ClassOrInterface)) { return undefined; } - if (ts.getObjectFlags(type) & ts.ObjectFlags.IdenticalBaseTypeCalculated) { - return ts.getObjectFlags(type) & ts.ObjectFlags.IdenticalBaseTypeExists ? (type as ts.TypeReference).cachedEquivalentBaseType : undefined; + if (getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeCalculated) { + return getObjectFlags(type) & ObjectFlags.IdenticalBaseTypeExists ? (type as TypeReference).cachedEquivalentBaseType : undefined; } - (type as ts.TypeReference).objectFlags |= ts.ObjectFlags.IdenticalBaseTypeCalculated; - const target = (type as ts.TypeReference).target as ts.InterfaceType; - if (ts.getObjectFlags(target) & ts.ObjectFlags.Class) { + (type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeCalculated; + const target = (type as TypeReference).target as InterfaceType; + if (getObjectFlags(target) & ObjectFlags.Class) { const baseTypeNode = getBaseTypeNodeOfClass(target); // A base type expression may circularly reference the class itself (e.g. as an argument to function call), so we only // check for base types specified as simple qualified names. - if (baseTypeNode && baseTypeNode.expression.kind !== ts.SyntaxKind.Identifier && baseTypeNode.expression.kind !== ts.SyntaxKind.PropertyAccessExpression) { + if (baseTypeNode && baseTypeNode.expression.kind !== SyntaxKind.Identifier && baseTypeNode.expression.kind !== SyntaxKind.PropertyAccessExpression) { return undefined; } } @@ -21558,103 +21756,103 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (getMembersOfSymbol(type.symbol).size) { return undefined; // If the interface has any members, they may subtype members in the base, so we should do a full structural comparison } - let instantiatedBase = !ts.length(target.typeParameters) ? bases[0] : instantiateType(bases[0], createTypeMapper(target.typeParameters!, getTypeArguments(type as ts.TypeReference).slice(0, target.typeParameters!.length))); - if (ts.length(getTypeArguments(type as ts.TypeReference)) > ts.length(target.typeParameters)) { - instantiatedBase = getTypeWithThisArgument(instantiatedBase, ts.last(getTypeArguments(type as ts.TypeReference))); + let instantiatedBase = !length(target.typeParameters) ? bases[0] : instantiateType(bases[0], createTypeMapper(target.typeParameters!, getTypeArguments(type as TypeReference).slice(0, target.typeParameters!.length))); + if (length(getTypeArguments(type as TypeReference)) > length(target.typeParameters)) { + instantiatedBase = getTypeWithThisArgument(instantiatedBase, last(getTypeArguments(type as TypeReference))); } - (type as ts.TypeReference).objectFlags |= ts.ObjectFlags.IdenticalBaseTypeExists; - return (type as ts.TypeReference).cachedEquivalentBaseType = instantiatedBase; + (type as TypeReference).objectFlags |= ObjectFlags.IdenticalBaseTypeExists; + return (type as TypeReference).cachedEquivalentBaseType = instantiatedBase; } - function isEmptyLiteralType(type: ts.Type): boolean { + function isEmptyLiteralType(type: Type): boolean { return strictNullChecks ? type === implicitNeverType : type === undefinedWideningType; } - function isEmptyArrayLiteralType(type: ts.Type): boolean { + function isEmptyArrayLiteralType(type: Type): boolean { const elementType = getElementTypeOfArrayType(type); return !!elementType && isEmptyLiteralType(elementType); } - function isTupleLikeType(type: ts.Type): boolean { - return isTupleType(type) || !!getPropertyOfType(type, "0" as ts.__String); + function isTupleLikeType(type: Type): boolean { + return isTupleType(type) || !!getPropertyOfType(type, "0" as __String); } - function isArrayOrTupleLikeType(type: ts.Type): boolean { + function isArrayOrTupleLikeType(type: Type): boolean { return isArrayLikeType(type) || isTupleLikeType(type); } - function getTupleElementType(type: ts.Type, index: number) { - const propType = getTypeOfPropertyOfType(type, "" + index as ts.__String); + function getTupleElementType(type: Type, index: number) { + const propType = getTypeOfPropertyOfType(type, "" + index as __String); if (propType) { return propType; } if (everyType(type, isTupleType)) { - return mapType(type, t => getRestTypeOfTupleType(t as ts.TupleTypeReference) || undefinedType); + return mapType(type, t => getRestTypeOfTupleType(t as TupleTypeReference) || undefinedType); } return undefined; } - function isNeitherUnitTypeNorNever(type: ts.Type): boolean { - return !(type.flags & (ts.TypeFlags.Unit | ts.TypeFlags.Never)); + function isNeitherUnitTypeNorNever(type: Type): boolean { + return !(type.flags & (TypeFlags.Unit | TypeFlags.Never)); } - function isUnitType(type: ts.Type): boolean { - return !!(type.flags & ts.TypeFlags.Unit); + function isUnitType(type: Type): boolean { + return !!(type.flags & TypeFlags.Unit); } - function isUnitLikeType(type: ts.Type): boolean { + function isUnitLikeType(type: Type): boolean { return isUnitType(getBaseConstraintOrType(type)); } - function extractUnitType(type: ts.Type) { - return type.flags & ts.TypeFlags.Intersection ? ts.find((type as ts.IntersectionType).types, isUnitType) || type : type; + function extractUnitType(type: Type) { + return type.flags & TypeFlags.Intersection ? find((type as IntersectionType).types, isUnitType) || type : type; } - function isLiteralType(type: ts.Type): boolean { - return type.flags & ts.TypeFlags.Boolean ? true : - type.flags & ts.TypeFlags.Union ? type.flags & ts.TypeFlags.EnumLiteral ? true : ts.every((type as ts.UnionType).types, isUnitType) : + function isLiteralType(type: Type): boolean { + return type.flags & TypeFlags.Boolean ? true : + type.flags & TypeFlags.Union ? type.flags & TypeFlags.EnumLiteral ? true : every((type as UnionType).types, isUnitType) : isUnitType(type); } - function getBaseTypeOfLiteralType(type: ts.Type): ts.Type { - return type.flags & ts.TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type as ts.LiteralType) : - type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) ? stringType : - type.flags & ts.TypeFlags.NumberLiteral ? numberType : - type.flags & ts.TypeFlags.BigIntLiteral ? bigintType : - type.flags & ts.TypeFlags.BooleanLiteral ? booleanType : - type.flags & ts.TypeFlags.Union ? getBaseTypeOfLiteralTypeUnion(type as ts.UnionType) : + function getBaseTypeOfLiteralType(type: Type): Type { + return type.flags & TypeFlags.EnumLiteral ? getBaseTypeOfEnumLiteralType(type as LiteralType) : + type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? stringType : + type.flags & TypeFlags.NumberLiteral ? numberType : + type.flags & TypeFlags.BigIntLiteral ? bigintType : + type.flags & TypeFlags.BooleanLiteral ? booleanType : + type.flags & TypeFlags.Union ? getBaseTypeOfLiteralTypeUnion(type as UnionType) : type; } - function getBaseTypeOfLiteralTypeUnion(type: ts.UnionType) { + function getBaseTypeOfLiteralTypeUnion(type: UnionType) { const key = `B${getTypeId(type)}`; return getCachedType(key) ?? setCachedType(key, mapType(type, getBaseTypeOfLiteralType)); } - function getWidenedLiteralType(type: ts.Type): ts.Type { - return type.flags & ts.TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as ts.LiteralType) : - type.flags & ts.TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType : - type.flags & ts.TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType : - type.flags & ts.TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType : - type.flags & ts.TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType : - type.flags & ts.TypeFlags.Union ? mapType(type as ts.UnionType, getWidenedLiteralType) : + function getWidenedLiteralType(type: Type): Type { + return type.flags & TypeFlags.EnumLiteral && isFreshLiteralType(type) ? getBaseTypeOfEnumLiteralType(type as LiteralType) : + type.flags & TypeFlags.StringLiteral && isFreshLiteralType(type) ? stringType : + type.flags & TypeFlags.NumberLiteral && isFreshLiteralType(type) ? numberType : + type.flags & TypeFlags.BigIntLiteral && isFreshLiteralType(type) ? bigintType : + type.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(type) ? booleanType : + type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedLiteralType) : type; } - function getWidenedUniqueESSymbolType(type: ts.Type): ts.Type { - return type.flags & ts.TypeFlags.UniqueESSymbol ? esSymbolType : - type.flags & ts.TypeFlags.Union ? mapType(type as ts.UnionType, getWidenedUniqueESSymbolType) : + function getWidenedUniqueESSymbolType(type: Type): Type { + return type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : + type.flags & TypeFlags.Union ? mapType(type as UnionType, getWidenedUniqueESSymbolType) : type; } - function getWidenedLiteralLikeTypeForContextualType(type: ts.Type, contextualType: ts.Type | undefined) { + function getWidenedLiteralLikeTypeForContextualType(type: Type, contextualType: Type | undefined) { if (!isLiteralOfContextualType(type, contextualType)) { type = getWidenedUniqueESSymbolType(getWidenedLiteralType(type)); } return getRegularTypeOfLiteralType(type); } - function getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(type: ts.Type | undefined, contextualSignatureReturnType: ts.Type | undefined, isAsync: boolean) { + function getWidenedLiteralLikeTypeForContextualReturnTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, isAsync: boolean) { if (type && isUnitType(type)) { const contextualType = !contextualSignatureReturnType ? undefined : isAsync ? getPromisedTypeOfPromise(contextualSignatureReturnType) : @@ -21664,7 +21862,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(type: ts.Type | undefined, contextualSignatureReturnType: ts.Type | undefined, kind: IterationTypeKind, isAsyncGenerator: boolean) { + function getWidenedLiteralLikeTypeForContextualIterationTypeIfNeeded(type: Type | undefined, contextualSignatureReturnType: Type | undefined, kind: IterationTypeKind, isAsyncGenerator: boolean) { if (type && isUnitType(type)) { const contextualType = !contextualSignatureReturnType ? undefined : getIterationTypeOfGeneratorFunctionReturnType(kind, contextualSignatureReturnType, isAsyncGenerator); @@ -21677,68 +21875,68 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Check if a Type was written as a tuple type literal. * Prefer using isTupleLikeType() unless the use of `elementTypes`/`getTypeArguments` is required. */ - function isTupleType(type: ts.Type): type is ts.TupleTypeReference { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference && (type as ts.TypeReference).target.objectFlags & ts.ObjectFlags.Tuple); + function isTupleType(type: Type): type is TupleTypeReference { + return !!(getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target.objectFlags & ObjectFlags.Tuple); } - function isGenericTupleType(type: ts.Type): type is ts.TupleTypeReference { - return isTupleType(type) && !!(type.target.combinedFlags & ts.ElementFlags.Variadic); + function isGenericTupleType(type: Type): type is TupleTypeReference { + return isTupleType(type) && !!(type.target.combinedFlags & ElementFlags.Variadic); } - function isSingleElementGenericTupleType(type: ts.Type): type is ts.TupleTypeReference { + function isSingleElementGenericTupleType(type: Type): type is TupleTypeReference { return isGenericTupleType(type) && type.target.elementFlags.length === 1; } - function getRestTypeOfTupleType(type: ts.TupleTypeReference) { + function getRestTypeOfTupleType(type: TupleTypeReference) { return getElementTypeOfSliceOfTupleType(type, type.target.fixedLength); } - function getRestArrayTypeOfTupleType(type: ts.TupleTypeReference) { + function getRestArrayTypeOfTupleType(type: TupleTypeReference) { const restType = getRestTypeOfTupleType(type); return restType && createArrayType(restType); } - function getElementTypeOfSliceOfTupleType(type: ts.TupleTypeReference, index: number, endSkipCount = 0, writing = false) { + function getElementTypeOfSliceOfTupleType(type: TupleTypeReference, index: number, endSkipCount = 0, writing = false) { const length = getTypeReferenceArity(type) - endSkipCount; if (index < length) { const typeArguments = getTypeArguments(type); - const elementTypes: ts.Type[] = []; + const elementTypes: Type[] = []; for (let i = index; i < length; i++) { const t = typeArguments[i]; - elementTypes.push(type.target.elementFlags[i] & ts.ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); + elementTypes.push(type.target.elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessType(t, numberType) : t); } return writing ? getIntersectionType(elementTypes) : getUnionType(elementTypes); } return undefined; } - function isTupleTypeStructureMatching(t1: ts.TupleTypeReference, t2: ts.TupleTypeReference) { + function isTupleTypeStructureMatching(t1: TupleTypeReference, t2: TupleTypeReference) { return getTypeReferenceArity(t1) === getTypeReferenceArity(t2) && - ts.every(t1.target.elementFlags, (f, i) => (f & ts.ElementFlags.Variable) === (t2.target.elementFlags[i] & ts.ElementFlags.Variable)); + every(t1.target.elementFlags, (f, i) => (f & ElementFlags.Variable) === (t2.target.elementFlags[i] & ElementFlags.Variable)); } - function isZeroBigInt({value}: ts.BigIntLiteralType) { + function isZeroBigInt({value}: BigIntLiteralType) { return value.base10Value === "0"; } - function removeDefinitelyFalsyTypes(type: ts.Type): ts.Type { + function removeDefinitelyFalsyTypes(type: Type): Type { return filterType(type, t => !!(getTypeFacts(t) & TypeFacts.Truthy)); } - function extractDefinitelyFalsyTypes(type: ts.Type): ts.Type { + function extractDefinitelyFalsyTypes(type: Type): Type { return mapType(type, getDefinitelyFalsyPartOfType); } - function getDefinitelyFalsyPartOfType(type: ts.Type): ts.Type { - return type.flags & ts.TypeFlags.String ? emptyStringType : - type.flags & ts.TypeFlags.Number ? zeroType : - type.flags & ts.TypeFlags.BigInt ? zeroBigIntType : + function getDefinitelyFalsyPartOfType(type: Type): Type { + return type.flags & TypeFlags.String ? emptyStringType : + type.flags & TypeFlags.Number ? zeroType : + type.flags & TypeFlags.BigInt ? zeroBigIntType : type === regularFalseType || type === falseType || - type.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Null | ts.TypeFlags.AnyOrUnknown) || - type.flags & ts.TypeFlags.StringLiteral && (type as ts.StringLiteralType).value === "" || - type.flags & ts.TypeFlags.NumberLiteral && (type as ts.NumberLiteralType).value === 0 || - type.flags & ts.TypeFlags.BigIntLiteral && isZeroBigInt(type as ts.BigIntLiteralType) ? type : + type.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null | TypeFlags.AnyOrUnknown) || + type.flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === "" || + type.flags & TypeFlags.NumberLiteral && (type as NumberLiteralType).value === 0 || + type.flags & TypeFlags.BigIntLiteral && isZeroBigInt(type as BigIntLiteralType) ? type : neverType; } @@ -21747,60 +21945,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param type - type to add undefined and/or null to if not present * @param flags - Either TypeFlags.Undefined or TypeFlags.Null, or both */ - function getNullableType(type: ts.Type, flags: ts.TypeFlags): ts.Type { - const missing = (flags & ~type.flags) & (ts.TypeFlags.Undefined | ts.TypeFlags.Null); + function getNullableType(type: Type, flags: TypeFlags): Type { + const missing = (flags & ~type.flags) & (TypeFlags.Undefined | TypeFlags.Null); return missing === 0 ? type : - missing === ts.TypeFlags.Undefined ? getUnionType([type, undefinedType]) : - missing === ts.TypeFlags.Null ? getUnionType([type, nullType]) : + missing === TypeFlags.Undefined ? getUnionType([type, undefinedType]) : + missing === TypeFlags.Null ? getUnionType([type, nullType]) : getUnionType([type, undefinedType, nullType]); } - function getOptionalType(type: ts.Type, isProperty = false): ts.Type { - ts.Debug.assert(strictNullChecks); + function getOptionalType(type: Type, isProperty = false): Type { + Debug.assert(strictNullChecks); const missingOrUndefined = isProperty ? missingType : undefinedType; - return type.flags & ts.TypeFlags.Undefined || type.flags & ts.TypeFlags.Union && (type as ts.UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]); + return type.flags & TypeFlags.Undefined || type.flags & TypeFlags.Union && (type as UnionType).types[0] === missingOrUndefined ? type : getUnionType([type, missingOrUndefined]); } - function getGlobalNonNullableTypeInstantiation(type: ts.Type) { + function getGlobalNonNullableTypeInstantiation(type: Type) { if (!deferredGlobalNonNullableTypeAlias) { - deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as ts.__String, ts.SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol; + deferredGlobalNonNullableTypeAlias = getGlobalSymbol("NonNullable" as __String, SymbolFlags.TypeAlias, /*diagnostic*/ undefined) || unknownSymbol; } return deferredGlobalNonNullableTypeAlias !== unknownSymbol ? getTypeAliasInstantiation(deferredGlobalNonNullableTypeAlias, [type]) : getIntersectionType([type, emptyObjectType]); } - function getNonNullableType(type: ts.Type): ts.Type { + function getNonNullableType(type: Type): Type { return strictNullChecks ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } - function addOptionalTypeMarker(type: ts.Type) { + function addOptionalTypeMarker(type: Type) { return strictNullChecks ? getUnionType([type, optionalType]) : type; } - function removeOptionalTypeMarker(type: ts.Type): ts.Type { + function removeOptionalTypeMarker(type: Type): Type { return strictNullChecks ? removeType(type, optionalType) : type; } - function propagateOptionalTypeMarker(type: ts.Type, node: ts.OptionalChain, wasOptional: boolean) { - return wasOptional ? ts.isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) : type; + function propagateOptionalTypeMarker(type: Type, node: OptionalChain, wasOptional: boolean) { + return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) : type; } - function getOptionalExpressionType(exprType: ts.Type, expression: ts.Expression) { - return ts.isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) : - ts.isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) : + function getOptionalExpressionType(exprType: Type, expression: Expression) { + return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) : + isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) : exprType; } - function removeMissingType(type: ts.Type, isOptional: boolean) { + function removeMissingType(type: Type, isOptional: boolean) { return exactOptionalPropertyTypes && isOptional ? removeType(type, missingType) : type; } - function containsMissingType(type: ts.Type) { - return exactOptionalPropertyTypes && (type === missingType || type.flags & ts.TypeFlags.Union && containsType((type as ts.UnionType).types, missingType)); + function containsMissingType(type: Type) { + return exactOptionalPropertyTypes && (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType)); } - function removeMissingOrUndefinedType(type: ts.Type): ts.Type { + function removeMissingOrUndefinedType(type: Type): Type { return exactOptionalPropertyTypes ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined); } @@ -21824,31 +22022,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param source * @param target */ - function isCoercibleUnderDoubleEquals(source: ts.Type, target: ts.Type): boolean { - return ((source.flags & (ts.TypeFlags.Number | ts.TypeFlags.String | ts.TypeFlags.BooleanLiteral)) !== 0) - && ((target.flags & (ts.TypeFlags.Number | ts.TypeFlags.String | ts.TypeFlags.Boolean)) !== 0); + function isCoercibleUnderDoubleEquals(source: Type, target: Type): boolean { + return ((source.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.BooleanLiteral)) !== 0) + && ((target.flags & (TypeFlags.Number | TypeFlags.String | TypeFlags.Boolean)) !== 0); } /** * Return true if type was inferred from an object literal, written as an object type literal, or is the shape of a module * with no call or construct signatures. */ - function isObjectTypeWithInferableIndex(type: ts.Type): boolean { - const objectFlags = ts.getObjectFlags(type); - return type.flags & ts.TypeFlags.Intersection - ? ts.every((type as ts.IntersectionType).types, isObjectTypeWithInferableIndex) + function isObjectTypeWithInferableIndex(type: Type): boolean { + const objectFlags = getObjectFlags(type); + return type.flags & TypeFlags.Intersection + ? every((type as IntersectionType).types, isObjectTypeWithInferableIndex) : !!( type.symbol - && (type.symbol.flags & (ts.SymbolFlags.ObjectLiteral | ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.Enum | ts.SymbolFlags.ValueModule)) !== 0 - && !(type.symbol.flags & ts.SymbolFlags.Class) + && (type.symbol.flags & (SymbolFlags.ObjectLiteral | SymbolFlags.TypeLiteral | SymbolFlags.Enum | SymbolFlags.ValueModule)) !== 0 + && !(type.symbol.flags & SymbolFlags.Class) && !typeHasCallOrConstructSignatures(type) ) || !!( - objectFlags & ts.ObjectFlags.ObjectRestType - ) || !!(objectFlags & ts.ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ts.ReverseMappedType).source)); + objectFlags & ObjectFlags.ObjectRestType + ) || !!(objectFlags & ObjectFlags.ReverseMapped && isObjectTypeWithInferableIndex((type as ReverseMappedType).source)); } - function createSymbolWithType(source: ts.Symbol, type: ts.Type | undefined) { - const symbol = createSymbol(source.flags, source.escapedName, ts.getCheckFlags(source) & ts.CheckFlags.Readonly); + function createSymbolWithType(source: Symbol, type: Type | undefined) { + const symbol = createSymbol(source.flags, source.escapedName, getCheckFlags(source) & CheckFlags.Readonly); symbol.declarations = source.declarations; symbol.parent = source.parent; symbol.type = type; @@ -21863,8 +22061,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol; } - function transformTypeOfMembers(type: ts.Type, f: (propertyType: ts.Type) => ts.Type) { - const members = ts.createSymbolTable(); + function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) { + const members = createSymbolTable(); for (const property of getPropertiesOfObjectType(type)) { const original = getTypeOfSymbol(property); const updated = f(original); @@ -21878,31 +22076,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * create a new that is exempt. Recursively mark object literal members as exempt. * Leave signatures alone since they are not subject to the check. */ - function getRegularTypeOfObjectLiteral(type: ts.Type): ts.Type { - if (!(isObjectLiteralType(type) && ts.getObjectFlags(type) & ts.ObjectFlags.FreshLiteral)) { + function getRegularTypeOfObjectLiteral(type: Type): Type { + if (!(isObjectLiteralType(type) && getObjectFlags(type) & ObjectFlags.FreshLiteral)) { return type; } - const regularType = (type as ts.FreshObjectLiteralType).regularType; + const regularType = (type as FreshObjectLiteralType).regularType; if (regularType) { return regularType; } - const resolved = type as ts.ResolvedType; + const resolved = type as ResolvedType; const members = transformTypeOfMembers(type, getRegularTypeOfObjectLiteral); const regularNew = createAnonymousType(resolved.symbol, members, resolved.callSignatures, resolved.constructSignatures, resolved.indexInfos); regularNew.flags = resolved.flags; - regularNew.objectFlags |= resolved.objectFlags & ~ts.ObjectFlags.FreshLiteral; - (type as ts.FreshObjectLiteralType).regularType = regularNew; + regularNew.objectFlags |= resolved.objectFlags & ~ObjectFlags.FreshLiteral; + (type as FreshObjectLiteralType).regularType = regularNew; return regularNew; } - function createWideningContext(parent: ts.WideningContext | undefined, propertyName: ts.__String | undefined, siblings: ts.Type[] | undefined): ts.WideningContext { + function createWideningContext(parent: WideningContext | undefined, propertyName: __String | undefined, siblings: Type[] | undefined): WideningContext { return { parent, propertyName, siblings, resolvedProperties: undefined }; } - function getSiblingsOfContext(context: ts.WideningContext): ts.Type[] { + function getSiblingsOfContext(context: WideningContext): Type[] { if (!context.siblings) { - const siblings: ts.Type[] = []; + const siblings: Type[] = []; for (const type of getSiblingsOfContext(context.parent!)) { if (isObjectLiteralType(type)) { const prop = getPropertyOfObjectType(type, context.propertyName!); @@ -21918,23 +22116,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return context.siblings; } - function getPropertiesOfContext(context: ts.WideningContext): ts.Symbol[] { + function getPropertiesOfContext(context: WideningContext): Symbol[] { if (!context.resolvedProperties) { - const names = new ts.Map() as ts.UnderscoreEscapedMap; + const names = new Map() as UnderscoreEscapedMap; for (const t of getSiblingsOfContext(context)) { - if (isObjectLiteralType(t) && !(ts.getObjectFlags(t) & ts.ObjectFlags.ContainsSpread)) { + if (isObjectLiteralType(t) && !(getObjectFlags(t) & ObjectFlags.ContainsSpread)) { for (const prop of getPropertiesOfType(t)) { names.set(prop.escapedName, prop); } } } - context.resolvedProperties = ts.arrayFrom(names.values()); + context.resolvedProperties = arrayFrom(names.values()); } return context.resolvedProperties; } - function getWidenedProperty(prop: ts.Symbol, context: ts.WideningContext | undefined): ts.Symbol { - if (!(prop.flags & ts.SymbolFlags.Property)) { + function getWidenedProperty(prop: Symbol, context: WideningContext | undefined): Symbol { + if (!(prop.flags & SymbolFlags.Property)) { // Since get accessors already widen their return value there is no need to // widen accessor based properties here. return prop; @@ -21945,19 +22143,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return widened === original ? prop : createSymbolWithType(prop, widened); } - function getUndefinedProperty(prop: ts.Symbol) { + function getUndefinedProperty(prop: Symbol) { const cached = undefinedProperties.get(prop.escapedName); if (cached) { return cached; } const result = createSymbolWithType(prop, missingType); - result.flags |= ts.SymbolFlags.Optional; + result.flags |= SymbolFlags.Optional; undefinedProperties.set(prop.escapedName, result); return result; } - function getWidenedTypeOfObjectLiteral(type: ts.Type, context: ts.WideningContext | undefined): ts.Type { - const members = ts.createSymbolTable(); + function getWidenedTypeOfObjectLiteral(type: Type, context: WideningContext | undefined): Type { + const members = createSymbolTable(); for (const prop of getPropertiesOfObjectType(type)) { members.set(prop.escapedName, getWidenedProperty(prop, context)); } @@ -21968,41 +22166,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - const result = createAnonymousType(type.symbol, members, ts.emptyArray, ts.emptyArray, - ts.sameMap(getIndexInfosOfType(type), info => createIndexInfo(info.keyType, getWidenedType(info.type), info.isReadonly))); - result.objectFlags |= (ts.getObjectFlags(type) & (ts.ObjectFlags.JSLiteral | ts.ObjectFlags.NonInferrableType)); // Retain js literal flag through widening + const result = createAnonymousType(type.symbol, members, emptyArray, emptyArray, + sameMap(getIndexInfosOfType(type), info => createIndexInfo(info.keyType, getWidenedType(info.type), info.isReadonly))); + result.objectFlags |= (getObjectFlags(type) & (ObjectFlags.JSLiteral | ObjectFlags.NonInferrableType)); // Retain js literal flag through widening return result; } - function getWidenedType(type: ts.Type) { + function getWidenedType(type: Type) { return getWidenedTypeWithContext(type, /*context*/ undefined); } - function getWidenedTypeWithContext(type: ts.Type, context: ts.WideningContext | undefined): ts.Type { - if (ts.getObjectFlags(type) & ts.ObjectFlags.RequiresWidening) { + function getWidenedTypeWithContext(type: Type, context: WideningContext | undefined): Type { + if (getObjectFlags(type) & ObjectFlags.RequiresWidening) { if (context === undefined && type.widened) { return type.widened; } - let result: ts.Type | undefined; - if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Nullable)) { + let result: Type | undefined; + if (type.flags & (TypeFlags.Any | TypeFlags.Nullable)) { result = anyType; } else if (isObjectLiteralType(type)) { result = getWidenedTypeOfObjectLiteral(type, context); } - else if (type.flags & ts.TypeFlags.Union) { - const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (type as ts.UnionType).types); - const widenedTypes = ts.sameMap((type as ts.UnionType).types, t => t.flags & ts.TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext)); + else if (type.flags & TypeFlags.Union) { + const unionContext = context || createWideningContext(/*parent*/ undefined, /*propertyName*/ undefined, (type as UnionType).types); + const widenedTypes = sameMap((type as UnionType).types, t => t.flags & TypeFlags.Nullable ? t : getWidenedTypeWithContext(t, unionContext)); // Widening an empty object literal transitions from a highly restrictive type to // a highly inclusive one. For that reason we perform subtype reduction here if the // union includes empty object types (e.g. reducing {} | string to just {}). - result = getUnionType(widenedTypes, ts.some(widenedTypes, isEmptyObjectType) ? ts.UnionReduction.Subtype : ts.UnionReduction.Literal); + result = getUnionType(widenedTypes, some(widenedTypes, isEmptyObjectType) ? UnionReduction.Subtype : UnionReduction.Literal); } - else if (type.flags & ts.TypeFlags.Intersection) { - result = getIntersectionType(ts.sameMap((type as ts.IntersectionType).types, getWidenedType)); + else if (type.flags & TypeFlags.Intersection) { + result = getIntersectionType(sameMap((type as IntersectionType).types, getWidenedType)); } else if (isArrayOrTupleType(type)) { - result = createTypeReference(type.target, ts.sameMap(getTypeArguments(type), getWidenedType)); + result = createTypeReference(type.target, sameMap(getTypeArguments(type), getWidenedType)); } if (result && context === undefined) { type.widened = result; @@ -22023,15 +22221,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * an object literal property (arbitrarily deeply), this function reports an error. If no error is * reported, reportImplicitAnyError is a suitable fallback to report a general error. */ - function reportWideningErrorsInType(type: ts.Type): boolean { + function reportWideningErrorsInType(type: Type): boolean { let errorReported = false; - if (ts.getObjectFlags(type) & ts.ObjectFlags.ContainsWideningType) { - if (type.flags & ts.TypeFlags.Union) { - if (ts.some((type as ts.UnionType).types, isEmptyObjectType)) { + if (getObjectFlags(type) & ObjectFlags.ContainsWideningType) { + if (type.flags & TypeFlags.Union) { + if (some((type as UnionType).types, isEmptyObjectType)) { errorReported = true; } else { - for (const t of (type as ts.UnionType).types) { + for (const t of (type as UnionType).types) { if (reportWideningErrorsInType(t)) { errorReported = true; } @@ -22048,9 +22246,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isObjectLiteralType(type)) { for (const p of getPropertiesOfObjectType(type)) { const t = getTypeOfSymbol(p); - if (ts.getObjectFlags(t) & ts.ObjectFlags.ContainsWideningType) { + if (getObjectFlags(t) & ObjectFlags.ContainsWideningType) { if (!reportWideningErrorsInType(t)) { - error(p.valueDeclaration, ts.Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); + error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, symbolToString(p), typeToString(getWidenedType(t))); } errorReported = true; } @@ -22060,79 +22258,79 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return errorReported; } - function reportImplicitAny(declaration: ts.Declaration, type: ts.Type, wideningKind?: WideningKind) { + function reportImplicitAny(declaration: Declaration, type: Type, wideningKind?: WideningKind) { const typeAsString = typeToString(getWidenedType(type)); - if (ts.isInJSFile(declaration) && !ts.isCheckJsEnabledForFile(ts.getSourceFileOfNode(declaration), compilerOptions)) { + if (isInJSFile(declaration) && !isCheckJsEnabledForFile(getSourceFileOfNode(declaration), compilerOptions)) { // Only report implicit any errors/suggestions in TS and ts-check JS files return; } - let diagnostic: ts.DiagnosticMessage; + let diagnostic: DiagnosticMessage; switch (declaration.kind) { - case ts.SyntaxKind.BinaryExpression: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - diagnostic = noImplicitAny ? ts.Diagnostics.Member_0_implicitly_has_an_1_type : ts.Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + case SyntaxKind.BinaryExpression: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; - case ts.SyntaxKind.Parameter: - const param = declaration as ts.ParameterDeclaration; - if (ts.isIdentifier(param.name) && - (ts.isCallSignatureDeclaration(param.parent) || ts.isMethodSignature(param.parent) || ts.isFunctionTypeNode(param.parent)) && + case SyntaxKind.Parameter: + const param = declaration as ParameterDeclaration; + if (isIdentifier(param.name) && + (isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) && param.parent.parameters.indexOf(param) > -1 && - (resolveName(param, param.name.escapedText, ts.SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) || - param.name.originalKeywordKind && ts.isTypeNodeKind(param.name.originalKeywordKind))) { + (resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) || + param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) { const newName = "arg" + param.parent.parameters.indexOf(param); - const typeName = ts.declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); - errorOrSuggestion(noImplicitAny, declaration, ts.Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); + const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); + errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); return; } - diagnostic = (declaration as ts.ParameterDeclaration).dotDotDotToken ? - noImplicitAny ? ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : - noImplicitAny ? ts.Diagnostics.Parameter_0_implicitly_has_an_1_type : ts.Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ? + noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : + noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; - case ts.SyntaxKind.BindingElement: - diagnostic = ts.Diagnostics.Binding_element_0_implicitly_has_an_1_type; + case SyntaxKind.BindingElement: + diagnostic = Diagnostics.Binding_element_0_implicitly_has_an_1_type; if (!noImplicitAny) { // Don't issue a suggestion for binding elements since the codefix doesn't yet support them. return; } break; - case ts.SyntaxKind.JSDocFunctionType: - error(declaration, ts.Diagnostics.Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); + case SyntaxKind.JSDocFunctionType: + error(declaration, Diagnostics.Function_type_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); return; - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - if (noImplicitAny && !(declaration as ts.NamedDeclaration).name) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + if (noImplicitAny && !(declaration as NamedDeclaration).name) { if (wideningKind === WideningKind.GeneratorYield) { - error(declaration, ts.Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString); + error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString); } else { - error(declaration, ts.Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); + error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString); } return; } - diagnostic = !noImplicitAny ? ts.Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage : - wideningKind === WideningKind.GeneratorYield ? ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type : - ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; + diagnostic = !noImplicitAny ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage : + wideningKind === WideningKind.GeneratorYield ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type : + Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; break; - case ts.SyntaxKind.MappedType: + case SyntaxKind.MappedType: if (noImplicitAny) { - error(declaration, ts.Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type); + error(declaration, Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type); } return; default: - diagnostic = noImplicitAny ? ts.Diagnostics.Variable_0_implicitly_has_an_1_type : ts.Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; } - errorOrSuggestion(noImplicitAny, declaration, diagnostic, ts.declarationNameToString(ts.getNameOfDeclaration(declaration)), typeAsString); + errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString); } - function reportErrorsFromWidening(declaration: ts.Declaration, type: ts.Type, wideningKind?: WideningKind) { + function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) { addLazyDiagnostic(() => { - if (noImplicitAny && ts.getObjectFlags(type) & ts.ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as ts.FunctionLikeDeclaration))) { + if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAny(declaration, type, wideningKind); @@ -22141,7 +22339,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function applyToParameterTypes(source: ts.Signature, target: ts.Signature, callback: (s: ts.Type, t: ts.Type) => void) { + function applyToParameterTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { const sourceCount = getParameterCount(source); const targetCount = getParameterCount(target); const sourceRestType = getEffectiveRestType(source); @@ -22163,7 +22361,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function applyToReturnTypes(source: ts.Signature, target: ts.Signature, callback: (s: ts.Type, t: ts.Type) => void) { + function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { const sourceTypePredicate = getTypePredicateOfSignature(source); const targetTypePredicate = getTypePredicateOfSignature(target); if (sourceTypePredicate && targetTypePredicate && typePredicateKindsMatch(sourceTypePredicate, targetTypePredicate) && sourceTypePredicate.type && targetTypePredicate.type) { @@ -22174,16 +22372,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function createInferenceContext(typeParameters: readonly ts.TypeParameter[], signature: ts.Signature | undefined, flags: ts.InferenceFlags, compareTypes?: ts.TypeComparer): ts.InferenceContext { + function createInferenceContext(typeParameters: readonly TypeParameter[], signature: Signature | undefined, flags: InferenceFlags, compareTypes?: TypeComparer): InferenceContext { return createInferenceContextWorker(typeParameters.map(createInferenceInfo), signature, flags, compareTypes || compareTypesAssignable); } - function cloneInferenceContext(context: T, extraFlags: ts.InferenceFlags = 0): ts.InferenceContext | T & undefined { - return context && createInferenceContextWorker(ts.map(context.inferences, cloneInferenceInfo), context.signature, context.flags | extraFlags, context.compareTypes); + function cloneInferenceContext(context: T, extraFlags: InferenceFlags = 0): InferenceContext | T & undefined { + return context && createInferenceContextWorker(map(context.inferences, cloneInferenceInfo), context.signature, context.flags | extraFlags, context.compareTypes); } - function createInferenceContextWorker(inferences: ts.InferenceInfo[], signature: ts.Signature | undefined, flags: ts.InferenceFlags, compareTypes: ts.TypeComparer): ts.InferenceContext { - const context: ts.InferenceContext = { + function createInferenceContextWorker(inferences: InferenceInfo[], signature: Signature | undefined, flags: InferenceFlags, compareTypes: TypeComparer): InferenceContext { + const context: InferenceContext = { inferences, signature, flags, @@ -22196,8 +22394,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return context; } - function makeFixingMapperForContext(context: ts.InferenceContext) { - return makeDeferredTypeMapper(ts.map(context.inferences, i => i.typeParameter), ts.map(context.inferences, (inference, i) => () => { + function makeFixingMapperForContext(context: InferenceContext) { + return makeDeferredTypeMapper(map(context.inferences, i => i.typeParameter), map(context.inferences, (inference, i) => () => { if (!inference.isFixed) { // Before we commit to a particular inference (and thus lock out any further inferences), // we infer from any intra-expression inference sites we have collected. @@ -22209,13 +22407,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { })); } - function makeNonFixingMapperForContext(context: ts.InferenceContext) { - return makeDeferredTypeMapper(ts.map(context.inferences, i => i.typeParameter), ts.map(context.inferences, (_, i) => () => { + function makeNonFixingMapperForContext(context: InferenceContext) { + return makeDeferredTypeMapper(map(context.inferences, i => i.typeParameter), map(context.inferences, (_, i) => () => { return getInferredType(context, i); })); } - function clearCachedInferences(inferences: ts.InferenceInfo[]) { + function clearCachedInferences(inferences: InferenceInfo[]) { for (const inference of inferences) { if (!inference.isFixed) { inference.inferredType = undefined; @@ -22223,7 +22421,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function addIntraExpressionInferenceSite(context: ts.InferenceContext, node: ts.Expression | ts.MethodDeclaration, type: ts.Type) { + function addIntraExpressionInferenceSite(context: InferenceContext, node: Expression | MethodDeclaration, type: Type) { (context.intraExpressionInferenceSites ??= []).push({ node, type }); } @@ -22240,12 +22438,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // arrow function. This happens automatically when the arrow functions are discrete arguments (because we // infer from each argument before processing the next), but when the arrow functions are elements of an // object or array literal, we need to perform intra-expression inferences early. - function inferFromIntraExpressionSites(context: ts.InferenceContext) { + function inferFromIntraExpressionSites(context: InferenceContext) { if (context.intraExpressionInferenceSites) { for (const { node, type } of context.intraExpressionInferenceSites) { - const contextualType = node.kind === ts.SyntaxKind.MethodDeclaration ? - getContextualTypeForObjectLiteralMethod(node as ts.MethodDeclaration, ts.ContextFlags.NoConstraints) : - getContextualType(node, ts.ContextFlags.NoConstraints); + const contextualType = node.kind === SyntaxKind.MethodDeclaration ? + getContextualTypeForObjectLiteralMethod(node as MethodDeclaration, ContextFlags.NoConstraints) : + getContextualType(node, ContextFlags.NoConstraints); if (contextualType) { inferTypes(context.inferences, type, contextualType); } @@ -22254,7 +22452,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function createInferenceInfo(typeParameter: ts.TypeParameter): ts.InferenceInfo { + function createInferenceInfo(typeParameter: TypeParameter): InferenceInfo { return { typeParameter, candidates: undefined, @@ -22267,7 +22465,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; } - function cloneInferenceInfo(inference: ts.InferenceInfo): ts.InferenceInfo { + function cloneInferenceInfo(inference: InferenceInfo): InferenceInfo { return { typeParameter: inference.typeParameter, candidates: inference.candidates && inference.candidates.slice(), @@ -22280,60 +22478,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; } - function cloneInferredPartOfContext(context: ts.InferenceContext): ts.InferenceContext | undefined { - const inferences = ts.filter(context.inferences, hasInferenceCandidates); + function cloneInferredPartOfContext(context: InferenceContext): InferenceContext | undefined { + const inferences = filter(context.inferences, hasInferenceCandidates); return inferences.length ? - createInferenceContextWorker(ts.map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) : + createInferenceContextWorker(map(inferences, cloneInferenceInfo), context.signature, context.flags, context.compareTypes) : undefined; } - function getMapperFromContext(context: T): ts.TypeMapper | T & undefined { + function getMapperFromContext(context: T): TypeMapper | T & undefined { return context && context.mapper; } // Return true if the given type could possibly reference a type parameter for which // we perform type inference (i.e. a type parameter of a generic function). We cache // results for union and intersection types for performance reasons. - function couldContainTypeVariables(type: ts.Type): boolean { - const objectFlags = ts.getObjectFlags(type); - if (objectFlags & ts.ObjectFlags.CouldContainTypeVariablesComputed) { - return !!(objectFlags & ts.ObjectFlags.CouldContainTypeVariables); - } - const result = !!(type.flags & ts.TypeFlags.Instantiable || - type.flags & ts.TypeFlags.Object && !isNonGenericTopLevelType(type) && ( - objectFlags & ts.ObjectFlags.Reference && ((type as ts.TypeReference).node || ts.forEach(getTypeArguments(type as ts.TypeReference), couldContainTypeVariables)) || - objectFlags & ts.ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.Class | ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.ObjectLiteral) && type.symbol.declarations || - objectFlags & (ts.ObjectFlags.Mapped | ts.ObjectFlags.ReverseMapped | ts.ObjectFlags.ObjectRestType | ts.ObjectFlags.InstantiationExpressionType)) || - type.flags & ts.TypeFlags.UnionOrIntersection && !(type.flags & ts.TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && ts.some((type as ts.UnionOrIntersectionType).types, couldContainTypeVariables)); - if (type.flags & ts.TypeFlags.ObjectFlagsType) { - (type as ts.ObjectFlagsType).objectFlags |= ts.ObjectFlags.CouldContainTypeVariablesComputed | (result ? ts.ObjectFlags.CouldContainTypeVariables : 0); + function couldContainTypeVariables(type: Type): boolean { + const objectFlags = getObjectFlags(type); + if (objectFlags & ObjectFlags.CouldContainTypeVariablesComputed) { + return !!(objectFlags & ObjectFlags.CouldContainTypeVariables); + } + const result = !!(type.flags & TypeFlags.Instantiable || + type.flags & TypeFlags.Object && !isNonGenericTopLevelType(type) && ( + objectFlags & ObjectFlags.Reference && ((type as TypeReference).node || forEach(getTypeArguments(type as TypeReference), couldContainTypeVariables)) || + objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations || + objectFlags & (ObjectFlags.Mapped | ObjectFlags.ReverseMapped | ObjectFlags.ObjectRestType | ObjectFlags.InstantiationExpressionType)) || + type.flags & TypeFlags.UnionOrIntersection && !(type.flags & TypeFlags.EnumLiteral) && !isNonGenericTopLevelType(type) && some((type as UnionOrIntersectionType).types, couldContainTypeVariables)); + if (type.flags & TypeFlags.ObjectFlagsType) { + (type as ObjectFlagsType).objectFlags |= ObjectFlags.CouldContainTypeVariablesComputed | (result ? ObjectFlags.CouldContainTypeVariables : 0); } return result; } - function isNonGenericTopLevelType(type: ts.Type) { + function isNonGenericTopLevelType(type: Type) { if (type.aliasSymbol && !type.aliasTypeArguments) { - const declaration = ts.getDeclarationOfKind(type.aliasSymbol, ts.SyntaxKind.TypeAliasDeclaration); - return !!(declaration && ts.findAncestor(declaration.parent, n => n.kind === ts.SyntaxKind.SourceFile ? true : n.kind === ts.SyntaxKind.ModuleDeclaration ? false : "quit")); + const declaration = getDeclarationOfKind(type.aliasSymbol, SyntaxKind.TypeAliasDeclaration); + return !!(declaration && findAncestor(declaration.parent, n => n.kind === SyntaxKind.SourceFile ? true : n.kind === SyntaxKind.ModuleDeclaration ? false : "quit")); } return false; } - function isTypeParameterAtTopLevel(type: ts.Type, typeParameter: ts.TypeParameter): boolean { + function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean { return !!(type === typeParameter || - type.flags & ts.TypeFlags.UnionOrIntersection && ts.some((type as ts.UnionOrIntersectionType).types, t => isTypeParameterAtTopLevel(t, typeParameter)) || - type.flags & ts.TypeFlags.Conditional && (getTrueTypeFromConditionalType(type as ts.ConditionalType) === typeParameter || getFalseTypeFromConditionalType(type as ts.ConditionalType) === typeParameter)); + type.flags & TypeFlags.UnionOrIntersection && some((type as UnionOrIntersectionType).types, t => isTypeParameterAtTopLevel(t, typeParameter)) || + type.flags & TypeFlags.Conditional && (getTrueTypeFromConditionalType(type as ConditionalType) === typeParameter || getFalseTypeFromConditionalType(type as ConditionalType) === typeParameter)); } /** Create an object with properties named in the string literal type. Every property has type `any` */ - function createEmptyObjectTypeFromStringLiteral(type: ts.Type) { - const members = ts.createSymbolTable(); + function createEmptyObjectTypeFromStringLiteral(type: Type) { + const members = createSymbolTable(); forEachType(type, t => { - if (!(t.flags & ts.TypeFlags.StringLiteral)) { + if (!(t.flags & TypeFlags.StringLiteral)) { return; } - const name = ts.escapeLeadingUnderscores((t as ts.StringLiteralType).value); - const literalProp = createSymbol(ts.SymbolFlags.Property, name); + const name = escapeLeadingUnderscores((t as StringLiteralType).value); + const literalProp = createSymbol(SymbolFlags.Property, name); literalProp.type = anyType; if (t.symbol) { literalProp.declarations = t.symbol.declarations; @@ -22341,8 +22539,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } members.set(name, literalProp); }); - const indexInfos = type.flags & ts.TypeFlags.String ? [createIndexInfo(stringType, emptyObjectType, /*isReadonly*/ false)] : ts.emptyArray; - return createAnonymousType(undefined, members, ts.emptyArray, ts.emptyArray, indexInfos); + const indexInfos = type.flags & TypeFlags.String ? [createIndexInfo(stringType, emptyObjectType, /*isReadonly*/ false)] : emptyArray; + return createAnonymousType(undefined, members, emptyArray, emptyArray, indexInfos); } /** @@ -22351,7 +22549,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * property is computed by inferring from the source property type to X for the type * variable T[P] (i.e. we treat the type T[P] as the type variable we're inferring for). */ - function inferTypeForHomomorphicMappedType(source: ts.Type, target: ts.MappedType, constraint: ts.IndexType): ts.Type | undefined { + function inferTypeForHomomorphicMappedType(source: Type, target: MappedType, constraint: IndexType): Type | undefined { if (inInferTypeForHomomorphicMappedType) { return undefined; } @@ -22370,13 +22568,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // an object literal type with at least one property of an inferable type. For example, an object // literal { a: 123, b: x => true } is marked non-inferable because it contains a context sensitive // arrow function, but is considered partially inferable because property 'a' has an inferable type. - function isPartiallyInferableType(type: ts.Type): boolean { - return !(ts.getObjectFlags(type) & ts.ObjectFlags.NonInferrableType) || - isObjectLiteralType(type) && ts.some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) || - isTupleType(type) && ts.some(getTypeArguments(type), isPartiallyInferableType); + function isPartiallyInferableType(type: Type): boolean { + return !(getObjectFlags(type) & ObjectFlags.NonInferrableType) || + isObjectLiteralType(type) && some(getPropertiesOfType(type), prop => isPartiallyInferableType(getTypeOfSymbol(prop))) || + isTupleType(type) && some(getTypeArguments(type), isPartiallyInferableType); } - function createReverseMappedType(source: ts.Type, target: ts.MappedType, constraint: ts.IndexType) { + function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) { // We consider a source type reverse mappable if it has a string index signature or if // it has one or more properties and is of a partially inferable type. if (!(getIndexInfoOfType(source, stringType) || getPropertiesOfType(source).length !== 0 && isPartiallyInferableType(source))) { @@ -22388,22 +22586,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createArrayType(inferReverseMappedType(getTypeArguments(source)[0], target, constraint), isReadonlyArrayType(source)); } if (isTupleType(source)) { - const elementTypes = ts.map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint)); + const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint)); const elementFlags = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ? - ts.sameMap(source.target.elementFlags, f => f & ts.ElementFlags.Optional ? ts.ElementFlags.Required : f) : + sameMap(source.target.elementFlags, f => f & ElementFlags.Optional ? ElementFlags.Required : f) : source.target.elementFlags; return createTupleType(elementTypes, elementFlags, source.target.readonly, source.target.labeledElementDeclarations); } // For all other object types we infer a new object type where the reverse mapping has been // applied to the type of each property. - const reversed = createObjectType(ts.ObjectFlags.ReverseMapped | ts.ObjectFlags.Anonymous, /*symbol*/ undefined) as ts.ReverseMappedType; + const reversed = createObjectType(ObjectFlags.ReverseMapped | ObjectFlags.Anonymous, /*symbol*/ undefined) as ReverseMappedType; reversed.source = source; reversed.mappedType = target; reversed.constraintType = constraint; return reversed; } - function getTypeOfReverseMappedSymbol(symbol: ts.ReverseMappedSymbol) { + function getTypeOfReverseMappedSymbol(symbol: ReverseMappedSymbol) { const links = getSymbolLinks(symbol); if (!links.type) { links.type = inferReverseMappedType(symbol.propertyType, symbol.mappedType, symbol.constraintType); @@ -22411,31 +22609,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.type; } - function inferReverseMappedType(sourceType: ts.Type, target: ts.MappedType, constraint: ts.IndexType): ts.Type { - const typeParameter = getIndexedAccessType(constraint.type, getTypeParameterFromMappedType(target)) as ts.TypeParameter; + function inferReverseMappedType(sourceType: Type, target: MappedType, constraint: IndexType): Type { + const typeParameter = getIndexedAccessType(constraint.type, getTypeParameterFromMappedType(target)) as TypeParameter; const templateType = getTemplateTypeFromMappedType(target); const inference = createInferenceInfo(typeParameter); inferTypes([inference], sourceType, templateType); return getTypeFromInference(inference) || unknownType; } - function* getUnmatchedProperties(source: ts.Type, target: ts.Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator { + function* getUnmatchedProperties(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): IterableIterator { const properties = getPropertiesOfType(target); for (const targetProp of properties) { // TODO: remove this when we support static private identifier fields and find other solutions to get privateNamesAndStaticFields test to pass if (isStaticPrivateIdentifierProperty(targetProp)) { continue; } - if (requireOptionalProperties || !(targetProp.flags & ts.SymbolFlags.Optional || ts.getCheckFlags(targetProp) & ts.CheckFlags.Partial)) { + if (requireOptionalProperties || !(targetProp.flags & SymbolFlags.Optional || getCheckFlags(targetProp) & CheckFlags.Partial)) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); if (!sourceProp) { yield targetProp; } else if (matchDiscriminantProperties) { const targetType = getTypeOfSymbol(targetProp); - if (targetType.flags & ts.TypeFlags.Unit) { + if (targetType.flags & TypeFlags.Unit) { const sourceType = getTypeOfSymbol(sourceProp); - if (!(sourceType.flags & ts.TypeFlags.Any || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType))) { + if (!(sourceType.flags & TypeFlags.Any || getRegularTypeOfLiteralType(sourceType) === getRegularTypeOfLiteralType(targetType))) { yield targetProp; } } @@ -22444,17 +22642,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getUnmatchedProperty(source: ts.Type, target: ts.Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): ts.Symbol | undefined { + function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): Symbol | undefined { const result = getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties).next(); if (!result.done) return result.value; } - function tupleTypesDefinitelyUnrelated(source: ts.TupleTypeReference, target: ts.TupleTypeReference) { - return !(target.target.combinedFlags & ts.ElementFlags.Variadic) && target.target.minLength > source.target.minLength || + function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) { + return !(target.target.combinedFlags & ElementFlags.Variadic) && target.target.minLength > source.target.minLength || !target.target.hasRestElement && (source.target.hasRestElement || target.target.fixedLength < source.target.fixedLength); } - function typesDefinitelyUnrelated(source: ts.Type, target: ts.Type) { + function typesDefinitelyUnrelated(source: Type, target: Type) { // Two tuple types with incompatible arities are definitely unrelated. // Two object types that each have a property that is unmatched in the other are definitely unrelated. return isTupleType(source) && isTupleType(target) ? tupleTypesDefinitelyUnrelated(source, target) : @@ -22462,21 +22660,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !!getUnmatchedProperty(target, source, /*requireOptionalProperties*/ false, /*matchDiscriminantProperties*/ false); } - function getTypeFromInference(inference: ts.InferenceInfo) { - return inference.candidates ? getUnionType(inference.candidates, ts.UnionReduction.Subtype) : + function getTypeFromInference(inference: InferenceInfo) { + return inference.candidates ? getUnionType(inference.candidates, UnionReduction.Subtype) : inference.contraCandidates ? getIntersectionType(inference.contraCandidates) : undefined; } - function hasSkipDirectInferenceFlag(node: ts.Node) { + function hasSkipDirectInferenceFlag(node: Node) { return !!getNodeLinks(node).skipDirectInference; } - function isFromInferenceBlockedSource(type: ts.Type) { - return !!(type.symbol && ts.some(type.symbol.declarations, hasSkipDirectInferenceFlag)); + function isFromInferenceBlockedSource(type: Type) { + return !!(type.symbol && some(type.symbol.declarations, hasSkipDirectInferenceFlag)); } - function templateLiteralTypesDefinitelyUnrelated(source: ts.TemplateLiteralType, target: ts.TemplateLiteralType) { + function templateLiteralTypesDefinitelyUnrelated(source: TemplateLiteralType, target: TemplateLiteralType) { // Two template literal types with diffences in their starting or ending text spans are definitely unrelated. const sourceStart = source.texts[0]; const targetStart = target.texts[0]; @@ -22504,7 +22702,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { */ function parseBigIntLiteralType(text: string) { const negative = text.startsWith("-"); - const base10Value = ts.parsePseudoBigInt(`${negative ? text.slice(1) : text}n`); + const base10Value = parsePseudoBigInt(`${negative ? text.slice(1) : text}n`); return getBigIntLiteralType({ negative, base10Value }); } @@ -22515,12 +22713,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { */ function isValidBigIntString(s: string, roundTripOnly: boolean): boolean { if (s === "") return false; - const scanner = ts.createScanner(ts.ScriptTarget.ESNext, /*skipTrivia*/ false); + const scanner = createScanner(ScriptTarget.ESNext, /*skipTrivia*/ false); let success = true; scanner.setOnError(() => success = false); scanner.setText(s + "n"); let result = scanner.scan(); - const negative = result === ts.SyntaxKind.MinusToken; + const negative = result === SyntaxKind.MinusToken; if (negative) { result = scanner.scan(); } @@ -22530,18 +22728,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // * a bigint can be scanned, and that when it is scanned, it is // * the full length of the input string (so the scanner is one character beyond the augmented input length) // * it does not contain a numeric seperator (the `BigInt` constructor does not accept a numeric seperator in its input) - return success && result === ts.SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & ts.TokenFlags.ContainsSeparator) - && (!roundTripOnly || s === ts.pseudoBigIntToString({ negative, base10Value: ts.parsePseudoBigInt(scanner.getTokenValue()) })); + return success && result === SyntaxKind.BigIntLiteral && scanner.getTextPos() === (s.length + 1) && !(flags & TokenFlags.ContainsSeparator) + && (!roundTripOnly || s === pseudoBigIntToString({ negative, base10Value: parsePseudoBigInt(scanner.getTokenValue()) })); } - function isMemberOfStringMapping(source: ts.Type, target: ts.Type): boolean { - if (target.flags & (ts.TypeFlags.String | ts.TypeFlags.Any)) { + function isMemberOfStringMapping(source: Type, target: Type): boolean { + if (target.flags & (TypeFlags.String | TypeFlags.Any)) { return true; } - if (target.flags & ts.TypeFlags.TemplateLiteral) { + if (target.flags & TypeFlags.TemplateLiteral) { return isTypeAssignableTo(source, target); } - if (target.flags & ts.TypeFlags.StringMapping) { + if (target.flags & TypeFlags.StringMapping) { // We need to see whether applying the same mappings of the target // onto the source would produce an identical type *and* that // it's compatible with the inner-most non-string-mapped type. @@ -22550,49 +22748,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // and the source is compatible with the unmapped target, then they must // still reside in the same domain. const mappingStack = []; - while (target.flags & ts.TypeFlags.StringMapping) { + while (target.flags & TypeFlags.StringMapping) { mappingStack.unshift(target.symbol); - target = (target as ts.StringMappingType).type; + target = (target as StringMappingType).type; } - const mappedSource = ts.reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source); + const mappedSource = reduceLeft(mappingStack, (memo, value) => getStringMappingType(value, memo), source); return mappedSource === source && isMemberOfStringMapping(source, target); } return false; } - function isValidTypeForTemplateLiteralPlaceholder(source: ts.Type, target: ts.Type): boolean { - if (source === target || target.flags & (ts.TypeFlags.Any | ts.TypeFlags.String)) { + function isValidTypeForTemplateLiteralPlaceholder(source: Type, target: Type): boolean { + if (source === target || target.flags & (TypeFlags.Any | TypeFlags.String)) { return true; } - if (source.flags & ts.TypeFlags.StringLiteral) { - const value = (source as ts.StringLiteralType).value; - return !!(target.flags & ts.TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) || - target.flags & ts.TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) || - target.flags & (ts.TypeFlags.BooleanLiteral | ts.TypeFlags.Nullable) && value === (target as ts.IntrinsicType).intrinsicName || - target.flags & ts.TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target)); + if (source.flags & TypeFlags.StringLiteral) { + const value = (source as StringLiteralType).value; + return !!(target.flags & TypeFlags.Number && isValidNumberString(value, /*roundTripOnly*/ false) || + target.flags & TypeFlags.BigInt && isValidBigIntString(value, /*roundTripOnly*/ false) || + target.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && value === (target as IntrinsicType).intrinsicName || + target.flags & TypeFlags.StringMapping && isMemberOfStringMapping(getStringLiteralType(value), target)); } - if (source.flags & ts.TypeFlags.TemplateLiteral) { - const texts = (source as ts.TemplateLiteralType).texts; - return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as ts.TemplateLiteralType).types[0], target); + if (source.flags & TypeFlags.TemplateLiteral) { + const texts = (source as TemplateLiteralType).texts; + return texts.length === 2 && texts[0] === "" && texts[1] === "" && isTypeAssignableTo((source as TemplateLiteralType).types[0], target); } return isTypeAssignableTo(source, target); } - function inferTypesFromTemplateLiteralType(source: ts.Type, target: ts.TemplateLiteralType): ts.Type[] | undefined { - return source.flags & ts.TypeFlags.StringLiteral ? inferFromLiteralPartsToTemplateLiteral([(source as ts.StringLiteralType).value], ts.emptyArray, target) : - source.flags & ts.TypeFlags.TemplateLiteral ? - ts.arraysEqual((source as ts.TemplateLiteralType).texts, target.texts) ? ts.map((source as ts.TemplateLiteralType).types, getStringLikeTypeForType) : - inferFromLiteralPartsToTemplateLiteral((source as ts.TemplateLiteralType).texts, (source as ts.TemplateLiteralType).types, target) : + function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined { + return source.flags & TypeFlags.StringLiteral ? inferFromLiteralPartsToTemplateLiteral([(source as StringLiteralType).value], emptyArray, target) : + source.flags & TypeFlags.TemplateLiteral ? + arraysEqual((source as TemplateLiteralType).texts, target.texts) ? map((source as TemplateLiteralType).types, getStringLikeTypeForType) : + inferFromLiteralPartsToTemplateLiteral((source as TemplateLiteralType).texts, (source as TemplateLiteralType).types, target) : undefined; } - function isTypeMatchedByTemplateLiteralType(source: ts.Type, target: ts.TemplateLiteralType): boolean { + function isTypeMatchedByTemplateLiteralType(source: Type, target: TemplateLiteralType): boolean { const inferences = inferTypesFromTemplateLiteralType(source, target); - return !!inferences && ts.every(inferences, (r, i) => isValidTypeForTemplateLiteralPlaceholder(r, target.types[i])); + return !!inferences && every(inferences, (r, i) => isValidTypeForTemplateLiteralPlaceholder(r, target.types[i])); } - function getStringLikeTypeForType(type: ts.Type) { - return type.flags & (ts.TypeFlags.Any | ts.TypeFlags.StringLike) ? type : getTemplateLiteralType(["", ""], [type]); + function getStringLikeTypeForType(type: Type) { + return type.flags & (TypeFlags.Any | TypeFlags.StringLike) ? type : getTemplateLiteralType(["", ""], [type]); } // This function infers from the text parts and type parts of a source literal to a target template literal. The number @@ -22614,7 +22812,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the source. The first match for the '.' in target occurs at character 1 in the source text part at index 1, and thus // the first inference is the template literal type `<${string}>`. The remainder of the source makes up the second // inference, the template literal type `<${number}-${number}>`. - function inferFromLiteralPartsToTemplateLiteral(sourceTexts: readonly string[], sourceTypes: readonly ts.Type[], target: ts.TemplateLiteralType): ts.Type[] | undefined { + function inferFromLiteralPartsToTemplateLiteral(sourceTexts: readonly string[], sourceTypes: readonly Type[], target: TemplateLiteralType): Type[] | undefined { const lastSourceIndex = sourceTexts.length - 1; const sourceStartText = sourceTexts[0]; const sourceEndText = sourceTexts[lastSourceIndex]; @@ -22625,7 +22823,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (lastSourceIndex === 0 && sourceStartText.length < targetStartText.length + targetEndText.length || !sourceStartText.startsWith(targetStartText) || !sourceEndText.endsWith(targetEndText)) return undefined; const remainingEndText = sourceEndText.slice(0, sourceEndText.length - targetEndText.length); - const matches: ts.Type[] = []; + const matches: Type[] = []; let seg = 0; let pos = targetStartText.length; for (let i = 1; i < lastTargetIndex; i++) { @@ -22670,18 +22868,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function inferTypes(inferences: ts.InferenceInfo[], originalSource: ts.Type, originalTarget: ts.Type, priority: ts.InferencePriority = 0, contravariant = false) { + function inferTypes(inferences: InferenceInfo[], originalSource: Type, originalTarget: Type, priority: InferencePriority = 0, contravariant = false) { let bivariant = false; - let propagationType: ts.Type; - let inferencePriority: number = ts.InferencePriority.MaxValue; + let propagationType: Type; + let inferencePriority: number = InferencePriority.MaxValue; let allowComplexConstraintInference = true; - let visited: ts.ESMap; + let visited: ESMap; let sourceStack: object[]; let targetStack: object[]; let expandingFlags = ExpandingFlags.None; inferFromTypes(originalSource, originalTarget); - function inferFromTypes(source: ts.Type, target: ts.Type): void { + function inferFromTypes(source: Type, target: Type): void { if (!couldContainTypeVariables(target)) { return; } @@ -22704,18 +22902,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // And if there weren't any type arguments, there's no reason to run inference as the types must be the same. return; } - if (source === target && source.flags & ts.TypeFlags.UnionOrIntersection) { + if (source === target && source.flags & TypeFlags.UnionOrIntersection) { // When source and target are the same union or intersection type, just relate each constituent // type to itself. - for (const t of (source as ts.UnionOrIntersectionType).types) { + for (const t of (source as UnionOrIntersectionType).types) { inferFromTypes(t, t); } return; } - if (target.flags & ts.TypeFlags.Union) { + if (target.flags & TypeFlags.Union) { // First, infer between identically matching source and target constituents and remove the // matching types. - const [tempSources, tempTargets] = inferFromMatchingTypes(source.flags & ts.TypeFlags.Union ? (source as ts.UnionType).types : [source], (target as ts.UnionType).types, isTypeOrBaseIdenticalTo); + const [tempSources, tempTargets] = inferFromMatchingTypes(source.flags & TypeFlags.Union ? (source as UnionType).types : [source], (target as UnionType).types, isTypeOrBaseIdenticalTo); // Next, infer between closely matching source and target constituents and remove // the matching types. Types closely match when they are instantiations of the same // object type or instantiations of the same type alias. @@ -22730,19 +22928,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // inferring a type parameter constraint. Instead, make a lower priority inference from // the full source to whatever remains in the target. For example, when inferring from // string to 'string | T', make a lower priority inference of string for T. - inferWithPriority(source, target, ts.InferencePriority.NakedTypeVariable); + inferWithPriority(source, target, InferencePriority.NakedTypeVariable); return; } source = getUnionType(sources); } - else if (target.flags & ts.TypeFlags.Intersection && !ts.every((target as ts.IntersectionType).types, isNonGenericObjectType)) { + else if (target.flags & TypeFlags.Intersection && !every((target as IntersectionType).types, isNonGenericObjectType)) { // We reduce intersection types unless they're simple combinations of object types. For example, // when inferring from 'string[] & { extra: any }' to 'string[] & T' we want to remove string[] and // infer { extra: any } for T. But when inferring to 'string[] & Iterable' we want to keep the // string[] on the source side and infer string for T. - if (!(source.flags & ts.TypeFlags.Union)) { + if (!(source.flags & TypeFlags.Union)) { // Infer between identically matching source and target constituents and remove the matching types. - const [sources, targets] = inferFromMatchingTypes(source.flags & ts.TypeFlags.Intersection ? (source as ts.IntersectionType).types : [source], (target as ts.IntersectionType).types, isTypeIdenticalTo); + const [sources, targets] = inferFromMatchingTypes(source.flags & TypeFlags.Intersection ? (source as IntersectionType).types : [source], (target as IntersectionType).types, isTypeIdenticalTo); if (sources.length === 0 || targets.length === 0) { return; } @@ -22750,10 +22948,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { target = getIntersectionType(targets); } } - else if (target.flags & (ts.TypeFlags.IndexedAccess | ts.TypeFlags.Substitution)) { + else if (target.flags & (TypeFlags.IndexedAccess | TypeFlags.Substitution)) { target = getActualTypeVariable(target); } - if (target.flags & ts.TypeFlags.TypeVariable) { + if (target.flags & TypeFlags.TypeVariable) { // Skip inference if the source is "blocked", which is used by the language service to // prevent inference on nodes currently being edited. if (isFromInferenceBlockedSource(source)) { @@ -22777,7 +22975,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // // As a special case, also ignore nonInferrableAnyType, which is a special form of the any type // used as a stand-in for binding elements when they are being inferred. - if (ts.getObjectFlags(source) & ts.ObjectFlags.NonInferrableType || source === nonInferrableAnyType) { + if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === nonInferrableAnyType) { return; } if (!inference.isFixed) { @@ -22792,17 +22990,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We make contravariant inferences only if we are in a pure contravariant position, // i.e. only if we have not descended into a bivariant position. if (contravariant && !bivariant) { - if (!ts.contains(inference.contraCandidates, candidate)) { - inference.contraCandidates = ts.append(inference.contraCandidates, candidate); + if (!contains(inference.contraCandidates, candidate)) { + inference.contraCandidates = append(inference.contraCandidates, candidate); clearCachedInferences(inferences); } } - else if (!ts.contains(inference.candidates, candidate)) { - inference.candidates = ts.append(inference.candidates, candidate); + else if (!contains(inference.candidates, candidate)) { + inference.candidates = append(inference.candidates, candidate); clearCachedInferences(inferences); } } - if (!(priority & ts.InferencePriority.ReturnType) && target.flags & ts.TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, target as ts.TypeParameter)) { + if (!(priority & InferencePriority.ReturnType) && target.flags & TypeFlags.TypeParameter && inference.topLevel && !isTypeParameterAtTopLevel(originalTarget, target as TypeParameter)) { inference.topLevel = false; clearCachedInferences(inferences); } @@ -22815,68 +23013,68 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (simplified !== target) { inferFromTypes(source, simplified); } - else if (target.flags & ts.TypeFlags.IndexedAccess) { - const indexType = getSimplifiedType((target as ts.IndexedAccessType).indexType, /*writing*/ false); + else if (target.flags & TypeFlags.IndexedAccess) { + const indexType = getSimplifiedType((target as IndexedAccessType).indexType, /*writing*/ false); // Generally simplifications of instantiable indexes are avoided to keep relationship checking correct, however if our target is an access, we can consider // that key of that access to be "instantiated", since we're looking to find the infernce goal in any way we can. - if (indexType.flags & ts.TypeFlags.Instantiable) { - const simplified = distributeIndexOverObjectType(getSimplifiedType((target as ts.IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false); + if (indexType.flags & TypeFlags.Instantiable) { + const simplified = distributeIndexOverObjectType(getSimplifiedType((target as IndexedAccessType).objectType, /*writing*/ false), indexType, /*writing*/ false); if (simplified && simplified !== target) { inferFromTypes(source, simplified); } } } } - if (ts.getObjectFlags(source) & ts.ObjectFlags.Reference && ts.getObjectFlags(target) & ts.ObjectFlags.Reference && ( - (source as ts.TypeReference).target === (target as ts.TypeReference).target || isArrayType(source) && isArrayType(target)) && - !((source as ts.TypeReference).node && (target as ts.TypeReference).node)) { + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( + (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target)) && + !((source as TypeReference).node && (target as TypeReference).node)) { // If source and target are references to the same generic type, infer from type arguments - inferFromTypeArguments(getTypeArguments(source as ts.TypeReference), getTypeArguments(target as ts.TypeReference), getVariances((source as ts.TypeReference).target)); + inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); } - else if (source.flags & ts.TypeFlags.Index && target.flags & ts.TypeFlags.Index) { - inferFromContravariantTypes((source as ts.IndexType).type, (target as ts.IndexType).type); + else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { + inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type); } - else if ((isLiteralType(source) || source.flags & ts.TypeFlags.String) && target.flags & ts.TypeFlags.Index) { + else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) { const empty = createEmptyObjectTypeFromStringLiteral(source); - inferFromContravariantTypesWithPriority(empty, (target as ts.IndexType).type, ts.InferencePriority.LiteralKeyof); + inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); } - else if (source.flags & ts.TypeFlags.IndexedAccess && target.flags & ts.TypeFlags.IndexedAccess) { - inferFromTypes((source as ts.IndexedAccessType).objectType, (target as ts.IndexedAccessType).objectType); - inferFromTypes((source as ts.IndexedAccessType).indexType, (target as ts.IndexedAccessType).indexType); + else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { + inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType); + inferFromTypes((source as IndexedAccessType).indexType, (target as IndexedAccessType).indexType); } - else if (source.flags & ts.TypeFlags.StringMapping && target.flags & ts.TypeFlags.StringMapping) { - if ((source as ts.StringMappingType).symbol === (target as ts.StringMappingType).symbol) { - inferFromTypes((source as ts.StringMappingType).type, (target as ts.StringMappingType).type); + else if (source.flags & TypeFlags.StringMapping && target.flags & TypeFlags.StringMapping) { + if ((source as StringMappingType).symbol === (target as StringMappingType).symbol) { + inferFromTypes((source as StringMappingType).type, (target as StringMappingType).type); } } - else if (source.flags & ts.TypeFlags.Substitution) { - inferFromTypes((source as ts.SubstitutionType).baseType, target); - inferWithPriority(getSubstitutionIntersection(source as ts.SubstitutionType), target, ts.InferencePriority.SubstituteSource); // Make substitute inference at a lower priority + else if (source.flags & TypeFlags.Substitution) { + inferFromTypes((source as SubstitutionType).baseType, target); + inferWithPriority(getSubstitutionIntersection(source as SubstitutionType), target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority } - else if (target.flags & ts.TypeFlags.Conditional) { + else if (target.flags & TypeFlags.Conditional) { invokeOnce(source, target, inferToConditionalType); } - else if (target.flags & ts.TypeFlags.UnionOrIntersection) { - inferToMultipleTypes(source, (target as ts.UnionOrIntersectionType).types, target.flags); + else if (target.flags & TypeFlags.UnionOrIntersection) { + inferToMultipleTypes(source, (target as UnionOrIntersectionType).types, target.flags); } - else if (source.flags & ts.TypeFlags.Union) { + else if (source.flags & TypeFlags.Union) { // Source is a union or intersection type, infer from each constituent type - const sourceTypes = (source as ts.UnionOrIntersectionType).types; + const sourceTypes = (source as UnionOrIntersectionType).types; for (const sourceType of sourceTypes) { inferFromTypes(sourceType, target); } } - else if (target.flags & ts.TypeFlags.TemplateLiteral) { - inferToTemplateLiteralType(source, target as ts.TemplateLiteralType); + else if (target.flags & TypeFlags.TemplateLiteral) { + inferToTemplateLiteralType(source, target as TemplateLiteralType); } else { source = getReducedType(source); - if (!(priority & ts.InferencePriority.NoConstraints && source.flags & (ts.TypeFlags.Intersection | ts.TypeFlags.Instantiable))) { + if (!(priority & InferencePriority.NoConstraints && source.flags & (TypeFlags.Intersection | TypeFlags.Instantiable))) { const apparentSource = getApparentType(source); // getApparentType can return _any_ type, since an indexed access or conditional may simplify to any other type. // If that occurs and it doesn't simplify to an object or intersection, we'll need to restart `inferFromTypes` // with the simplified source. - if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection))) { + if (apparentSource !== source && allowComplexConstraintInference && !(apparentSource.flags & (TypeFlags.Object | TypeFlags.Intersection))) { // TODO: The `allowComplexConstraintInference` flag is a hack! This forbids inference from complex constraints within constraints! // This isn't required algorithmically, but rather is used to lower the memory burden caused by performing inference // that is _too good_ in projects with complicated constraints (eg, fp-ts). In such cases, if we did not limit ourselves @@ -22889,50 +23087,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } source = apparentSource; } - if (source.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection)) { + if (source.flags & (TypeFlags.Object | TypeFlags.Intersection)) { invokeOnce(source, target, inferFromObjectTypes); } } } - function inferWithPriority(source: ts.Type, target: ts.Type, newPriority: ts.InferencePriority) { + function inferWithPriority(source: Type, target: Type, newPriority: InferencePriority) { const savePriority = priority; priority |= newPriority; inferFromTypes(source, target); priority = savePriority; } - function inferFromContravariantTypesWithPriority(source: ts.Type, target: ts.Type, newPriority: ts.InferencePriority) { + function inferFromContravariantTypesWithPriority(source: Type, target: Type, newPriority: InferencePriority) { const savePriority = priority; priority |= newPriority; inferFromContravariantTypes(source, target); priority = savePriority; } - function inferToMultipleTypesWithPriority(source: ts.Type, targets: ts.Type[], targetFlags: ts.TypeFlags, newPriority: ts.InferencePriority) { + function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) { const savePriority = priority; priority |= newPriority; inferToMultipleTypes(source, targets, targetFlags); priority = savePriority; } - function invokeOnce(source: ts.Type, target: ts.Type, action: (source: ts.Type, target: ts.Type) => void) { + function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) { const key = source.id + "," + target.id; const status = visited && visited.get(key); if (status !== undefined) { inferencePriority = Math.min(inferencePriority, status); return; } - (visited || (visited = new ts.Map())).set(key, ts.InferencePriority.Circularity); + (visited || (visited = new Map())).set(key, InferencePriority.Circularity); const saveInferencePriority = inferencePriority; - inferencePriority = ts.InferencePriority.MaxValue; + inferencePriority = InferencePriority.MaxValue; // We stop inferring and report a circularity if we encounter duplicate recursion identities on both // the source side and the target side. const saveExpandingFlags = expandingFlags; const sourceIdentity = getRecursionIdentity(source); const targetIdentity = getRecursionIdentity(target); - if (ts.contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; - if (ts.contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; + if (contains(sourceStack, sourceIdentity)) expandingFlags |= ExpandingFlags.Source; + if (contains(targetStack, targetIdentity)) expandingFlags |= ExpandingFlags.Target; if (expandingFlags !== ExpandingFlags.Both) { (sourceStack || (sourceStack = [])).push(sourceIdentity); (targetStack || (targetStack = [])).push(targetIdentity); @@ -22941,35 +23139,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { sourceStack.pop(); } else { - inferencePriority = ts.InferencePriority.Circularity; + inferencePriority = InferencePriority.Circularity; } expandingFlags = saveExpandingFlags; visited.set(key, inferencePriority); inferencePriority = Math.min(inferencePriority, saveInferencePriority); } - function inferFromMatchingTypes(sources: ts.Type[], targets: ts.Type[], matches: (s: ts.Type, t: ts.Type) => boolean): [ts.Type[], ts.Type[]] { - let matchedSources: ts.Type[] | undefined; - let matchedTargets: ts.Type[] | undefined; + function inferFromMatchingTypes(sources: Type[], targets: Type[], matches: (s: Type, t: Type) => boolean): [Type[], Type[]] { + let matchedSources: Type[] | undefined; + let matchedTargets: Type[] | undefined; for (const t of targets) { for (const s of sources) { if (matches(s, t)) { inferFromTypes(s, t); - matchedSources = ts.appendIfUnique(matchedSources, s); - matchedTargets = ts.appendIfUnique(matchedTargets, t); + matchedSources = appendIfUnique(matchedSources, s); + matchedTargets = appendIfUnique(matchedTargets, t); } } } return [ - matchedSources ? ts.filter(sources, t => !ts.contains(matchedSources, t)) : sources, - matchedTargets ? ts.filter(targets, t => !ts.contains(matchedTargets, t)) : targets, + matchedSources ? filter(sources, t => !contains(matchedSources, t)) : sources, + matchedTargets ? filter(targets, t => !contains(matchedTargets, t)) : targets, ]; } - function inferFromTypeArguments(sourceTypes: readonly ts.Type[], targetTypes: readonly ts.Type[], variances: readonly ts.VarianceFlags[]) { + function inferFromTypeArguments(sourceTypes: readonly Type[], targetTypes: readonly Type[], variances: readonly VarianceFlags[]) { const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length; for (let i = 0; i < count; i++) { - if (i < variances.length && (variances[i] & ts.VarianceFlags.VarianceMask) === ts.VarianceFlags.Contravariant) { + if (i < variances.length && (variances[i] & VarianceFlags.VarianceMask) === VarianceFlags.Contravariant) { inferFromContravariantTypes(sourceTypes[i], targetTypes[i]); } else { @@ -22978,14 +23176,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function inferFromContravariantTypes(source: ts.Type, target: ts.Type) { + function inferFromContravariantTypes(source: Type, target: Type) { contravariant = !contravariant; inferFromTypes(source, target); contravariant = !contravariant; } - function inferFromContravariantTypesIfStrictFunctionTypes(source: ts.Type, target: ts.Type) { - if (strictFunctionTypes || priority & ts.InferencePriority.AlwaysStrict) { + function inferFromContravariantTypesIfStrictFunctionTypes(source: Type, target: Type) { + if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) { inferFromContravariantTypes(source, target); } else { @@ -22993,8 +23191,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getInferenceInfoForType(type: ts.Type) { - if (type.flags & ts.TypeFlags.TypeVariable) { + function getInferenceInfoForType(type: Type) { + if (type.flags & TypeFlags.TypeVariable) { for (const inference of inferences) { if (type === inference.typeParameter) { return inference; @@ -23004,10 +23202,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getSingleTypeVariableFromIntersectionTypes(types: ts.Type[]) { - let typeVariable: ts.Type | undefined; + function getSingleTypeVariableFromIntersectionTypes(types: Type[]) { + let typeVariable: Type | undefined; for (const type of types) { - const t = type.flags & ts.TypeFlags.Intersection && ts.find((type as ts.IntersectionType).types, t => !!getInferenceInfoForType(t)); + const t = type.flags & TypeFlags.Intersection && find((type as IntersectionType).types, t => !!getInferenceInfoForType(t)); if (!t || typeVariable && t !== typeVariable) { return undefined; } @@ -23016,11 +23214,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeVariable; } - function inferToMultipleTypes(source: ts.Type, targets: ts.Type[], targetFlags: ts.TypeFlags) { + function inferToMultipleTypes(source: Type, targets: Type[], targetFlags: TypeFlags) { let typeVariableCount = 0; - if (targetFlags & ts.TypeFlags.Union) { - let nakedTypeVariable: ts.Type | undefined; - const sources = source.flags & ts.TypeFlags.Union ? (source as ts.UnionType).types : [source]; + if (targetFlags & TypeFlags.Union) { + let nakedTypeVariable: Type | undefined; + const sources = source.flags & TypeFlags.Union ? (source as UnionType).types : [source]; const matched = new Array(sources.length); let inferenceCircularity = false; // First infer to types that are not naked type variables. For each source type we @@ -23035,10 +23233,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { for (let i = 0; i < sources.length; i++) { const saveInferencePriority = inferencePriority; - inferencePriority = ts.InferencePriority.MaxValue; + inferencePriority = InferencePriority.MaxValue; inferFromTypes(sources[i], t); if (inferencePriority === priority) matched[i] = true; - inferenceCircularity = inferenceCircularity || inferencePriority === ts.InferencePriority.Circularity; + inferenceCircularity = inferenceCircularity || inferencePriority === InferencePriority.Circularity; inferencePriority = Math.min(inferencePriority, saveInferencePriority); } } @@ -23049,7 +23247,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // 'A | B' to 'T & (X | Y)' where we want to infer 'A | B' for T. const intersectionTypeVariable = getSingleTypeVariableFromIntersectionTypes(targets); if (intersectionTypeVariable) { - inferWithPriority(source, intersectionTypeVariable, ts.InferencePriority.NakedTypeVariable); + inferWithPriority(source, intersectionTypeVariable, InferencePriority.NakedTypeVariable); } return; } @@ -23058,7 +23256,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // types from which no inferences have been made so far and infer from that union to the // naked type variable. if (typeVariableCount === 1 && !inferenceCircularity) { - const unmatched = ts.flatMap(sources, (s, i) => matched[i] ? undefined : s); + const unmatched = flatMap(sources, (s, i) => matched[i] ? undefined : s); if (unmatched.length) { inferFromTypes(getUnionType(unmatched), nakedTypeVariable!); return; @@ -23082,47 +23280,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // less specific. For example, when inferring from Promise to T | Promise, // we want to infer string for T, not Promise | string. For intersection types // we only infer to single naked type variables. - if (targetFlags & ts.TypeFlags.Intersection ? typeVariableCount === 1 : typeVariableCount > 0) { + if (targetFlags & TypeFlags.Intersection ? typeVariableCount === 1 : typeVariableCount > 0) { for (const t of targets) { if (getInferenceInfoForType(t)) { - inferWithPriority(source, t, ts.InferencePriority.NakedTypeVariable); + inferWithPriority(source, t, InferencePriority.NakedTypeVariable); } } } } - function inferToMappedType(source: ts.Type, target: ts.MappedType, constraintType: ts.Type): boolean { - if (constraintType.flags & ts.TypeFlags.Union) { + function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean { + if (constraintType.flags & TypeFlags.Union) { let result = false; - for (const type of (constraintType as ts.UnionType).types) { + for (const type of (constraintType as UnionType).types) { result = inferToMappedType(source, target, type) || result; } return result; } - if (constraintType.flags & ts.TypeFlags.Index) { + if (constraintType.flags & TypeFlags.Index) { // We're inferring from some source type S to a homomorphic mapped type { [P in keyof T]: X }, // where T is a type variable. Use inferTypeForHomomorphicMappedType to infer a suitable source // type and then make a secondary inference from that type to T. We make a secondary inference // such that direct inferences to T get priority over inferences to Partial, for example. - const inference = getInferenceInfoForType((constraintType as ts.IndexType).type); + const inference = getInferenceInfoForType((constraintType as IndexType).type); if (inference && !inference.isFixed && !isFromInferenceBlockedSource(source)) { - const inferredType = inferTypeForHomomorphicMappedType(source, target, constraintType as ts.IndexType); + const inferredType = inferTypeForHomomorphicMappedType(source, target, constraintType as IndexType); if (inferredType) { // We assign a lower priority to inferences made from types containing non-inferrable // types because we may only have a partial result (i.e. we may have failed to make // reverse inferences for some properties). inferWithPriority(inferredType, inference.typeParameter, - ts.getObjectFlags(source) & ts.ObjectFlags.NonInferrableType ? - ts.InferencePriority.PartialHomomorphicMappedType : - ts.InferencePriority.HomomorphicMappedType); + getObjectFlags(source) & ObjectFlags.NonInferrableType ? + InferencePriority.PartialHomomorphicMappedType : + InferencePriority.HomomorphicMappedType); } } return true; } - if (constraintType.flags & ts.TypeFlags.TypeParameter) { + if (constraintType.flags & TypeFlags.TypeParameter) { // We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type // parameter. First infer from 'keyof S' to K. - inferWithPriority(getIndexType(source), constraintType, ts.InferencePriority.MappedTypeConstraint); + inferWithPriority(getIndexType(source), constraintType, InferencePriority.MappedTypeConstraint); // If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X }, // where K extends keyof T, we make the same inferences as for a homomorphic mapped type // { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a @@ -23133,28 +23331,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // If no inferences can be made to K's constraint, infer from a union of the property types // in the source to the template type X. - const propTypes = ts.map(getPropertiesOfType(source), getTypeOfSymbol); - const indexTypes = ts.map(getIndexInfosOfType(source), info => info !== enumNumberIndexInfo ? info.type : neverType); - inferFromTypes(getUnionType(ts.concatenate(propTypes, indexTypes)), getTemplateTypeFromMappedType(target)); + const propTypes = map(getPropertiesOfType(source), getTypeOfSymbol); + const indexTypes = map(getIndexInfosOfType(source), info => info !== enumNumberIndexInfo ? info.type : neverType); + inferFromTypes(getUnionType(concatenate(propTypes, indexTypes)), getTemplateTypeFromMappedType(target)); return true; } return false; } - function inferToConditionalType(source: ts.Type, target: ts.ConditionalType) { - if (source.flags & ts.TypeFlags.Conditional) { - inferFromTypes((source as ts.ConditionalType).checkType, target.checkType); - inferFromTypes((source as ts.ConditionalType).extendsType, target.extendsType); - inferFromTypes(getTrueTypeFromConditionalType(source as ts.ConditionalType), getTrueTypeFromConditionalType(target)); - inferFromTypes(getFalseTypeFromConditionalType(source as ts.ConditionalType), getFalseTypeFromConditionalType(target)); + function inferToConditionalType(source: Type, target: ConditionalType) { + if (source.flags & TypeFlags.Conditional) { + inferFromTypes((source as ConditionalType).checkType, target.checkType); + inferFromTypes((source as ConditionalType).extendsType, target.extendsType); + inferFromTypes(getTrueTypeFromConditionalType(source as ConditionalType), getTrueTypeFromConditionalType(target)); + inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target)); } else { const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; - inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? ts.InferencePriority.ContravariantConditional : 0); + inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0); } } - function inferToTemplateLiteralType(source: ts.Type, target: ts.TemplateLiteralType) { + function inferToTemplateLiteralType(source: Type, target: TemplateLiteralType) { const matches = inferTypesFromTemplateLiteralType(source, target); const types = target.types; // When the target template literal contains only placeholders (meaning that inference is intended to extract @@ -23163,54 +23361,54 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // assignment check will fail. If we make no inferences, we'll likely end up with the constraint 'string' which, // upon instantiation, would collapse all the placeholders to just 'string', and an assignment check might // succeed. That would be a pointless and confusing outcome. - if (matches || ts.every(target.texts, s => s.length === 0)) { + if (matches || every(target.texts, s => s.length === 0)) { for (let i = 0; i < types.length; i++) { const source = matches ? matches[i] : neverType; const target = types[i]; // If we are inferring from a string literal type to a type variable whose constraint includes one of the // allowed template literal placeholder types, infer from a literal type corresponding to the constraint. - if (source.flags & ts.TypeFlags.StringLiteral && target.flags & ts.TypeFlags.TypeVariable) { + if (source.flags & TypeFlags.StringLiteral && target.flags & TypeFlags.TypeVariable) { const inferenceContext = getInferenceInfoForType(target); const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined; if (constraint && !isTypeAny(constraint)) { - const constraintTypes = constraint.flags & ts.TypeFlags.Union ? (constraint as ts.UnionType).types : [constraint]; - let allTypeFlags: ts.TypeFlags = ts.reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as ts.TypeFlags); + const constraintTypes = constraint.flags & TypeFlags.Union ? (constraint as UnionType).types : [constraint]; + let allTypeFlags: TypeFlags = reduceLeft(constraintTypes, (flags, t) => flags | t.flags, 0 as TypeFlags); // If the constraint contains `string`, we don't need to look for a more preferred type - if (!(allTypeFlags & ts.TypeFlags.String)) { - const str = (source as ts.StringLiteralType).value; + if (!(allTypeFlags & TypeFlags.String)) { + const str = (source as StringLiteralType).value; // If the type contains `number` or a number literal and the string isn't a valid number, exclude numbers - if (allTypeFlags & ts.TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) { - allTypeFlags &= ~ts.TypeFlags.NumberLike; + if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) { + allTypeFlags &= ~TypeFlags.NumberLike; } // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints - if (allTypeFlags & ts.TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) { - allTypeFlags &= ~ts.TypeFlags.BigIntLike; + if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) { + allTypeFlags &= ~TypeFlags.BigIntLike; } // for each type in the constraint, find the highest priority matching type - const matchingType = ts.reduceLeft(constraintTypes, (left, right) => + const matchingType = reduceLeft(constraintTypes, (left, right) => !(right.flags & allTypeFlags) ? left : - left.flags & ts.TypeFlags.String ? left : right.flags & ts.TypeFlags.String ? source : - left.flags & ts.TypeFlags.TemplateLiteral ? left : right.flags & ts.TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as ts.TemplateLiteralType) ? source : - left.flags & ts.TypeFlags.StringMapping ? left : right.flags & ts.TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source : - left.flags & ts.TypeFlags.StringLiteral ? left : right.flags & ts.TypeFlags.StringLiteral && (right as ts.StringLiteralType).value === str ? right : - left.flags & ts.TypeFlags.Number ? left : right.flags & ts.TypeFlags.Number ? getNumberLiteralType(+str) : - left.flags & ts.TypeFlags.Enum ? left : right.flags & ts.TypeFlags.Enum ? getNumberLiteralType(+str) : - left.flags & ts.TypeFlags.NumberLiteral ? left : right.flags & ts.TypeFlags.NumberLiteral && (right as ts.NumberLiteralType).value === +str ? right : - left.flags & ts.TypeFlags.BigInt ? left : right.flags & ts.TypeFlags.BigInt ? parseBigIntLiteralType(str) : - left.flags & ts.TypeFlags.BigIntLiteral ? left : right.flags & ts.TypeFlags.BigIntLiteral && ts.pseudoBigIntToString((right as ts.BigIntLiteralType).value) === str ? right : - left.flags & ts.TypeFlags.Boolean ? left : right.flags & ts.TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType : - left.flags & ts.TypeFlags.BooleanLiteral ? left : right.flags & ts.TypeFlags.BooleanLiteral && (right as ts.IntrinsicType).intrinsicName === str ? right : - left.flags & ts.TypeFlags.Undefined ? left : right.flags & ts.TypeFlags.Undefined && (right as ts.IntrinsicType).intrinsicName === str ? right : - left.flags & ts.TypeFlags.Null ? left : right.flags & ts.TypeFlags.Null && (right as ts.IntrinsicType).intrinsicName === str ? right : + left.flags & TypeFlags.String ? left : right.flags & TypeFlags.String ? source : + left.flags & TypeFlags.TemplateLiteral ? left : right.flags & TypeFlags.TemplateLiteral && isTypeMatchedByTemplateLiteralType(source, right as TemplateLiteralType) ? source : + left.flags & TypeFlags.StringMapping ? left : right.flags & TypeFlags.StringMapping && str === applyStringMapping(right.symbol, str) ? source : + left.flags & TypeFlags.StringLiteral ? left : right.flags & TypeFlags.StringLiteral && (right as StringLiteralType).value === str ? right : + left.flags & TypeFlags.Number ? left : right.flags & TypeFlags.Number ? getNumberLiteralType(+str) : + left.flags & TypeFlags.Enum ? left : right.flags & TypeFlags.Enum ? getNumberLiteralType(+str) : + left.flags & TypeFlags.NumberLiteral ? left : right.flags & TypeFlags.NumberLiteral && (right as NumberLiteralType).value === +str ? right : + left.flags & TypeFlags.BigInt ? left : right.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : + left.flags & TypeFlags.BigIntLiteral ? left : right.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((right as BigIntLiteralType).value) === str ? right : + left.flags & TypeFlags.Boolean ? left : right.flags & TypeFlags.Boolean ? str === "true" ? trueType : str === "false" ? falseType : booleanType : + left.flags & TypeFlags.BooleanLiteral ? left : right.flags & TypeFlags.BooleanLiteral && (right as IntrinsicType).intrinsicName === str ? right : + left.flags & TypeFlags.Undefined ? left : right.flags & TypeFlags.Undefined && (right as IntrinsicType).intrinsicName === str ? right : + left.flags & TypeFlags.Null ? left : right.flags & TypeFlags.Null && (right as IntrinsicType).intrinsicName === str ? right : left, - neverType as ts.Type); + neverType as Type); - if (!(matchingType.flags & ts.TypeFlags.Never)) { + if (!(matchingType.flags & TypeFlags.Never)) { inferFromTypes(matchingType, target); continue; } @@ -23223,11 +23421,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function inferFromObjectTypes(source: ts.Type, target: ts.Type) { - if (ts.getObjectFlags(source) & ts.ObjectFlags.Reference && ts.getObjectFlags(target) & ts.ObjectFlags.Reference && ( - (source as ts.TypeReference).target === (target as ts.TypeReference).target || isArrayType(source) && isArrayType(target))) { + function inferFromObjectTypes(source: Type, target: Type) { + if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && ( + (source as TypeReference).target === (target as TypeReference).target || isArrayType(source) && isArrayType(target))) { // If source and target are references to the same generic type, infer from type arguments - inferFromTypeArguments(getTypeArguments(source as ts.TypeReference), getTypeArguments(target as ts.TypeReference), getVariances((source as ts.TypeReference).target)); + inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); return; } if (isGenericMappedType(source) && isGenericMappedType(target)) { @@ -23239,9 +23437,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const targetNameType = getNameTypeFromMappedType(target); if (sourceNameType && targetNameType) inferFromTypes(sourceNameType, targetNameType); } - if (ts.getObjectFlags(target) & ts.ObjectFlags.Mapped && !(target as ts.MappedType).declaration.nameType) { - const constraintType = getConstraintTypeFromMappedType(target as ts.MappedType); - if (inferToMappedType(source, target as ts.MappedType, constraintType)) { + if (getObjectFlags(target) & ObjectFlags.Mapped && !(target as MappedType).declaration.nameType) { + const constraintType = getConstraintTypeFromMappedType(target as MappedType); + if (inferToMappedType(source, target as MappedType, constraintType)) { return; } } @@ -23262,22 +23460,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } const startLength = isTupleType(source) ? Math.min(source.target.fixedLength, target.target.fixedLength) : 0; - const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ts.ElementFlags.Fixed) : 0, - target.target.hasRestElement ? getEndElementCount(target.target, ts.ElementFlags.Fixed) : 0); + const endLength = Math.min(isTupleType(source) ? getEndElementCount(source.target, ElementFlags.Fixed) : 0, + target.target.hasRestElement ? getEndElementCount(target.target, ElementFlags.Fixed) : 0); // Infer between starting fixed elements. for (let i = 0; i < startLength; i++) { inferFromTypes(getTypeArguments(source)[i], elementTypes[i]); } - if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ts.ElementFlags.Rest) { + if (!isTupleType(source) || sourceArity - startLength - endLength === 1 && source.target.elementFlags[startLength] & ElementFlags.Rest) { // Single rest element remains in source, infer from that to every element in target const restType = getTypeArguments(source)[startLength]; for (let i = startLength; i < targetArity - endLength; i++) { - inferFromTypes(elementFlags[i] & ts.ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]); + inferFromTypes(elementFlags[i] & ElementFlags.Variadic ? createArrayType(restType) : restType, elementTypes[i]); } } else { const middleLength = targetArity - startLength - endLength; - if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ts.ElementFlags.Variadic && isTupleType(source)) { + if (middleLength === 2 && elementFlags[startLength] & elementFlags[startLength + 1] & ElementFlags.Variadic && isTupleType(source)) { // Middle of target is [...T, ...U] and source is tuple type const targetInfo = getInferenceInfoForType(elementTypes[startLength]); if (targetInfo && targetInfo.impliedArity !== undefined) { @@ -23286,14 +23484,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { inferFromTypes(sliceTupleType(source, startLength + targetInfo.impliedArity, endLength), elementTypes[startLength + 1]); } } - else if (middleLength === 1 && elementFlags[startLength] & ts.ElementFlags.Variadic) { + else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Variadic) { // Middle of target is exactly one variadic element. Infer the slice between the fixed parts in the source. // If target ends in optional element(s), make a lower priority a speculative inference. - const endsInOptional = target.target.elementFlags[targetArity - 1] & ts.ElementFlags.Optional; + const endsInOptional = target.target.elementFlags[targetArity - 1] & ElementFlags.Optional; const sourceSlice = isTupleType(source) ? sliceTupleType(source, startLength, endLength) : createArrayType(getTypeArguments(source)[0]); - inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? ts.InferencePriority.SpeculativeTuple : 0); + inferWithPriority(sourceSlice, elementTypes[startLength], endsInOptional ? InferencePriority.SpeculativeTuple : 0); } - else if (middleLength === 1 && elementFlags[startLength] & ts.ElementFlags.Rest) { + else if (middleLength === 1 && elementFlags[startLength] & ElementFlags.Rest) { // Middle of target is exactly one rest element. If middle of source is not empty, infer union of middle element types. const restType = isTupleType(source) ? getElementTypeOfSliceOfTupleType(source, startLength, endLength) : getTypeArguments(source)[0]; if (restType) { @@ -23313,23 +23511,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } inferFromProperties(source, target); - inferFromSignatures(source, target, ts.SignatureKind.Call); - inferFromSignatures(source, target, ts.SignatureKind.Construct); + inferFromSignatures(source, target, SignatureKind.Call); + inferFromSignatures(source, target, SignatureKind.Construct); inferFromIndexTypes(source, target); } } - function inferFromProperties(source: ts.Type, target: ts.Type) { + function inferFromProperties(source: Type, target: Type) { const properties = getPropertiesOfObjectType(target); for (const targetProp of properties) { const sourceProp = getPropertyOfType(source, targetProp.escapedName); - if (sourceProp && !ts.some(sourceProp.declarations, hasSkipDirectInferenceFlag)) { + if (sourceProp && !some(sourceProp.declarations, hasSkipDirectInferenceFlag)) { inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp)); } } } - function inferFromSignatures(source: ts.Type, target: ts.Type, kind: ts.SignatureKind) { + function inferFromSignatures(source: Type, target: Type, kind: SignatureKind) { const sourceSignatures = getSignaturesOfType(source, kind); const targetSignatures = getSignaturesOfType(target, kind); const sourceLen = sourceSignatures.length; @@ -23340,27 +23538,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function inferFromSignature(source: ts.Signature, target: ts.Signature) { + function inferFromSignature(source: Signature, target: Signature) { const saveBivariant = bivariant; - const kind = target.declaration ? target.declaration.kind : ts.SyntaxKind.Unknown; + const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; // Once we descend into a bivariant signature we remain bivariant for all nested inferences - bivariant = bivariant || kind === ts.SyntaxKind.MethodDeclaration || kind === ts.SyntaxKind.MethodSignature || kind === ts.SyntaxKind.Constructor; + bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor; applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes); bivariant = saveBivariant; applyToReturnTypes(source, target, inferFromTypes); } - function inferFromIndexTypes(source: ts.Type, target: ts.Type) { + function inferFromIndexTypes(source: Type, target: Type) { // Inferences across mapped type index signatures are pretty much the same a inferences to homomorphic variables - const priority = (ts.getObjectFlags(source) & ts.getObjectFlags(target) & ts.ObjectFlags.Mapped) ? ts.InferencePriority.HomomorphicMappedType : 0; + const priority = (getObjectFlags(source) & getObjectFlags(target) & ObjectFlags.Mapped) ? InferencePriority.HomomorphicMappedType : 0; const indexInfos = getIndexInfosOfType(target); if (isObjectTypeWithInferableIndex(source)) { for (const targetInfo of indexInfos) { - const propTypes: ts.Type[] = []; + const propTypes: Type[] = []; for (const prop of getPropertiesOfType(source)) { - if (isApplicableIndexType(getLiteralTypeFromProperty(prop, ts.TypeFlags.StringOrNumberLiteralOrUnique), targetInfo.keyType)) { + if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), targetInfo.keyType)) { const propType = getTypeOfSymbol(prop); - propTypes.push(prop.flags & ts.SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType); + propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType); } } for (const info of getIndexInfosOfType(source)) { @@ -23382,45 +23580,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isTypeOrBaseIdenticalTo(s: ts.Type, t: ts.Type) { + function isTypeOrBaseIdenticalTo(s: Type, t: Type) { return exactOptionalPropertyTypes && t === missingType ? s === t : - (isTypeIdenticalTo(s, t) || !!(t.flags & ts.TypeFlags.String && s.flags & ts.TypeFlags.StringLiteral || t.flags & ts.TypeFlags.Number && s.flags & ts.TypeFlags.NumberLiteral)); + (isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral)); } - function isTypeCloselyMatchedBy(s: ts.Type, t: ts.Type) { - return !!(s.flags & ts.TypeFlags.Object && t.flags & ts.TypeFlags.Object && s.symbol && s.symbol === t.symbol || + function isTypeCloselyMatchedBy(s: Type, t: Type) { + return !!(s.flags & TypeFlags.Object && t.flags & TypeFlags.Object && s.symbol && s.symbol === t.symbol || s.aliasSymbol && s.aliasTypeArguments && s.aliasSymbol === t.aliasSymbol); } - function hasPrimitiveConstraint(type: ts.TypeParameter): boolean { + function hasPrimitiveConstraint(type: TypeParameter): boolean { const constraint = getConstraintOfTypeParameter(type); - return !!constraint && maybeTypeOfKind(constraint.flags & ts.TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ts.ConditionalType) : constraint, ts.TypeFlags.Primitive | ts.TypeFlags.Index | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping); + return !!constraint && maybeTypeOfKind(constraint.flags & TypeFlags.Conditional ? getDefaultConstraintOfConditionalType(constraint as ConditionalType) : constraint, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping); } - function isObjectLiteralType(type: ts.Type) { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.ObjectLiteral); + function isObjectLiteralType(type: Type) { + return !!(getObjectFlags(type) & ObjectFlags.ObjectLiteral); } - function isObjectOrArrayLiteralType(type: ts.Type) { - return !!(ts.getObjectFlags(type) & (ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ArrayLiteral)); + function isObjectOrArrayLiteralType(type: Type) { + return !!(getObjectFlags(type) & (ObjectFlags.ObjectLiteral | ObjectFlags.ArrayLiteral)); } - function unionObjectAndArrayLiteralCandidates(candidates: ts.Type[]): ts.Type[] { + function unionObjectAndArrayLiteralCandidates(candidates: Type[]): Type[] { if (candidates.length > 1) { - const objectLiterals = ts.filter(candidates, isObjectOrArrayLiteralType); + const objectLiterals = filter(candidates, isObjectOrArrayLiteralType); if (objectLiterals.length) { - const literalsType = getUnionType(objectLiterals, ts.UnionReduction.Subtype); - return ts.concatenate(ts.filter(candidates, t => !isObjectOrArrayLiteralType(t)), [literalsType]); + const literalsType = getUnionType(objectLiterals, UnionReduction.Subtype); + return concatenate(filter(candidates, t => !isObjectOrArrayLiteralType(t)), [literalsType]); } } return candidates; } - function getContravariantInference(inference: ts.InferenceInfo) { - return inference.priority! & ts.InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!); + function getContravariantInference(inference: InferenceInfo) { + return inference.priority! & InferencePriority.PriorityImpliesCombination ? getIntersectionType(inference.contraCandidates!) : getCommonSubtype(inference.contraCandidates!); } - function getCovariantInference(inference: ts.InferenceInfo, signature: ts.Signature) { + function getCovariantInference(inference: InferenceInfo, signature: Signature) { // Extract all object and array literal types and replace them with a single widened and normalized type. const candidates = unionObjectAndArrayLiteralCandidates(inference.candidates!); // We widen inferred literal types if @@ -23430,35 +23628,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter); const widenLiteralTypes = !primitiveConstraint && inference.topLevel && (inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter)); - const baseCandidates = primitiveConstraint ? ts.sameMap(candidates, getRegularTypeOfLiteralType) : - widenLiteralTypes ? ts.sameMap(candidates, getWidenedLiteralType) : + const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) : + widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates; // If all inferences were made from a position that implies a combined result, infer a union type. // Otherwise, infer a common supertype. - const unwidenedType = inference.priority! & ts.InferencePriority.PriorityImpliesCombination ? - getUnionType(baseCandidates, ts.UnionReduction.Subtype) : + const unwidenedType = inference.priority! & InferencePriority.PriorityImpliesCombination ? + getUnionType(baseCandidates, UnionReduction.Subtype) : getCommonSupertype(baseCandidates); return getWidenedType(unwidenedType); } - function getInferredType(context: ts.InferenceContext, index: number): ts.Type { + function getInferredType(context: InferenceContext, index: number): Type { const inference = context.inferences[index]; if (!inference.inferredType) { - let inferredType: ts.Type | undefined; + let inferredType: Type | undefined; const signature = context.signature; if (signature) { const inferredCovariantType = inference.candidates ? getCovariantInference(inference, signature) : undefined; if (inference.contraCandidates) { // If we have both co- and contra-variant inferences, we prefer the contra-variant inference // unless the co-variant inference is a subtype of some contra-variant inference and not 'never'. - inferredType = inferredCovariantType && !(inferredCovariantType.flags & ts.TypeFlags.Never) && - ts.some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) ? + inferredType = inferredCovariantType && !(inferredCovariantType.flags & TypeFlags.Never) && + some(inference.contraCandidates, t => isTypeSubtypeOf(inferredCovariantType, t)) ? inferredCovariantType : getContravariantInference(inference); } else if (inferredCovariantType) { inferredType = inferredCovariantType; } - else if (context.flags & ts.InferenceFlags.NoDefault) { + else if (context.flags & InferenceFlags.NoDefault) { // We use silentNeverType as the wildcard that signals no inferences. inferredType = silentNeverType; } @@ -23480,7 +23678,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { inferredType = getTypeFromInference(inference); } - inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & ts.InferenceFlags.AnyDefault)); + inference.inferredType = inferredType || getDefaultTypeArgumentType(!!(context.flags & InferenceFlags.AnyDefault)); const constraint = getConstraintOfTypeParameter(inference.typeParameter); if (constraint) { @@ -23494,12 +23692,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return inference.inferredType; } - function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): ts.Type { + function getDefaultTypeArgumentType(isInJavaScriptFile: boolean): Type { return isInJavaScriptFile ? anyType : unknownType; } - function getInferredTypes(context: ts.InferenceContext): ts.Type[] { - const result: ts.Type[] = []; + function getInferredTypes(context: InferenceContext): Type[] { + const result: Type[] = []; for (let i = 0; i < context.inferences.length; i++) { result.push(getInferredType(context, i)); } @@ -23508,29 +23706,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // EXPRESSION TYPE CHECKING - function getCannotFindNameDiagnosticForName(node: ts.Identifier): ts.DiagnosticMessage { + function getCannotFindNameDiagnosticForName(node: Identifier): DiagnosticMessage { switch (node.escapedText) { case "document": case "console": - return ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom; + return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_include_dom; case "$": return compilerOptions.types - ? ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery_and_then_add_jquery_to_the_types_field_in_your_tsconfig - : ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery; + ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery_and_then_add_jquery_to_the_types_field_in_your_tsconfig + : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_jQuery_Try_npm_i_save_dev_types_Slashjquery; case "describe": case "suite": case "it": case "test": return compilerOptions.types - ? ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha_and_then_add_jest_or_mocha_to_the_types_field_in_your_tsconfig - : ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha; + ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha_and_then_add_jest_or_mocha_to_the_types_field_in_your_tsconfig + : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_a_test_runner_Try_npm_i_save_dev_types_Slashjest_or_npm_i_save_dev_types_Slashmocha; case "process": case "require": case "Buffer": case "module": return compilerOptions.types - ? ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode_and_then_add_node_to_the_types_field_in_your_tsconfig - : ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode; + ? Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode_and_then_add_node_to_the_types_field_in_your_tsconfig + : Diagnostics.Cannot_find_name_0_Do_you_need_to_install_type_definitions_for_node_Try_npm_i_save_dev_types_Slashnode; case "Map": case "Set": case "Promise": @@ -23549,160 +23747,160 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { case "Reflect": case "BigInt64Array": case "BigUint64Array": - return ts.Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_1_or_later; + return Diagnostics.Cannot_find_name_0_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_1_or_later; case "await": - if (ts.isCallExpression(node.parent)) { - return ts.Diagnostics.Cannot_find_name_0_Did_you_mean_to_write_this_in_an_async_function; + if (isCallExpression(node.parent)) { + return Diagnostics.Cannot_find_name_0_Did_you_mean_to_write_this_in_an_async_function; } // falls through default: - if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { - return ts.Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer; + if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { + return Diagnostics.No_value_exists_in_scope_for_the_shorthand_property_0_Either_declare_one_or_provide_an_initializer; } else { - return ts.Diagnostics.Cannot_find_name_0; + return Diagnostics.Cannot_find_name_0; } } } - function getResolvedSymbol(node: ts.Identifier): ts.Symbol { + function getResolvedSymbol(node: Identifier): Symbol { const links = getNodeLinks(node); if (!links.resolvedSymbol) { - links.resolvedSymbol = !ts.nodeIsMissing(node) && + links.resolvedSymbol = !nodeIsMissing(node) && resolveName( node, node.escapedText, - ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue, + SymbolFlags.Value | SymbolFlags.ExportValue, getCannotFindNameDiagnosticForName(node), node, - !ts.isWriteOnlyAccess(node), + !isWriteOnlyAccess(node), /*excludeGlobals*/ false) || unknownSymbol; } return links.resolvedSymbol; } - function isInTypeQuery(node: ts.Node): boolean { + function isInTypeQuery(node: Node): boolean { // TypeScript 1.0 spec (April 2014): 3.6.3 // A type query consists of the keyword typeof followed by an expression. // The expression is restricted to a single identifier or a sequence of identifiers separated by periods - return !!ts.findAncestor( + return !!findAncestor( node, - n => n.kind === ts.SyntaxKind.TypeQuery ? true : n.kind === ts.SyntaxKind.Identifier || n.kind === ts.SyntaxKind.QualifiedName ? false : "quit"); + n => n.kind === SyntaxKind.TypeQuery ? true : n.kind === SyntaxKind.Identifier || n.kind === SyntaxKind.QualifiedName ? false : "quit"); } // Return the flow cache key for a "dotted name" (i.e. a sequence of identifiers // separated by dots). The key consists of the id of the symbol referenced by the // leftmost identifier followed by zero or more property names separated by dots. // The result is undefined if the reference isn't a dotted name. - function getFlowCacheKey(node: ts.Node, declaredType: ts.Type, initialType: ts.Type, flowContainer: ts.Node | undefined): string | undefined { + function getFlowCacheKey(node: Node, declaredType: Type, initialType: Type, flowContainer: Node | undefined): string | undefined { switch (node.kind) { - case ts.SyntaxKind.Identifier: - if (!ts.isThisInTypeQuery(node)) { - const symbol = getResolvedSymbol(node as ts.Identifier); + case SyntaxKind.Identifier: + if (!isThisInTypeQuery(node)) { + const symbol = getResolvedSymbol(node as Identifier); return symbol !== unknownSymbol ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}|${getSymbolId(symbol)}` : undefined; } // falls through - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.ThisKeyword: return `0|${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}`; - case ts.SyntaxKind.NonNullExpression: - case ts.SyntaxKind.ParenthesizedExpression: - return getFlowCacheKey((node as ts.NonNullExpression | ts.ParenthesizedExpression).expression, declaredType, initialType, flowContainer); - case ts.SyntaxKind.QualifiedName: - const left = getFlowCacheKey((node as ts.QualifiedName).left, declaredType, initialType, flowContainer); - return left && left + "." + (node as ts.QualifiedName).right.escapedText; - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - const propName = getAccessedPropertyName(node as ts.AccessExpression); + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + return getFlowCacheKey((node as NonNullExpression | ParenthesizedExpression).expression, declaredType, initialType, flowContainer); + case SyntaxKind.QualifiedName: + const left = getFlowCacheKey((node as QualifiedName).left, declaredType, initialType, flowContainer); + return left && left + "." + (node as QualifiedName).right.escapedText; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const propName = getAccessedPropertyName(node as AccessExpression); if (propName !== undefined) { - const key = getFlowCacheKey((node as ts.AccessExpression).expression, declaredType, initialType, flowContainer); + const key = getFlowCacheKey((node as AccessExpression).expression, declaredType, initialType, flowContainer); return key && key + "." + propName; } break; - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: // Handle pseudo-references originating in getNarrowedTypeOfSymbol. return `${getNodeId(node)}#${getTypeId(declaredType)}`; } return undefined; } - function isMatchingReference(source: ts.Node, target: ts.Node): boolean { + function isMatchingReference(source: Node, target: Node): boolean { switch (target.kind) { - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.NonNullExpression: - return isMatchingReference(source, (target as ts.NonNullExpression | ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.BinaryExpression: - return (ts.isAssignmentExpression(target) && isMatchingReference(source, target.left)) || - (ts.isBinaryExpression(target) && target.operatorToken.kind === ts.SyntaxKind.CommaToken && isMatchingReference(source, target.right)); + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NonNullExpression: + return isMatchingReference(source, (target as NonNullExpression | ParenthesizedExpression).expression); + case SyntaxKind.BinaryExpression: + return (isAssignmentExpression(target) && isMatchingReference(source, target.left)) || + (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source, target.right)); } switch (source.kind) { - case ts.SyntaxKind.MetaProperty: - return target.kind === ts.SyntaxKind.MetaProperty - && (source as ts.MetaProperty).keywordToken === (target as ts.MetaProperty).keywordToken - && (source as ts.MetaProperty).name.escapedText === (target as ts.MetaProperty).name.escapedText; - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PrivateIdentifier: - return ts.isThisInTypeQuery(source) ? - target.kind === ts.SyntaxKind.ThisKeyword : - target.kind === ts.SyntaxKind.Identifier && getResolvedSymbol(source as ts.Identifier) === getResolvedSymbol(target as ts.Identifier) || - (target.kind === ts.SyntaxKind.VariableDeclaration || target.kind === ts.SyntaxKind.BindingElement) && - getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as ts.Identifier)) === getSymbolOfNode(target); - case ts.SyntaxKind.ThisKeyword: - return target.kind === ts.SyntaxKind.ThisKeyword; - case ts.SyntaxKind.SuperKeyword: - return target.kind === ts.SyntaxKind.SuperKeyword; - case ts.SyntaxKind.NonNullExpression: - case ts.SyntaxKind.ParenthesizedExpression: - return isMatchingReference((source as ts.NonNullExpression | ts.ParenthesizedExpression).expression, target); - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - const sourcePropertyName = getAccessedPropertyName(source as ts.AccessExpression); - const targetPropertyName = ts.isAccessExpression(target) ? getAccessedPropertyName(target) : undefined; + case SyntaxKind.MetaProperty: + return target.kind === SyntaxKind.MetaProperty + && (source as MetaProperty).keywordToken === (target as MetaProperty).keywordToken + && (source as MetaProperty).name.escapedText === (target as MetaProperty).name.escapedText; + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: + return isThisInTypeQuery(source) ? + target.kind === SyntaxKind.ThisKeyword : + target.kind === SyntaxKind.Identifier && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) || + (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) && + getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfNode(target); + case SyntaxKind.ThisKeyword: + return target.kind === SyntaxKind.ThisKeyword; + case SyntaxKind.SuperKeyword: + return target.kind === SyntaxKind.SuperKeyword; + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + return isMatchingReference((source as NonNullExpression | ParenthesizedExpression).expression, target); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const sourcePropertyName = getAccessedPropertyName(source as AccessExpression); + const targetPropertyName = isAccessExpression(target) ? getAccessedPropertyName(target) : undefined; return sourcePropertyName !== undefined && targetPropertyName !== undefined && targetPropertyName === sourcePropertyName && - isMatchingReference((source as ts.AccessExpression).expression, (target as ts.AccessExpression).expression); - case ts.SyntaxKind.QualifiedName: - return ts.isAccessExpression(target) && - (source as ts.QualifiedName).right.escapedText === getAccessedPropertyName(target) && - isMatchingReference((source as ts.QualifiedName).left, target.expression); - case ts.SyntaxKind.BinaryExpression: - return (ts.isBinaryExpression(source) && source.operatorToken.kind === ts.SyntaxKind.CommaToken && isMatchingReference(source.right, target)); + isMatchingReference((source as AccessExpression).expression, (target as AccessExpression).expression); + case SyntaxKind.QualifiedName: + return isAccessExpression(target) && + (source as QualifiedName).right.escapedText === getAccessedPropertyName(target) && + isMatchingReference((source as QualifiedName).left, target.expression); + case SyntaxKind.BinaryExpression: + return (isBinaryExpression(source) && source.operatorToken.kind === SyntaxKind.CommaToken && isMatchingReference(source.right, target)); } return false; } - function getAccessedPropertyName(access: ts.AccessExpression | ts.BindingElement | ts.ParameterDeclaration): ts.__String | undefined { - if (ts.isPropertyAccessExpression(access)) { + function getAccessedPropertyName(access: AccessExpression | BindingElement | ParameterDeclaration): __String | undefined { + if (isPropertyAccessExpression(access)) { return access.name.escapedText; } - if (ts.isElementAccessExpression(access)) { + if (isElementAccessExpression(access)) { return tryGetElementAccessExpressionName(access); } - if (ts.isBindingElement(access)) { + if (isBindingElement(access)) { const name = getDestructuringPropertyName(access); - return name ? ts.escapeLeadingUnderscores(name) : undefined; + return name ? escapeLeadingUnderscores(name) : undefined; } - if (ts.isParameter(access)) { - return ("" + access.parent.parameters.indexOf(access)) as ts.__String; + if (isParameter(access)) { + return ("" + access.parent.parameters.indexOf(access)) as __String; } return undefined; } - function tryGetNameFromType(type: ts.Type) { - return type.flags & ts.TypeFlags.UniqueESSymbol ? (type as ts.UniqueESSymbolType).escapedName : - type.flags & ts.TypeFlags.StringOrNumberLiteral ? ts.escapeLeadingUnderscores("" + (type as ts.StringLiteralType | ts.NumberLiteralType).value) : undefined; + function tryGetNameFromType(type: Type) { + return type.flags & TypeFlags.UniqueESSymbol ? (type as UniqueESSymbolType).escapedName : + type.flags & TypeFlags.StringOrNumberLiteral ? escapeLeadingUnderscores("" + (type as StringLiteralType | NumberLiteralType).value) : undefined; } - function tryGetElementAccessExpressionName(node: ts.ElementAccessExpression) { - if (ts.isStringOrNumericLiteralLike(node.argumentExpression)) { - return ts.escapeLeadingUnderscores(node.argumentExpression.text); + function tryGetElementAccessExpressionName(node: ElementAccessExpression) { + if (isStringOrNumericLiteralLike(node.argumentExpression)) { + return escapeLeadingUnderscores(node.argumentExpression.text); } - if (ts.isEntityNameExpression(node.argumentExpression)) { - const symbol = resolveEntityName(node.argumentExpression, ts.SymbolFlags.Value, /*ignoreErrors*/ true); - if (!symbol || !(isConstVariable(symbol) || (symbol.flags & ts.SymbolFlags.EnumMember))) return undefined; + if (isEntityNameExpression(node.argumentExpression)) { + const symbol = resolveEntityName(node.argumentExpression, SymbolFlags.Value, /*ignoreErrors*/ true); + if (!symbol || !(isConstVariable(symbol) || (symbol.flags & SymbolFlags.EnumMember))) return undefined; const declaration = symbol.valueDeclaration; if (declaration === undefined) return undefined; @@ -23715,21 +23913,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node.argumentExpression)) { - const initializer = ts.getEffectiveInitializer(declaration); + if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node.argumentExpression)) { + const initializer = getEffectiveInitializer(declaration); if (initializer) { return tryGetNameFromType(getTypeOfExpression(initializer)); } - if (ts.isEnumMember(declaration)) { - return ts.getTextOfPropertyName(declaration.name); + if (isEnumMember(declaration)) { + return getTextOfPropertyName(declaration.name); } } } return undefined; } - function containsMatchingReference(source: ts.Node, target: ts.Node) { - while (ts.isAccessExpression(source)) { + function containsMatchingReference(source: Node, target: Node) { + while (isAccessExpression(source)) { source = source.expression; if (isMatchingReference(source, target)) { return true; @@ -23738,8 +23936,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function optionalChainContainsReference(source: ts.Node, target: ts.Node) { - while (ts.isOptionalChain(source)) { + function optionalChainContainsReference(source: Node, target: Node) { + while (isOptionalChain(source)) { source = source.expression; if (isMatchingReference(source, target)) { return true; @@ -23748,23 +23946,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isDiscriminantProperty(type: ts.Type | undefined, name: ts.__String) { - if (type && type.flags & ts.TypeFlags.Union) { - const prop = getUnionOrIntersectionProperty(type as ts.UnionType, name); - if (prop && ts.getCheckFlags(prop) & ts.CheckFlags.SyntheticProperty) { - if ((prop as ts.TransientSymbol).isDiscriminantProperty === undefined) { - (prop as ts.TransientSymbol).isDiscriminantProperty = - ((prop as ts.TransientSymbol).checkFlags & ts.CheckFlags.Discriminant) === ts.CheckFlags.Discriminant && + function isDiscriminantProperty(type: Type | undefined, name: __String) { + if (type && type.flags & TypeFlags.Union) { + const prop = getUnionOrIntersectionProperty(type as UnionType, name); + if (prop && getCheckFlags(prop) & CheckFlags.SyntheticProperty) { + if ((prop as TransientSymbol).isDiscriminantProperty === undefined) { + (prop as TransientSymbol).isDiscriminantProperty = + ((prop as TransientSymbol).checkFlags & CheckFlags.Discriminant) === CheckFlags.Discriminant && !isGenericType(getTypeOfSymbol(prop)); } - return !!(prop as ts.TransientSymbol).isDiscriminantProperty; + return !!(prop as TransientSymbol).isDiscriminantProperty; } } return false; } - function findDiscriminantProperties(sourceProperties: ts.Symbol[], target: ts.Type): ts.Symbol[] | undefined { - let result: ts.Symbol[] | undefined; + function findDiscriminantProperties(sourceProperties: Symbol[], target: Type): Symbol[] | undefined { + let result: Symbol[] | undefined; for (const sourceProperty of sourceProperties) { if (isDiscriminantProperty(target, sourceProperty.escapedName)) { if (result) { @@ -23781,11 +23979,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // types of the property by that name in each constituent type. No map is returned if some key property // has a non-literal type or if less than 10 or less than 50% of the constituents have a unique key. // Entries with duplicate keys have unknownType as the value. - function mapTypesByKeyProperty(types: ts.Type[], name: ts.__String) { - const map = new ts.Map(); + function mapTypesByKeyProperty(types: Type[], name: __String) { + const map = new Map(); let count = 0; for (const type of types) { - if (type.flags & (ts.TypeFlags.Object | ts.TypeFlags.Intersection | ts.TypeFlags.InstantiableNonPrimitive)) { + if (type.flags & (TypeFlags.Object | TypeFlags.Intersection | TypeFlags.InstantiableNonPrimitive)) { const discriminant = getTypeOfPropertyOfType(type, name); if (discriminant) { if (!isLiteralType(discriminant)) { @@ -23812,22 +24010,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return the name of a discriminant property for which it was possible and feasible to construct a map of // constituent types keyed by the literal types of the property by that name in each constituent type. - function getKeyPropertyName(unionType: ts.UnionType): ts.__String | undefined { + function getKeyPropertyName(unionType: UnionType): __String | undefined { const types = unionType.types; // We only construct maps for unions with many non-primitive constituents. - if (types.length < 10 || ts.getObjectFlags(unionType) & ts.ObjectFlags.PrimitiveUnion || - ts.countWhere(types, t => !!(t.flags & (ts.TypeFlags.Object | ts.TypeFlags.InstantiableNonPrimitive))) < 10) { + if (types.length < 10 || getObjectFlags(unionType) & ObjectFlags.PrimitiveUnion || + countWhere(types, t => !!(t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive))) < 10) { return undefined; } if (unionType.keyPropertyName === undefined) { // The candidate key property name is the name of the first property with a unit type in one of the // constituent types. - const keyPropertyName = ts.forEach(types, t => - t.flags & (ts.TypeFlags.Object | ts.TypeFlags.InstantiableNonPrimitive) ? - ts.forEach(getPropertiesOfType(t), p => isUnitType(getTypeOfSymbol(p)) ? p.escapedName : undefined) : + const keyPropertyName = forEach(types, t => + t.flags & (TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) ? + forEach(getPropertiesOfType(t), p => isUnitType(getTypeOfSymbol(p)) ? p.escapedName : undefined) : undefined); const mapByKeyProperty = keyPropertyName && mapTypesByKeyProperty(types, keyPropertyName); - unionType.keyPropertyName = mapByKeyProperty ? keyPropertyName : "" as ts.__String; + unionType.keyPropertyName = mapByKeyProperty ? keyPropertyName : "" as __String; unionType.constituentMap = mapByKeyProperty; } return (unionType.keyPropertyName as string).length ? unionType.keyPropertyName : undefined; @@ -23835,30 +24033,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Given a union type for which getKeyPropertyName returned a non-undefined result, return the constituent // that corresponds to the given key type for that property name. - function getConstituentTypeForKeyType(unionType: ts.UnionType, keyType: ts.Type) { + function getConstituentTypeForKeyType(unionType: UnionType, keyType: Type) { const result = unionType.constituentMap?.get(getTypeId(getRegularTypeOfLiteralType(keyType))); return result !== unknownType ? result : undefined; } - function getMatchingUnionConstituentForType(unionType: ts.UnionType, type: ts.Type) { + function getMatchingUnionConstituentForType(unionType: UnionType, type: Type) { const keyPropertyName = getKeyPropertyName(unionType); const propType = keyPropertyName && getTypeOfPropertyOfType(type, keyPropertyName); return propType && getConstituentTypeForKeyType(unionType, propType); } - function getMatchingUnionConstituentForObjectLiteral(unionType: ts.UnionType, node: ts.ObjectLiteralExpression) { + function getMatchingUnionConstituentForObjectLiteral(unionType: UnionType, node: ObjectLiteralExpression) { const keyPropertyName = getKeyPropertyName(unionType); - const propNode = keyPropertyName && ts.find(node.properties, p => p.symbol && p.kind === ts.SyntaxKind.PropertyAssignment && + const propNode = keyPropertyName && find(node.properties, p => p.symbol && p.kind === SyntaxKind.PropertyAssignment && p.symbol.escapedName === keyPropertyName && isPossiblyDiscriminantValue(p.initializer)); - const propType = propNode && getContextFreeTypeOfExpression((propNode as ts.PropertyAssignment).initializer); + const propType = propNode && getContextFreeTypeOfExpression((propNode as PropertyAssignment).initializer); return propType && getConstituentTypeForKeyType(unionType, propType); } - function isOrContainsMatchingReference(source: ts.Node, target: ts.Node) { + function isOrContainsMatchingReference(source: Node, target: Node) { return isMatchingReference(source, target) || containsMatchingReference(source, target); } - function hasMatchingArgument(expression: ts.CallExpression | ts.NewExpression, reference: ts.Node) { + function hasMatchingArgument(expression: CallExpression | NewExpression, reference: Node) { if (expression.arguments) { for (const argument of expression.arguments) { if (isOrContainsMatchingReference(reference, argument)) { @@ -23866,14 +24064,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - if (expression.expression.kind === ts.SyntaxKind.PropertyAccessExpression && - isOrContainsMatchingReference(reference, (expression.expression as ts.PropertyAccessExpression).expression)) { + if (expression.expression.kind === SyntaxKind.PropertyAccessExpression && + isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression).expression)) { return true; } return false; } - function getFlowNodeId(flow: ts.FlowNode): number { + function getFlowNodeId(flow: FlowNode): number { if (!flow.id || flow.id < 0) { flow.id = nextFlowId; nextFlowId++; @@ -23881,11 +24079,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return flow.id; } - function typeMaybeAssignableTo(source: ts.Type, target: ts.Type) { - if (!(source.flags & ts.TypeFlags.Union)) { + function typeMaybeAssignableTo(source: Type, target: Type) { + if (!(source.flags & TypeFlags.Union)) { return isTypeAssignableTo(source, target); } - for (const t of (source as ts.UnionType).types) { + for (const t of (source as UnionType).types) { if (isTypeAssignableTo(t, target)) { return true; } @@ -23896,21 +24094,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Remove those constituent types of declaredType to which no constituent type of assignedType is assignable. // For example, when a variable of type number | string | boolean is assigned a value of type number | boolean, // we remove type string. - function getAssignmentReducedType(declaredType: ts.UnionType, assignedType: ts.Type) { + function getAssignmentReducedType(declaredType: UnionType, assignedType: Type) { if (declaredType === assignedType) { return declaredType; } - if (assignedType.flags & ts.TypeFlags.Never) { + if (assignedType.flags & TypeFlags.Never) { return assignedType; } const key = `A${getTypeId(declaredType)},${getTypeId(assignedType)}`; return getCachedType(key) ?? setCachedType(key, getAssignmentReducedTypeWorker(declaredType, assignedType)); } - function getAssignmentReducedTypeWorker(declaredType: ts.UnionType, assignedType: ts.Type) { + function getAssignmentReducedTypeWorker(declaredType: UnionType, assignedType: Type) { const filteredType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t)); // Ensure that we narrow to fresh types if the assignment is a fresh boolean literal type. - const reducedType = assignedType.flags & ts.TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType) ? mapType(filteredType, getFreshTypeOfLiteralType) : filteredType; + const reducedType = assignedType.flags & TypeFlags.BooleanLiteral && isFreshLiteralType(assignedType) ? mapType(filteredType, getFreshTypeOfLiteralType) : filteredType; // Our crude heuristic produces an invalid result in some cases: see GH#26130. // For now, when that happens, we give up and don't narrow at all. (This also // means we'll never narrow for erroneous assignments where the assigned type @@ -23918,98 +24116,98 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isTypeAssignableTo(assignedType, reducedType) ? reducedType : declaredType; } - function isFunctionObjectType(type: ts.ObjectType): boolean { + function isFunctionObjectType(type: ObjectType): boolean { // We do a quick check for a "bind" property before performing the more expensive subtype // check. This gives us a quicker out in the common case where an object type is not a function. const resolved = resolveStructuredTypeMembers(type); return !!(resolved.callSignatures.length || resolved.constructSignatures.length || - resolved.members.get("bind" as ts.__String) && isTypeSubtypeOf(type, globalFunctionType)); + resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); } - function getTypeFacts(type: ts.Type): TypeFacts { - if (type.flags & (ts.TypeFlags.Intersection | ts.TypeFlags.Instantiable)) { + function getTypeFacts(type: Type): TypeFacts { + if (type.flags & (TypeFlags.Intersection | TypeFlags.Instantiable)) { type = getBaseConstraintOfType(type) || unknownType; } const flags = type.flags; - if (flags & (ts.TypeFlags.String | ts.TypeFlags.StringMapping)) { + if (flags & (TypeFlags.String | TypeFlags.StringMapping)) { return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; } - if (flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral)) { - const isEmpty = flags & ts.TypeFlags.StringLiteral && (type as ts.StringLiteralType).value === ""; + if (flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral)) { + const isEmpty = flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === ""; return strictNullChecks ? isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } - if (flags & (ts.TypeFlags.Number | ts.TypeFlags.Enum)) { + if (flags & (TypeFlags.Number | TypeFlags.Enum)) { return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } - if (flags & ts.TypeFlags.NumberLiteral) { - const isZero = (type as ts.NumberLiteralType).value === 0; + if (flags & TypeFlags.NumberLiteral) { + const isZero = (type as NumberLiteralType).value === 0; return strictNullChecks ? isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts : isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts; } - if (flags & ts.TypeFlags.BigInt) { + if (flags & TypeFlags.BigInt) { return strictNullChecks ? TypeFacts.BigIntStrictFacts : TypeFacts.BigIntFacts; } - if (flags & ts.TypeFlags.BigIntLiteral) { - const isZero = isZeroBigInt(type as ts.BigIntLiteralType); + if (flags & TypeFlags.BigIntLiteral) { + const isZero = isZeroBigInt(type as BigIntLiteralType); return strictNullChecks ? isZero ? TypeFacts.ZeroBigIntStrictFacts : TypeFacts.NonZeroBigIntStrictFacts : isZero ? TypeFacts.ZeroBigIntFacts : TypeFacts.NonZeroBigIntFacts; } - if (flags & ts.TypeFlags.Boolean) { + if (flags & TypeFlags.Boolean) { return strictNullChecks ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts; } - if (flags & ts.TypeFlags.BooleanLike) { + if (flags & TypeFlags.BooleanLike) { return strictNullChecks ? (type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts : (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } - if (flags & ts.TypeFlags.Object) { - return ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous && isEmptyObjectType(type as ts.ObjectType) ? + if (flags & TypeFlags.Object) { + return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ? strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts : - isFunctionObjectType(type as ts.ObjectType) ? + isFunctionObjectType(type as ObjectType) ? strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } - if (flags & ts.TypeFlags.Void) { + if (flags & TypeFlags.Void) { return TypeFacts.VoidFacts; } - if (flags & ts.TypeFlags.Undefined) { + if (flags & TypeFlags.Undefined) { return TypeFacts.UndefinedFacts; } - if (flags & ts.TypeFlags.Null) { + if (flags & TypeFlags.Null) { return TypeFacts.NullFacts; } - if (flags & ts.TypeFlags.ESSymbolLike) { + if (flags & TypeFlags.ESSymbolLike) { return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts; } - if (flags & ts.TypeFlags.NonPrimitive) { + if (flags & TypeFlags.NonPrimitive) { return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } - if (flags & ts.TypeFlags.Never) { + if (flags & TypeFlags.Never) { return TypeFacts.None; } - if (flags & ts.TypeFlags.Union) { - return ts.reduceLeft((type as ts.UnionType).types, (facts, t) => facts | getTypeFacts(t), TypeFacts.None); + if (flags & TypeFlags.Union) { + return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t), TypeFacts.None); } - if (flags & ts.TypeFlags.Intersection) { - return getIntersectionTypeFacts(type as ts.IntersectionType); + if (flags & TypeFlags.Intersection) { + return getIntersectionTypeFacts(type as IntersectionType); } return TypeFacts.UnknownFacts; } - function getIntersectionTypeFacts(type: ts.IntersectionType): TypeFacts { + function getIntersectionTypeFacts(type: IntersectionType): TypeFacts { // When an intersection contains a primitive type we ignore object type constituents as they are // presumably type tags. For example, in string & { __kind__: "name" } we ignore the object type. - const ignoreObjects = maybeTypeOfKind(type, ts.TypeFlags.Primitive); + const ignoreObjects = maybeTypeOfKind(type, TypeFlags.Primitive); // When computing the type facts of an intersection type, certain type facts are computed as `and` // and others are computed as `or`. let oredFacts = TypeFacts.None; let andedFacts = TypeFacts.All; for (const t of type.types) { - if (!(ignoreObjects && t.flags & ts.TypeFlags.Object)) { + if (!(ignoreObjects && t.flags & TypeFlags.Object)) { const f = getTypeFacts(t); oredFacts |= f; andedFacts &= f; @@ -24018,21 +24216,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return oredFacts & TypeFacts.OrFactsMask | andedFacts & TypeFacts.AndFactsMask; } - function getTypeWithFacts(type: ts.Type, include: TypeFacts) { + function getTypeWithFacts(type: Type, include: TypeFacts) { return filterType(type, t => (getTypeFacts(t) & include) !== 0); } // This function is similar to getTypeWithFacts, except that in strictNullChecks mode it replaces type // unknown with the union {} | null | undefined (and reduces that accordingly), and it intersects remaining // instantiable types with {}, {} | null, or {} | undefined in order to remove null and/or undefined. - function getAdjustedTypeWithFacts(type: ts.Type, facts: TypeFacts) { - const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & ts.TypeFlags.Unknown ? unknownUnionType : type, facts)); + function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts) { + const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts)); if (strictNullChecks) { switch (facts) { case TypeFacts.NEUndefined: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, ts.TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t); + return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t); case TypeFacts.NENull: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, ts.TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t); + return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t); case TypeFacts.NEUndefinedOrNull: case TypeFacts.Truthy: return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t): t); @@ -24041,105 +24239,105 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return reduced; } - function recombineUnknownType(type: ts.Type) { + function recombineUnknownType(type: Type) { return type === unknownUnionType ? unknownType : type; } - function getTypeWithDefault(type: ts.Type, defaultExpression: ts.Expression) { + function getTypeWithDefault(type: Type, defaultExpression: Expression) { return defaultExpression ? getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) : type; } - function getTypeOfDestructuredProperty(type: ts.Type, name: ts.PropertyName) { + function getTypeOfDestructuredProperty(type: Type, name: PropertyName) { const nameType = getLiteralTypeFromPropertyName(name); if (!isTypeUsableAsPropertyName(nameType)) return errorType; const text = getPropertyNameFromType(nameType); return getTypeOfPropertyOfType(type, text) || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type) || errorType; } - function getTypeOfDestructuredArrayElement(type: ts.Type, index: number) { + function getTypeOfDestructuredArrayElement(type: Type, index: number) { return everyType(type, isTupleLikeType) && getTupleElementType(type, index) || includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || errorType; } - function includeUndefinedInIndexSignature(type: ts.Type | undefined): ts.Type | undefined { + function includeUndefinedInIndexSignature(type: Type | undefined): Type | undefined { if (!type) return type; return compilerOptions.noUncheckedIndexedAccess ? getUnionType([type, undefinedType]) : type; } - function getTypeOfDestructuredSpreadExpression(type: ts.Type) { + function getTypeOfDestructuredSpreadExpression(type: Type) { return createArrayType(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) || errorType); } - function getAssignedTypeOfBinaryExpression(node: ts.BinaryExpression): ts.Type { + function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type { const isDestructuringDefaultAssignment = - node.parent.kind === ts.SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) || - node.parent.kind === ts.SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent); + node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) || + node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent); return isDestructuringDefaultAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : getTypeOfExpression(node.right); } - function isDestructuringAssignmentTarget(parent: ts.Node) { - return parent.parent.kind === ts.SyntaxKind.BinaryExpression && (parent.parent as ts.BinaryExpression).left === parent || - parent.parent.kind === ts.SyntaxKind.ForOfStatement && (parent.parent as ts.ForOfStatement).initializer === parent; + function isDestructuringAssignmentTarget(parent: Node) { + return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent || + parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent; } - function getAssignedTypeOfArrayLiteralElement(node: ts.ArrayLiteralExpression, element: ts.Expression): ts.Type { + function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { return getTypeOfDestructuredArrayElement(getAssignedType(node), node.elements.indexOf(element)); } - function getAssignedTypeOfSpreadExpression(node: ts.SpreadElement): ts.Type { - return getTypeOfDestructuredSpreadExpression(getAssignedType(node.parent as ts.ArrayLiteralExpression)); + function getAssignedTypeOfSpreadExpression(node: SpreadElement): Type { + return getTypeOfDestructuredSpreadExpression(getAssignedType(node.parent as ArrayLiteralExpression)); } - function getAssignedTypeOfPropertyAssignment(node: ts.PropertyAssignment | ts.ShorthandPropertyAssignment): ts.Type { + function getAssignedTypeOfPropertyAssignment(node: PropertyAssignment | ShorthandPropertyAssignment): Type { return getTypeOfDestructuredProperty(getAssignedType(node.parent), node.name); } - function getAssignedTypeOfShorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment): ts.Type { + function getAssignedTypeOfShorthandPropertyAssignment(node: ShorthandPropertyAssignment): Type { return getTypeWithDefault(getAssignedTypeOfPropertyAssignment(node), node.objectAssignmentInitializer!); } - function getAssignedType(node: ts.Expression): ts.Type { + function getAssignedType(node: Expression): Type { const { parent } = node; switch (parent.kind) { - case ts.SyntaxKind.ForInStatement: + case SyntaxKind.ForInStatement: return stringType; - case ts.SyntaxKind.ForOfStatement: - return checkRightHandSideOfForOf(parent as ts.ForOfStatement) || errorType; - case ts.SyntaxKind.BinaryExpression: - return getAssignedTypeOfBinaryExpression(parent as ts.BinaryExpression); - case ts.SyntaxKind.DeleteExpression: + case SyntaxKind.ForOfStatement: + return checkRightHandSideOfForOf(parent as ForOfStatement) || errorType; + case SyntaxKind.BinaryExpression: + return getAssignedTypeOfBinaryExpression(parent as BinaryExpression); + case SyntaxKind.DeleteExpression: return undefinedType; - case ts.SyntaxKind.ArrayLiteralExpression: - return getAssignedTypeOfArrayLiteralElement(parent as ts.ArrayLiteralExpression, node); - case ts.SyntaxKind.SpreadElement: - return getAssignedTypeOfSpreadExpression(parent as ts.SpreadElement); - case ts.SyntaxKind.PropertyAssignment: - return getAssignedTypeOfPropertyAssignment(parent as ts.PropertyAssignment); - case ts.SyntaxKind.ShorthandPropertyAssignment: - return getAssignedTypeOfShorthandPropertyAssignment(parent as ts.ShorthandPropertyAssignment); + case SyntaxKind.ArrayLiteralExpression: + return getAssignedTypeOfArrayLiteralElement(parent as ArrayLiteralExpression, node); + case SyntaxKind.SpreadElement: + return getAssignedTypeOfSpreadExpression(parent as SpreadElement); + case SyntaxKind.PropertyAssignment: + return getAssignedTypeOfPropertyAssignment(parent as PropertyAssignment); + case SyntaxKind.ShorthandPropertyAssignment: + return getAssignedTypeOfShorthandPropertyAssignment(parent as ShorthandPropertyAssignment); } return errorType; } - function getInitialTypeOfBindingElement(node: ts.BindingElement): ts.Type { + function getInitialTypeOfBindingElement(node: BindingElement): Type { const pattern = node.parent; - const parentType = getInitialType(pattern.parent as ts.VariableDeclaration | ts.BindingElement); - const type = pattern.kind === ts.SyntaxKind.ObjectBindingPattern ? - getTypeOfDestructuredProperty(parentType, node.propertyName || node.name as ts.Identifier) : + const parentType = getInitialType(pattern.parent as VariableDeclaration | BindingElement); + const type = pattern.kind === SyntaxKind.ObjectBindingPattern ? + getTypeOfDestructuredProperty(parentType, node.propertyName || node.name as Identifier) : !node.dotDotDotToken ? getTypeOfDestructuredArrayElement(parentType, pattern.elements.indexOf(node)) : getTypeOfDestructuredSpreadExpression(parentType); return getTypeWithDefault(type, node.initializer!); } - function getTypeOfInitializer(node: ts.Expression) { + function getTypeOfInitializer(node: Expression) { // Return the cached type if one is available. If the type of the variable was inferred // from its initializer, we'll already have cached the type. Otherwise we compute it now // without caching such that transient types are reflected. @@ -24147,66 +24345,66 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType || getTypeOfExpression(node); } - function getInitialTypeOfVariableDeclaration(node: ts.VariableDeclaration) { + function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) { if (node.initializer) { return getTypeOfInitializer(node.initializer); } - if (node.parent.parent.kind === ts.SyntaxKind.ForInStatement) { + if (node.parent.parent.kind === SyntaxKind.ForInStatement) { return stringType; } - if (node.parent.parent.kind === ts.SyntaxKind.ForOfStatement) { + if (node.parent.parent.kind === SyntaxKind.ForOfStatement) { return checkRightHandSideOfForOf(node.parent.parent) || errorType; } return errorType; } - function getInitialType(node: ts.VariableDeclaration | ts.BindingElement) { - return node.kind === ts.SyntaxKind.VariableDeclaration ? + function getInitialType(node: VariableDeclaration | BindingElement) { + return node.kind === SyntaxKind.VariableDeclaration ? getInitialTypeOfVariableDeclaration(node) : getInitialTypeOfBindingElement(node); } - function isEmptyArrayAssignment(node: ts.VariableDeclaration | ts.BindingElement | ts.Expression) { - return node.kind === ts.SyntaxKind.VariableDeclaration && (node as ts.VariableDeclaration).initializer && - isEmptyArrayLiteral((node as ts.VariableDeclaration).initializer!) || - node.kind !== ts.SyntaxKind.BindingElement && node.parent.kind === ts.SyntaxKind.BinaryExpression && - isEmptyArrayLiteral((node.parent as ts.BinaryExpression).right); + function isEmptyArrayAssignment(node: VariableDeclaration | BindingElement | Expression) { + return node.kind === SyntaxKind.VariableDeclaration && (node as VariableDeclaration).initializer && + isEmptyArrayLiteral((node as VariableDeclaration).initializer!) || + node.kind !== SyntaxKind.BindingElement && node.parent.kind === SyntaxKind.BinaryExpression && + isEmptyArrayLiteral((node.parent as BinaryExpression).right); } - function getReferenceCandidate(node: ts.Expression): ts.Expression { + function getReferenceCandidate(node: Expression): Expression { switch (node.kind) { - case ts.SyntaxKind.ParenthesizedExpression: - return getReferenceCandidate((node as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.BinaryExpression: - switch ((node as ts.BinaryExpression).operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.BarBarEqualsToken: - case ts.SyntaxKind.AmpersandAmpersandEqualsToken: - case ts.SyntaxKind.QuestionQuestionEqualsToken: - return getReferenceCandidate((node as ts.BinaryExpression).left); - case ts.SyntaxKind.CommaToken: - return getReferenceCandidate((node as ts.BinaryExpression).right); + case SyntaxKind.ParenthesizedExpression: + return getReferenceCandidate((node as ParenthesizedExpression).expression); + case SyntaxKind.BinaryExpression: + switch ((node as BinaryExpression).operatorToken.kind) { + case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: + return getReferenceCandidate((node as BinaryExpression).left); + case SyntaxKind.CommaToken: + return getReferenceCandidate((node as BinaryExpression).right); } } return node; } - function getReferenceRoot(node: ts.Node): ts.Node { + function getReferenceRoot(node: Node): Node { const { parent } = node; - return parent.kind === ts.SyntaxKind.ParenthesizedExpression || - parent.kind === ts.SyntaxKind.BinaryExpression && (parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken && (parent as ts.BinaryExpression).left === node || - parent.kind === ts.SyntaxKind.BinaryExpression && (parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken && (parent as ts.BinaryExpression).right === node ? + return parent.kind === SyntaxKind.ParenthesizedExpression || + parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken && (parent as BinaryExpression).left === node || + parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken && (parent as BinaryExpression).right === node ? getReferenceRoot(parent) : node; } - function getTypeOfSwitchClause(clause: ts.CaseClause | ts.DefaultClause) { - if (clause.kind === ts.SyntaxKind.CaseClause) { + function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) { + if (clause.kind === SyntaxKind.CaseClause) { return getRegularTypeOfLiteralType(getTypeOfExpression(clause.expression)); } return neverType; } - function getSwitchClauseTypes(switchStatement: ts.SwitchStatement): ts.Type[] { + function getSwitchClauseTypes(switchStatement: SwitchStatement): Type[] { const links = getNodeLinks(switchStatement); if (!links.switchTypes) { links.switchTypes = []; @@ -24219,112 +24417,112 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Get the type names from all cases in a switch on `typeof`. The default clause and/or duplicate type names are // represented as undefined. Return undefined if one or more case clause expressions are not string literals. - function getSwitchClauseTypeOfWitnesses(switchStatement: ts.SwitchStatement): (string | undefined)[] | undefined { - if (ts.some(switchStatement.caseBlock.clauses, clause => clause.kind === ts.SyntaxKind.CaseClause && !ts.isStringLiteralLike(clause.expression))) { + function getSwitchClauseTypeOfWitnesses(switchStatement: SwitchStatement): (string | undefined)[] | undefined { + if (some(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.CaseClause && !isStringLiteralLike(clause.expression))) { return undefined; } const witnesses: (string | undefined)[] = []; for (const clause of switchStatement.caseBlock.clauses) { - const text = clause.kind === ts.SyntaxKind.CaseClause ? (clause.expression as ts.StringLiteralLike).text : undefined; - witnesses.push(text && !ts.contains(witnesses, text) ? text : undefined); + const text = clause.kind === SyntaxKind.CaseClause ? (clause.expression as StringLiteralLike).text : undefined; + witnesses.push(text && !contains(witnesses, text) ? text : undefined); } return witnesses; } - function eachTypeContainedIn(source: ts.Type, types: ts.Type[]) { - return source.flags & ts.TypeFlags.Union ? !ts.forEach((source as ts.UnionType).types, t => !ts.contains(types, t)) : ts.contains(types, source); + function eachTypeContainedIn(source: Type, types: Type[]) { + return source.flags & TypeFlags.Union ? !forEach((source as UnionType).types, t => !contains(types, t)) : contains(types, source); } - function isTypeSubsetOf(source: ts.Type, target: ts.Type) { - return source === target || target.flags & ts.TypeFlags.Union && isTypeSubsetOfUnion(source, target as ts.UnionType); + function isTypeSubsetOf(source: Type, target: Type) { + return source === target || target.flags & TypeFlags.Union && isTypeSubsetOfUnion(source, target as UnionType); } - function isTypeSubsetOfUnion(source: ts.Type, target: ts.UnionType) { - if (source.flags & ts.TypeFlags.Union) { - for (const t of (source as ts.UnionType).types) { + function isTypeSubsetOfUnion(source: Type, target: UnionType) { + if (source.flags & TypeFlags.Union) { + for (const t of (source as UnionType).types) { if (!containsType(target.types, t)) { return false; } } return true; } - if (source.flags & ts.TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source as ts.LiteralType) === target) { + if (source.flags & TypeFlags.EnumLiteral && getBaseTypeOfEnumLiteralType(source as LiteralType) === target) { return true; } return containsType(target.types, source); } - function forEachType(type: ts.Type, f: (t: ts.Type) => T | undefined): T | undefined { - return type.flags & ts.TypeFlags.Union ? ts.forEach((type as ts.UnionType).types, f) : f(type); + function forEachType(type: Type, f: (t: Type) => T | undefined): T | undefined { + return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type); } - function someType(type: ts.Type, f: (t: ts.Type) => boolean): boolean { - return type.flags & ts.TypeFlags.Union ? ts.some((type as ts.UnionType).types, f) : f(type); + function someType(type: Type, f: (t: Type) => boolean): boolean { + return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type); } - function everyType(type: ts.Type, f: (t: ts.Type) => boolean): boolean { - return type.flags & ts.TypeFlags.Union ? ts.every((type as ts.UnionType).types, f) : f(type); + function everyType(type: Type, f: (t: Type) => boolean): boolean { + return type.flags & TypeFlags.Union ? every((type as UnionType).types, f) : f(type); } - function everyContainedType(type: ts.Type, f: (t: ts.Type) => boolean): boolean { - return type.flags & ts.TypeFlags.UnionOrIntersection ? ts.every((type as ts.UnionOrIntersectionType).types, f) : f(type); + function everyContainedType(type: Type, f: (t: Type) => boolean): boolean { + return type.flags & TypeFlags.UnionOrIntersection ? every((type as UnionOrIntersectionType).types, f) : f(type); } - function filterType(type: ts.Type, f: (t: ts.Type) => boolean): ts.Type { - if (type.flags & ts.TypeFlags.Union) { - const types = (type as ts.UnionType).types; - const filtered = ts.filter(types, f); + function filterType(type: Type, f: (t: Type) => boolean): Type { + if (type.flags & TypeFlags.Union) { + const types = (type as UnionType).types; + const filtered = filter(types, f); if (filtered === types) { return type; } - const origin = (type as ts.UnionType).origin; - let newOrigin: ts.Type | undefined; - if (origin && origin.flags & ts.TypeFlags.Union) { + const origin = (type as UnionType).origin; + let newOrigin: Type | undefined; + if (origin && origin.flags & TypeFlags.Union) { // If the origin type is a (denormalized) union type, filter its non-union constituents. If that ends // up removing a smaller number of types than in the normalized constituent set (meaning some of the // filtered types are within nested unions in the origin), then we can't construct a new origin type. // Otherwise, if we have exactly one type left in the origin set, return that as the filtered type. // Otherwise, construct a new filtered origin type. - const originTypes = (origin as ts.UnionType).types; - const originFiltered = ts.filter(originTypes, t => !!(t.flags & ts.TypeFlags.Union) || f(t)); + const originTypes = (origin as UnionType).types; + const originFiltered = filter(originTypes, t => !!(t.flags & TypeFlags.Union) || f(t)); if (originTypes.length - originFiltered.length === types.length - filtered.length) { if (originFiltered.length === 1) { return originFiltered[0]; } - newOrigin = createOriginUnionOrIntersectionType(ts.TypeFlags.Union, originFiltered); + newOrigin = createOriginUnionOrIntersectionType(TypeFlags.Union, originFiltered); } } - return getUnionTypeFromSortedList(filtered, (type as ts.UnionType).objectFlags, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, newOrigin); + return getUnionTypeFromSortedList(filtered, (type as UnionType).objectFlags, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, newOrigin); } - return type.flags & ts.TypeFlags.Never || f(type) ? type : neverType; + return type.flags & TypeFlags.Never || f(type) ? type : neverType; } - function removeType(type: ts.Type, targetType: ts.Type) { + function removeType(type: Type, targetType: Type) { return filterType(type, t => t !== targetType); } - function countTypes(type: ts.Type) { - return type.flags & ts.TypeFlags.Union ? (type as ts.UnionType).types.length : 1; + function countTypes(type: Type) { + return type.flags & TypeFlags.Union ? (type as UnionType).types.length : 1; } // Apply a mapping function to a type and return the resulting type. If the source type // is a union type, the mapping function is applied to each constituent type and a union // of the resulting types is returned. - function mapType(type: ts.Type, mapper: (t: ts.Type) => ts.Type, noReductions?: boolean): ts.Type; - function mapType(type: ts.Type, mapper: (t: ts.Type) => ts.Type | undefined, noReductions?: boolean): ts.Type | undefined; - function mapType(type: ts.Type, mapper: (t: ts.Type) => ts.Type | undefined, noReductions?: boolean): ts.Type | undefined { - if (type.flags & ts.TypeFlags.Never) { + function mapType(type: Type, mapper: (t: Type) => Type, noReductions?: boolean): Type; + function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined; + function mapType(type: Type, mapper: (t: Type) => Type | undefined, noReductions?: boolean): Type | undefined { + if (type.flags & TypeFlags.Never) { return type; } - if (!(type.flags & ts.TypeFlags.Union)) { + if (!(type.flags & TypeFlags.Union)) { return mapper(type); } - const origin = (type as ts.UnionType).origin; - const types = origin && origin.flags & ts.TypeFlags.Union ? (origin as ts.UnionType).types : (type as ts.UnionType).types; - let mappedTypes: ts.Type[] | undefined; + const origin = (type as UnionType).origin; + const types = origin && origin.flags & TypeFlags.Union ? (origin as UnionType).types : (type as UnionType).types; + let mappedTypes: Type[] | undefined; let changed = false; for (const t of types) { - const mapped = t.flags & ts.TypeFlags.Union ? mapType(t, mapper, noReductions) : mapper(t); + const mapped = t.flags & TypeFlags.Union ? mapType(t, mapper, noReductions) : mapper(t); changed ||= t !== mapped; if (mapped) { if (!mappedTypes) { @@ -24335,16 +24533,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return changed ? mappedTypes && getUnionType(mappedTypes, noReductions ? ts.UnionReduction.None : ts.UnionReduction.Literal) : type; + return changed ? mappedTypes && getUnionType(mappedTypes, noReductions ? UnionReduction.None : UnionReduction.Literal) : type; } - function mapTypeWithAlias(type: ts.Type, mapper: (t: ts.Type) => ts.Type, aliasSymbol: ts.Symbol | undefined, aliasTypeArguments: readonly ts.Type[] | undefined) { - return type.flags & ts.TypeFlags.Union && aliasSymbol ? - getUnionType(ts.map((type as ts.UnionType).types, mapper), ts.UnionReduction.Literal, aliasSymbol, aliasTypeArguments) : + function mapTypeWithAlias(type: Type, mapper: (t: Type) => Type, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined) { + return type.flags & TypeFlags.Union && aliasSymbol ? + getUnionType(map((type as UnionType).types, mapper), UnionReduction.Literal, aliasSymbol, aliasTypeArguments) : mapType(type, mapper); } - function extractTypesOfKind(type: ts.Type, kind: ts.TypeFlags) { + function extractTypesOfKind(type: Type, kind: TypeFlags) { return filterType(type, t => (t.flags & kind) !== 0); } @@ -24353,78 +24551,78 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // from typeWithLiterals. This is essentially a limited form of intersection between the two types. We avoid a // true intersection because it is more costly and, when applied to union types, generates a large number of // types we don't actually care about. - function replacePrimitivesWithLiterals(typeWithPrimitives: ts.Type, typeWithLiterals: ts.Type) { - if (maybeTypeOfKind(typeWithPrimitives, ts.TypeFlags.String | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.Number | ts.TypeFlags.BigInt) && - maybeTypeOfKind(typeWithLiterals, ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping | ts.TypeFlags.NumberLiteral | ts.TypeFlags.BigIntLiteral)) { + function replacePrimitivesWithLiterals(typeWithPrimitives: Type, typeWithLiterals: Type) { + if (maybeTypeOfKind(typeWithPrimitives, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.Number | TypeFlags.BigInt) && + maybeTypeOfKind(typeWithLiterals, TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping | TypeFlags.NumberLiteral | TypeFlags.BigIntLiteral)) { return mapType(typeWithPrimitives, t => - t.flags & ts.TypeFlags.String ? extractTypesOfKind(typeWithLiterals, ts.TypeFlags.String | ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) : - isPatternLiteralType(t) && !maybeTypeOfKind(typeWithLiterals, ts.TypeFlags.String | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) ? extractTypesOfKind(typeWithLiterals, ts.TypeFlags.StringLiteral) : - t.flags & ts.TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, ts.TypeFlags.Number | ts.TypeFlags.NumberLiteral) : - t.flags & ts.TypeFlags.BigInt ? extractTypesOfKind(typeWithLiterals, ts.TypeFlags.BigInt | ts.TypeFlags.BigIntLiteral) : t); + t.flags & TypeFlags.String ? extractTypesOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) : + isPatternLiteralType(t) && !maybeTypeOfKind(typeWithLiterals, TypeFlags.String | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) ? extractTypesOfKind(typeWithLiterals, TypeFlags.StringLiteral) : + t.flags & TypeFlags.Number ? extractTypesOfKind(typeWithLiterals, TypeFlags.Number | TypeFlags.NumberLiteral) : + t.flags & TypeFlags.BigInt ? extractTypesOfKind(typeWithLiterals, TypeFlags.BigInt | TypeFlags.BigIntLiteral) : t); } return typeWithPrimitives; } - function isIncomplete(flowType: ts.FlowType) { + function isIncomplete(flowType: FlowType) { return flowType.flags === 0; } - function getTypeFromFlowType(flowType: ts.FlowType) { - return flowType.flags === 0 ? (flowType as ts.IncompleteType).type : flowType as ts.Type; + function getTypeFromFlowType(flowType: FlowType) { + return flowType.flags === 0 ? (flowType as IncompleteType).type : flowType as Type; } - function createFlowType(type: ts.Type, incomplete: boolean): ts.FlowType { - return incomplete ? { flags: 0, type: type.flags & ts.TypeFlags.Never ? silentNeverType : type } : type; + function createFlowType(type: Type, incomplete: boolean): FlowType { + return incomplete ? { flags: 0, type: type.flags & TypeFlags.Never ? silentNeverType : type } : type; } // An evolving array type tracks the element types that have so far been seen in an // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving // array types are ultimately converted into manifest array types (using getFinalArrayType) // and never escape the getFlowTypeOfReference function. - function createEvolvingArrayType(elementType: ts.Type): ts.EvolvingArrayType { - const result = createObjectType(ts.ObjectFlags.EvolvingArray) as ts.EvolvingArrayType; + function createEvolvingArrayType(elementType: Type): EvolvingArrayType { + const result = createObjectType(ObjectFlags.EvolvingArray) as EvolvingArrayType; result.elementType = elementType; return result; } - function getEvolvingArrayType(elementType: ts.Type): ts.EvolvingArrayType { + function getEvolvingArrayType(elementType: Type): EvolvingArrayType { return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } // When adding evolving array element types we do not perform subtype reduction. Instead, // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. - function addEvolvingArrayElementType(evolvingArrayType: ts.EvolvingArrayType, node: ts.Expression): ts.EvolvingArrayType { + function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { const elementType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node))); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } - function createFinalArrayType(elementType: ts.Type) { - return elementType.flags & ts.TypeFlags.Never ? + function createFinalArrayType(elementType: Type) { + return elementType.flags & TypeFlags.Never ? autoArrayType : - createArrayType(elementType.flags & ts.TypeFlags.Union ? - getUnionType((elementType as ts.UnionType).types, ts.UnionReduction.Subtype) : + createArrayType(elementType.flags & TypeFlags.Union ? + getUnionType((elementType as UnionType).types, UnionReduction.Subtype) : elementType); } // We perform subtype reduction upon obtaining the final array type from an evolving array type. - function getFinalArrayType(evolvingArrayType: ts.EvolvingArrayType): ts.Type { + function getFinalArrayType(evolvingArrayType: EvolvingArrayType): Type { return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } - function finalizeEvolvingArrayType(type: ts.Type): ts.Type { - return ts.getObjectFlags(type) & ts.ObjectFlags.EvolvingArray ? getFinalArrayType(type as ts.EvolvingArrayType) : type; + function finalizeEvolvingArrayType(type: Type): Type { + return getObjectFlags(type) & ObjectFlags.EvolvingArray ? getFinalArrayType(type as EvolvingArrayType) : type; } - function getElementTypeOfEvolvingArrayType(type: ts.Type) { - return ts.getObjectFlags(type) & ts.ObjectFlags.EvolvingArray ? (type as ts.EvolvingArrayType).elementType : neverType; + function getElementTypeOfEvolvingArrayType(type: Type) { + return getObjectFlags(type) & ObjectFlags.EvolvingArray ? (type as EvolvingArrayType).elementType : neverType; } - function isEvolvingArrayTypeList(types: ts.Type[]) { + function isEvolvingArrayTypeList(types: Type[]) { let hasEvolvingArrayType = false; for (const t of types) { - if (!(t.flags & ts.TypeFlags.Never)) { - if (!(ts.getObjectFlags(t) & ts.ObjectFlags.EvolvingArray)) { + if (!(t.flags & TypeFlags.Never)) { + if (!(getObjectFlags(t) & ObjectFlags.EvolvingArray)) { return false; } hasEvolvingArrayType = true; @@ -24435,38 +24633,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if the given node is 'x' in an 'x.length', x.push(value)', 'x.unshift(value)' or // 'x[n] = value' operation, where 'n' is an expression of type any, undefined, or a number-like type. - function isEvolvingArrayOperationTarget(node: ts.Node) { + function isEvolvingArrayOperationTarget(node: Node) { const root = getReferenceRoot(node); const parent = root.parent; - const isLengthPushOrUnshift = ts.isPropertyAccessExpression(parent) && ( + const isLengthPushOrUnshift = isPropertyAccessExpression(parent) && ( parent.name.escapedText === "length" || - parent.parent.kind === ts.SyntaxKind.CallExpression - && ts.isIdentifier(parent.name) - && ts.isPushOrUnshiftIdentifier(parent.name)); - const isElementAssignment = parent.kind === ts.SyntaxKind.ElementAccessExpression && - (parent as ts.ElementAccessExpression).expression === root && - parent.parent.kind === ts.SyntaxKind.BinaryExpression && - (parent.parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken && - (parent.parent as ts.BinaryExpression).left === parent && - !ts.isAssignmentTarget(parent.parent) && - isTypeAssignableToKind(getTypeOfExpression((parent as ts.ElementAccessExpression).argumentExpression), ts.TypeFlags.NumberLike); + parent.parent.kind === SyntaxKind.CallExpression + && isIdentifier(parent.name) + && isPushOrUnshiftIdentifier(parent.name)); + const isElementAssignment = parent.kind === SyntaxKind.ElementAccessExpression && + (parent as ElementAccessExpression).expression === root && + parent.parent.kind === SyntaxKind.BinaryExpression && + (parent.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken && + (parent.parent as BinaryExpression).left === parent && + !isAssignmentTarget(parent.parent) && + isTypeAssignableToKind(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression), TypeFlags.NumberLike); return isLengthPushOrUnshift || isElementAssignment; } - function isDeclarationWithExplicitTypeAnnotation(node: ts.Declaration) { - return (ts.isVariableDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isParameter(node)) && - !!(ts.getEffectiveTypeAnnotationNode(node) || - ts.isInJSFile(node) && ts.hasInitializer(node) && node.initializer && ts.isFunctionExpressionOrArrowFunction(node.initializer) && ts.getEffectiveReturnTypeNode(node.initializer)); + function isDeclarationWithExplicitTypeAnnotation(node: Declaration) { + return (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isParameter(node)) && + !!(getEffectiveTypeAnnotationNode(node) || + isInJSFile(node) && hasInitializer(node) && node.initializer && isFunctionExpressionOrArrowFunction(node.initializer) && getEffectiveReturnTypeNode(node.initializer)); } - function getExplicitTypeOfSymbol(symbol: ts.Symbol, diagnostic?: ts.Diagnostic) { + function getExplicitTypeOfSymbol(symbol: Symbol, diagnostic?: Diagnostic) { symbol = resolveSymbol(symbol); - if (symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.Class | ts.SymbolFlags.ValueModule)) { + if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule)) { return getTypeOfSymbol(symbol); } - if (symbol.flags & (ts.SymbolFlags.Variable | ts.SymbolFlags.Property)) { - if (ts.getCheckFlags(symbol) & ts.CheckFlags.Mapped) { - const origin = (symbol as ts.MappedSymbol).syntheticOrigin; + if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) { + if (getCheckFlags(symbol) & CheckFlags.Mapped) { + const origin = (symbol as MappedSymbol).syntheticOrigin; if (origin && getExplicitTypeOfSymbol(origin)) { return getTypeOfSymbol(symbol); } @@ -24476,7 +24674,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isDeclarationWithExplicitTypeAnnotation(declaration)) { return getTypeOfSymbol(symbol); } - if (ts.isVariableDeclaration(declaration) && declaration.parent.parent.kind === ts.SyntaxKind.ForOfStatement) { + if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForOfStatement) { const statement = declaration.parent.parent; const expressionType = getTypeOfDottedName(statement.expression, /*diagnostic*/ undefined); if (expressionType) { @@ -24485,7 +24683,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (diagnostic) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(declaration, ts.Diagnostics._0_needs_an_explicit_type_annotation, symbolToString(symbol))); + addRelatedInfo(diagnostic, createDiagnosticForNode(declaration, Diagnostics._0_needs_an_explicit_type_annotation, symbolToString(symbol))); } } } @@ -24495,26 +24693,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // that reference function, method, class or value module symbols; or variable, property or // parameter symbols with declarations that have explicit type annotations. Such references are // resolvable with no possibility of triggering circularities in control flow analysis. - function getTypeOfDottedName(node: ts.Expression, diagnostic: ts.Diagnostic | undefined): ts.Type | undefined { - if (!(node.flags & ts.NodeFlags.InWithStatement)) { + function getTypeOfDottedName(node: Expression, diagnostic: Diagnostic | undefined): Type | undefined { + if (!(node.flags & NodeFlags.InWithStatement)) { switch (node.kind) { - case ts.SyntaxKind.Identifier: - const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(node as ts.Identifier)); + case SyntaxKind.Identifier: + const symbol = getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(node as Identifier)); return getExplicitTypeOfSymbol(symbol, diagnostic); - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.ThisKeyword: return getExplicitThisType(node); - case ts.SyntaxKind.SuperKeyword: + case SyntaxKind.SuperKeyword: return checkSuperExpression(node); - case ts.SyntaxKind.PropertyAccessExpression: { - const type = getTypeOfDottedName((node as ts.PropertyAccessExpression).expression, diagnostic); + case SyntaxKind.PropertyAccessExpression: { + const type = getTypeOfDottedName((node as PropertyAccessExpression).expression, diagnostic); if (type) { - const name = (node as ts.PropertyAccessExpression).name; - let prop: ts.Symbol | undefined; - if (ts.isPrivateIdentifier(name)) { + const name = (node as PropertyAccessExpression).name; + let prop: Symbol | undefined; + if (isPrivateIdentifier(name)) { if (!type.symbol) { return undefined; } - prop = getPropertyOfType(type, ts.getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText)); + prop = getPropertyOfType(type, getSymbolNameForPrivateIdentifier(type.symbol, name.escapedText)); } else { prop = getPropertyOfType(type, name.escapedText); @@ -24523,13 +24721,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return undefined; } - case ts.SyntaxKind.ParenthesizedExpression: - return getTypeOfDottedName((node as ts.ParenthesizedExpression).expression, diagnostic); + case SyntaxKind.ParenthesizedExpression: + return getTypeOfDottedName((node as ParenthesizedExpression).expression, diagnostic); } } } - function getEffectsSignature(node: ts.CallExpression) { + function getEffectsSignature(node: CallExpression) { const links = getNodeLinks(node); let signature = links.effectsSignature; if (signature === undefined) { @@ -24537,12 +24735,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // expressions are potential type predicate function calls. In order to avoid triggering // circularities in control flow analysis, we use getTypeOfDottedName when resolving the call // target expression of an assertion. - let funcType: ts.Type | undefined; - if (node.parent.kind === ts.SyntaxKind.ExpressionStatement) { + let funcType: Type | undefined; + if (node.parent.kind === SyntaxKind.ExpressionStatement) { funcType = getTypeOfDottedName(node.expression, /*diagnostic*/ undefined); } - else if (node.expression.kind !== ts.SyntaxKind.SuperKeyword) { - if (ts.isOptionalChain(node)) { + else if (node.expression.kind !== SyntaxKind.SuperKeyword) { + if (isOptionalChain(node)) { funcType = checkNonNullType( getOptionalExpressionType(checkExpression(node.expression), node.expression), node.expression @@ -24552,56 +24750,56 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { funcType = checkNonNullExpression(node.expression); } } - const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, ts.SignatureKind.Call); + const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call); const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] : - ts.some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) : + some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) : undefined; signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate : unknownSignature; } return signature === unknownSignature ? undefined : signature; } - function hasTypePredicateOrNeverReturnType(signature: ts.Signature) { + function hasTypePredicateOrNeverReturnType(signature: Signature) { return !!(getTypePredicateOfSignature(signature) || - signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & ts.TypeFlags.Never); + signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never); } - function getTypePredicateArgument(predicate: ts.TypePredicate, callExpression: ts.CallExpression) { - if (predicate.kind === ts.TypePredicateKind.Identifier || predicate.kind === ts.TypePredicateKind.AssertsIdentifier) { + function getTypePredicateArgument(predicate: TypePredicate, callExpression: CallExpression) { + if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) { return callExpression.arguments[predicate.parameterIndex]; } - const invokedExpression = ts.skipParentheses(callExpression.expression); - return ts.isAccessExpression(invokedExpression) ? ts.skipParentheses(invokedExpression.expression) : undefined; + const invokedExpression = skipParentheses(callExpression.expression); + return isAccessExpression(invokedExpression) ? skipParentheses(invokedExpression.expression) : undefined; } - function reportFlowControlError(node: ts.Node) { - const block = ts.findAncestor(node, ts.isFunctionOrModuleBlock) as ts.Block | ts.ModuleBlock | ts.SourceFile; - const sourceFile = ts.getSourceFileOfNode(node); - const span = ts.getSpanOfTokenAtPosition(sourceFile, block.statements.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, ts.Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis)); + function reportFlowControlError(node: Node) { + const block = findAncestor(node, isFunctionOrModuleBlock) as Block | ModuleBlock | SourceFile; + const sourceFile = getSourceFileOfNode(node); + const span = getSpanOfTokenAtPosition(sourceFile, block.statements.pos); + diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis)); } - function isReachableFlowNode(flow: ts.FlowNode) { + function isReachableFlowNode(flow: FlowNode) { const result = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ false); lastFlowNode = flow; lastFlowNodeReachable = result; return result; } - function isFalseExpression(expr: ts.Expression): boolean { - const node = ts.skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true); - return node.kind === ts.SyntaxKind.FalseKeyword || node.kind === ts.SyntaxKind.BinaryExpression && ( - (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken && (isFalseExpression((node as ts.BinaryExpression).left) || isFalseExpression((node as ts.BinaryExpression).right)) || - (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.BarBarToken && isFalseExpression((node as ts.BinaryExpression).left) && isFalseExpression((node as ts.BinaryExpression).right)); + function isFalseExpression(expr: Expression): boolean { + const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true); + return node.kind === SyntaxKind.FalseKeyword || node.kind === SyntaxKind.BinaryExpression && ( + (node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken && (isFalseExpression((node as BinaryExpression).left) || isFalseExpression((node as BinaryExpression).right)) || + (node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken && isFalseExpression((node as BinaryExpression).left) && isFalseExpression((node as BinaryExpression).right)); } - function isReachableFlowNodeWorker(flow: ts.FlowNode, noCacheCheck: boolean): boolean { + function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean { while (true) { if (flow === lastFlowNode) { return lastFlowNodeReachable; } const flags = flow.flags; - if (flags & ts.FlowFlags.Shared) { + if (flags & FlowFlags.Shared) { if (!noCacheCheck) { const id = getFlowNodeId(flow); const reachable = flowNodeReachable[id]; @@ -24609,67 +24807,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } noCacheCheck = false; } - if (flags & (ts.FlowFlags.Assignment | ts.FlowFlags.Condition | ts.FlowFlags.ArrayMutation)) { - flow = (flow as ts.FlowAssignment | ts.FlowCondition | ts.FlowArrayMutation).antecedent; + if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation)) { + flow = (flow as FlowAssignment | FlowCondition | FlowArrayMutation).antecedent; } - else if (flags & ts.FlowFlags.Call) { - const signature = getEffectsSignature((flow as ts.FlowCall).node); + else if (flags & FlowFlags.Call) { + const signature = getEffectsSignature((flow as FlowCall).node); if (signature) { const predicate = getTypePredicateOfSignature(signature); - if (predicate && predicate.kind === ts.TypePredicateKind.AssertsIdentifier && !predicate.type) { - const predicateArgument = (flow as ts.FlowCall).node.arguments[predicate.parameterIndex]; + if (predicate && predicate.kind === TypePredicateKind.AssertsIdentifier && !predicate.type) { + const predicateArgument = (flow as FlowCall).node.arguments[predicate.parameterIndex]; if (predicateArgument && isFalseExpression(predicateArgument)) { return false; } } - if (getReturnTypeOfSignature(signature).flags & ts.TypeFlags.Never) { + if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) { return false; } } - flow = (flow as ts.FlowCall).antecedent; + flow = (flow as FlowCall).antecedent; } - else if (flags & ts.FlowFlags.BranchLabel) { + else if (flags & FlowFlags.BranchLabel) { // A branching point is reachable if any branch is reachable. - return ts.some((flow as ts.FlowLabel).antecedents, f => isReachableFlowNodeWorker(f, /*noCacheCheck*/ false)); + return some((flow as FlowLabel).antecedents, f => isReachableFlowNodeWorker(f, /*noCacheCheck*/ false)); } - else if (flags & ts.FlowFlags.LoopLabel) { - const antecedents = (flow as ts.FlowLabel).antecedents; + else if (flags & FlowFlags.LoopLabel) { + const antecedents = (flow as FlowLabel).antecedents; if (antecedents === undefined || antecedents.length === 0) { return false; } // A loop is reachable if the control flow path that leads to the top is reachable. flow = antecedents[0]; } - else if (flags & ts.FlowFlags.SwitchClause) { + else if (flags & FlowFlags.SwitchClause) { // The control flow path representing an unmatched value in a switch statement with // no default clause is unreachable if the switch statement is exhaustive. - if ((flow as ts.FlowSwitchClause).clauseStart === (flow as ts.FlowSwitchClause).clauseEnd && isExhaustiveSwitchStatement((flow as ts.FlowSwitchClause).switchStatement)) { + if ((flow as FlowSwitchClause).clauseStart === (flow as FlowSwitchClause).clauseEnd && isExhaustiveSwitchStatement((flow as FlowSwitchClause).switchStatement)) { return false; } - flow = (flow as ts.FlowSwitchClause).antecedent; + flow = (flow as FlowSwitchClause).antecedent; } - else if (flags & ts.FlowFlags.ReduceLabel) { + else if (flags & FlowFlags.ReduceLabel) { // Cache is unreliable once we start adjusting labels lastFlowNode = undefined; - const target = (flow as ts.FlowReduceLabel).target; + const target = (flow as FlowReduceLabel).target; const saveAntecedents = target.antecedents; - target.antecedents = (flow as ts.FlowReduceLabel).antecedents; - const result = isReachableFlowNodeWorker((flow as ts.FlowReduceLabel).antecedent, /*noCacheCheck*/ false); + target.antecedents = (flow as FlowReduceLabel).antecedents; + const result = isReachableFlowNodeWorker((flow as FlowReduceLabel).antecedent, /*noCacheCheck*/ false); target.antecedents = saveAntecedents; return result; } else { - return !(flags & ts.FlowFlags.Unreachable); + return !(flags & FlowFlags.Unreachable); } } } // Return true if the given flow node is preceded by a 'super(...)' call in every possible code path // leading to the node. - function isPostSuperFlowNode(flow: ts.FlowNode, noCacheCheck: boolean): boolean { + function isPostSuperFlowNode(flow: FlowNode, noCacheCheck: boolean): boolean { while (true) { const flags = flow.flags; - if (flags & ts.FlowFlags.Shared) { + if (flags & FlowFlags.Shared) { if (!noCacheCheck) { const id = getFlowNodeId(flow); const postSuper = flowNodePostSuper[id]; @@ -24677,53 +24875,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } noCacheCheck = false; } - if (flags & (ts.FlowFlags.Assignment | ts.FlowFlags.Condition | ts.FlowFlags.ArrayMutation | ts.FlowFlags.SwitchClause)) { - flow = (flow as ts.FlowAssignment | ts.FlowCondition | ts.FlowArrayMutation | ts.FlowSwitchClause).antecedent; + if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.SwitchClause)) { + flow = (flow as FlowAssignment | FlowCondition | FlowArrayMutation | FlowSwitchClause).antecedent; } - else if (flags & ts.FlowFlags.Call) { - if ((flow as ts.FlowCall).node.expression.kind === ts.SyntaxKind.SuperKeyword) { + else if (flags & FlowFlags.Call) { + if ((flow as FlowCall).node.expression.kind === SyntaxKind.SuperKeyword) { return true; } - flow = (flow as ts.FlowCall).antecedent; + flow = (flow as FlowCall).antecedent; } - else if (flags & ts.FlowFlags.BranchLabel) { + else if (flags & FlowFlags.BranchLabel) { // A branching point is post-super if every branch is post-super. - return ts.every((flow as ts.FlowLabel).antecedents, f => isPostSuperFlowNode(f, /*noCacheCheck*/ false)); + return every((flow as FlowLabel).antecedents, f => isPostSuperFlowNode(f, /*noCacheCheck*/ false)); } - else if (flags & ts.FlowFlags.LoopLabel) { + else if (flags & FlowFlags.LoopLabel) { // A loop is post-super if the control flow path that leads to the top is post-super. - flow = (flow as ts.FlowLabel).antecedents![0]; + flow = (flow as FlowLabel).antecedents![0]; } - else if (flags & ts.FlowFlags.ReduceLabel) { - const target = (flow as ts.FlowReduceLabel).target; + else if (flags & FlowFlags.ReduceLabel) { + const target = (flow as FlowReduceLabel).target; const saveAntecedents = target.antecedents; - target.antecedents = (flow as ts.FlowReduceLabel).antecedents; - const result = isPostSuperFlowNode((flow as ts.FlowReduceLabel).antecedent, /*noCacheCheck*/ false); + target.antecedents = (flow as FlowReduceLabel).antecedents; + const result = isPostSuperFlowNode((flow as FlowReduceLabel).antecedent, /*noCacheCheck*/ false); target.antecedents = saveAntecedents; return result; } else { // Unreachable nodes are considered post-super to silence errors - return !!(flags & ts.FlowFlags.Unreachable); + return !!(flags & FlowFlags.Unreachable); } } } - function isConstantReference(node: ts.Node): boolean { + function isConstantReference(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.Identifier: { - const symbol = getResolvedSymbol(node as ts.Identifier); - return isConstVariable(symbol) || ts.isParameterOrCatchClauseVariable(symbol) && !isSymbolAssigned(symbol); + case SyntaxKind.Identifier: { + const symbol = getResolvedSymbol(node as Identifier); + return isConstVariable(symbol) || isParameterOrCatchClauseVariable(symbol) && !isSymbolAssigned(symbol); } - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: // The resolvedSymbol property is initialized by checkPropertyAccess or checkElementAccess before we get here. - return isConstantReference((node as ts.AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol); + return isConstantReference((node as AccessExpression).expression) && isReadonlySymbol(getNodeLinks(node).resolvedSymbol || unknownSymbol); } return false; } - function getFlowTypeOfReference(reference: ts.Node, declaredType: ts.Type, initialType = declaredType, flowContainer?: ts.Node, flowNode = reference.flowNode) { + function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, flowNode = reference.flowNode) { let key: string | undefined; let isKeySet = false; let flowDepth = 0; @@ -24741,8 +24939,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // we give type 'any[]' to 'x' instead of using the type determined by control flow analysis such that operations // on empty arrays are possible without implicit any errors and new element types can be inferred without // type mismatch errors. - const resultType = ts.getObjectFlags(evolvedType) & ts.ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType); - if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === ts.SyntaxKind.NonNullExpression && !(resultType.flags & ts.TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & ts.TypeFlags.Never) { + const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType); + if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && !(resultType.flags & TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { return declaredType; } // The non-null unknown type should never escape control flow analysis. @@ -24756,20 +24954,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return key = getFlowCacheKey(reference, declaredType, initialType, flowContainer); } - function getTypeAtFlowNode(flow: ts.FlowNode): ts.FlowType { + function getTypeAtFlowNode(flow: FlowNode): FlowType { if (flowDepth === 2000) { // We have made 2000 recursive invocations. To avoid overflowing the call stack we report an error // and disable further control flow analysis in the containing function or module body. - ts.tracing?.instant(ts.tracing.Phase.CheckTypes, "getTypeAtFlowNode_DepthLimit", { flowId: flow.id }); + tracing?.instant(tracing.Phase.CheckTypes, "getTypeAtFlowNode_DepthLimit", { flowId: flow.id }); flowAnalysisDisabled = true; reportFlowControlError(reference); return errorType; } flowDepth++; - let sharedFlow: ts.FlowNode | undefined; + let sharedFlow: FlowNode | undefined; while (true) { const flags = flow.flags; - if (flags & ts.FlowFlags.Shared) { + if (flags & FlowFlags.Shared) { // We cache results of flow type resolution for shared nodes that were previously visited in // the same getFlowTypeOfReference invocation. A node is considered shared when it is the // antecedent of more than one node. @@ -24781,57 +24979,57 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } sharedFlow = flow; } - let type: ts.FlowType | undefined; - if (flags & ts.FlowFlags.Assignment) { - type = getTypeAtFlowAssignment(flow as ts.FlowAssignment); + let type: FlowType | undefined; + if (flags & FlowFlags.Assignment) { + type = getTypeAtFlowAssignment(flow as FlowAssignment); if (!type) { - flow = (flow as ts.FlowAssignment).antecedent; + flow = (flow as FlowAssignment).antecedent; continue; } } - else if (flags & ts.FlowFlags.Call) { - type = getTypeAtFlowCall(flow as ts.FlowCall); + else if (flags & FlowFlags.Call) { + type = getTypeAtFlowCall(flow as FlowCall); if (!type) { - flow = (flow as ts.FlowCall).antecedent; + flow = (flow as FlowCall).antecedent; continue; } } - else if (flags & ts.FlowFlags.Condition) { - type = getTypeAtFlowCondition(flow as ts.FlowCondition); + else if (flags & FlowFlags.Condition) { + type = getTypeAtFlowCondition(flow as FlowCondition); } - else if (flags & ts.FlowFlags.SwitchClause) { - type = getTypeAtSwitchClause(flow as ts.FlowSwitchClause); + else if (flags & FlowFlags.SwitchClause) { + type = getTypeAtSwitchClause(flow as FlowSwitchClause); } - else if (flags & ts.FlowFlags.Label) { - if ((flow as ts.FlowLabel).antecedents!.length === 1) { - flow = (flow as ts.FlowLabel).antecedents![0]; + else if (flags & FlowFlags.Label) { + if ((flow as FlowLabel).antecedents!.length === 1) { + flow = (flow as FlowLabel).antecedents![0]; continue; } - type = flags & ts.FlowFlags.BranchLabel ? - getTypeAtFlowBranchLabel(flow as ts.FlowLabel) : - getTypeAtFlowLoopLabel(flow as ts.FlowLabel); + type = flags & FlowFlags.BranchLabel ? + getTypeAtFlowBranchLabel(flow as FlowLabel) : + getTypeAtFlowLoopLabel(flow as FlowLabel); } - else if (flags & ts.FlowFlags.ArrayMutation) { - type = getTypeAtFlowArrayMutation(flow as ts.FlowArrayMutation); + else if (flags & FlowFlags.ArrayMutation) { + type = getTypeAtFlowArrayMutation(flow as FlowArrayMutation); if (!type) { - flow = (flow as ts.FlowArrayMutation).antecedent; + flow = (flow as FlowArrayMutation).antecedent; continue; } } - else if (flags & ts.FlowFlags.ReduceLabel) { - const target = (flow as ts.FlowReduceLabel).target; + else if (flags & FlowFlags.ReduceLabel) { + const target = (flow as FlowReduceLabel).target; const saveAntecedents = target.antecedents; - target.antecedents = (flow as ts.FlowReduceLabel).antecedents; - type = getTypeAtFlowNode((flow as ts.FlowReduceLabel).antecedent); + target.antecedents = (flow as FlowReduceLabel).antecedents; + type = getTypeAtFlowNode((flow as FlowReduceLabel).antecedent); target.antecedents = saveAntecedents; } - else if (flags & ts.FlowFlags.Start) { + else if (flags & FlowFlags.Start) { // Check if we should continue with the control flow of the containing function. - const container = (flow as ts.FlowStart).node; + const container = (flow as FlowStart).node; if (container && container !== flowContainer && - reference.kind !== ts.SyntaxKind.PropertyAccessExpression && - reference.kind !== ts.SyntaxKind.ElementAccessExpression && - reference.kind !== ts.SyntaxKind.ThisKeyword) { + reference.kind !== SyntaxKind.PropertyAccessExpression && + reference.kind !== SyntaxKind.ElementAccessExpression && + reference.kind !== SyntaxKind.ThisKeyword) { flow = container.flowNode!; continue; } @@ -24854,14 +25052,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getInitialOrAssignedType(flow: ts.FlowAssignment) { + function getInitialOrAssignedType(flow: FlowAssignment) { const node = flow.node; - return getNarrowableTypeForReference(node.kind === ts.SyntaxKind.VariableDeclaration || node.kind === ts.SyntaxKind.BindingElement ? - getInitialType(node as ts.VariableDeclaration | ts.BindingElement) : + return getNarrowableTypeForReference(node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement ? + getInitialType(node as VariableDeclaration | BindingElement) : getAssignedType(node), reference); } - function getTypeAtFlowAssignment(flow: ts.FlowAssignment) { + function getTypeAtFlowAssignment(flow: FlowAssignment) { const node = flow.node; // Assignments only narrow the computed type if the declared type is a union type. Thus, we // only need to evaluate the assigned type if the declared type is a union type. @@ -24869,7 +25067,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isReachableFlowNode(flow)) { return unreachableNeverType; } - if (ts.getAssignmentTargetKind(node) === ts.AssignmentKind.Compound) { + if (getAssignmentTargetKind(node) === AssignmentKind.Compound) { const flowType = getTypeAtFlowNode(flow.antecedent); return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType)); } @@ -24880,8 +25078,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const assignedType = getWidenedLiteralType(getInitialOrAssignedType(flow)); return isTypeAssignableTo(assignedType, declaredType) ? assignedType : anyArrayType; } - if (declaredType.flags & ts.TypeFlags.Union) { - return getAssignmentReducedType(declaredType as ts.UnionType, getInitialOrAssignedType(flow)); + if (declaredType.flags & TypeFlags.Union) { + return getAssignmentReducedType(declaredType as UnionType, getInitialOrAssignedType(flow)); } return declaredType; } @@ -24895,77 +25093,77 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // A matching dotted name might also be an expando property on a function *expression*, // in which case we continue control flow analysis back to the function's declaration - if (ts.isVariableDeclaration(node) && (ts.isInJSFile(node) || ts.isVarConst(node))) { - const init = ts.getDeclaredExpandoInitializer(node); - if (init && (init.kind === ts.SyntaxKind.FunctionExpression || init.kind === ts.SyntaxKind.ArrowFunction)) { + if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) { + const init = getDeclaredExpandoInitializer(node); + if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) { return getTypeAtFlowNode(flow.antecedent); } } return declaredType; } // for (const _ in ref) acts as a nonnull on ref - if (ts.isVariableDeclaration(node) && node.parent.parent.kind === ts.SyntaxKind.ForInStatement && isMatchingReference(reference, node.parent.parent.expression)) { + if (isVariableDeclaration(node) && node.parent.parent.kind === SyntaxKind.ForInStatement && isMatchingReference(reference, node.parent.parent.expression)) { return getNonNullableTypeIfNeeded(finalizeEvolvingArrayType(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent)))); } // Assignment doesn't affect reference return undefined; } - function narrowTypeByAssertion(type: ts.Type, expr: ts.Expression): ts.Type { - const node = ts.skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true); - if (node.kind === ts.SyntaxKind.FalseKeyword) { + function narrowTypeByAssertion(type: Type, expr: Expression): Type { + const node = skipParentheses(expr, /*excludeJSDocTypeAssertions*/ true); + if (node.kind === SyntaxKind.FalseKeyword) { return unreachableNeverType; } - if (node.kind === ts.SyntaxKind.BinaryExpression) { - if ((node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) { - return narrowTypeByAssertion(narrowTypeByAssertion(type, (node as ts.BinaryExpression).left), (node as ts.BinaryExpression).right); + if (node.kind === SyntaxKind.BinaryExpression) { + if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + return narrowTypeByAssertion(narrowTypeByAssertion(type, (node as BinaryExpression).left), (node as BinaryExpression).right); } - if ((node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.BarBarToken) { - return getUnionType([narrowTypeByAssertion(type, (node as ts.BinaryExpression).left), narrowTypeByAssertion(type, (node as ts.BinaryExpression).right)]); + if ((node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken) { + return getUnionType([narrowTypeByAssertion(type, (node as BinaryExpression).left), narrowTypeByAssertion(type, (node as BinaryExpression).right)]); } } return narrowType(type, node, /*assumeTrue*/ true); } - function getTypeAtFlowCall(flow: ts.FlowCall): ts.FlowType | undefined { + function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined { const signature = getEffectsSignature(flow.node); if (signature) { const predicate = getTypePredicateOfSignature(signature); - if (predicate && (predicate.kind === ts.TypePredicateKind.AssertsThis || predicate.kind === ts.TypePredicateKind.AssertsIdentifier)) { + if (predicate && (predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier)) { const flowType = getTypeAtFlowNode(flow.antecedent); const type = finalizeEvolvingArrayType(getTypeFromFlowType(flowType)); const narrowedType = predicate.type ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) : - predicate.kind === ts.TypePredicateKind.AssertsIdentifier && predicate.parameterIndex >= 0 && predicate.parameterIndex < flow.node.arguments.length ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) : + predicate.kind === TypePredicateKind.AssertsIdentifier && predicate.parameterIndex >= 0 && predicate.parameterIndex < flow.node.arguments.length ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) : type; return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType)); } - if (getReturnTypeOfSignature(signature).flags & ts.TypeFlags.Never) { + if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) { return unreachableNeverType; } } return undefined; } - function getTypeAtFlowArrayMutation(flow: ts.FlowArrayMutation): ts.FlowType | undefined { + function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined { if (declaredType === autoType || declaredType === autoArrayType) { const node = flow.node; - const expr = node.kind === ts.SyntaxKind.CallExpression ? - (node.expression as ts.PropertyAccessExpression).expression : - (node.left as ts.ElementAccessExpression).expression; + const expr = node.kind === SyntaxKind.CallExpression ? + (node.expression as PropertyAccessExpression).expression : + (node.left as ElementAccessExpression).expression; if (isMatchingReference(reference, getReferenceCandidate(expr))) { const flowType = getTypeAtFlowNode(flow.antecedent); const type = getTypeFromFlowType(flowType); - if (ts.getObjectFlags(type) & ts.ObjectFlags.EvolvingArray) { - let evolvedType = type as ts.EvolvingArrayType; - if (node.kind === ts.SyntaxKind.CallExpression) { + if (getObjectFlags(type) & ObjectFlags.EvolvingArray) { + let evolvedType = type as EvolvingArrayType; + if (node.kind === SyntaxKind.CallExpression) { for (const arg of node.arguments) { evolvedType = addEvolvingArrayElementType(evolvedType, arg); } } else { // We must get the context free expression type so as to not recur in an uncached fashion on the LHS (which causes exponential blowup in compile time) - const indexType = getContextFreeTypeOfExpression((node.left as ts.ElementAccessExpression).argumentExpression); - if (isTypeAssignableToKind(indexType, ts.TypeFlags.NumberLike)) { + const indexType = getContextFreeTypeOfExpression((node.left as ElementAccessExpression).argumentExpression); + if (isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { evolvedType = addEvolvingArrayElementType(evolvedType, node.right); } } @@ -24977,10 +25175,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getTypeAtFlowCondition(flow: ts.FlowCondition): ts.FlowType { + function getTypeAtFlowCondition(flow: FlowCondition): FlowType { const flowType = getTypeAtFlowNode(flow.antecedent); const type = getTypeFromFlowType(flowType); - if (type.flags & ts.TypeFlags.Never) { + if (type.flags & TypeFlags.Never) { return flowType; } // If we have an antecedent type (meaning we're reachable in some way), we first @@ -24990,7 +25188,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // have the complete type. We proceed by switching to the silent never type which // doesn't report errors when operators are applied to it. Note that this is the // *only* place a silent never type is ever generated. - const assumeTrue = (flow.flags & ts.FlowFlags.TrueCondition) !== 0; + const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0; const nonEvolvingType = finalizeEvolvingArrayType(type); const narrowedType = narrowType(nonEvolvingType, flow.node, assumeTrue); if (narrowedType === nonEvolvingType) { @@ -24999,25 +25197,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createFlowType(narrowedType, isIncomplete(flowType)); } - function getTypeAtSwitchClause(flow: ts.FlowSwitchClause): ts.FlowType { + function getTypeAtSwitchClause(flow: FlowSwitchClause): FlowType { const expr = flow.switchStatement.expression; const flowType = getTypeAtFlowNode(flow.antecedent); let type = getTypeFromFlowType(flowType); if (isMatchingReference(reference, expr)) { type = narrowTypeBySwitchOnDiscriminant(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } - else if (expr.kind === ts.SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as ts.TypeOfExpression).expression)) { + else if (expr.kind === SyntaxKind.TypeOfExpression && isMatchingReference(reference, (expr as TypeOfExpression).expression)) { type = narrowTypeBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } else { if (strictNullChecks) { if (optionalChainContainsReference(expr, reference)) { type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, - t => !(t.flags & (ts.TypeFlags.Undefined | ts.TypeFlags.Never))); + t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never))); } - else if (expr.kind === ts.SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as ts.TypeOfExpression).expression, reference)) { + else if (expr.kind === SyntaxKind.TypeOfExpression && optionalChainContainsReference((expr as TypeOfExpression).expression, reference)) { type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, - t => !(t.flags & ts.TypeFlags.Never || t.flags & ts.TypeFlags.StringLiteral && (t as ts.StringLiteralType).value === "undefined")); + t => !(t.flags & TypeFlags.Never || t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === "undefined")); } } const access = getDiscriminantPropertyAccess(expr, type); @@ -25028,15 +25226,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createFlowType(type, isIncomplete(flowType)); } - function getTypeAtFlowBranchLabel(flow: ts.FlowLabel): ts.FlowType { - const antecedentTypes: ts.Type[] = []; + function getTypeAtFlowBranchLabel(flow: FlowLabel): FlowType { + const antecedentTypes: Type[] = []; let subtypeReduction = false; let seenIncomplete = false; - let bypassFlow: ts.FlowSwitchClause | undefined; + let bypassFlow: FlowSwitchClause | undefined; for (const antecedent of flow.antecedents!) { - if (!bypassFlow && antecedent.flags & ts.FlowFlags.SwitchClause && (antecedent as ts.FlowSwitchClause).clauseStart === (antecedent as ts.FlowSwitchClause).clauseEnd) { + if (!bypassFlow && antecedent.flags & FlowFlags.SwitchClause && (antecedent as FlowSwitchClause).clauseStart === (antecedent as FlowSwitchClause).clauseEnd) { // The antecedent is the bypass branch of a potentially exhaustive switch statement. - bypassFlow = antecedent as ts.FlowSwitchClause; + bypassFlow = antecedent as FlowSwitchClause; continue; } const flowType = getTypeAtFlowNode(antecedent); @@ -25048,7 +25246,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (type === declaredType && declaredType === initialType) { return type; } - ts.pushIfUnique(antecedentTypes, type); + pushIfUnique(antecedentTypes, type); // If an antecedent type is not a subset of the declared type, we need to perform // subtype reduction. This happens when a "foreign" type is injected into the control // flow using the instanceof operator or a user defined type predicate. @@ -25065,7 +25263,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the bypass flow contributes a type we haven't seen yet and the switch statement // isn't exhaustive, process the bypass flow type. Since exhaustiveness checks increase // the risk of circularities, we only want to perform them when they make a difference. - if (!ts.contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) { + if (!contains(antecedentTypes, type) && !isExhaustiveSwitchStatement(bypassFlow.switchStatement)) { if (type === declaredType && declaredType === initialType) { return type; } @@ -25078,14 +25276,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? ts.UnionReduction.Subtype : ts.UnionReduction.Literal), seenIncomplete); + return createFlowType(getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal), seenIncomplete); } - function getTypeAtFlowLoopLabel(flow: ts.FlowLabel): ts.FlowType { + function getTypeAtFlowLoopLabel(flow: FlowLabel): FlowType { // If we have previously computed the control flow type for the reference at // this flow loop junction, return the cached type. const id = getFlowNodeId(flow); - const cache = flowLoopCaches[id] || (flowLoopCaches[id] = new ts.Map()); + const cache = flowLoopCaches[id] || (flowLoopCaches[id] = new Map()); const key = getOrSetCacheKey(); if (!key) { // No cache key is generated when binding patterns are in unnarrowable situations @@ -25105,14 +25303,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // path that leads to the top. for (let i = flowLoopStart; i < flowLoopCount; i++) { if (flowLoopNodes[i] === flow && flowLoopKeys[i] === key && flowLoopTypes[i].length) { - return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], ts.UnionReduction.Literal), /*incomplete*/ true); + return createFlowType(getUnionOrEvolvingArrayType(flowLoopTypes[i], UnionReduction.Literal), /*incomplete*/ true); } } // Add the flow loop junction and reference to the in-process stack and analyze // each antecedent code path. - const antecedentTypes: ts.Type[] = []; + const antecedentTypes: Type[] = []; let subtypeReduction = false; - let firstAntecedentType: ts.FlowType | undefined; + let firstAntecedentType: FlowType | undefined; for (const antecedent of flow.antecedents!) { let flowType; if (!firstAntecedentType) { @@ -25141,7 +25339,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } const type = getTypeFromFlowType(flowType); - ts.pushIfUnique(antecedentTypes, type); + pushIfUnique(antecedentTypes, type); // If an antecedent type is not a subset of the declared type, we need to perform // subtype reduction. This happens when a "foreign" type is injected into the control // flow using the instanceof operator or a user defined type predicate. @@ -25157,7 +25355,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // The result is incomplete if the first antecedent (the non-looping control flow path) // is incomplete. - const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? ts.UnionReduction.Subtype : ts.UnionReduction.Literal); + const result = getUnionOrEvolvingArrayType(antecedentTypes, subtypeReduction ? UnionReduction.Subtype : UnionReduction.Literal); if (isIncomplete(firstAntecedentType!)) { return createFlowType(result, /*incomplete*/ true); } @@ -25168,49 +25366,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // At flow control branch or loop junctions, if the type along every antecedent code path // is an evolving array type, we construct a combined evolving array type. Otherwise we // finalize all evolving array types. - function getUnionOrEvolvingArrayType(types: ts.Type[], subtypeReduction: ts.UnionReduction) { + function getUnionOrEvolvingArrayType(types: Type[], subtypeReduction: UnionReduction) { if (isEvolvingArrayTypeList(types)) { - return getEvolvingArrayType(getUnionType(ts.map(types, getElementTypeOfEvolvingArrayType))); + return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType))); } - const result = recombineUnknownType(getUnionType(ts.sameMap(types, finalizeEvolvingArrayType), subtypeReduction)); - if (result !== declaredType && result.flags & declaredType.flags & ts.TypeFlags.Union && ts.arraysEqual((result as ts.UnionType).types, (declaredType as ts.UnionType).types)) { + const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction)); + if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) { return declaredType; } return result; } - function getCandidateDiscriminantPropertyAccess(expr: ts.Expression) { - if (ts.isBindingPattern(reference) || ts.isFunctionExpressionOrArrowFunction(reference) || ts.isObjectLiteralMethod(reference)) { + function getCandidateDiscriminantPropertyAccess(expr: Expression) { + if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { // When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in // getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or // parameter declared in the same parameter list is a candidate. - if (ts.isIdentifier(expr)) { + if (isIdentifier(expr)) { const symbol = getResolvedSymbol(expr); const declaration = symbol.valueDeclaration; - if (declaration && (ts.isBindingElement(declaration) || ts.isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { return declaration; } } } - else if (ts.isAccessExpression(expr)) { + else if (isAccessExpression(expr)) { // An access expression is a candidate if the reference matches the left hand expression. if (isMatchingReference(reference, expr.expression)) { return expr; } } - else if (ts.isIdentifier(expr)) { + else if (isIdentifier(expr)) { const symbol = getResolvedSymbol(expr); if (isConstVariable(symbol)) { const declaration = symbol.valueDeclaration!; // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind' - if (ts.isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && ts.isAccessExpression(declaration.initializer) && + if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { return declaration.initializer; } // Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind' - if (ts.isBindingElement(declaration) && !declaration.initializer) { + if (isBindingElement(declaration) && !declaration.initializer) { const parent = declaration.parent.parent; - if (ts.isVariableDeclaration(parent) && !parent.type && parent.initializer && (ts.isIdentifier(parent.initializer) || ts.isAccessExpression(parent.initializer)) && + if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && isMatchingReference(reference, parent.initializer)) { return declaration; } @@ -25220,9 +25418,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getDiscriminantPropertyAccess(expr: ts.Expression, computedType: ts.Type) { - const type = declaredType.flags & ts.TypeFlags.Union ? declaredType : computedType; - if (type.flags & ts.TypeFlags.Union) { + function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) { + const type = declaredType.flags & TypeFlags.Union ? declaredType : computedType; + if (type.flags & TypeFlags.Union) { const access = getCandidateDiscriminantPropertyAccess(expr); if (access) { const name = getAccessedPropertyName(access); @@ -25234,12 +25432,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function narrowTypeByDiscriminant(type: ts.Type, access: ts.AccessExpression | ts.BindingElement | ts.ParameterDeclaration, narrowType: (t: ts.Type) => ts.Type): ts.Type { + function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type { const propName = getAccessedPropertyName(access); if (propName === undefined) { return type; } - const removeNullable = strictNullChecks && ts.isOptionalChain(access) && maybeTypeOfKind(type, ts.TypeFlags.Nullable); + const removeNullable = strictNullChecks && isOptionalChain(access) && maybeTypeOfKind(type, TypeFlags.Nullable); let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName); if (!propType) { return type; @@ -25248,17 +25446,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const narrowedPropType = narrowType(propType); return filterType(type, t => { const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName); - return !(discriminantType.flags & ts.TypeFlags.Never) && !(narrowedPropType.flags & ts.TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType); + return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType); }); } - function narrowTypeByDiscriminantProperty(type: ts.Type, access: ts.AccessExpression | ts.BindingElement | ts.ParameterDeclaration, operator: ts.SyntaxKind, value: ts.Expression, assumeTrue: boolean) { - if ((operator === ts.SyntaxKind.EqualsEqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & ts.TypeFlags.Union) { - const keyPropertyName = getKeyPropertyName(type as ts.UnionType); + function narrowTypeByDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, operator: SyntaxKind, value: Expression, assumeTrue: boolean) { + if ((operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) && type.flags & TypeFlags.Union) { + const keyPropertyName = getKeyPropertyName(type as UnionType); if (keyPropertyName && keyPropertyName === getAccessedPropertyName(access)) { - const candidate = getConstituentTypeForKeyType(type as ts.UnionType, getTypeOfExpression(value)); + const candidate = getConstituentTypeForKeyType(type as UnionType, getTypeOfExpression(value)); if (candidate) { - return operator === (assumeTrue ? ts.SyntaxKind.EqualsEqualsEqualsToken : ts.SyntaxKind.ExclamationEqualsEqualsToken) ? candidate : + return operator === (assumeTrue ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken) ? candidate : isUnitType(getTypeOfPropertyOfType(candidate, keyPropertyName) || unknownType) ? removeType(type, candidate) : type; } @@ -25267,10 +25465,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return narrowTypeByDiscriminant(type, access, t => narrowTypeByEquality(t, operator, value, assumeTrue)); } - function narrowTypeBySwitchOnDiscriminantProperty(type: ts.Type, access: ts.AccessExpression | ts.BindingElement | ts.ParameterDeclaration, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number) { - if (clauseStart < clauseEnd && type.flags & ts.TypeFlags.Union && getKeyPropertyName(type as ts.UnionType) === getAccessedPropertyName(access)) { + function narrowTypeBySwitchOnDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { + if (clauseStart < clauseEnd && type.flags & TypeFlags.Union && getKeyPropertyName(type as UnionType) === getAccessedPropertyName(access)) { const clauseTypes = getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd); - const candidate = getUnionType(ts.map(clauseTypes, t => getConstituentTypeForKeyType(type as ts.UnionType, t) || unknownType)); + const candidate = getUnionType(map(clauseTypes, t => getConstituentTypeForKeyType(type as UnionType, t) || unknownType)); if (candidate !== unknownType) { return candidate; } @@ -25278,7 +25476,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return narrowTypeByDiscriminant(type, access, t => narrowTypeBySwitchOnDiscriminant(t, switchStatement, clauseStart, clauseEnd)); } - function narrowTypeByTruthiness(type: ts.Type, expr: ts.Expression, assumeTrue: boolean): ts.Type { + function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { if (isMatchingReference(reference, expr)) { return getAdjustedTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy); } @@ -25292,14 +25490,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function isTypePresencePossible(type: ts.Type, propName: ts.__String, assumeTrue: boolean) { + function isTypePresencePossible(type: Type, propName: __String, assumeTrue: boolean) { const prop = getPropertyOfType(type, propName); return prop ? - !!(prop.flags & ts.SymbolFlags.Optional) || assumeTrue : + !!(prop.flags & SymbolFlags.Optional) || assumeTrue : !!getApplicableIndexInfoForName(type, propName) || !assumeTrue; } - function narrowTypeByInKeyword(type: ts.Type, nameType: ts.StringLiteralType | ts.NumberLiteralType | ts.UniqueESSymbolType, assumeTrue: boolean) { + function narrowTypeByInKeyword(type: Type, nameType: StringLiteralType | NumberLiteralType | UniqueESSymbolType, assumeTrue: boolean) { const name = getPropertyNameFromType(nameType); const isKnownProperty = someType(type, t => isTypePresencePossible(t, name, /*assumeTrue*/ true)); if (isKnownProperty) { @@ -25318,25 +25516,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function narrowTypeByBinaryExpression(type: ts.Type, expr: ts.BinaryExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { switch (expr.operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.BarBarEqualsToken: - case ts.SyntaxKind.AmpersandAmpersandEqualsToken: - case ts.SyntaxKind.QuestionQuestionEqualsToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue); - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: const operator = expr.operatorToken.kind; const left = getReferenceCandidate(expr.left); const right = getReferenceCandidate(expr.right); - if (left.kind === ts.SyntaxKind.TypeOfExpression && ts.isStringLiteralLike(right)) { - return narrowTypeByTypeof(type, left as ts.TypeOfExpression, operator, right, assumeTrue); + if (left.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(right)) { + return narrowTypeByTypeof(type, left as TypeOfExpression, operator, right, assumeTrue); } - if (right.kind === ts.SyntaxKind.TypeOfExpression && ts.isStringLiteralLike(left)) { - return narrowTypeByTypeof(type, right as ts.TypeOfExpression, operator, left, assumeTrue); + if (right.kind === SyntaxKind.TypeOfExpression && isStringLiteralLike(left)) { + return narrowTypeByTypeof(type, right as TypeOfExpression, operator, left, assumeTrue); } if (isMatchingReference(reference, left)) { return narrowTypeByEquality(type, operator, right, assumeTrue); @@ -25367,34 +25565,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return narrowTypeByConstructor(type, operator, left, assumeTrue); } break; - case ts.SyntaxKind.InstanceOfKeyword: + case SyntaxKind.InstanceOfKeyword: return narrowTypeByInstanceof(type, expr, assumeTrue); - case ts.SyntaxKind.InKeyword: - if (ts.isPrivateIdentifier(expr.left)) { + case SyntaxKind.InKeyword: + if (isPrivateIdentifier(expr.left)) { return narrowTypeByPrivateIdentifierInInExpression(type, expr, assumeTrue); } const target = getReferenceCandidate(expr.right); const leftType = getTypeOfExpression(expr.left); - if (leftType.flags & ts.TypeFlags.StringOrNumberLiteralOrUnique) { - if (containsMissingType(type) && ts.isAccessExpression(reference) && isMatchingReference(reference.expression, target) && - getAccessedPropertyName(reference) === getPropertyNameFromType(leftType as ts.StringLiteralType | ts.NumberLiteralType | ts.UniqueESSymbolType)) { + if (leftType.flags & TypeFlags.StringOrNumberLiteralOrUnique) { + if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target) && + getAccessedPropertyName(reference) === getPropertyNameFromType(leftType as StringLiteralType | NumberLiteralType | UniqueESSymbolType)) { return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); } if (isMatchingReference(reference, target)) { - return narrowTypeByInKeyword(type, leftType as ts.StringLiteralType | ts.NumberLiteralType | ts.UniqueESSymbolType, assumeTrue); + return narrowTypeByInKeyword(type, leftType as StringLiteralType | NumberLiteralType | UniqueESSymbolType, assumeTrue); } } break; - case ts.SyntaxKind.CommaToken: + case SyntaxKind.CommaToken: return narrowType(type, expr.right, assumeTrue); // Ordinarily we won't see && and || expressions in control flow analysis because the Binder breaks those // expressions down to individual conditional control flows. However, we may encounter them when analyzing // aliased conditional expressions. - case ts.SyntaxKind.AmpersandAmpersandToken: + case SyntaxKind.AmpersandAmpersandToken: return assumeTrue ? narrowType(narrowType(type, expr.left, /*assumeTrue*/ true), expr.right, /*assumeTrue*/ true) : getUnionType([narrowType(type, expr.left, /*assumeTrue*/ false), narrowType(type, expr.right, /*assumeTrue*/ false)]); - case ts.SyntaxKind.BarBarToken: + case SyntaxKind.BarBarToken: return assumeTrue ? getUnionType([narrowType(type, expr.left, /*assumeTrue*/ true), narrowType(type, expr.right, /*assumeTrue*/ true)]) : narrowType(narrowType(type, expr.left, /*assumeTrue*/ false), expr.right, /*assumeTrue*/ false); @@ -25402,25 +25600,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function narrowTypeByPrivateIdentifierInInExpression(type: ts.Type, expr: ts.BinaryExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByPrivateIdentifierInInExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { const target = getReferenceCandidate(expr.right); if (!isMatchingReference(reference, target)) { return type; } - ts.Debug.assertNode(expr.left, ts.isPrivateIdentifier); + Debug.assertNode(expr.left, isPrivateIdentifier); const symbol = getSymbolForPrivateIdentifierExpression(expr.left); if (symbol === undefined) { return type; } const classSymbol = symbol.parent!; - const targetType = ts.hasStaticModifier(ts.Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration")) - ? getTypeOfSymbol(classSymbol) as ts.InterfaceType + const targetType = hasStaticModifier(Debug.checkDefined(symbol.valueDeclaration, "should always have a declaration")) + ? getTypeOfSymbol(classSymbol) as InterfaceType : getDeclaredTypeOfSymbol(classSymbol); return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true); } - function narrowTypeByOptionalChainContainment(type: ts.Type, operator: ts.SyntaxKind, value: ts.Expression, assumeTrue: boolean): ts.Type { + function narrowTypeByOptionalChainContainment(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type { // We are in a branch of obj?.foo === value (or any one of the other equality operators). We narrow obj as follows: // When operator is === and type of value excludes undefined, null and undefined is removed from type of obj in true branch. // When operator is !== and type of value excludes undefined, null and undefined is removed from type of obj in false branch. @@ -25430,41 +25628,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When operator is !== and type of value is undefined, null and undefined is removed from type of obj in true branch. // When operator is == and type of value is null or undefined, null and undefined is removed from type of obj in false branch. // When operator is != and type of value is null or undefined, null and undefined is removed from type of obj in true branch. - const equalsOperator = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.EqualsEqualsEqualsToken; - const nullableFlags = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken ? ts.TypeFlags.Nullable : ts.TypeFlags.Undefined; + const equalsOperator = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken; + const nullableFlags = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? TypeFlags.Nullable : TypeFlags.Undefined; const valueType = getTypeOfExpression(value); // Note that we include any and unknown in the exclusion test because their domain includes null and undefined. const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) || - equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (ts.TypeFlags.AnyOrUnknown | nullableFlags))); + equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags))); return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } - function narrowTypeByEquality(type: ts.Type, operator: ts.SyntaxKind, value: ts.Expression, assumeTrue: boolean): ts.Type { - if (type.flags & ts.TypeFlags.Any) { + function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type { + if (type.flags & TypeFlags.Any) { return type; } - if (operator === ts.SyntaxKind.ExclamationEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsEqualsToken) { + if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } const valueType = getTypeOfExpression(value); - const doubleEquals = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken; - if (valueType.flags & ts.TypeFlags.Nullable) { + const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; + if (valueType.flags & TypeFlags.Nullable) { if (!strictNullChecks) { return type; } const facts = doubleEquals ? assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull : - valueType.flags & ts.TypeFlags.Null ? + valueType.flags & TypeFlags.Null ? assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull : assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined; return getAdjustedTypeWithFacts(type, facts); } if (assumeTrue) { - if (!doubleEquals && (type.flags & ts.TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) { - if (valueType.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) { + if (!doubleEquals && (type.flags & TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) { + if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) { return valueType; } - if (valueType.flags & ts.TypeFlags.Object) { + if (valueType.flags & TypeFlags.Object) { return nonPrimitiveType; } } @@ -25477,9 +25675,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function narrowTypeByTypeof(type: ts.Type, typeOfExpr: ts.TypeOfExpression, operator: ts.SyntaxKind, literal: ts.LiteralExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type { // We have '==', '!=', '===', or !==' operator with 'typeof xxx' and string literal operands - if (operator === ts.SyntaxKind.ExclamationEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsEqualsToken) { + if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } const target = getReferenceCandidate(typeOfExpr.expression); @@ -25496,18 +25694,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return narrowTypeByLiteralExpression(type, literal, assumeTrue); } - function narrowTypeByLiteralExpression(type: ts.Type, literal: ts.LiteralExpression, assumeTrue: boolean) { + function narrowTypeByLiteralExpression(type: Type, literal: LiteralExpression, assumeTrue: boolean) { return assumeTrue ? narrowTypeByTypeName(type, literal.text) : getTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject); } - function narrowTypeBySwitchOptionalChainContainment(type: ts.Type, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: ts.Type) => boolean) { - const everyClauseChecks = clauseStart !== clauseEnd && ts.every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck); + function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) { + const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck); return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; } - function narrowTypeBySwitchOnDiscriminant(type: ts.Type, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number) { + function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { // We only narrow if all case expressions specify // values with unit types, except for the case where // `type` is unknown. In this instance we map object @@ -25517,17 +25715,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } const clauseTypes = switchTypes.slice(clauseStart, clauseEnd); - const hasDefaultClause = clauseStart === clauseEnd || ts.contains(clauseTypes, neverType); - if ((type.flags & ts.TypeFlags.Unknown) && !hasDefaultClause) { - let groundClauseTypes: ts.Type[] | undefined; + const hasDefaultClause = clauseStart === clauseEnd || contains(clauseTypes, neverType); + if ((type.flags & TypeFlags.Unknown) && !hasDefaultClause) { + let groundClauseTypes: Type[] | undefined; for (let i = 0; i < clauseTypes.length; i += 1) { const t = clauseTypes[i]; - if (t.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.NonPrimitive)) { + if (t.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive)) { if (groundClauseTypes !== undefined) { groundClauseTypes.push(t); } } - else if (t.flags & ts.TypeFlags.Object) { + else if (t.flags & TypeFlags.Object) { if (groundClauseTypes === undefined) { groundClauseTypes = clauseTypes.slice(0, i); } @@ -25541,30 +25739,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const discriminantType = getUnionType(clauseTypes); const caseType = - discriminantType.flags & ts.TypeFlags.Never ? neverType : + discriminantType.flags & TypeFlags.Never ? neverType : replacePrimitivesWithLiterals(filterType(type, t => areTypesComparable(discriminantType, t)), discriminantType); if (!hasDefaultClause) { return caseType; } - const defaultType = filterType(type, t => !(isUnitLikeType(t) && ts.contains(switchTypes, getRegularTypeOfLiteralType(extractUnitType(t))))); - return caseType.flags & ts.TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); + const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, getRegularTypeOfLiteralType(extractUnitType(t))))); + return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]); } - function narrowTypeByTypeName(type: ts.Type, typeName: string) { + function narrowTypeByTypeName(type: Type, typeName: string) { switch (typeName) { case "string": return narrowTypeByTypeFacts(type, stringType, TypeFacts.TypeofEQString); case "number": return narrowTypeByTypeFacts(type, numberType, TypeFacts.TypeofEQNumber); case "bigint": return narrowTypeByTypeFacts(type, bigintType, TypeFacts.TypeofEQBigInt); case "boolean": return narrowTypeByTypeFacts(type, booleanType, TypeFacts.TypeofEQBoolean); case "symbol": return narrowTypeByTypeFacts(type, esSymbolType, TypeFacts.TypeofEQSymbol); - case "object": return type.flags & ts.TypeFlags.Any ? type : getUnionType([narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQObject), narrowTypeByTypeFacts(type, nullType, TypeFacts.EQNull)]); - case "function": return type.flags & ts.TypeFlags.Any ? type : narrowTypeByTypeFacts(type, globalFunctionType, TypeFacts.TypeofEQFunction); + case "object": return type.flags & TypeFlags.Any ? type : getUnionType([narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQObject), narrowTypeByTypeFacts(type, nullType, TypeFacts.EQNull)]); + case "function": return type.flags & TypeFlags.Any ? type : narrowTypeByTypeFacts(type, globalFunctionType, TypeFacts.TypeofEQFunction); case "undefined": return narrowTypeByTypeFacts(type, undefinedType, TypeFacts.EQUndefined); } return narrowTypeByTypeFacts(type, nonPrimitiveType, TypeFacts.TypeofEQHostObject); } - function narrowTypeByTypeFacts(type: ts.Type, impliedType: ts.Type, facts: TypeFacts) { + function narrowTypeByTypeFacts(type: Type, impliedType: Type, facts: TypeFacts) { return mapType(type, t => // We first check if a constituent is a subtype of the implied type. If so, we either keep or eliminate // the constituent based on its type facts. We use the strict subtype relation because it treats `object` @@ -25581,13 +25779,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { neverType); } - function narrowTypeBySwitchOnTypeOf(type: ts.Type, switchStatement: ts.SwitchStatement, clauseStart: number, clauseEnd: number): ts.Type { + function narrowTypeBySwitchOnTypeOf(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type { const witnesses = getSwitchClauseTypeOfWitnesses(switchStatement); if (!witnesses) { return type; } // Equal start and end denotes implicit fallthrough; undefined marks explicit default clause. - const defaultIndex = ts.findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === ts.SyntaxKind.DefaultClause); + const defaultIndex = findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.DefaultClause); const hasDefaultClause = clauseStart === clauseEnd || (defaultIndex >= clauseStart && defaultIndex < clauseEnd); if (hasDefaultClause) { // In the default clause we filter constituents down to those that are not-equal to all handled cases. @@ -25596,18 +25794,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // In the non-default cause we create a union of the type narrowed by each of the listed cases. const clauseWitnesses = witnesses.slice(clauseStart, clauseEnd); - return getUnionType(ts.map(clauseWitnesses, text => text ? narrowTypeByTypeName(type, text) : neverType)); + return getUnionType(map(clauseWitnesses, text => text ? narrowTypeByTypeName(type, text) : neverType)); } - function isMatchingConstructorReference(expr: ts.Expression) { - return (ts.isPropertyAccessExpression(expr) && ts.idText(expr.name) === "constructor" || - ts.isElementAccessExpression(expr) && ts.isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") && + function isMatchingConstructorReference(expr: Expression) { + return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" || + isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") && isMatchingReference(reference, expr.expression); } - function narrowTypeByConstructor(type: ts.Type, operator: ts.SyntaxKind, identifier: ts.Expression, assumeTrue: boolean): ts.Type { + function narrowTypeByConstructor(type: Type, operator: SyntaxKind, identifier: Expression, assumeTrue: boolean): Type { // Do not narrow when checking inequality. - if (assumeTrue ? (operator !== ts.SyntaxKind.EqualsEqualsToken && operator !== ts.SyntaxKind.EqualsEqualsEqualsToken) : (operator !== ts.SyntaxKind.ExclamationEqualsToken && operator !== ts.SyntaxKind.ExclamationEqualsEqualsToken)) { + if (assumeTrue ? (operator !== SyntaxKind.EqualsEqualsToken && operator !== SyntaxKind.EqualsEqualsEqualsToken) : (operator !== SyntaxKind.ExclamationEqualsToken && operator !== SyntaxKind.ExclamationEqualsEqualsToken)) { return type; } @@ -25618,7 +25816,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Get the prototype property of the type identifier so we can find out its type. - const prototypeProperty = getPropertyOfType(identifierType, "prototype" as ts.__String); + const prototypeProperty = getPropertyOfType(identifierType, "prototype" as __String); if (!prototypeProperty) { return type; } @@ -25638,13 +25836,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Filter out types that are not considered to be "constructed by" the `candidate` type. return filterType(type, t => isConstructedBy(t, candidate)); - function isConstructedBy(source: ts.Type, target: ts.Type) { + function isConstructedBy(source: Type, target: Type) { // If either the source or target type are a class type then we need to check that they are the same exact type. // This is because you may have a class `A` that defines some set of properties, and another class `B` // that defines the same set of properties as class `A`, in that case they are structurally the same // type, but when you do something like `instanceOfA.constructor === B` it will return false. - if (source.flags & ts.TypeFlags.Object && ts.getObjectFlags(source) & ts.ObjectFlags.Class || - target.flags & ts.TypeFlags.Object && ts.getObjectFlags(target) & ts.ObjectFlags.Class) { + if (source.flags & TypeFlags.Object && getObjectFlags(source) & ObjectFlags.Class || + target.flags & TypeFlags.Object && getObjectFlags(target) & ObjectFlags.Class) { return source.symbol === target.symbol; } @@ -25653,7 +25851,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function narrowTypeByInstanceof(type: ts.Type, expr: ts.BinaryExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { const left = getReferenceCandidate(expr.left); if (!isMatchingReference(reference, left)) { if (assumeTrue && strictNullChecks && optionalChainContainsReference(left, reference)) { @@ -25668,8 +25866,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - let targetType: ts.Type | undefined; - const prototypeProperty = getPropertyOfType(rightType, "prototype" as ts.__String); + let targetType: Type | undefined; + const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String); if (prototypeProperty) { // Target type is type of the prototype property const prototypePropertyType = getTypeOfSymbol(prototypeProperty); @@ -25684,41 +25882,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (!targetType) { - const constructSignatures = getSignaturesOfType(rightType, ts.SignatureKind.Construct); + const constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct); targetType = constructSignatures.length ? - getUnionType(ts.map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))) : + getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))) : emptyObjectType; } // We can't narrow a union based off instanceof without negated types see #31576 for more info - if (!assumeTrue && rightType.flags & ts.TypeFlags.Union) { - const nonConstructorTypeInUnion = ts.find((rightType as ts.UnionType).types, (t) => !isConstructorType(t)); + if (!assumeTrue && rightType.flags & TypeFlags.Union) { + const nonConstructorTypeInUnion = find((rightType as UnionType).types, (t) => !isConstructorType(t)); if (!nonConstructorTypeInUnion) return type; } return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true); } - function getNarrowedType(type: ts.Type, candidate: ts.Type, assumeTrue: boolean, checkDerived: boolean) { - const key = type.flags & ts.TypeFlags.Union ? `N${getTypeId(type)},${getTypeId(candidate)},${(assumeTrue ? 1 : 0) | (checkDerived ? 2 : 0)}` : undefined; + function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) { + const key = type.flags & TypeFlags.Union ? `N${getTypeId(type)},${getTypeId(candidate)},${(assumeTrue ? 1 : 0) | (checkDerived ? 2 : 0)}` : undefined; return getCachedType(key) ?? setCachedType(key, getNarrowedTypeWorker(type, candidate, assumeTrue, checkDerived)); } - function getNarrowedTypeWorker(type: ts.Type, candidate: ts.Type, assumeTrue: boolean, checkDerived: boolean) { + function getNarrowedTypeWorker(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) { const isRelated = checkDerived ? isTypeDerivedFrom : isTypeSubtypeOf; if (!assumeTrue) { return filterType(type, t => !isRelated(t, candidate)); } - if (type.flags & ts.TypeFlags.AnyOrUnknown) { + if (type.flags & TypeFlags.AnyOrUnknown) { return candidate; } // We first attempt to filter the current type, narrowing constituents as appropriate and removing // constituents that are unrelated to the candidate. - const keyPropertyName = type.flags & ts.TypeFlags.Union ? getKeyPropertyName(type as ts.UnionType) : undefined; + const keyPropertyName = type.flags & TypeFlags.Union ? getKeyPropertyName(type as UnionType) : undefined; const narrowedType = mapType(candidate, c => { // If a discriminant property is available, use that to reduce the type. const discriminant = keyPropertyName && getTypeOfPropertyOfType(c, keyPropertyName); - const matching = discriminant && getConstituentTypeForKeyType(type as ts.UnionType, discriminant); + const matching = discriminant && getConstituentTypeForKeyType(type as UnionType, discriminant); // For each constituent t in the current type, if t and and c are directly related, pick the most // specific of the two. When t and c are related in both directions, we prefer c for type predicates // because that is the asserted type, but t for `instanceof` because generics aren't reflected in @@ -25728,33 +25926,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { t => isTypeSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : neverType); // If no constituents are directly related, create intersections for any generic constituents that // are related by constraint. - return directlyRelated.flags & ts.TypeFlags.Never ? - mapType(type, t => maybeTypeOfKind(t, ts.TypeFlags.Instantiable) && isRelated(c, getBaseConstraintOfType(t) || unknownType) ? getIntersectionType([t, c]) : neverType) : + return directlyRelated.flags & TypeFlags.Never ? + mapType(type, t => maybeTypeOfKind(t, TypeFlags.Instantiable) && isRelated(c, getBaseConstraintOfType(t) || unknownType) ? getIntersectionType([t, c]) : neverType) : directlyRelated; }); // If filtering produced a non-empty type, return that. Otherwise, pick the most specific of the two // based on assignability, or as a last resort produce an intersection. - return !(narrowedType.flags & ts.TypeFlags.Never) ? narrowedType : + return !(narrowedType.flags & TypeFlags.Never) ? narrowedType : isTypeSubtypeOf(candidate, type) ? candidate : isTypeAssignableTo(type, candidate) ? type : isTypeAssignableTo(candidate, type) ? candidate : getIntersectionType([type, candidate]); } - function narrowTypeByCallExpression(type: ts.Type, callExpression: ts.CallExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type { if (hasMatchingArgument(callExpression, reference)) { - const signature = assumeTrue || !ts.isCallChain(callExpression) ? getEffectsSignature(callExpression) : undefined; + const signature = assumeTrue || !isCallChain(callExpression) ? getEffectsSignature(callExpression) : undefined; const predicate = signature && getTypePredicateOfSignature(signature); - if (predicate && (predicate.kind === ts.TypePredicateKind.This || predicate.kind === ts.TypePredicateKind.Identifier)) { + if (predicate && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier)) { return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue); } } - if (containsMissingType(type) && ts.isAccessExpression(reference) && ts.isPropertyAccessExpression(callExpression.expression)) { + if (containsMissingType(type) && isAccessExpression(reference) && isPropertyAccessExpression(callExpression.expression)) { const callAccess = callExpression.expression; if (isMatchingReference(reference.expression, getReferenceCandidate(callAccess.expression)) && - ts.isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" && callExpression.arguments.length === 1) { + isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" && callExpression.arguments.length === 1) { const argument = callExpression.arguments[0]; - if (ts.isStringLiteralLike(argument) && getAccessedPropertyName(reference) === ts.escapeLeadingUnderscores(argument.text)) { + if (isStringLiteralLike(argument) && getAccessedPropertyName(reference) === escapeLeadingUnderscores(argument.text)) { return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); } } @@ -25762,7 +25960,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function narrowTypeByTypePredicate(type: ts.Type, predicate: ts.TypePredicate, callExpression: ts.CallExpression, assumeTrue: boolean): ts.Type { + function narrowTypeByTypePredicate(type: Type, predicate: TypePredicate, callExpression: CallExpression, assumeTrue: boolean): Type { // Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function' if (predicate.type && !(isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType))) { const predicateArgument = getTypePredicateArgument(predicate, callExpression); @@ -25785,21 +25983,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Narrow the given type based on the given expression having the assumed boolean value. The returned type // will be a subtype or the same type as the argument. - function narrowType(type: ts.Type, expr: ts.Expression, assumeTrue: boolean): ts.Type { + function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type { // for `a?.b`, we emulate a synthetic `a !== null && a !== undefined` condition for `a` - if (ts.isExpressionOfOptionalChainRoot(expr) || - ts.isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) { + if (isExpressionOfOptionalChainRoot(expr) || + isBinaryExpression(expr.parent) && expr.parent.operatorToken.kind === SyntaxKind.QuestionQuestionToken && expr.parent.left === expr) { return narrowTypeByOptionality(type, expr, assumeTrue); } switch (expr.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: // When narrowing a reference to a const variable, non-assigned parameter, or readonly property, we inline // up to five levels of aliased conditional expressions that are themselves declared as const variables. if (!isMatchingReference(reference, expr) && inlineLevel < 5) { - const symbol = getResolvedSymbol(expr as ts.Identifier); + const symbol = getResolvedSymbol(expr as Identifier); if (isConstVariable(symbol)) { const declaration = symbol.valueDeclaration; - if (declaration && ts.isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) { + if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) { inlineLevel++; const result = narrowType(type, declaration.initializer, assumeTrue); inlineLevel--; @@ -25808,28 +26006,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } // falls through - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.SuperKeyword: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return narrowTypeByTruthiness(type, expr, assumeTrue); - case ts.SyntaxKind.CallExpression: - return narrowTypeByCallExpression(type, expr as ts.CallExpression, assumeTrue); - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.NonNullExpression: - return narrowType(type, (expr as ts.ParenthesizedExpression | ts.NonNullExpression).expression, assumeTrue); - case ts.SyntaxKind.BinaryExpression: - return narrowTypeByBinaryExpression(type, expr as ts.BinaryExpression, assumeTrue); - case ts.SyntaxKind.PrefixUnaryExpression: - if ((expr as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.ExclamationToken) { - return narrowType(type, (expr as ts.PrefixUnaryExpression).operand, !assumeTrue); + case SyntaxKind.CallExpression: + return narrowTypeByCallExpression(type, expr as CallExpression, assumeTrue); + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NonNullExpression: + return narrowType(type, (expr as ParenthesizedExpression | NonNullExpression).expression, assumeTrue); + case SyntaxKind.BinaryExpression: + return narrowTypeByBinaryExpression(type, expr as BinaryExpression, assumeTrue); + case SyntaxKind.PrefixUnaryExpression: + if ((expr as PrefixUnaryExpression).operator === SyntaxKind.ExclamationToken) { + return narrowType(type, (expr as PrefixUnaryExpression).operand, !assumeTrue); } break; } return type; } - function narrowTypeByOptionality(type: ts.Type, expr: ts.Expression, assumePresent: boolean): ts.Type { + function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type { if (isMatchingReference(reference, expr)) { return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull); } @@ -25841,25 +26039,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeOfSymbolAtLocation(symbol: ts.Symbol, location: ts.Node) { + function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) { symbol = symbol.exportSymbol || symbol; // If we have an identifier or a property access at the given location, if the location is // an dotted name expression, and if the location is not an assignment target, obtain the type // of the expression (which will reflect control flow analysis). If the expression indeed // resolved to the given symbol, return the narrowed type. - if (location.kind === ts.SyntaxKind.Identifier || location.kind === ts.SyntaxKind.PrivateIdentifier) { - if (ts.isRightSideOfQualifiedNameOrPropertyAccess(location)) { + if (location.kind === SyntaxKind.Identifier || location.kind === SyntaxKind.PrivateIdentifier) { + if (isRightSideOfQualifiedNameOrPropertyAccess(location)) { location = location.parent; } - if (ts.isExpressionNode(location) && (!ts.isAssignmentTarget(location) || ts.isWriteAccess(location))) { - const type = getTypeOfExpression(location as ts.Expression); + if (isExpressionNode(location) && (!isAssignmentTarget(location) || isWriteAccess(location))) { + const type = getTypeOfExpression(location as Expression); if (getExportSymbolOfValueSymbolIfExported(getNodeLinks(location).resolvedSymbol) === symbol) { return type; } } } - if (ts.isDeclarationName(location) && ts.isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) { + if (isDeclarationName(location) && isSetAccessor(location.parent) && getAnnotatedAccessorTypeNode(location.parent)) { return getWriteTypeOfAccessors(location.parent.symbol); } // The location isn't a reference to the given symbol, meaning we're being asked @@ -25870,23 +26068,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getNonMissingTypeOfSymbol(symbol); } - function getControlFlowContainer(node: ts.Node): ts.Node { - return ts.findAncestor(node.parent, node => - ts.isFunctionLike(node) && !ts.getImmediatelyInvokedFunctionExpression(node) || - node.kind === ts.SyntaxKind.ModuleBlock || - node.kind === ts.SyntaxKind.SourceFile || - node.kind === ts.SyntaxKind.PropertyDeclaration)!; + function getControlFlowContainer(node: Node): Node { + return findAncestor(node.parent, node => + isFunctionLike(node) && !getImmediatelyInvokedFunctionExpression(node) || + node.kind === SyntaxKind.ModuleBlock || + node.kind === SyntaxKind.SourceFile || + node.kind === SyntaxKind.PropertyDeclaration)!; } // Check if a parameter or catch variable is assigned anywhere - function isSymbolAssigned(symbol: ts.Symbol) { + function isSymbolAssigned(symbol: Symbol) { if (!symbol.valueDeclaration) { return false; } - const parent = ts.getRootDeclaration(symbol.valueDeclaration).parent; + const parent = getRootDeclaration(symbol.valueDeclaration).parent; const links = getNodeLinks(parent); - if (!(links.flags & ts.NodeCheckFlags.AssignmentsMarked)) { - links.flags |= ts.NodeCheckFlags.AssignmentsMarked; + if (!(links.flags & NodeCheckFlags.AssignmentsMarked)) { + links.flags |= NodeCheckFlags.AssignmentsMarked; if (!hasParentWithAssignmentsMarked(parent)) { markNodeAssignments(parent); } @@ -25894,34 +26092,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol.isAssigned || false; } - function hasParentWithAssignmentsMarked(node: ts.Node) { - return !!ts.findAncestor(node.parent, node => - (ts.isFunctionLike(node) || ts.isCatchClause(node)) && !!(getNodeLinks(node).flags & ts.NodeCheckFlags.AssignmentsMarked)); + function hasParentWithAssignmentsMarked(node: Node) { + return !!findAncestor(node.parent, node => + (isFunctionLike(node) || isCatchClause(node)) && !!(getNodeLinks(node).flags & NodeCheckFlags.AssignmentsMarked)); } - function markNodeAssignments(node: ts.Node) { - if (node.kind === ts.SyntaxKind.Identifier) { - if (ts.isAssignmentTarget(node)) { - const symbol = getResolvedSymbol(node as ts.Identifier); - if (ts.isParameterOrCatchClauseVariable(symbol)) { + function markNodeAssignments(node: Node) { + if (node.kind === SyntaxKind.Identifier) { + if (isAssignmentTarget(node)) { + const symbol = getResolvedSymbol(node as Identifier); + if (isParameterOrCatchClauseVariable(symbol)) { symbol.isAssigned = true; } } } else { - ts.forEachChild(node, markNodeAssignments); + forEachChild(node, markNodeAssignments); } } - function isConstVariable(symbol: ts.Symbol) { - return symbol.flags & ts.SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & ts.NodeFlags.Const) !== 0; + function isConstVariable(symbol: Symbol) { + return symbol.flags & SymbolFlags.Variable && (getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const) !== 0; } /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ - function removeOptionalityFromDeclaredType(declaredType: ts.Type, declaration: ts.VariableLikeDeclaration): ts.Type { + function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type { if (pushTypeResolution(declaration.symbol, TypeSystemPropertyName.DeclaredType)) { const annotationIncludesUndefined = strictNullChecks && - declaration.kind === ts.SyntaxKind.Parameter && + declaration.kind === SyntaxKind.Parameter && declaration.initializer && getTypeFacts(declaredType) & TypeFacts.IsUndefined && !(getTypeFacts(checkExpression(declaration.initializer)) & TypeFacts.IsUndefined); @@ -25935,44 +26133,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isConstraintPosition(type: ts.Type, node: ts.Node) { + function isConstraintPosition(type: Type, node: Node) { const parent = node.parent; // In an element access obj[x], we consider obj to be in a constraint position, except when obj is of // a generic type without a nullable constraint and x is a generic type. This is because when both obj // and x are of generic types T and K, we want the resulting type to be T[K]. - return parent.kind === ts.SyntaxKind.PropertyAccessExpression || - parent.kind === ts.SyntaxKind.QualifiedName || - parent.kind === ts.SyntaxKind.CallExpression && (parent as ts.CallExpression).expression === node || - parent.kind === ts.SyntaxKind.ElementAccessExpression && (parent as ts.ElementAccessExpression).expression === node && - !(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ts.ElementAccessExpression).argumentExpression))); + return parent.kind === SyntaxKind.PropertyAccessExpression || + parent.kind === SyntaxKind.QualifiedName || + parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node || + parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node && + !(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression))); } - function isGenericTypeWithUnionConstraint(type: ts.Type): boolean { - return type.flags & ts.TypeFlags.Intersection ? - ts.some((type as ts.IntersectionType).types, isGenericTypeWithUnionConstraint) : - !!(type.flags & ts.TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (ts.TypeFlags.Nullable | ts.TypeFlags.Union)); + function isGenericTypeWithUnionConstraint(type: Type): boolean { + return type.flags & TypeFlags.Intersection ? + some((type as IntersectionType).types, isGenericTypeWithUnionConstraint) : + !!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union)); } - function isGenericTypeWithoutNullableConstraint(type: ts.Type): boolean { - return type.flags & ts.TypeFlags.Intersection ? - ts.some((type as ts.IntersectionType).types, isGenericTypeWithoutNullableConstraint) : - !!(type.flags & ts.TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), ts.TypeFlags.Nullable)); + function isGenericTypeWithoutNullableConstraint(type: Type): boolean { + return type.flags & TypeFlags.Intersection ? + some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) : + !!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable)); } - function hasContextualTypeWithNoGenericTypes(node: ts.Node, checkMode: CheckMode | undefined) { + function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) { // Computing the contextual type for a child of a JSX element involves resolving the type of the // element's tag name, so we exclude that here to avoid circularities. // If check mode has `CheckMode.RestBindingElement`, we skip binding pattern contextual types, // as we want the type of a rest element to be generic when possible. - const contextualType = (ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) && - !((ts.isJsxOpeningElement(node.parent) || ts.isJsxSelfClosingElement(node.parent)) && node.parent.tagName === node) && + const contextualType = (isIdentifier(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node)) && + !((isJsxOpeningElement(node.parent) || isJsxSelfClosingElement(node.parent)) && node.parent.tagName === node) && (checkMode && checkMode & CheckMode.RestBindingElement ? - getContextualType(node, ts.ContextFlags.SkipBindingPatterns) + getContextualType(node, ContextFlags.SkipBindingPatterns) : getContextualType(node, /*contextFlags*/ undefined)); return contextualType && !isGenericType(contextualType); } - function getNarrowableTypeForReference(type: ts.Type, reference: ts.Node, checkMode?: CheckMode) { + function getNarrowableTypeForReference(type: Type, reference: Node, checkMode?: CheckMode) { // When the type of a reference is or contains an instantiable type with a union type constraint, and // when the reference is in a constraint position (where it is known we'll obtain the apparent type) or // has a contextual type containing no top-level instantiables (meaning constraints will determine @@ -25986,31 +26184,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return substituteConstraints ? mapType(type, getBaseConstraintOrType) : type; } - function isExportOrExportExpression(location: ts.Node) { - return !!ts.findAncestor(location, n => { + function isExportOrExportExpression(location: Node) { + return !!findAncestor(location, n => { const parent = n.parent; if (parent === undefined) { return "quit"; } - if (ts.isExportAssignment(parent)) { - return parent.expression === n && ts.isEntityNameExpression(n); + if (isExportAssignment(parent)) { + return parent.expression === n && isEntityNameExpression(n); } - if (ts.isExportSpecifier(parent)) { + if (isExportSpecifier(parent)) { return parent.name === n || parent.propertyName === n; } return false; }); } - function markAliasReferenced(symbol: ts.Symbol, location: ts.Node) { - if (isNonLocalAlias(symbol, /*excludes*/ ts.SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol, ts.SymbolFlags.Value)) { + function markAliasReferenced(symbol: Symbol, location: Node) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(location) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { const target = resolveAlias(symbol); - if (getAllSymbolFlags(target) & (ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue)) { + if (getAllSymbolFlags(target) & (SymbolFlags.Value | SymbolFlags.ExportValue)) { // An alias resolving to a const enum cannot be elided if (1) 'isolatedModules' is enabled // (because the const enum value will not be inlined), or if (2) the alias is an export // of a const enum declaration that will be preserved. if (compilerOptions.isolatedModules || - ts.shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(location) || + shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(location) || !isConstEnumOrConstEnumOnlyModule(getExportSymbolOfValueSymbolIfExported(target)) ) { markAliasSymbolAsReferenced(symbol); @@ -26022,7 +26220,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getNarrowedTypeOfSymbol(symbol: ts.Symbol, location: ts.Identifier) { + function getNarrowedTypeOfSymbol(symbol: Symbol, location: Identifier) { const declaration = symbol.valueDeclaration; if (declaration) { // If we have a non-rest binding element with no initializer declared as a const variable or a const-like @@ -26048,19 +26246,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the binding pattern AST instance for '{ kind, payload }' as a pseudo-reference and narrow this reference // as if it occurred in the specified location. We then recompute the narrowed binding element type by // destructuring from the narrowed parent type. - if (ts.isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) { + if (isBindingElement(declaration) && !declaration.initializer && !declaration.dotDotDotToken && declaration.parent.elements.length >= 2) { const parent = declaration.parent.parent; - if (parent.kind === ts.SyntaxKind.VariableDeclaration && ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const || parent.kind === ts.SyntaxKind.Parameter) { + if (parent.kind === SyntaxKind.VariableDeclaration && getCombinedNodeFlags(declaration) & NodeFlags.Const || parent.kind === SyntaxKind.Parameter) { const links = getNodeLinks(parent); - if (!(links.flags & ts.NodeCheckFlags.InCheckIdentifier)) { - links.flags |= ts.NodeCheckFlags.InCheckIdentifier; + if (!(links.flags & NodeCheckFlags.InCheckIdentifier)) { + links.flags |= NodeCheckFlags.InCheckIdentifier; const parentType = getTypeForBindingElementParent(parent, CheckMode.Normal); const parentTypeConstraint = parentType && mapType(parentType, getBaseConstraintOrType); - links.flags &= ~ts.NodeCheckFlags.InCheckIdentifier; - if (parentTypeConstraint && parentTypeConstraint.flags & ts.TypeFlags.Union && !(parent.kind === ts.SyntaxKind.Parameter && isSymbolAssigned(symbol))) { + links.flags &= ~NodeCheckFlags.InCheckIdentifier; + if (parentTypeConstraint && parentTypeConstraint.flags & TypeFlags.Union && !(parent.kind === SyntaxKind.Parameter && isSymbolAssigned(symbol))) { const pattern = declaration.parent; const narrowedType = getFlowTypeOfReference(pattern, parentTypeConstraint, parentTypeConstraint, /*flowContainer*/ undefined, location.flowNode); - if (narrowedType.flags & ts.TypeFlags.Never) { + if (narrowedType.flags & TypeFlags.Never) { return neverType; } return getBindingElementTypeFromParentType(declaration, narrowedType); @@ -26088,15 +26286,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the arrow function AST node for '(kind, payload) => ...' as a pseudo-reference and narrow this reference as // if it occurred in the specified location. We then recompute the narrowed parameter type by indexing into the // narrowed tuple type. - if (ts.isParameter(declaration) && !declaration.type && !declaration.initializer && !declaration.dotDotDotToken) { + if (isParameter(declaration) && !declaration.type && !declaration.initializer && !declaration.dotDotDotToken) { const func = declaration.parent; if (func.parameters.length >= 2 && isContextSensitiveFunctionOrObjectLiteralMethod(func)) { const contextualSignature = getContextualSignature(func); if (contextualSignature && contextualSignature.parameters.length === 1 && signatureHasRestParameter(contextualSignature)) { const restType = getReducedApparentType(getTypeOfSymbol(contextualSignature.parameters[0])); - if (restType.flags & ts.TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) { + if (restType.flags & TypeFlags.Union && everyType(restType, isTupleType) && !isSymbolAssigned(symbol)) { const narrowedType = getFlowTypeOfReference(func, restType, restType, /*flowContainer*/ undefined, location.flowNode); - const index = func.parameters.indexOf(declaration) - (ts.getThisParameter(func) ? 1 : 0); + const index = func.parameters.indexOf(declaration) - (getThisParameter(func) ? 1 : 0); return getIndexedAccessType(narrowedType, getNumberLiteralType(index)); } } @@ -26106,8 +26304,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getTypeOfSymbol(symbol); } - function checkIdentifier(node: ts.Identifier, checkMode: CheckMode | undefined): ts.Type { - if (ts.isThisInTypeQuery(node)) { + function checkIdentifier(node: Identifier, checkMode: CheckMode | undefined): Type { + if (isThisInTypeQuery(node)) { return checkThisExpression(node); } @@ -26124,21 +26322,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // can explicitly bound arguments objects if (symbol === argumentsSymbol) { if (isInPropertyInitializerOrClassStaticBlock(node)) { - error(node, ts.Diagnostics.arguments_cannot_be_referenced_in_property_initializers); + error(node, Diagnostics.arguments_cannot_be_referenced_in_property_initializers); return errorType; } - const container = ts.getContainingFunction(node)!; - if (languageVersion < ts.ScriptTarget.ES2015) { - if (container.kind === ts.SyntaxKind.ArrowFunction) { - error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); + const container = getContainingFunction(node)!; + if (languageVersion < ScriptTarget.ES2015) { + if (container.kind === SyntaxKind.ArrowFunction) { + error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } - else if (ts.hasSyntacticModifier(container, ts.ModifierFlags.Async)) { - error(node, ts.Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); + else if (hasSyntacticModifier(container, ModifierFlags.Async)) { + error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_async_function_or_method_in_ES3_and_ES5_Consider_using_a_standard_function_or_method); } } - getNodeLinks(container).flags |= ts.NodeCheckFlags.CaptureArguments; + getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; return getTypeOfSymbol(symbol); } @@ -26153,38 +26351,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } let declaration = localOrExportSymbol.valueDeclaration; - if (declaration && localOrExportSymbol.flags & ts.SymbolFlags.Class) { + if (declaration && localOrExportSymbol.flags & SymbolFlags.Class) { // Due to the emit for class decorators, any reference to the class from inside of the class body // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind // behavior of class names in ES6. - if (declaration.kind === ts.SyntaxKind.ClassDeclaration - && ts.nodeIsDecorated(declaration as ts.ClassDeclaration)) { - let container = ts.getContainingClass(node); + if (declaration.kind === SyntaxKind.ClassDeclaration + && nodeIsDecorated(declaration as ClassDeclaration)) { + let container = getContainingClass(node); while (container !== undefined) { if (container === declaration && container.name !== node) { - getNodeLinks(declaration).flags |= ts.NodeCheckFlags.ClassWithConstructorReference; - getNodeLinks(node).flags |= ts.NodeCheckFlags.ConstructorReferenceInClass; + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; break; } - container = ts.getContainingClass(container); + container = getContainingClass(container); } } - else if (declaration.kind === ts.SyntaxKind.ClassExpression) { + else if (declaration.kind === SyntaxKind.ClassExpression) { // When we emit a class expression with static members that contain a reference // to the constructor in the initializer, we will need to substitute that // binding with an alias as the class name is not in scope. - let container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); - while (container.kind !== ts.SyntaxKind.SourceFile) { + let container = getThisContainer(node, /*includeArrowFunctions*/ false); + while (container.kind !== SyntaxKind.SourceFile) { if (container.parent === declaration) { - if (ts.isPropertyDeclaration(container) && ts.isStatic(container) || ts.isClassStaticBlockDeclaration(container)) { - getNodeLinks(declaration).flags |= ts.NodeCheckFlags.ClassWithConstructorReference; - getNodeLinks(node).flags |= ts.NodeCheckFlags.ConstructorReferenceInClass; + if (isPropertyDeclaration(container) && isStatic(container) || isClassStaticBlockDeclaration(container)) { + getNodeLinks(declaration).flags |= NodeCheckFlags.ClassWithConstructorReference; + getNodeLinks(node).flags |= NodeCheckFlags.ConstructorReferenceInClass; } break; } - container = ts.getThisContainer(container, /*includeArrowFunctions*/ false); + container = getThisContainer(container, /*includeArrowFunctions*/ false); } } } @@ -26192,38 +26390,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkNestedBlockScopedBinding(node, symbol); let type = getNarrowedTypeOfSymbol(localOrExportSymbol, node); - const assignmentKind = ts.getAssignmentTargetKind(node); + const assignmentKind = getAssignmentTargetKind(node); if (assignmentKind) { - if (!(localOrExportSymbol.flags & ts.SymbolFlags.Variable) && - !(ts.isInJSFile(node) && localOrExportSymbol.flags & ts.SymbolFlags.ValueModule)) { - const assignmentError = localOrExportSymbol.flags & ts.SymbolFlags.Enum ? ts.Diagnostics.Cannot_assign_to_0_because_it_is_an_enum - : localOrExportSymbol.flags & ts.SymbolFlags.Class ? ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_class - : localOrExportSymbol.flags & ts.SymbolFlags.Module ? ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace - : localOrExportSymbol.flags & ts.SymbolFlags.Function ? ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_function - : localOrExportSymbol.flags & ts.SymbolFlags.Alias ? ts.Diagnostics.Cannot_assign_to_0_because_it_is_an_import - : ts.Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable; + if (!(localOrExportSymbol.flags & SymbolFlags.Variable) && + !(isInJSFile(node) && localOrExportSymbol.flags & SymbolFlags.ValueModule)) { + const assignmentError = localOrExportSymbol.flags & SymbolFlags.Enum ? Diagnostics.Cannot_assign_to_0_because_it_is_an_enum + : localOrExportSymbol.flags & SymbolFlags.Class ? Diagnostics.Cannot_assign_to_0_because_it_is_a_class + : localOrExportSymbol.flags & SymbolFlags.Module ? Diagnostics.Cannot_assign_to_0_because_it_is_a_namespace + : localOrExportSymbol.flags & SymbolFlags.Function ? Diagnostics.Cannot_assign_to_0_because_it_is_a_function + : localOrExportSymbol.flags & SymbolFlags.Alias ? Diagnostics.Cannot_assign_to_0_because_it_is_an_import + : Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable; error(node, assignmentError, symbolToString(symbol)); return errorType; } if (isReadonlySymbol(localOrExportSymbol)) { - if (localOrExportSymbol.flags & ts.SymbolFlags.Variable) { - error(node, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_constant, symbolToString(symbol)); + if (localOrExportSymbol.flags & SymbolFlags.Variable) { + error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant, symbolToString(symbol)); } else { - error(node, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(symbol)); + error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(symbol)); } return errorType; } } - const isAlias = localOrExportSymbol.flags & ts.SymbolFlags.Alias; + const isAlias = localOrExportSymbol.flags & SymbolFlags.Alias; // We only narrow variables and parameters occurring in a non-assignment position. For all other // entities we simply return the declared type. - if (localOrExportSymbol.flags & ts.SymbolFlags.Variable) { - if (assignmentKind === ts.AssignmentKind.Definite) { + if (localOrExportSymbol.flags & SymbolFlags.Variable) { + if (assignmentKind === AssignmentKind.Definite) { return type; } } @@ -26243,17 +26441,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The declaration container is the innermost function that encloses the declaration of the variable // or parameter. The flow container is the innermost function starting with which we analyze the control // flow graph to determine the control flow based type. - const isParameter = ts.getRootDeclaration(declaration).kind === ts.SyntaxKind.Parameter; + const isParameter = getRootDeclaration(declaration).kind === SyntaxKind.Parameter; const declarationContainer = getControlFlowContainer(declaration); let flowContainer = getControlFlowContainer(node); const isOuterVariable = flowContainer !== declarationContainer; - const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent && ts.isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); - const isModuleExports = symbol.flags & ts.SymbolFlags.ModuleExports; + const isSpreadDestructuringAssignmentTarget = node.parent && node.parent.parent && isSpreadAssignment(node.parent) && isDestructuringAssignmentTarget(node.parent.parent); + const isModuleExports = symbol.flags & SymbolFlags.ModuleExports; // When the control flow originates in a function expression or arrow function and we are referencing // a const variable or parameter from an outer function, we extend the origin of the control flow // analysis to include the immediately enclosing function. - while (flowContainer !== declarationContainer && (flowContainer.kind === ts.SyntaxKind.FunctionExpression || - flowContainer.kind === ts.SyntaxKind.ArrowFunction || ts.isObjectLiteralOrClassExpressionMethodOrAccessor(flowContainer)) && + while (flowContainer !== declarationContainer && (flowContainer.kind === SyntaxKind.FunctionExpression || + flowContainer.kind === SyntaxKind.ArrowFunction || isObjectLiteralOrClassExpressionMethodOrAccessor(flowContainer)) && (isConstVariable(localOrExportSymbol) && type !== autoArrayType || isParameter && !isSymbolAssigned(localOrExportSymbol))) { flowContainer = getControlFlowContainer(flowContainer); } @@ -26261,12 +26459,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isSameScopedBindingElement(node, declaration) || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Void)) !== 0 || - isInTypeQuery(node) || node.parent.kind === ts.SyntaxKind.ExportSpecifier) || - node.parent.kind === ts.SyntaxKind.NonNullExpression || - declaration.kind === ts.SyntaxKind.VariableDeclaration && (declaration as ts.VariableDeclaration).exclamationToken || - declaration.flags & ts.NodeFlags.Ambient; - const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as ts.VariableLikeDeclaration) : type) : + type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 || + isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || + node.parent.kind === SyntaxKind.NonNullExpression || + declaration.kind === SyntaxKind.VariableDeclaration && (declaration as VariableDeclaration).exclamationToken || + declaration.flags & NodeFlags.Ambient; + const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : getOptionalType(type); const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer); @@ -26276,66 +26474,66 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isEvolvingArrayOperationTarget(node) && (type === autoType || type === autoArrayType)) { if (flowType === autoType || flowType === autoArrayType) { if (noImplicitAny) { - error(ts.getNameOfDeclaration(declaration), ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType)); - error(node, ts.Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); + error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType)); + error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } return convertAutoToAny(flowType); } } else if (!assumeInitialized && !containsUndefinedType(type) && containsUndefinedType(flowType)) { - error(node, ts.Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); + error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol)); // Return the declared type to reduce follow-on errors return type; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } - function isSameScopedBindingElement(node: ts.Identifier, declaration: ts.Declaration) { - if (ts.isBindingElement(declaration)) { - const bindingElement = ts.findAncestor(node, ts.isBindingElement); - return bindingElement && ts.getRootDeclaration(bindingElement) === ts.getRootDeclaration(declaration); + function isSameScopedBindingElement(node: Identifier, declaration: Declaration) { + if (isBindingElement(declaration)) { + const bindingElement = findAncestor(node, isBindingElement); + return bindingElement && getRootDeclaration(bindingElement) === getRootDeclaration(declaration); } } - function shouldMarkIdentifierAliasReferenced(node: ts.Identifier): boolean { + function shouldMarkIdentifierAliasReferenced(node: Identifier): boolean { const parent = node.parent; if (parent) { // A property access expression LHS? checkPropertyAccessExpression will handle that. - if (ts.isPropertyAccessExpression(parent) && parent.expression === node) { + if (isPropertyAccessExpression(parent) && parent.expression === node) { return false; } // Next two check for an identifier inside a type only export. - if (ts.isExportSpecifier(parent) && parent.isTypeOnly) { + if (isExportSpecifier(parent) && parent.isTypeOnly) { return false; } const greatGrandparent = parent.parent?.parent; - if (greatGrandparent && ts.isExportDeclaration(greatGrandparent) && greatGrandparent.isTypeOnly) { + if (greatGrandparent && isExportDeclaration(greatGrandparent) && greatGrandparent.isTypeOnly) { return false; } } return true; } - function isInsideFunctionOrInstancePropertyInitializer(node: ts.Node, threshold: ts.Node): boolean { - return !!ts.findAncestor(node, n => n === threshold ? "quit" : ts.isFunctionLike(n) || ( - n.parent && ts.isPropertyDeclaration(n.parent) && !ts.hasStaticModifier(n.parent) && n.parent.initializer === n + function isInsideFunctionOrInstancePropertyInitializer(node: Node, threshold: Node): boolean { + return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n) || ( + n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) && n.parent.initializer === n )); } - function getPartOfForStatementContainingNode(node: ts.Node, container: ts.ForStatement) { - return ts.findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement); + function getPartOfForStatementContainingNode(node: Node, container: ForStatement) { + return findAncestor(node, n => n === container ? "quit" : n === container.initializer || n === container.condition || n === container.incrementor || n === container.statement); } - function getEnclosingIterationStatement(node: ts.Node): ts.Node | undefined { - return ts.findAncestor(node, n => (!n || ts.nodeStartsNewLexicalEnvironment(n)) ? "quit" : ts.isIterationStatement(n, /*lookInLabeledStatements*/ false)); + function getEnclosingIterationStatement(node: Node): Node | undefined { + return findAncestor(node, n => (!n || nodeStartsNewLexicalEnvironment(n)) ? "quit" : isIterationStatement(n, /*lookInLabeledStatements*/ false)); } - function checkNestedBlockScopedBinding(node: ts.Identifier, symbol: ts.Symbol): void { - if (languageVersion >= ts.ScriptTarget.ES2015 || - (symbol.flags & (ts.SymbolFlags.BlockScopedVariable | ts.SymbolFlags.Class)) === 0 || + function checkNestedBlockScopedBinding(node: Identifier, symbol: Symbol): void { + if (languageVersion >= ScriptTarget.ES2015 || + (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.Class)) === 0 || !symbol.valueDeclaration || - ts.isSourceFile(symbol.valueDeclaration) || - symbol.valueDeclaration.parent.kind === ts.SyntaxKind.CatchClause) { + isSourceFile(symbol.valueDeclaration) || + symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) { return; } @@ -26344,7 +26542,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // 2. walk from the declaration up to the boundary of lexical environment and check // if there is an iteration statement in between declaration and boundary (is binding/class declared inside iteration statement) - const container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); const isCaptured = isInsideFunctionOrInstancePropertyInitializer(node, container); const enclosingIterationStatement = getEnclosingIterationStatement(container); @@ -26352,16 +26550,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isCaptured) { // mark iteration statement as containing block-scoped binding captured in some function let capturesBlockScopeBindingInLoopBody = true; - if (ts.isForStatement(container)) { - const varDeclList = ts.getAncestor(symbol.valueDeclaration, ts.SyntaxKind.VariableDeclarationList); + if (isForStatement(container)) { + const varDeclList = getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList); if (varDeclList && varDeclList.parent === container) { const part = getPartOfForStatementContainingNode(node.parent, container); if (part) { const links = getNodeLinks(part); - links.flags |= ts.NodeCheckFlags.ContainsCapturedBlockScopeBinding; + links.flags |= NodeCheckFlags.ContainsCapturedBlockScopeBinding; const capturedBindings = links.capturedBlockScopeBindings || (links.capturedBlockScopeBindings = []); - ts.pushIfUnique(capturedBindings, symbol); + pushIfUnique(capturedBindings, symbol); if (part === container.initializer) { capturesBlockScopeBindingInLoopBody = false; // Initializer is outside of loop body @@ -26370,48 +26568,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (capturesBlockScopeBindingInLoopBody) { - getNodeLinks(enclosingIterationStatement).flags |= ts.NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } } // mark variables that are declared in loop initializer and reassigned inside the body of ForStatement. // if body of ForStatement will be converted to function then we'll need a extra machinery to propagate reassigned values back. - if (ts.isForStatement(container)) { - const varDeclList = ts.getAncestor(symbol.valueDeclaration, ts.SyntaxKind.VariableDeclarationList); + if (isForStatement(container)) { + const varDeclList = getAncestor(symbol.valueDeclaration, SyntaxKind.VariableDeclarationList); if (varDeclList && varDeclList.parent === container && isAssignedInBodyOfForStatement(node, container)) { - getNodeLinks(symbol.valueDeclaration).flags |= ts.NodeCheckFlags.NeedsLoopOutParameter; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.NeedsLoopOutParameter; } } // set 'declared inside loop' bit on the block-scoped binding - getNodeLinks(symbol.valueDeclaration).flags |= ts.NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop; } if (isCaptured) { - getNodeLinks(symbol.valueDeclaration).flags |= ts.NodeCheckFlags.CapturedBlockScopedBinding; + getNodeLinks(symbol.valueDeclaration).flags |= NodeCheckFlags.CapturedBlockScopedBinding; } } - function isBindingCapturedByNode(node: ts.Node, decl: ts.VariableDeclaration | ts.BindingElement) { + function isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement) { const links = getNodeLinks(node); - return !!links && ts.contains(links.capturedBlockScopeBindings, getSymbolOfNode(decl)); + return !!links && contains(links.capturedBlockScopeBindings, getSymbolOfNode(decl)); } - function isAssignedInBodyOfForStatement(node: ts.Identifier, container: ts.ForStatement): boolean { + function isAssignedInBodyOfForStatement(node: Identifier, container: ForStatement): boolean { // skip parenthesized nodes - let current: ts.Node = node; - while (current.parent.kind === ts.SyntaxKind.ParenthesizedExpression) { + let current: Node = node; + while (current.parent.kind === SyntaxKind.ParenthesizedExpression) { current = current.parent; } // check if node is used as LHS in some assignment expression let isAssigned = false; - if (ts.isAssignmentTarget(current)) { + if (isAssignmentTarget(current)) { isAssigned = true; } - else if ((current.parent.kind === ts.SyntaxKind.PrefixUnaryExpression || current.parent.kind === ts.SyntaxKind.PostfixUnaryExpression)) { - const expr = current.parent as ts.PrefixUnaryExpression | ts.PostfixUnaryExpression; - isAssigned = expr.operator === ts.SyntaxKind.PlusPlusToken || expr.operator === ts.SyntaxKind.MinusMinusToken; + else if ((current.parent.kind === SyntaxKind.PrefixUnaryExpression || current.parent.kind === SyntaxKind.PostfixUnaryExpression)) { + const expr = current.parent as PrefixUnaryExpression | PostfixUnaryExpression; + isAssigned = expr.operator === SyntaxKind.PlusPlusToken || expr.operator === SyntaxKind.MinusMinusToken; } if (!isAssigned) { @@ -26420,24 +26618,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // at this point we know that node is the target of assignment // now check that modification happens inside the statement part of the ForStatement - return !!ts.findAncestor(current, n => n === container ? "quit" : n === container.statement); + return !!findAncestor(current, n => n === container ? "quit" : n === container.statement); } - function captureLexicalThis(node: ts.Node, container: ts.Node): void { - getNodeLinks(node).flags |= ts.NodeCheckFlags.LexicalThis; - if (container.kind === ts.SyntaxKind.PropertyDeclaration || container.kind === ts.SyntaxKind.Constructor) { + function captureLexicalThis(node: Node, container: Node): void { + getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis; + if (container.kind === SyntaxKind.PropertyDeclaration || container.kind === SyntaxKind.Constructor) { const classNode = container.parent; - getNodeLinks(classNode).flags |= ts.NodeCheckFlags.CaptureThis; + getNodeLinks(classNode).flags |= NodeCheckFlags.CaptureThis; } else { - getNodeLinks(container).flags |= ts.NodeCheckFlags.CaptureThis; + getNodeLinks(container).flags |= NodeCheckFlags.CaptureThis; } } - function findFirstSuperCall(node: ts.Node): ts.SuperCall | undefined { - return ts.isSuperCall(node) ? node : - ts.isFunctionLike(node) ? undefined : - ts.forEachChild(node, findFirstSuperCall); + function findFirstSuperCall(node: Node): SuperCall | undefined { + return isSuperCall(node) ? node : + isFunctionLike(node) ? undefined : + forEachChild(node, findFirstSuperCall); } /** @@ -26445,17 +26643,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Otherwise, return false * @param classDecl a class declaration to check if it extends null */ - function classDeclarationExtendsNull(classDecl: ts.ClassDeclaration): boolean { + function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean { const classSymbol = getSymbolOfNode(classDecl); - const classInstanceType = getDeclaredTypeOfSymbol(classSymbol) as ts.InterfaceType; + const classInstanceType = getDeclaredTypeOfSymbol(classSymbol) as InterfaceType; const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); return baseConstructorType === nullWideningType; } - function checkThisBeforeSuper(node: ts.Node, container: ts.Node, diagnosticMessage: ts.DiagnosticMessage) { - const containingClassDecl = container.parent as ts.ClassDeclaration; - const baseTypeNode = ts.getClassExtendsHeritageElement(containingClassDecl); + function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) { + const containingClassDecl = container.parent as ClassDeclaration; + const baseTypeNode = getClassExtendsHeritageElement(containingClassDecl); // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. @@ -26466,53 +26664,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkThisInStaticClassFieldInitializerInDecoratedClass(thisExpression: ts.Node, container: ts.Node) { - if (ts.isPropertyDeclaration(container) && ts.hasStaticModifier(container) && - container.initializer && ts.textRangeContainsPositionInclusive(container.initializer, thisExpression.pos) && ts.hasDecorators(container.parent)) { - error(thisExpression, ts.Diagnostics.Cannot_use_this_in_a_static_property_initializer_of_a_decorated_class); + function checkThisInStaticClassFieldInitializerInDecoratedClass(thisExpression: Node, container: Node) { + if (isPropertyDeclaration(container) && hasStaticModifier(container) && + container.initializer && textRangeContainsPositionInclusive(container.initializer, thisExpression.pos) && hasDecorators(container.parent)) { + error(thisExpression, Diagnostics.Cannot_use_this_in_a_static_property_initializer_of_a_decorated_class); } } - function checkThisExpression(node: ts.Node): ts.Type { + function checkThisExpression(node: Node): Type { const isNodeInTypeQuery = isInTypeQuery(node); // Stop at the first arrow function so that we can // tell whether 'this' needs to be captured. - let container = ts.getThisContainer(node, /* includeArrowFunctions */ true); + let container = getThisContainer(node, /* includeArrowFunctions */ true); let capturedByArrowFunction = false; - if (container.kind === ts.SyntaxKind.Constructor) { - checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); + if (container.kind === SyntaxKind.Constructor) { + checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); } // Now skip arrow functions to get the "real" owner of 'this'. - if (container.kind === ts.SyntaxKind.ArrowFunction) { - container = ts.getThisContainer(container, /* includeArrowFunctions */ false); + if (container.kind === SyntaxKind.ArrowFunction) { + container = getThisContainer(container, /* includeArrowFunctions */ false); capturedByArrowFunction = true; } checkThisInStaticClassFieldInitializerInDecoratedClass(node, container); switch (container.kind) { - case ts.SyntaxKind.ModuleDeclaration: - error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); + case SyntaxKind.ModuleDeclaration: + error(node, Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case ts.SyntaxKind.EnumDeclaration: - error(node, ts.Diagnostics.this_cannot_be_referenced_in_current_location); + case SyntaxKind.EnumDeclaration: + error(node, Diagnostics.this_cannot_be_referenced_in_current_location); // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks break; - case ts.SyntaxKind.Constructor: + case SyntaxKind.Constructor: if (isInConstructorArgumentInitializer(node, container)) { - error(node, ts.Diagnostics.this_cannot_be_referenced_in_constructor_arguments); + error(node, Diagnostics.this_cannot_be_referenced_in_constructor_arguments); // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks } break; - case ts.SyntaxKind.ComputedPropertyName: - error(node, ts.Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); + case SyntaxKind.ComputedPropertyName: + error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); break; } // When targeting es6, mark that we'll need to capture `this` in its lexically bound scope. - if (!isNodeInTypeQuery && capturedByArrowFunction && languageVersion < ts.ScriptTarget.ES2015) { + if (!isNodeInTypeQuery && capturedByArrowFunction && languageVersion < ScriptTarget.ES2015) { captureLexicalThis(node, container); } @@ -26520,15 +26718,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (noImplicitThis) { const globalThisType = getTypeOfSymbol(globalThisSymbol); if (type === globalThisType && capturedByArrowFunction) { - error(node, ts.Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this); + error(node, Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this); } else if (!type) { // With noImplicitThis, functions may not reference 'this' if it has type 'any' - const diag = error(node, ts.Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); - if (!ts.isSourceFile(container)) { + const diag = error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation); + if (!isSourceFile(container)) { const outsideThis = tryGetThisTypeAt(container); if (outsideThis && outsideThis !== globalThisType) { - ts.addRelatedInfo(diag, ts.createDiagnosticForNode(container, ts.Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container)); + addRelatedInfo(diag, createDiagnosticForNode(container, Diagnostics.An_outer_value_of_this_is_shadowed_by_this_container)); } } } @@ -26536,10 +26734,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type || anyType; } - function tryGetThisTypeAt(node: ts.Node, includeGlobalThis = true, container = ts.getThisContainer(node, /*includeArrowFunctions*/ false)): ts.Type | undefined { - const isInJS = ts.isInJSFile(node); - if (ts.isFunctionLike(container) && - (!isInParameterInitializerBeforeContainingFunction(node) || ts.getThisParameter(container))) { + function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined { + const isInJS = isInJSFile(node); + if (isFunctionLike(container) && + (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) { let thisType = getThisTypeOfDeclaration(container) || isInJS && getTypeForThisExpressionFromJSDoc(container); // Note: a parameter initializer should refer to class-this unless function-this is explicitly annotated. // If this is a function in a JS file, it might be a class method. @@ -26547,12 +26745,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const className = getClassNameFromPrototypeMethod(container); if (isInJS && className) { const classSymbol = checkExpression(className).symbol; - if (classSymbol && classSymbol.members && (classSymbol.flags & ts.SymbolFlags.Function)) { - thisType = (getDeclaredTypeOfSymbol(classSymbol) as ts.InterfaceType).thisType; + if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) { + thisType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType; } } else if (isJSConstructor(container)) { - thisType = (getDeclaredTypeOfSymbol(getMergedSymbol(container.symbol)) as ts.InterfaceType).thisType; + thisType = (getDeclaredTypeOfSymbol(getMergedSymbol(container.symbol)) as InterfaceType).thisType; } thisType ||= getContextualThisParameterType(container); } @@ -26562,13 +26760,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isClassLike(container.parent)) { + if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - const type = ts.isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType).thisType!; + const type = isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; return getFlowTypeOfReference(node, type); } - if (ts.isSourceFile(container)) { + if (isSourceFile(container)) { // look up in the source file's locals or exports if (container.commonJsModuleIndicator) { const fileSymbol = getSymbolOfNode(container); @@ -26584,113 +26782,113 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getExplicitThisType(node: ts.Expression) { - const container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); - if (ts.isFunctionLike(container)) { + function getExplicitThisType(node: Expression) { + const container = getThisContainer(node, /*includeArrowFunctions*/ false); + if (isFunctionLike(container)) { const signature = getSignatureFromDeclaration(container); if (signature.thisParameter) { return getExplicitTypeOfSymbol(signature.thisParameter); } } - if (ts.isClassLike(container.parent)) { + if (isClassLike(container.parent)) { const symbol = getSymbolOfNode(container.parent); - return ts.isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType).thisType!; + return isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; } } - function getClassNameFromPrototypeMethod(container: ts.Node) { + function getClassNameFromPrototypeMethod(container: Node) { // Check if it's the RHS of a x.prototype.y = function [name]() { .... } - if (container.kind === ts.SyntaxKind.FunctionExpression && - ts.isBinaryExpression(container.parent) && - ts.getAssignmentDeclarationKind(container.parent) === ts.AssignmentDeclarationKind.PrototypeProperty) { + if (container.kind === SyntaxKind.FunctionExpression && + isBinaryExpression(container.parent) && + getAssignmentDeclarationKind(container.parent) === AssignmentDeclarationKind.PrototypeProperty) { // Get the 'x' of 'x.prototype.y = container' return ((container.parent // x.prototype.y = container - .left as ts.PropertyAccessExpression) // x.prototype.y - .expression as ts.PropertyAccessExpression) // x.prototype + .left as PropertyAccessExpression) // x.prototype.y + .expression as PropertyAccessExpression) // x.prototype .expression; // x } // x.prototype = { method() { } } - else if (container.kind === ts.SyntaxKind.MethodDeclaration && - container.parent.kind === ts.SyntaxKind.ObjectLiteralExpression && - ts.isBinaryExpression(container.parent.parent) && - ts.getAssignmentDeclarationKind(container.parent.parent) === ts.AssignmentDeclarationKind.Prototype) { - return (container.parent.parent.left as ts.PropertyAccessExpression).expression; + else if (container.kind === SyntaxKind.MethodDeclaration && + container.parent.kind === SyntaxKind.ObjectLiteralExpression && + isBinaryExpression(container.parent.parent) && + getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.Prototype) { + return (container.parent.parent.left as PropertyAccessExpression).expression; } // x.prototype = { method: function() { } } - else if (container.kind === ts.SyntaxKind.FunctionExpression && - container.parent.kind === ts.SyntaxKind.PropertyAssignment && - container.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression && - ts.isBinaryExpression(container.parent.parent.parent) && - ts.getAssignmentDeclarationKind(container.parent.parent.parent) === ts.AssignmentDeclarationKind.Prototype) { - return (container.parent.parent.parent.left as ts.PropertyAccessExpression).expression; + else if (container.kind === SyntaxKind.FunctionExpression && + container.parent.kind === SyntaxKind.PropertyAssignment && + container.parent.parent.kind === SyntaxKind.ObjectLiteralExpression && + isBinaryExpression(container.parent.parent.parent) && + getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.Prototype) { + return (container.parent.parent.parent.left as PropertyAccessExpression).expression; } // Object.defineProperty(x, "method", { value: function() { } }); // Object.defineProperty(x, "method", { set: (x: () => void) => void }); // Object.defineProperty(x, "method", { get: () => function() { }) }); - else if (container.kind === ts.SyntaxKind.FunctionExpression && - ts.isPropertyAssignment(container.parent) && - ts.isIdentifier(container.parent.name) && + else if (container.kind === SyntaxKind.FunctionExpression && + isPropertyAssignment(container.parent) && + isIdentifier(container.parent.name) && (container.parent.name.escapedText === "value" || container.parent.name.escapedText === "get" || container.parent.name.escapedText === "set") && - ts.isObjectLiteralExpression(container.parent.parent) && - ts.isCallExpression(container.parent.parent.parent) && + isObjectLiteralExpression(container.parent.parent) && + isCallExpression(container.parent.parent.parent) && container.parent.parent.parent.arguments[2] === container.parent.parent && - ts.getAssignmentDeclarationKind(container.parent.parent.parent) === ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty) { - return (container.parent.parent.parent.arguments[0] as ts.PropertyAccessExpression).expression; + getAssignmentDeclarationKind(container.parent.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty) { + return (container.parent.parent.parent.arguments[0] as PropertyAccessExpression).expression; } // Object.defineProperty(x, "method", { value() { } }); // Object.defineProperty(x, "method", { set(x: () => void) {} }); // Object.defineProperty(x, "method", { get() { return () => {} } }); - else if (ts.isMethodDeclaration(container) && - ts.isIdentifier(container.name) && + else if (isMethodDeclaration(container) && + isIdentifier(container.name) && (container.name.escapedText === "value" || container.name.escapedText === "get" || container.name.escapedText === "set") && - ts.isObjectLiteralExpression(container.parent) && - ts.isCallExpression(container.parent.parent) && + isObjectLiteralExpression(container.parent) && + isCallExpression(container.parent.parent) && container.parent.parent.arguments[2] === container.parent && - ts.getAssignmentDeclarationKind(container.parent.parent) === ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty) { - return (container.parent.parent.arguments[0] as ts.PropertyAccessExpression).expression; + getAssignmentDeclarationKind(container.parent.parent) === AssignmentDeclarationKind.ObjectDefinePrototypeProperty) { + return (container.parent.parent.arguments[0] as PropertyAccessExpression).expression; } } - function getTypeForThisExpressionFromJSDoc(node: ts.Node) { - const jsdocType = ts.getJSDocType(node); - if (jsdocType && jsdocType.kind === ts.SyntaxKind.JSDocFunctionType) { - const jsDocFunctionType = jsdocType as ts.JSDocFunctionType; + function getTypeForThisExpressionFromJSDoc(node: Node) { + const jsdocType = getJSDocType(node); + if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) { + const jsDocFunctionType = jsdocType as JSDocFunctionType; if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].name && - (jsDocFunctionType.parameters[0].name as ts.Identifier).escapedText === ts.InternalSymbolName.This) { + (jsDocFunctionType.parameters[0].name as Identifier).escapedText === InternalSymbolName.This) { return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type!); } } - const thisTag = ts.getJSDocThisTag(node); + const thisTag = getJSDocThisTag(node); if (thisTag && thisTag.typeExpression) { return getTypeFromTypeNode(thisTag.typeExpression); } } - function isInConstructorArgumentInitializer(node: ts.Node, constructorDecl: ts.Node): boolean { - return !!ts.findAncestor(node, n => ts.isFunctionLikeDeclaration(n) ? "quit" : n.kind === ts.SyntaxKind.Parameter && n.parent === constructorDecl); + function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean { + return !!findAncestor(node, n => isFunctionLikeDeclaration(n) ? "quit" : n.kind === SyntaxKind.Parameter && n.parent === constructorDecl); } - function checkSuperExpression(node: ts.Node): ts.Type { - const isCallExpression = node.parent.kind === ts.SyntaxKind.CallExpression && (node.parent as ts.CallExpression).expression === node; + function checkSuperExpression(node: Node): Type { + const isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (node.parent as CallExpression).expression === node; - const immediateContainer = ts.getSuperContainer(node, /*stopOnFunctions*/ true); + const immediateContainer = getSuperContainer(node, /*stopOnFunctions*/ true); let container = immediateContainer; let needToCaptureLexicalThis = false; let inAsyncFunction = false; // adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting if (!isCallExpression) { - while (container && container.kind === ts.SyntaxKind.ArrowFunction) { - if (ts.hasSyntacticModifier(container, ts.ModifierFlags.Async)) inAsyncFunction = true; - container = ts.getSuperContainer(container, /*stopOnFunctions*/ true); - needToCaptureLexicalThis = languageVersion < ts.ScriptTarget.ES2015; + while (container && container.kind === SyntaxKind.ArrowFunction) { + if (hasSyntacticModifier(container, ModifierFlags.Async)) inAsyncFunction = true; + container = getSuperContainer(container, /*stopOnFunctions*/ true); + needToCaptureLexicalThis = languageVersion < ScriptTarget.ES2015; } - if (container && ts.hasSyntacticModifier(container, ts.ModifierFlags.Async)) inAsyncFunction = true; + if (container && hasSyntacticModifier(container, ModifierFlags.Async)) inAsyncFunction = true; } const canUseSuperExpression = isLegalUsageOfSuperExpression(container); - let nodeCheckFlag: ts.NodeCheckFlags = 0; + let nodeCheckFlag: NodeCheckFlags = 0; if (!canUseSuperExpression) { // issue more specific error if super is used in computed property name @@ -26698,43 +26896,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // class B { // [super.foo()]() {} // } - const current = ts.findAncestor(node, n => n === container ? "quit" : n.kind === ts.SyntaxKind.ComputedPropertyName); - if (current && current.kind === ts.SyntaxKind.ComputedPropertyName) { - error(node, ts.Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); + const current = findAncestor(node, n => n === container ? "quit" : n.kind === SyntaxKind.ComputedPropertyName); + if (current && current.kind === SyntaxKind.ComputedPropertyName) { + error(node, Diagnostics.super_cannot_be_referenced_in_a_computed_property_name); } else if (isCallExpression) { - error(node, ts.Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); + error(node, Diagnostics.Super_calls_are_not_permitted_outside_constructors_or_in_nested_functions_inside_constructors); } - else if (!container || !container.parent || !(ts.isClassLike(container.parent) || container.parent.kind === ts.SyntaxKind.ObjectLiteralExpression)) { - error(node, ts.Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); + else if (!container || !container.parent || !(isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression)) { + error(node, Diagnostics.super_can_only_be_referenced_in_members_of_derived_classes_or_object_literal_expressions); } else { - error(node, ts.Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); + error(node, Diagnostics.super_property_access_is_permitted_only_in_a_constructor_member_function_or_member_accessor_of_a_derived_class); } return errorType; } - if (!isCallExpression && immediateContainer.kind === ts.SyntaxKind.Constructor) { - checkThisBeforeSuper(node, container, ts.Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); + if (!isCallExpression && immediateContainer.kind === SyntaxKind.Constructor) { + checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); } - if (ts.isStatic(container) || isCallExpression) { - nodeCheckFlag = ts.NodeCheckFlags.SuperStatic; + if (isStatic(container) || isCallExpression) { + nodeCheckFlag = NodeCheckFlags.SuperStatic; if (!isCallExpression && - languageVersion >= ts.ScriptTarget.ES2015 && languageVersion <= ts.ScriptTarget.ES2021 && - (ts.isPropertyDeclaration(container) || ts.isClassStaticBlockDeclaration(container))) { + languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 && + (isPropertyDeclaration(container) || isClassStaticBlockDeclaration(container))) { // for `super.x` or `super[x]` in a static initializer, mark all enclosing // block scope containers so that we can report potential collisions with // `Reflect`. - ts.forEachEnclosingBlockScopeContainer(node.parent, current => { - if (!ts.isSourceFile(current) || ts.isExternalOrCommonJsModule(current)) { - getNodeLinks(current).flags |= ts.NodeCheckFlags.ContainsSuperPropertyInStaticInitializer; + forEachEnclosingBlockScopeContainer(node.parent, current => { + if (!isSourceFile(current) || isExternalOrCommonJsModule(current)) { + getNodeLinks(current).flags |= NodeCheckFlags.ContainsSuperPropertyInStaticInitializer; } }); } } else { - nodeCheckFlag = ts.NodeCheckFlags.SuperInstance; + nodeCheckFlag = NodeCheckFlags.SuperInstance; } getNodeLinks(node).flags |= nodeCheckFlag; @@ -26798,12 +26996,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // as a call expression cannot be used as the target of a destructuring assignment while a property access can. // // For element access expressions (`super[x]`), we emit a generic helper that forwards the element access in both situations. - if (container.kind === ts.SyntaxKind.MethodDeclaration && inAsyncFunction) { - if (ts.isSuperProperty(node.parent) && ts.isAssignmentTarget(node.parent)) { - getNodeLinks(container).flags |= ts.NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync; + if (container.kind === SyntaxKind.MethodDeclaration && inAsyncFunction) { + if (isSuperProperty(node.parent) && isAssignmentTarget(node.parent)) { + getNodeLinks(container).flags |= NodeCheckFlags.MethodWithSuperPropertyAssignmentInAsync; } else { - getNodeLinks(container).flags |= ts.NodeCheckFlags.MethodWithSuperPropertyAccessInAsync; + getNodeLinks(container).flags |= NodeCheckFlags.MethodWithSuperPropertyAccessInAsync; } } @@ -26814,9 +27012,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { captureLexicalThis(node.parent, container); } - if (container.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) { - if (languageVersion < ts.ScriptTarget.ES2015) { - error(node, ts.Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); + if (container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + if (languageVersion < ScriptTarget.ES2015) { + error(node, Diagnostics.super_is_only_allowed_in_members_of_object_literal_expressions_when_option_target_is_ES2015_or_higher); return errorType; } else { @@ -26826,29 +27024,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // at this point the only legal case for parent is ClassLikeDeclaration - const classLikeDeclaration = container.parent as ts.ClassLikeDeclaration; - if (!ts.getClassExtendsHeritageElement(classLikeDeclaration)) { - error(node, ts.Diagnostics.super_can_only_be_referenced_in_a_derived_class); + const classLikeDeclaration = container.parent as ClassLikeDeclaration; + if (!getClassExtendsHeritageElement(classLikeDeclaration)) { + error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); return errorType; } - const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)) as ts.InterfaceType; + const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)) as InterfaceType; const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { return errorType; } - if (container.kind === ts.SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) { + if (container.kind === SyntaxKind.Constructor && isInConstructorArgumentInitializer(node, container)) { // issue custom error message for super property access in constructor arguments (to be aligned with old compiler) - error(node, ts.Diagnostics.super_cannot_be_referenced_in_constructor_arguments); + error(node, Diagnostics.super_cannot_be_referenced_in_constructor_arguments); return errorType; } - return nodeCheckFlag === ts.NodeCheckFlags.SuperStatic + return nodeCheckFlag === NodeCheckFlags.SuperStatic ? getBaseConstructorTypeOfClass(classType) : getTypeWithThisArgument(baseClassType, classType.thisType); - function isLegalUsageOfSuperExpression(container: ts.Node): boolean { + function isLegalUsageOfSuperExpression(container: Node): boolean { if (!container) { return false; } @@ -26856,7 +27054,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isCallExpression) { // TS 1.0 SPEC (April 2014): 4.8.1 // Super calls are only permitted in constructors of derived classes - return container.kind === ts.SyntaxKind.Constructor; + return container.kind === SyntaxKind.Constructor; } else { // TS 1.0 SPEC (April 2014) @@ -26865,23 +27063,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // - In a static member function or static member accessor // topmost container must be something that is directly nested in the class declaration\object literal expression - if (ts.isClassLike(container.parent) || container.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) { - if (ts.isStatic(container)) { - return container.kind === ts.SyntaxKind.MethodDeclaration || - container.kind === ts.SyntaxKind.MethodSignature || - container.kind === ts.SyntaxKind.GetAccessor || - container.kind === ts.SyntaxKind.SetAccessor || - container.kind === ts.SyntaxKind.PropertyDeclaration || - container.kind === ts.SyntaxKind.ClassStaticBlockDeclaration; + if (isClassLike(container.parent) || container.parent.kind === SyntaxKind.ObjectLiteralExpression) { + if (isStatic(container)) { + return container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.PropertyDeclaration || + container.kind === SyntaxKind.ClassStaticBlockDeclaration; } else { - return container.kind === ts.SyntaxKind.MethodDeclaration || - container.kind === ts.SyntaxKind.MethodSignature || - container.kind === ts.SyntaxKind.GetAccessor || - container.kind === ts.SyntaxKind.SetAccessor || - container.kind === ts.SyntaxKind.PropertyDeclaration || - container.kind === ts.SyntaxKind.PropertySignature || - container.kind === ts.SyntaxKind.Constructor; + return container.kind === SyntaxKind.MethodDeclaration || + container.kind === SyntaxKind.MethodSignature || + container.kind === SyntaxKind.GetAccessor || + container.kind === SyntaxKind.SetAccessor || + container.kind === SyntaxKind.PropertyDeclaration || + container.kind === SyntaxKind.PropertySignature || + container.kind === SyntaxKind.Constructor; } } } @@ -26890,26 +27088,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getContainingObjectLiteral(func: ts.SignatureDeclaration): ts.ObjectLiteralExpression | undefined { - return (func.kind === ts.SyntaxKind.MethodDeclaration || - func.kind === ts.SyntaxKind.GetAccessor || - func.kind === ts.SyntaxKind.SetAccessor) && func.parent.kind === ts.SyntaxKind.ObjectLiteralExpression ? func.parent : - func.kind === ts.SyntaxKind.FunctionExpression && func.parent.kind === ts.SyntaxKind.PropertyAssignment ? func.parent.parent as ts.ObjectLiteralExpression : + function getContainingObjectLiteral(func: SignatureDeclaration): ObjectLiteralExpression | undefined { + return (func.kind === SyntaxKind.MethodDeclaration || + func.kind === SyntaxKind.GetAccessor || + func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : + func.kind === SyntaxKind.FunctionExpression && func.parent.kind === SyntaxKind.PropertyAssignment ? func.parent.parent as ObjectLiteralExpression : undefined; } - function getThisTypeArgument(type: ts.Type): ts.Type | undefined { - return ts.getObjectFlags(type) & ts.ObjectFlags.Reference && (type as ts.TypeReference).target === globalThisType ? getTypeArguments(type as ts.TypeReference)[0] : undefined; + function getThisTypeArgument(type: Type): Type | undefined { + return getObjectFlags(type) & ObjectFlags.Reference && (type as TypeReference).target === globalThisType ? getTypeArguments(type as TypeReference)[0] : undefined; } - function getThisTypeFromContextualType(type: ts.Type): ts.Type | undefined { + function getThisTypeFromContextualType(type: Type): Type | undefined { return mapType(type, t => { - return t.flags & ts.TypeFlags.Intersection ? ts.forEach((t as ts.IntersectionType).types, getThisTypeArgument) : getThisTypeArgument(t); + return t.flags & TypeFlags.Intersection ? forEach((t as IntersectionType).types, getThisTypeArgument) : getThisTypeArgument(t); }); } - function getContextualThisParameterType(func: ts.SignatureDeclaration): ts.Type | undefined { - if (func.kind === ts.SyntaxKind.ArrowFunction) { + function getContextualThisParameterType(func: SignatureDeclaration): Type | undefined { + if (func.kind === SyntaxKind.ArrowFunction) { return undefined; } if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) { @@ -26921,7 +27119,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - const inJs = ts.isInJSFile(func); + const inJs = isInJSFile(func); if (noImplicitThis || inJs) { const containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { @@ -26936,10 +27134,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (thisType) { return instantiateType(thisType, getMapperFromContext(getInferenceContext(containingLiteral))); } - if (literal.parent.kind !== ts.SyntaxKind.PropertyAssignment) { + if (literal.parent.kind !== SyntaxKind.PropertyAssignment) { break; } - literal = literal.parent.parent as ts.ObjectLiteralExpression; + literal = literal.parent.parent as ObjectLiteralExpression; type = getApparentTypeOfContextualType(literal, /*contextFlags*/ undefined); } // There was no contextual ThisType for the containing object literal, so the contextual type @@ -26949,14 +27147,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. - const parent = ts.walkUpParenthesizedExpressions(func.parent); - if (parent.kind === ts.SyntaxKind.BinaryExpression && (parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken) { - const target = (parent as ts.BinaryExpression).left; - if (ts.isAccessExpression(target)) { + const parent = walkUpParenthesizedExpressions(func.parent); + if (parent.kind === SyntaxKind.BinaryExpression && (parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + const target = (parent as BinaryExpression).left; + if (isAccessExpression(target)) { const { expression } = target; // Don't contextually type `this` as `exports` in `exports.Point = function(x, y) { this.x = x; this.y = y; }` - if (inJs && ts.isIdentifier(expression)) { - const sourceFile = ts.getSourceFileOfNode(parent); + if (inJs && isIdentifier(expression)) { + const sourceFile = getSourceFileOfNode(parent); if (sourceFile.commonJsModuleIndicator && getResolvedSymbol(expression) === sourceFile.symbol) { return undefined; } @@ -26970,12 +27168,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Return contextual type of parameter or undefined if no contextual type is available - function getContextuallyTypedParameterType(parameter: ts.ParameterDeclaration): ts.Type | undefined { + function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type | undefined { const func = parameter.parent; if (!isContextSensitiveFunctionOrObjectLiteralMethod(func)) { return undefined; } - const iife = ts.getImmediatelyInvokedFunctionExpression(func); + const iife = getImmediatelyInvokedFunctionExpression(func); if (iife && iife.arguments) { const args = getEffectiveCallArguments(iife); const indexOfParameter = func.parameters.indexOf(parameter); @@ -26993,39 +27191,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const contextualSignature = getContextualSignature(func); if (contextualSignature) { - const index = func.parameters.indexOf(parameter) - (ts.getThisParameter(func) ? 1 : 0); - return parameter.dotDotDotToken && ts.lastOrUndefined(func.parameters) === parameter ? + const index = func.parameters.indexOf(parameter) - (getThisParameter(func) ? 1 : 0); + return parameter.dotDotDotToken && lastOrUndefined(func.parameters) === parameter ? getRestTypeAtPosition(contextualSignature, index) : tryGetTypeAtPosition(contextualSignature, index); } } - function getContextualTypeForVariableLikeDeclaration(declaration: ts.VariableLikeDeclaration, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const typeNode = ts.getEffectiveTypeAnnotationNode(declaration); + function getContextualTypeForVariableLikeDeclaration(declaration: VariableLikeDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + const typeNode = getEffectiveTypeAnnotationNode(declaration); if (typeNode) { return getTypeFromTypeNode(typeNode); } switch (declaration.kind) { - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: return getContextuallyTypedParameterType(declaration); - case ts.SyntaxKind.BindingElement: + case SyntaxKind.BindingElement: return getContextualTypeForBindingElement(declaration, contextFlags); - case ts.SyntaxKind.PropertyDeclaration: - if (ts.isStatic(declaration)) { + case SyntaxKind.PropertyDeclaration: + if (isStatic(declaration)) { return getContextualTypeForStaticPropertyDeclaration(declaration, contextFlags); } // By default, do nothing and return undefined - only the above cases have context implied by a parent } } - function getContextualTypeForBindingElement(declaration: ts.BindingElement, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { + function getContextualTypeForBindingElement(declaration: BindingElement, contextFlags: ContextFlags | undefined): Type | undefined { const parent = declaration.parent.parent; const name = declaration.propertyName || declaration.name; const parentType = getContextualTypeForVariableLikeDeclaration(parent, contextFlags) || - parent.kind !== ts.SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent, declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal); - if (!parentType || ts.isBindingPattern(name) || ts.isComputedNonLiteralName(name)) return undefined; - if (parent.name.kind === ts.SyntaxKind.ArrayBindingPattern) { - const index = ts.indexOfNode(declaration.parent.elements, declaration); + parent.kind !== SyntaxKind.BindingElement && parent.initializer && checkDeclarationInitializer(parent, declaration.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal); + if (!parentType || isBindingPattern(name) || isComputedNonLiteralName(name)) return undefined; + if (parent.name.kind === SyntaxKind.ArrayBindingPattern) { + const index = indexOfNode(declaration.parent.elements, declaration); if (index < 0) return undefined; return getContextualTypeForElementExpression(parentType, index); } @@ -27036,8 +27234,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getContextualTypeForStaticPropertyDeclaration(declaration: ts.PropertyDeclaration, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const parentType = ts.isExpression(declaration.parent) && getContextualType(declaration.parent, contextFlags); + function getContextualTypeForStaticPropertyDeclaration(declaration: PropertyDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + const parentType = isExpression(declaration.parent) && getContextualType(declaration.parent, contextFlags); if (!parentType) return undefined; return getTypeOfPropertyOfContextualType(parentType, getSymbolOfNode(declaration).escapedName); } @@ -27050,32 +27248,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the contextual type of an initializer expression is the type implied by the binding pattern. // Otherwise, in a binding pattern inside a variable or parameter declaration, // the contextual type of an initializer expression is the type annotation of the containing declaration, if present. - function getContextualTypeForInitializerExpression(node: ts.Expression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const declaration = node.parent as ts.VariableLikeDeclaration; - if (ts.hasInitializer(declaration) && node === declaration.initializer) { + function getContextualTypeForInitializerExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + const declaration = node.parent as VariableLikeDeclaration; + if (hasInitializer(declaration) && node === declaration.initializer) { const result = getContextualTypeForVariableLikeDeclaration(declaration, contextFlags); if (result) { return result; } - if (!(contextFlags! & ts.ContextFlags.SkipBindingPatterns) && ts.isBindingPattern(declaration.name) && declaration.name.elements.length > 0) { + if (!(contextFlags! & ContextFlags.SkipBindingPatterns) && isBindingPattern(declaration.name) && declaration.name.elements.length > 0) { return getTypeFromBindingPattern(declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false); } } return undefined; } - function getContextualTypeForReturnExpression(node: ts.Expression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const func = ts.getContainingFunction(node); + function getContextualTypeForReturnExpression(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + const func = getContainingFunction(node); if (func) { let contextualReturnType = getContextualReturnType(func, contextFlags); if (contextualReturnType) { - const functionFlags = ts.getFunctionFlags(func); - if (functionFlags & ts.FunctionFlags.Generator) { // Generator or AsyncGenerator function - const isAsyncGenerator = (functionFlags & ts.FunctionFlags.Async) !== 0; - if (contextualReturnType.flags & ts.TypeFlags.Union) { + const functionFlags = getFunctionFlags(func); + if (functionFlags & FunctionFlags.Generator) { // Generator or AsyncGenerator function + const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0; + if (contextualReturnType.flags & TypeFlags.Union) { contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator)); } - const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & ts.FunctionFlags.Async) !== 0); + const iterationReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, contextualReturnType, (functionFlags & FunctionFlags.Async) !== 0); if (!iterationReturnType) { return undefined; } @@ -27083,7 +27281,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // falls through to unwrap Promise for AsyncGenerators } - if (functionFlags & ts.FunctionFlags.Async) { // Async function or AsyncGenerator function + if (functionFlags & FunctionFlags.Async) { // Async function or AsyncGenerator function // Get the awaited type without the `Awaited` alias const contextualAwaitedType = mapType(contextualReturnType, getAwaitedTypeNoAlias); return contextualAwaitedType && getUnionType([contextualAwaitedType, createPromiseLikeType(contextualAwaitedType)]); @@ -27095,7 +27293,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualTypeForAwaitOperand(node: ts.AwaitExpression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { + function getContextualTypeForAwaitOperand(node: AwaitExpression, contextFlags: ContextFlags | undefined): Type | undefined { const contextualType = getContextualType(node, contextFlags); if (contextualType) { const contextualAwaitedType = getAwaitedTypeNoAlias(contextualType); @@ -27104,14 +27302,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualTypeForYieldOperand(node: ts.YieldExpression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const func = ts.getContainingFunction(node); + function getContextualTypeForYieldOperand(node: YieldExpression, contextFlags: ContextFlags | undefined): Type | undefined { + const func = getContainingFunction(node); if (func) { - const functionFlags = ts.getFunctionFlags(func); + const functionFlags = getFunctionFlags(func); let contextualReturnType = getContextualReturnType(func, contextFlags); if (contextualReturnType) { - const isAsyncGenerator = (functionFlags & ts.FunctionFlags.Async) !== 0; - if (!node.asteriskToken && contextualReturnType.flags & ts.TypeFlags.Union) { + const isAsyncGenerator = (functionFlags & FunctionFlags.Async) !== 0; + if (!node.asteriskToken && contextualReturnType.flags & TypeFlags.Union) { contextualReturnType = filterType(contextualReturnType, type => !!getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, type, isAsyncGenerator)); } return node.asteriskToken @@ -27123,13 +27321,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isInParameterInitializerBeforeContainingFunction(node: ts.Node) { + function isInParameterInitializerBeforeContainingFunction(node: Node) { let inBindingInitializer = false; - while (node.parent && !ts.isFunctionLike(node.parent)) { - if (ts.isParameter(node.parent) && (inBindingInitializer || node.parent.initializer === node)) { + while (node.parent && !isFunctionLike(node.parent)) { + if (isParameter(node.parent) && (inBindingInitializer || node.parent.initializer === node)) { return true; } - if (ts.isBindingElement(node.parent) && node.parent.initializer === node) { + if (isBindingElement(node.parent) && node.parent.initializer === node) { inBindingInitializer = true; } @@ -27139,8 +27337,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function getContextualIterationType(kind: IterationTypeKind, functionDecl: ts.SignatureDeclaration): ts.Type | undefined { - const isAsync = !!(ts.getFunctionFlags(functionDecl) & ts.FunctionFlags.Async); + function getContextualIterationType(kind: IterationTypeKind, functionDecl: SignatureDeclaration): Type | undefined { + const isAsync = !!(getFunctionFlags(functionDecl) & FunctionFlags.Async); const contextualReturnType = getContextualReturnType(functionDecl, /*contextFlags*/ undefined); if (contextualReturnType) { return getIterationTypeOfGeneratorFunctionReturnType(kind, contextualReturnType, isAsync) @@ -27150,7 +27348,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getContextualReturnType(functionDecl: ts.SignatureDeclaration, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { + function getContextualReturnType(functionDecl: SignatureDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { // If the containing function has a return type annotation, is a constructor, or is a get accessor whose // corresponding set accessor has a type annotation, return statements in the function are contextually typed const returnType = getReturnTypeFromAnnotation(functionDecl); @@ -27159,11 +27357,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Otherwise, if the containing function is contextually typed by a function type with exactly one call signature // and that call signature is non-generic, return statements are contextually typed by the return type of the signature - const signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl as ts.FunctionExpression); + const signature = getContextualSignatureForFunctionLikeDeclaration(functionDecl as FunctionExpression); if (signature && !isResolvingReturnTypeOfSignature(signature)) { return getReturnTypeOfSignature(signature); } - const iife = ts.getImmediatelyInvokedFunctionExpression(functionDecl); + const iife = getImmediatelyInvokedFunctionExpression(functionDecl); if (iife) { return getContextualType(iife, contextFlags); } @@ -27171,14 +27369,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // In a typed function call, an argument or substitution expression is contextually typed by the type of the corresponding parameter. - function getContextualTypeForArgument(callTarget: ts.CallLikeExpression, arg: ts.Expression): ts.Type | undefined { + function getContextualTypeForArgument(callTarget: CallLikeExpression, arg: Expression): Type | undefined { const args = getEffectiveCallArguments(callTarget); const argIndex = args.indexOf(arg); // -1 for e.g. the expression of a CallExpression, or the tag of a TaggedTemplateExpression return argIndex === -1 ? undefined : getContextualTypeForArgumentAtIndex(callTarget, argIndex); } - function getContextualTypeForArgumentAtIndex(callTarget: ts.CallLikeExpression, argIndex: number): ts.Type { - if (ts.isImportCall(callTarget)) { + function getContextualTypeForArgumentAtIndex(callTarget: CallLikeExpression, argIndex: number): Type { + if (isImportCall(callTarget)) { return argIndex === 0 ? stringType : argIndex === 1 ? getGlobalImportCallOptionsType(/*reportErrors*/ false) : anyType; @@ -27188,44 +27386,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // that could cause infinite recursion. Instead, return anySignature. const signature = getNodeLinks(callTarget).resolvedSignature === resolvingSignature ? resolvingSignature : getResolvedSignature(callTarget); - if (ts.isJsxOpeningLikeElement(callTarget) && argIndex === 0) { + if (isJsxOpeningLikeElement(callTarget) && argIndex === 0) { return getEffectiveFirstArgumentForJsxSignature(signature, callTarget); } const restIndex = signature.parameters.length - 1; return signatureHasRestParameter(signature) && argIndex >= restIndex ? - getIndexedAccessType(getTypeOfSymbol(signature.parameters[restIndex]), getNumberLiteralType(argIndex - restIndex), ts.AccessFlags.Contextual) : + getIndexedAccessType(getTypeOfSymbol(signature.parameters[restIndex]), getNumberLiteralType(argIndex - restIndex), AccessFlags.Contextual) : getTypeAtPosition(signature, argIndex); } - function getContextualTypeForSubstitutionExpression(template: ts.TemplateExpression, substitutionExpression: ts.Expression) { - if (template.parent.kind === ts.SyntaxKind.TaggedTemplateExpression) { - return getContextualTypeForArgument(template.parent as ts.TaggedTemplateExpression, substitutionExpression); + function getContextualTypeForSubstitutionExpression(template: TemplateExpression, substitutionExpression: Expression) { + if (template.parent.kind === SyntaxKind.TaggedTemplateExpression) { + return getContextualTypeForArgument(template.parent as TaggedTemplateExpression, substitutionExpression); } return undefined; } - function getContextualTypeForBinaryOperand(node: ts.Expression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const binaryExpression = node.parent as ts.BinaryExpression; + function getContextualTypeForBinaryOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + const binaryExpression = node.parent as BinaryExpression; const { left, operatorToken, right } = binaryExpression; switch (operatorToken.kind) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.AmpersandAmpersandEqualsToken: - case ts.SyntaxKind.BarBarEqualsToken: - case ts.SyntaxKind.QuestionQuestionEqualsToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: + case SyntaxKind.BarBarEqualsToken: + case SyntaxKind.QuestionQuestionEqualsToken: return node === right ? getContextualTypeForAssignmentDeclaration(binaryExpression) : undefined; - case ts.SyntaxKind.BarBarToken: - case ts.SyntaxKind.QuestionQuestionToken: + case SyntaxKind.BarBarToken: + case SyntaxKind.QuestionQuestionToken: // When an || expression has a contextual type, the operands are contextually typed by that type, except // when that type originates in a binding pattern, the right operand is contextually typed by the type of // the left operand. When an || expression has no contextual type, the right operand is contextually typed // by the type of the left operand, except for the special case of Javascript declarations of the form // `namespace.prop = namespace.prop || {}`. const type = getContextualType(binaryExpression, contextFlags); - return node === right && (type && type.pattern || !type && !ts.isDefaultedExpandoInitializer(binaryExpression)) ? + return node === right && (type && type.pattern || !type && !isDefaultedExpandoInitializer(binaryExpression)) ? getTypeOfExpression(left) : type; - case ts.SyntaxKind.AmpersandAmpersandToken: - case ts.SyntaxKind.CommaToken: + case SyntaxKind.AmpersandAmpersandToken: + case SyntaxKind.CommaToken: return node === right ? getContextualType(binaryExpression, contextFlags) : undefined; default: return undefined; @@ -27236,18 +27434,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Try to find a resolved symbol for an expression without also resolving its type, as * getSymbolAtLocation would (as that could be reentrant into contextual typing) */ - function getSymbolForExpression(e: ts.Expression) { + function getSymbolForExpression(e: Expression) { if (e.symbol) { return e.symbol; } - if (ts.isIdentifier(e)) { + if (isIdentifier(e)) { return getResolvedSymbol(e); } - if (ts.isPropertyAccessExpression(e)) { + if (isPropertyAccessExpression(e)) { const lhsType = getTypeOfExpression(e.expression); - return ts.isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) : getPropertyOfType(lhsType, e.name.escapedText); + return isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) : getPropertyOfType(lhsType, e.name.escapedText); } - if (ts.isElementAccessExpression(e)) { + if (isElementAccessExpression(e)) { const propType = checkExpressionCached(e.argumentExpression); if (!isTypeUsableAsPropertyName(propType)) { return undefined; @@ -27257,7 +27455,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return undefined; - function tryGetPrivateIdentifierPropertyOfType(type: ts.Type, id: ts.PrivateIdentifier) { + function tryGetPrivateIdentifierPropertyOfType(type: Type, id: PrivateIdentifier) { const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(id.escapedText, id); return lexicallyScopedSymbol && getPrivateIdentifierPropertyOfType(type, lexicallyScopedSymbol); } @@ -27265,25 +27463,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // In an assignment expression, the right operand is contextually typed by the type of the left operand. // Don't do this for assignment declarations unless there is a type tag on the assignment, to avoid circularity from checking the right operand. - function getContextualTypeForAssignmentDeclaration(binaryExpression: ts.BinaryExpression): ts.Type | undefined { - const kind = ts.getAssignmentDeclarationKind(binaryExpression); + function getContextualTypeForAssignmentDeclaration(binaryExpression: BinaryExpression): Type | undefined { + const kind = getAssignmentDeclarationKind(binaryExpression); switch (kind) { - case ts.AssignmentDeclarationKind.None: - case ts.AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.None: + case AssignmentDeclarationKind.ThisProperty: const lhsSymbol = getSymbolForExpression(binaryExpression.left); const decl = lhsSymbol && lhsSymbol.valueDeclaration; // Unannotated, uninitialized property declarations have a type implied by their usage in the constructor. // We avoid calling back into `getTypeOfExpression` and reentering contextual typing to avoid a bogus circularity error in that case. - if (decl && (ts.isPropertyDeclaration(decl) || ts.isPropertySignature(decl))) { - const overallAnnotation = ts.getEffectiveTypeAnnotationNode(decl); + if (decl && (isPropertyDeclaration(decl) || isPropertySignature(decl))) { + const overallAnnotation = getEffectiveTypeAnnotationNode(decl); return (overallAnnotation && instantiateType(getTypeFromTypeNode(overallAnnotation), getSymbolLinks(lhsSymbol).mapper)) || - (ts.isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); + (isPropertyDeclaration(decl) ? decl.initializer && getTypeOfExpression(binaryExpression.left) : undefined); } - if (kind === ts.AssignmentDeclarationKind.None) { + if (kind === AssignmentDeclarationKind.None) { return getTypeOfExpression(binaryExpression.left); } return getContextualTypeForThisPropertyAssignment(binaryExpression); - case ts.AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.Property: if (isPossiblyAliasedThisProperty(binaryExpression, kind)) { return getContextualTypeForThisPropertyAssignment(binaryExpression); } @@ -27297,18 +27495,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!decl) { return undefined; } - const lhs = ts.cast(binaryExpression.left, ts.isAccessExpression); - const overallAnnotation = ts.getEffectiveTypeAnnotationNode(decl); + const lhs = cast(binaryExpression.left, isAccessExpression); + const overallAnnotation = getEffectiveTypeAnnotationNode(decl); if (overallAnnotation) { return getTypeFromTypeNode(overallAnnotation); } - else if (ts.isIdentifier(lhs.expression)) { + else if (isIdentifier(lhs.expression)) { const id = lhs.expression; - const parentSymbol = resolveName(id, id.escapedText, ts.SymbolFlags.Value, undefined, id.escapedText, /*isUse*/ true); + const parentSymbol = resolveName(id, id.escapedText, SymbolFlags.Value, undefined, id.escapedText, /*isUse*/ true); if (parentSymbol) { - const annotated = parentSymbol.valueDeclaration && ts.getEffectiveTypeAnnotationNode(parentSymbol.valueDeclaration); + const annotated = parentSymbol.valueDeclaration && getEffectiveTypeAnnotationNode(parentSymbol.valueDeclaration); if (annotated) { - const nameStr = ts.getElementOrPropertyAccessName(lhs); + const nameStr = getElementOrPropertyAccessName(lhs); if (nameStr !== undefined) { return getTypeOfPropertyOfContextualType(getTypeFromTypeNode(annotated), nameStr); } @@ -27316,44 +27514,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } } - return ts.isInJSFile(decl) ? undefined : getTypeOfExpression(binaryExpression.left); + return isInJSFile(decl) ? undefined : getTypeOfExpression(binaryExpression.left); } - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.Prototype: - case ts.AssignmentDeclarationKind.PrototypeProperty: - case ts.AssignmentDeclarationKind.ModuleExports: - let valueDeclaration: ts.Declaration | undefined; - if (kind !== ts.AssignmentDeclarationKind.ModuleExports) { + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: + case AssignmentDeclarationKind.ModuleExports: + let valueDeclaration: Declaration | undefined; + if (kind !== AssignmentDeclarationKind.ModuleExports) { valueDeclaration = binaryExpression.left.symbol?.valueDeclaration; } valueDeclaration ||= binaryExpression.symbol?.valueDeclaration; - const annotated = valueDeclaration && ts.getEffectiveTypeAnnotationNode(valueDeclaration); + const annotated = valueDeclaration && getEffectiveTypeAnnotationNode(valueDeclaration); return annotated ? getTypeFromTypeNode(annotated) : undefined; - case ts.AssignmentDeclarationKind.ObjectDefinePropertyValue: - case ts.AssignmentDeclarationKind.ObjectDefinePropertyExports: - case ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty: - return ts.Debug.fail("Does not apply"); + case AssignmentDeclarationKind.ObjectDefinePropertyValue: + case AssignmentDeclarationKind.ObjectDefinePropertyExports: + case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: + return Debug.fail("Does not apply"); default: - return ts.Debug.assertNever(kind); + return Debug.assertNever(kind); } } - function isPossiblyAliasedThisProperty(declaration: ts.BinaryExpression, kind = ts.getAssignmentDeclarationKind(declaration)) { - if (kind === ts.AssignmentDeclarationKind.ThisProperty) { + function isPossiblyAliasedThisProperty(declaration: BinaryExpression, kind = getAssignmentDeclarationKind(declaration)) { + if (kind === AssignmentDeclarationKind.ThisProperty) { return true; } - if (!ts.isInJSFile(declaration) || kind !== ts.AssignmentDeclarationKind.Property || !ts.isIdentifier((declaration.left as ts.AccessExpression).expression)) { + if (!isInJSFile(declaration) || kind !== AssignmentDeclarationKind.Property || !isIdentifier((declaration.left as AccessExpression).expression)) { return false; } - const name = ((declaration.left as ts.AccessExpression).expression as ts.Identifier).escapedText; - const symbol = resolveName(declaration.left, name, ts.SymbolFlags.Value, undefined, undefined, /*isUse*/ true, /*excludeGlobals*/ true); - return ts.isThisInitializedDeclaration(symbol?.valueDeclaration); + const name = ((declaration.left as AccessExpression).expression as Identifier).escapedText; + const symbol = resolveName(declaration.left, name, SymbolFlags.Value, undefined, undefined, /*isUse*/ true, /*excludeGlobals*/ true); + return isThisInitializedDeclaration(symbol?.valueDeclaration); } - function getContextualTypeForThisPropertyAssignment(binaryExpression: ts.BinaryExpression): ts.Type | undefined { + function getContextualTypeForThisPropertyAssignment(binaryExpression: BinaryExpression): Type | undefined { if (!binaryExpression.symbol) return getTypeOfExpression(binaryExpression.left); if (binaryExpression.symbol.valueDeclaration) { - const annotated = ts.getEffectiveTypeAnnotationNode(binaryExpression.symbol.valueDeclaration); + const annotated = getEffectiveTypeAnnotationNode(binaryExpression.symbol.valueDeclaration); if (annotated) { const type = getTypeFromTypeNode(annotated); if (type) { @@ -27361,42 +27559,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - const thisAccess = ts.cast(binaryExpression.left, ts.isAccessExpression); - if (!ts.isObjectLiteralMethod(ts.getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) { + const thisAccess = cast(binaryExpression.left, isAccessExpression); + if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) { return undefined; } const thisType = checkThisExpression(thisAccess.expression); - const nameStr = ts.getElementOrPropertyAccessName(thisAccess); + const nameStr = getElementOrPropertyAccessName(thisAccess); return nameStr !== undefined && getTypeOfPropertyOfContextualType(thisType, nameStr) || undefined; } - function isCircularMappedProperty(symbol: ts.Symbol) { - return !!(ts.getCheckFlags(symbol) & ts.CheckFlags.Mapped && !(symbol as ts.MappedSymbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); + function isCircularMappedProperty(symbol: Symbol) { + return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); } - function getTypeOfPropertyOfContextualType(type: ts.Type, name: ts.__String, nameType?: ts.Type) { + function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { if (isGenericMappedType(t) && !t.declaration.nameType) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - const propertyNameType = nameType || getStringLiteralType(ts.unescapeLeadingUnderscores(name)); + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { return substituteIndexedMappedType(t, propertyNameType); } } - else if (t.flags & ts.TypeFlags.StructuredType) { + else if (t.flags & TypeFlags.StructuredType) { const prop = getPropertyOfType(t, name); if (prop) { return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop); } if (isTupleType(t)) { const restType = getRestTypeOfTupleType(t); - if (restType && ts.isNumericLiteralName(name) && +name >= 0) { + if (restType && isNumericLiteralName(name) && +name >= 0) { return restType; } } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(ts.unescapeLeadingUnderscores(name)))?.type; + return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } return undefined; }, /*noReductions*/ true); @@ -27405,18 +27603,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // In an object literal contextually typed by a type T, the contextual type of a property assignment is the type of // the matching property in T, if one exists. Otherwise, it is the type of the numeric index signature in T, if one // exists. Otherwise, it is the type of the string index signature in T, if one exists. - function getContextualTypeForObjectLiteralMethod(node: ts.MethodDeclaration, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - ts.Debug.assert(ts.isObjectLiteralMethod(node)); - if (node.flags & ts.NodeFlags.InWithStatement) { + function getContextualTypeForObjectLiteralMethod(node: MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + Debug.assert(isObjectLiteralMethod(node)); + if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } return getContextualTypeForObjectLiteralElement(node, contextFlags); } - function getContextualTypeForObjectLiteralElement(element: ts.ObjectLiteralElementLike, contextFlags: ts.ContextFlags | undefined) { - const objectLiteral = element.parent as ts.ObjectLiteralExpression; - const propertyAssignmentType = ts.isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element, contextFlags); + function getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike, contextFlags: ContextFlags | undefined) { + const objectLiteral = element.parent as ObjectLiteralExpression; + const propertyAssignmentType = isPropertyAssignment(element) && getContextualTypeForVariableLikeDeclaration(element, contextFlags); if (propertyAssignmentType) { return propertyAssignmentType; } @@ -27442,9 +27640,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the type of the property with the numeric name N in T, if one exists. Otherwise, if T has a numeric index signature, // it is the type of the numeric index signature in T. Otherwise, in ES6 and higher, the contextual type is the iterated // type of T. - function getContextualTypeForElementExpression(arrayContextualType: ts.Type | undefined, index: number): ts.Type | undefined { + function getContextualTypeForElementExpression(arrayContextualType: Type | undefined, index: number): Type | undefined { return arrayContextualType && ( - getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as ts.__String) + getTypeOfPropertyOfContextualType(arrayContextualType, "" + index as __String) || mapType( arrayContextualType, t => getIteratedTypeOrElementType(IterationUse.Element, t, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false), @@ -27452,19 +27650,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // In a contextually typed conditional expression, the true/false expressions are contextually typed by the same type. - function getContextualTypeForConditionalOperand(node: ts.Expression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const conditional = node.parent as ts.ConditionalExpression; + function getContextualTypeForConditionalOperand(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + const conditional = node.parent as ConditionalExpression; return node === conditional.whenTrue || node === conditional.whenFalse ? getContextualType(conditional, contextFlags) : undefined; } - function getContextualTypeForChildJsxExpression(node: ts.JsxElement, child: ts.JsxChild, contextFlags: ts.ContextFlags | undefined) { + function getContextualTypeForChildJsxExpression(node: JsxElement, child: JsxChild, contextFlags: ContextFlags | undefined) { const attributesType = getApparentTypeOfContextualType(node.openingElement.tagName, contextFlags); // JSX expression is in children of JSX Element, we will look for an "children" attribute (we get the name from JSX.ElementAttributesProperty) const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(node)); if (!(attributesType && !isTypeAny(attributesType) && jsxChildrenPropertyName && jsxChildrenPropertyName !== "")) { return undefined; } - const realChildren = ts.getSemanticJsxChildren(node.children); + const realChildren = getSemanticJsxChildren(node.children); const childIndex = realChildren.indexOf(child); const childFieldType = getTypeOfPropertyOfContextualType(attributesType, jsxChildrenPropertyName); return childFieldType && (realChildren.length === 1 ? childFieldType : mapType(childFieldType, t => { @@ -27477,20 +27675,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }, /*noReductions*/ true)); } - function getContextualTypeForJsxExpression(node: ts.JsxExpression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { + function getContextualTypeForJsxExpression(node: JsxExpression, contextFlags: ContextFlags | undefined): Type | undefined { const exprParent = node.parent; - return ts.isJsxAttributeLike(exprParent) + return isJsxAttributeLike(exprParent) ? getContextualType(node, contextFlags) - : ts.isJsxElement(exprParent) + : isJsxElement(exprParent) ? getContextualTypeForChildJsxExpression(exprParent, node, contextFlags) : undefined; } - function getContextualTypeForJsxAttribute(attribute: ts.JsxAttribute | ts.JsxSpreadAttribute, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { + function getContextualTypeForJsxAttribute(attribute: JsxAttribute | JsxSpreadAttribute, contextFlags: ContextFlags | undefined): Type | undefined { // When we trying to resolve JsxOpeningLikeElement as a stateless function element, we will already give its attributes a contextual type // which is a type of the parameter of the signature we are trying out. // If there is no contextual type (e.g. we are trying to resolve stateful component), get attributes type from resolving element's tagName - if (ts.isJsxAttribute(attribute)) { + if (isJsxAttribute(attribute)) { const attributesType = getApparentTypeOfContextualType(attribute.parent, contextFlags); if (!attributesType || isTypeAny(attributesType)) { return undefined; @@ -27505,37 +27703,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if the given expression is possibly a discriminant value. We limit the kinds of // expressions we check to those that don't depend on their contextual type in order not to cause // recursive (and possibly infinite) invocations of getContextualType. - function isPossiblyDiscriminantValue(node: ts.Expression): boolean { + function isPossiblyDiscriminantValue(node: Expression): boolean { switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.UndefinedKeyword: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.UndefinedKeyword: return true; - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ParenthesizedExpression: - return isPossiblyDiscriminantValue((node as ts.PropertyAccessExpression | ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.JsxExpression: - return !(node as ts.JsxExpression).expression || isPossiblyDiscriminantValue((node as ts.JsxExpression).expression!); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ParenthesizedExpression: + return isPossiblyDiscriminantValue((node as PropertyAccessExpression | ParenthesizedExpression).expression); + case SyntaxKind.JsxExpression: + return !(node as JsxExpression).expression || isPossiblyDiscriminantValue((node as JsxExpression).expression!); } return false; } - function discriminateContextualTypeByObjectMembers(node: ts.ObjectLiteralExpression, contextualType: ts.UnionType) { + function discriminateContextualTypeByObjectMembers(node: ObjectLiteralExpression, contextualType: UnionType) { return getMatchingUnionConstituentForObjectLiteral(contextualType, node) || discriminateTypeByDiscriminableItems(contextualType, - ts.concatenate( - ts.map( - ts.filter(node.properties, p => !!p.symbol && p.kind === ts.SyntaxKind.PropertyAssignment && isPossiblyDiscriminantValue(p.initializer) && isDiscriminantProperty(contextualType, p.symbol.escapedName)), - prop => ([() => getContextFreeTypeOfExpression((prop as ts.PropertyAssignment).initializer), prop.symbol.escapedName] as [() => ts.Type, ts.__String]) + concatenate( + map( + filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.PropertyAssignment && isPossiblyDiscriminantValue(p.initializer) && isDiscriminantProperty(contextualType, p.symbol.escapedName)), + prop => ([() => getContextFreeTypeOfExpression((prop as PropertyAssignment).initializer), prop.symbol.escapedName] as [() => Type, __String]) ), - ts.map( - ts.filter(getPropertiesOfType(contextualType), s => !!(s.flags & ts.SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), - s => [() => undefinedType, s.escapedName] as [() => ts.Type, ts.__String] + map( + filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), + s => [() => undefinedType, s.escapedName] as [() => Type, __String] ) ), isTypeAssignableTo, @@ -27543,16 +27741,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { ); } - function discriminateContextualTypeByJSXAttributes(node: ts.JsxAttributes, contextualType: ts.UnionType) { + function discriminateContextualTypeByJSXAttributes(node: JsxAttributes, contextualType: UnionType) { return discriminateTypeByDiscriminableItems(contextualType, - ts.concatenate( - ts.map( - ts.filter(node.properties, p => !!p.symbol && p.kind === ts.SyntaxKind.JsxAttribute && isDiscriminantProperty(contextualType, p.symbol.escapedName) && (!p.initializer || isPossiblyDiscriminantValue(p.initializer))), - prop => ([!(prop as ts.JsxAttribute).initializer ? (() => trueType) : (() => getContextFreeTypeOfExpression((prop as ts.JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => ts.Type, ts.__String]) + concatenate( + map( + filter(node.properties, p => !!p.symbol && p.kind === SyntaxKind.JsxAttribute && isDiscriminantProperty(contextualType, p.symbol.escapedName) && (!p.initializer || isPossiblyDiscriminantValue(p.initializer))), + prop => ([!(prop as JsxAttribute).initializer ? (() => trueType) : (() => getContextFreeTypeOfExpression((prop as JsxAttribute).initializer!)), prop.symbol.escapedName] as [() => Type, __String]) ), - ts.map( - ts.filter(getPropertiesOfType(contextualType), s => !!(s.flags & ts.SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), - s => [() => undefinedType, s.escapedName] as [() => ts.Type, ts.__String] + map( + filter(getPropertiesOfType(contextualType), s => !!(s.flags & SymbolFlags.Optional) && !!node?.symbol?.members && !node.symbol.members.has(s.escapedName) && isDiscriminantProperty(contextualType, s.escapedName)), + s => [() => undefinedType, s.escapedName] as [() => Type, __String] ) ), isTypeAssignableTo, @@ -27562,28 +27760,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily // be "pushed" onto a node using the contextualType property. - function getApparentTypeOfContextualType(node: ts.Expression | ts.MethodDeclaration, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - const contextualType = ts.isObjectLiteralMethod(node) ? + function getApparentTypeOfContextualType(node: Expression | MethodDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { + const contextualType = isObjectLiteralMethod(node) ? getContextualTypeForObjectLiteralMethod(node, contextFlags) : getContextualType(node, contextFlags); const instantiatedType = instantiateContextualType(contextualType, node, contextFlags); - if (instantiatedType && !(contextFlags && contextFlags & ts.ContextFlags.NoConstraints && instantiatedType.flags & ts.TypeFlags.TypeVariable)) { + if (instantiatedType && !(contextFlags && contextFlags & ContextFlags.NoConstraints && instantiatedType.flags & TypeFlags.TypeVariable)) { const apparentType = mapType(instantiatedType, getApparentType, /*noReductions*/ true); - return apparentType.flags & ts.TypeFlags.Union && ts.isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as ts.UnionType) : - apparentType.flags & ts.TypeFlags.Union && ts.isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as ts.UnionType) : + return apparentType.flags & TypeFlags.Union && isObjectLiteralExpression(node) ? discriminateContextualTypeByObjectMembers(node, apparentType as UnionType) : + apparentType.flags & TypeFlags.Union && isJsxAttributes(node) ? discriminateContextualTypeByJSXAttributes(node, apparentType as UnionType) : apparentType; } } // If the given contextual type contains instantiable types and if a mapper representing // return type inferences is available, instantiate those types using that mapper. - function instantiateContextualType(contextualType: ts.Type | undefined, node: ts.Node, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - if (contextualType && maybeTypeOfKind(contextualType, ts.TypeFlags.Instantiable)) { + function instantiateContextualType(contextualType: Type | undefined, node: Node, contextFlags: ContextFlags | undefined): Type | undefined { + if (contextualType && maybeTypeOfKind(contextualType, TypeFlags.Instantiable)) { const inferenceContext = getInferenceContext(node); // If no inferences have been made, and none of the type parameters for which we are inferring // specify default types, nothing is gained from instantiating as type parameters would just be // replaced with their constraints similar to the apparent type. - if (inferenceContext && contextFlags! & ts.ContextFlags.Signature && ts.some(inferenceContext.inferences, hasInferenceCandidatesOrDefault)) { + if (inferenceContext && contextFlags! & ContextFlags.Signature && some(inferenceContext.inferences, hasInferenceCandidatesOrDefault)) { // For contextual signatures we incorporate all inferences made so far, e.g. from return // types as well as arguments to the left in a function call. return instantiateInstantiableTypes(contextualType, inferenceContext.nonFixingMapper); @@ -27594,7 +27792,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the 'boolean' type from the contextual type such that contextually typed boolean // literals actually end up widening to 'boolean' (see #48363). const type = instantiateInstantiableTypes(contextualType, inferenceContext.returnMapper); - return type.flags & ts.TypeFlags.Union && containsType((type as ts.UnionType).types, regularFalseType) && containsType((type as ts.UnionType).types, regularTrueType) ? + return type.flags & TypeFlags.Union && containsType((type as UnionType).types, regularFalseType) && containsType((type as UnionType).types, regularTrueType) ? filterType(type, t => t !== regularFalseType && t !== regularTrueType) : type; } @@ -27605,15 +27803,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // This function is similar to instantiateType, except that (a) it only instantiates types that // are classified as instantiable (i.e. it doesn't instantiate object types), and (b) it performs // no reductions on instantiated union types. - function instantiateInstantiableTypes(type: ts.Type, mapper: ts.TypeMapper): ts.Type { - if (type.flags & ts.TypeFlags.Instantiable) { + function instantiateInstantiableTypes(type: Type, mapper: TypeMapper): Type { + if (type.flags & TypeFlags.Instantiable) { return instantiateType(type, mapper); } - if (type.flags & ts.TypeFlags.Union) { - return getUnionType(ts.map((type as ts.UnionType).types, t => instantiateInstantiableTypes(t, mapper)), ts.UnionReduction.None); + if (type.flags & TypeFlags.Union) { + return getUnionType(map((type as UnionType).types, t => instantiateInstantiableTypes(t, mapper)), UnionReduction.None); } - if (type.flags & ts.TypeFlags.Intersection) { - return getIntersectionType(ts.map((type as ts.IntersectionType).types, t => instantiateInstantiableTypes(t, mapper))); + if (type.flags & TypeFlags.Intersection) { + return getIntersectionType(map((type as IntersectionType).types, t => instantiateInstantiableTypes(t, mapper))); } return type; } @@ -27635,8 +27833,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param node the expression whose contextual type will be returned. * @returns the contextual type of an expression. */ - function getContextualType(node: ts.Expression, contextFlags: ts.ContextFlags | undefined): ts.Type | undefined { - if (node.flags & ts.NodeFlags.InWithStatement) { + function getContextualType(node: Expression, contextFlags: ContextFlags | undefined): Type | undefined { + if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } @@ -27645,78 +27843,78 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const { parent } = node; switch (parent.kind) { - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.BindingElement: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.Parameter: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.BindingElement: return getContextualTypeForInitializerExpression(node, contextFlags); - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.ReturnStatement: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ReturnStatement: return getContextualTypeForReturnExpression(node, contextFlags); - case ts.SyntaxKind.YieldExpression: - return getContextualTypeForYieldOperand(parent as ts.YieldExpression, contextFlags); - case ts.SyntaxKind.AwaitExpression: - return getContextualTypeForAwaitOperand(parent as ts.AwaitExpression, contextFlags); - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - return getContextualTypeForArgument(parent as ts.CallExpression | ts.NewExpression, node); - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.AsExpression: - return ts.isConstTypeReference((parent as ts.AssertionExpression).type) ? tryFindWhenConstTypeReference(parent as ts.AssertionExpression) : getTypeFromTypeNode((parent as ts.AssertionExpression).type); - case ts.SyntaxKind.BinaryExpression: + case SyntaxKind.YieldExpression: + return getContextualTypeForYieldOperand(parent as YieldExpression, contextFlags); + case SyntaxKind.AwaitExpression: + return getContextualTypeForAwaitOperand(parent as AwaitExpression, contextFlags); + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + return getContextualTypeForArgument(parent as CallExpression | NewExpression, node); + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + return isConstTypeReference((parent as AssertionExpression).type) ? tryFindWhenConstTypeReference(parent as AssertionExpression) : getTypeFromTypeNode((parent as AssertionExpression).type); + case SyntaxKind.BinaryExpression: return getContextualTypeForBinaryOperand(node, contextFlags); - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - return getContextualTypeForObjectLiteralElement(parent as ts.PropertyAssignment | ts.ShorthandPropertyAssignment, contextFlags); - case ts.SyntaxKind.SpreadAssignment: - return getContextualType(parent.parent as ts.ObjectLiteralExpression, contextFlags); - case ts.SyntaxKind.ArrayLiteralExpression: { - const arrayLiteral = parent as ts.ArrayLiteralExpression; + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + return getContextualTypeForObjectLiteralElement(parent as PropertyAssignment | ShorthandPropertyAssignment, contextFlags); + case SyntaxKind.SpreadAssignment: + return getContextualType(parent.parent as ObjectLiteralExpression, contextFlags); + case SyntaxKind.ArrayLiteralExpression: { + const arrayLiteral = parent as ArrayLiteralExpression; const type = getApparentTypeOfContextualType(arrayLiteral, contextFlags); - return getContextualTypeForElementExpression(type, ts.indexOfNode(arrayLiteral.elements, node)); + return getContextualTypeForElementExpression(type, indexOfNode(arrayLiteral.elements, node)); } - case ts.SyntaxKind.ConditionalExpression: + case SyntaxKind.ConditionalExpression: return getContextualTypeForConditionalOperand(node, contextFlags); - case ts.SyntaxKind.TemplateSpan: - ts.Debug.assert(parent.parent.kind === ts.SyntaxKind.TemplateExpression); - return getContextualTypeForSubstitutionExpression(parent.parent as ts.TemplateExpression, node); - case ts.SyntaxKind.ParenthesizedExpression: { + case SyntaxKind.TemplateSpan: + Debug.assert(parent.parent.kind === SyntaxKind.TemplateExpression); + return getContextualTypeForSubstitutionExpression(parent.parent as TemplateExpression, node); + case SyntaxKind.ParenthesizedExpression: { // Like in `checkParenthesizedExpression`, an `/** @type {xyz} */` comment before a parenthesized expression acts as a type cast. - const tag = ts.isInJSFile(parent) ? ts.getJSDocTypeTag(parent) : undefined; - return !tag ? getContextualType(parent as ts.ParenthesizedExpression, contextFlags) : - ts.isJSDocTypeTag(tag) && ts.isConstTypeReference(tag.typeExpression.type) ? tryFindWhenConstTypeReference(parent as ts.ParenthesizedExpression) : + const tag = isInJSFile(parent) ? getJSDocTypeTag(parent) : undefined; + return !tag ? getContextualType(parent as ParenthesizedExpression, contextFlags) : + isJSDocTypeTag(tag) && isConstTypeReference(tag.typeExpression.type) ? tryFindWhenConstTypeReference(parent as ParenthesizedExpression) : getTypeFromTypeNode(tag.typeExpression.type); } - case ts.SyntaxKind.NonNullExpression: - return getContextualType(parent as ts.NonNullExpression, contextFlags); - case ts.SyntaxKind.SatisfiesExpression: - return getTypeFromTypeNode((parent as ts.SatisfiesExpression).type); - case ts.SyntaxKind.ExportAssignment: - return tryGetTypeFromEffectiveTypeNode(parent as ts.ExportAssignment); - case ts.SyntaxKind.JsxExpression: - return getContextualTypeForJsxExpression(parent as ts.JsxExpression, contextFlags); - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.JsxSpreadAttribute: - return getContextualTypeForJsxAttribute(parent as ts.JsxAttribute | ts.JsxSpreadAttribute, contextFlags); - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxSelfClosingElement: - return getContextualJsxElementAttributesType(parent as ts.JsxOpeningLikeElement, contextFlags); + case SyntaxKind.NonNullExpression: + return getContextualType(parent as NonNullExpression, contextFlags); + case SyntaxKind.SatisfiesExpression: + return getTypeFromTypeNode((parent as SatisfiesExpression).type); + case SyntaxKind.ExportAssignment: + return tryGetTypeFromEffectiveTypeNode(parent as ExportAssignment); + case SyntaxKind.JsxExpression: + return getContextualTypeForJsxExpression(parent as JsxExpression, contextFlags); + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + return getContextualTypeForJsxAttribute(parent as JsxAttribute | JsxSpreadAttribute, contextFlags); + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxSelfClosingElement: + return getContextualJsxElementAttributesType(parent as JsxOpeningLikeElement, contextFlags); } return undefined; - function tryFindWhenConstTypeReference(node: ts.Expression) { + function tryFindWhenConstTypeReference(node: Expression) { return getContextualType(node, contextFlags); } } - function getInferenceContext(node: ts.Node) { - const ancestor = ts.findAncestor(node, n => !!n.inferenceContext); + function getInferenceContext(node: Node) { + const ancestor = findAncestor(node, n => !!n.inferenceContext); return ancestor && ancestor.inferenceContext!; } - function getContextualJsxElementAttributesType(node: ts.JsxOpeningLikeElement, contextFlags: ts.ContextFlags | undefined) { - if (ts.isJsxOpeningElement(node) && node.parent.contextualType && contextFlags !== ts.ContextFlags.Completions) { + function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) { + if (isJsxOpeningElement(node) && node.parent.contextualType && contextFlags !== ContextFlags.Completions) { // Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit // _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type // (as below) instead! @@ -27725,13 +27923,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getContextualTypeForArgumentAtIndex(node, 0); } - function getEffectiveFirstArgumentForJsxSignature(signature: ts.Signature, node: ts.JsxOpeningLikeElement) { - return getJsxReferenceKind(node) !== ts.JsxReferenceKind.Component + function getEffectiveFirstArgumentForJsxSignature(signature: Signature, node: JsxOpeningLikeElement) { + return getJsxReferenceKind(node) !== JsxReferenceKind.Component ? getJsxPropsTypeFromCallSignature(signature, node) : getJsxPropsTypeFromClassType(signature, node); } - function getJsxPropsTypeFromCallSignature(sig: ts.Signature, context: ts.JsxOpeningLikeElement) { + function getJsxPropsTypeFromCallSignature(sig: Signature, context: JsxOpeningLikeElement) { let propsType = getTypeOfFirstParameterOfSignatureWithFallback(sig, unknownType); propsType = getJsxManagedAttributesFromLocatedAttributes(context, getJsxNamespaceAt(context), propsType); const intrinsicAttribs = getJsxType(JsxNames.IntrinsicAttributes, context); @@ -27741,14 +27939,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return propsType; } - function getJsxPropsTypeForSignatureFromMember(sig: ts.Signature, forcedLookupLocation: ts.__String) { + function getJsxPropsTypeForSignatureFromMember(sig: Signature, forcedLookupLocation: __String) { if (sig.compositeSignatures) { // JSX Elements using the legacy `props`-field based lookup (eg, react class components) need to treat the `props` member as an input // instead of an output position when resolving the signature. We need to go back to the input signatures of the composite signature, // get the type of `props` on each return type individually, and then _intersect them_, rather than union them (as would normally occur // for a union signature). It's an unfortunate quirk of looking in the output of the signature for the type we want to use for the input. // The default behavior of `getTypeOfFirstParameterOfSignatureWithFallback` when no `props` member name is defined is much more sane. - const results: ts.Type[] = []; + const results: Type[] = []; for (const signature of sig.compositeSignatures) { const instance = getReturnTypeOfSignature(signature); if (isTypeAny(instance)) { @@ -27766,15 +27964,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isTypeAny(instanceType) ? instanceType : getTypeOfPropertyOfType(instanceType, forcedLookupLocation); } - function getStaticTypeOfReferencedJsxConstructor(context: ts.JsxOpeningLikeElement) { + function getStaticTypeOfReferencedJsxConstructor(context: JsxOpeningLikeElement) { if (isJsxIntrinsicIdentifier(context.tagName)) { const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(context); const fakeSignature = createSignatureForJSXIntrinsic(context, result); return getOrCreateTypeFromSignature(fakeSignature); } const tagType = checkExpressionCached(context.tagName); - if (tagType.flags & ts.TypeFlags.StringLiteral) { - const result = getIntrinsicAttributesTypeFromStringLiteralType(tagType as ts.StringLiteralType, context); + if (tagType.flags & TypeFlags.StringLiteral) { + const result = getIntrinsicAttributesTypeFromStringLiteralType(tagType as StringLiteralType, context); if (!result) { return errorType; } @@ -27784,27 +27982,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return tagType; } - function getJsxManagedAttributesFromLocatedAttributes(context: ts.JsxOpeningLikeElement, ns: ts.Symbol, attributesType: ts.Type) { + function getJsxManagedAttributesFromLocatedAttributes(context: JsxOpeningLikeElement, ns: Symbol, attributesType: Type) { const managedSym = getJsxLibraryManagedAttributes(ns); if (managedSym) { const declaredManagedType = getDeclaredTypeOfSymbol(managedSym); // fetches interface type, or initializes symbol links type parmaeters const ctorType = getStaticTypeOfReferencedJsxConstructor(context); - if (managedSym.flags & ts.SymbolFlags.TypeAlias) { + if (managedSym.flags & SymbolFlags.TypeAlias) { const params = getSymbolLinks(managedSym).typeParameters; - if (ts.length(params) >= 2) { - const args = fillMissingTypeArguments([ctorType, attributesType], params, 2, ts.isInJSFile(context)); + if (length(params) >= 2) { + const args = fillMissingTypeArguments([ctorType, attributesType], params, 2, isInJSFile(context)); return getTypeAliasInstantiation(managedSym, args); } } - if (ts.length((declaredManagedType as ts.GenericType).typeParameters) >= 2) { - const args = fillMissingTypeArguments([ctorType, attributesType], (declaredManagedType as ts.GenericType).typeParameters, 2, ts.isInJSFile(context)); - return createTypeReference((declaredManagedType as ts.GenericType), args); + if (length((declaredManagedType as GenericType).typeParameters) >= 2) { + const args = fillMissingTypeArguments([ctorType, attributesType], (declaredManagedType as GenericType).typeParameters, 2, isInJSFile(context)); + return createTypeReference((declaredManagedType as GenericType), args); } } return attributesType; } - function getJsxPropsTypeFromClassType(sig: ts.Signature, context: ts.JsxOpeningLikeElement) { + function getJsxPropsTypeFromClassType(sig: Signature, context: JsxOpeningLikeElement) { const ns = getJsxNamespaceAt(context); const forcedLookupLocation = getJsxElementPropertiesName(ns); let attributesType = forcedLookupLocation === undefined @@ -27818,8 +28016,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!attributesType) { // There is no property named 'props' on this instance type - if (!!forcedLookupLocation && !!ts.length(context.attributes.properties)) { - error(context, ts.Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, ts.unescapeLeadingUnderscores(forcedLookupLocation)); + if (!!forcedLookupLocation && !!length(context.attributes.properties)) { + error(context, Diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, unescapeLeadingUnderscores(forcedLookupLocation)); } return unknownType; } @@ -27837,10 +28035,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isErrorType(intrinsicClassAttribs)) { const typeParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(intrinsicClassAttribs.symbol); const hostClassType = getReturnTypeOfSignature(sig); - let libraryManagedAttributeType: ts.Type; + let libraryManagedAttributeType: Type; if (typeParams) { // apply JSX.IntrinsicClassElements - const inferredArgs = fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), ts.isInJSFile(context)); + const inferredArgs = fillMissingTypeArguments([hostClassType], typeParams, getMinTypeArgumentCount(typeParams), isInJSFile(context)); libraryManagedAttributeType = instantiateType(intrinsicClassAttribs, createTypeMapper(typeParams, inferredArgs)); } // or JSX.IntrinsicClassElements has no generics. @@ -27857,9 +28055,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getIntersectedSignatures(signatures: readonly ts.Signature[]) { - return ts.getStrictOptionValue(compilerOptions, "noImplicitAny") - ? ts.reduceLeft( + function getIntersectedSignatures(signatures: readonly Signature[]) { + return getStrictOptionValue(compilerOptions, "noImplicitAny") + ? reduceLeft( signatures, (left, right) => left === right || !left ? left @@ -27868,7 +28066,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { : undefined; } - function combineIntersectionThisParam(left: ts.Symbol | undefined, right: ts.Symbol | undefined, mapper: ts.TypeMapper | undefined): ts.Symbol | undefined { + function combineIntersectionThisParam(left: Symbol | undefined, right: Symbol | undefined, mapper: TypeMapper | undefined): Symbol | undefined { if (!left || !right) { return left || right; } @@ -27879,7 +28077,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createSymbolWithType(left, thisType); } - function combineIntersectionParameters(left: ts.Signature, right: ts.Signature, mapper: ts.TypeMapper | undefined) { + function combineIntersectionParameters(left: Signature, right: Signature, mapper: TypeMapper | undefined) { const leftCount = getParameterCount(left); const rightCount = getParameterCount(right); const longest = leftCount >= rightCount ? left : right; @@ -27887,7 +28085,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const longestCount = longest === left ? leftCount : rightCount; const eitherHasEffectiveRest = (hasEffectiveRestParameter(left) || hasEffectiveRestParameter(right)); const needsExtraRestElement = eitherHasEffectiveRest && !hasEffectiveRestParameter(longest); - const params = new Array(longestCount + (needsExtraRestElement ? 1 : 0)); + const params = new Array(longestCount + (needsExtraRestElement ? 1 : 0)); for (let i = 0; i < longestCount; i++) { let longestParamType = tryGetTypeAtPosition(longest, i)!; if (longest === right) { @@ -27908,14 +28106,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !rightName ? leftName : undefined; const paramSymbol = createSymbol( - ts.SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? ts.SymbolFlags.Optional : 0), - paramName || `arg${i}` as ts.__String + SymbolFlags.FunctionScopedVariable | (isOptional && !isRestParam ? SymbolFlags.Optional : 0), + paramName || `arg${i}` as __String ); paramSymbol.type = isRestParam ? createArrayType(unionParamType) : unionParamType; params[i] = paramSymbol; } if (needsExtraRestElement) { - const restParamSymbol = createSymbol(ts.SymbolFlags.FunctionScopedVariable, "args" as ts.__String); + const restParamSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "args" as __String); restParamSymbol.type = createArrayType(getTypeAtPosition(shorter, longestCount)); if (shorter === right) { restParamSymbol.type = instantiateType(restParamSymbol.type, mapper); @@ -27925,9 +28123,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return params; } - function combineSignaturesOfIntersectionMembers(left: ts.Signature, right: ts.Signature): ts.Signature { + function combineSignaturesOfIntersectionMembers(left: Signature, right: Signature): Signature { const typeParams = left.typeParameters || right.typeParameters; - let paramMapper: ts.TypeMapper | undefined; + let paramMapper: TypeMapper | undefined; if (left.typeParameters && right.typeParameters) { paramMapper = createTypeMapper(right.typeParameters, left.typeParameters); // We just use the type parameter defaults from the first signature @@ -27944,26 +28142,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /*resolvedReturnType*/ undefined, /*resolvedTypePredicate*/ undefined, minArgCount, - (left.flags | right.flags) & ts.SignatureFlags.PropagatingFlags + (left.flags | right.flags) & SignatureFlags.PropagatingFlags ); - result.compositeKind = ts.TypeFlags.Intersection; - result.compositeSignatures = ts.concatenate(left.compositeKind === ts.TypeFlags.Intersection && left.compositeSignatures || [left], [right]); + result.compositeKind = TypeFlags.Intersection; + result.compositeSignatures = concatenate(left.compositeKind === TypeFlags.Intersection && left.compositeSignatures || [left], [right]); if (paramMapper) { - result.mapper = left.compositeKind === ts.TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; + result.mapper = left.compositeKind === TypeFlags.Intersection && left.mapper && left.compositeSignatures ? combineTypeMappers(left.mapper, paramMapper) : paramMapper; } return result; } // If the given type is an object or union type with a single signature, and if that signature has at // least as many parameters as the given function, return the signature. Otherwise return undefined. - function getContextualCallSignature(type: ts.Type, node: ts.SignatureDeclaration): ts.Signature | undefined { - const signatures = getSignaturesOfType(type, ts.SignatureKind.Call); - const applicableByArity = ts.filter(signatures, s => !isAritySmaller(s, node)); + function getContextualCallSignature(type: Type, node: SignatureDeclaration): Signature | undefined { + const signatures = getSignaturesOfType(type, SignatureKind.Call); + const applicableByArity = filter(signatures, s => !isAritySmaller(s, node)); return applicableByArity.length === 1 ? applicableByArity[0] : getIntersectedSignatures(applicableByArity); } /** If the contextual signature has fewer parameters than the function expression, do not use it */ - function isAritySmaller(signature: ts.Signature, target: ts.SignatureDeclaration) { + function isAritySmaller(signature: Signature, target: SignatureDeclaration) { let targetParameterCount = 0; for (; targetParameterCount < target.parameters.length; targetParameterCount++) { const param = target.parameters[targetParameterCount]; @@ -27971,16 +28169,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { break; } } - if (target.parameters.length && ts.parameterIsThisKeyword(target.parameters[0])) { + if (target.parameters.length && parameterIsThisKeyword(target.parameters[0])) { targetParameterCount--; } return !hasEffectiveRestParameter(signature) && getParameterCount(signature) < targetParameterCount; } - function getContextualSignatureForFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration): ts.Signature | undefined { + function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature | undefined { // Only function expressions, arrow functions, and object literal methods are contextually typed. - return ts.isFunctionExpressionOrArrowFunction(node) || ts.isObjectLiteralMethod(node) - ? getContextualSignature(node as ts.FunctionExpression) + return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node) + ? getContextualSignature(node as FunctionExpression) : undefined; } @@ -27989,21 +28187,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the contextual type is a union type, get the signature from each type possible and if they are // all identical ignoring their return type, the result is same signature but with return type as // union type of return types from these signatures - function getContextualSignature(node: ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration): ts.Signature | undefined { - ts.Debug.assert(node.kind !== ts.SyntaxKind.MethodDeclaration || ts.isObjectLiteralMethod(node)); + function getContextualSignature(node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined { + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); const typeTagSignature = getSignatureOfTypeTag(node); if (typeTagSignature) { return typeTagSignature; } - const type = getApparentTypeOfContextualType(node, ts.ContextFlags.Signature); + const type = getApparentTypeOfContextualType(node, ContextFlags.Signature); if (!type) { return undefined; } - if (!(type.flags & ts.TypeFlags.Union)) { + if (!(type.flags & TypeFlags.Union)) { return getContextualCallSignature(type, node); } - let signatureList: ts.Signature[] | undefined; - const types = (type as ts.UnionType).types; + let signatureList: Signature[] | undefined; + const types = (type as UnionType).types; for (const current of types) { const signature = getContextualCallSignature(current, node); if (signature) { @@ -28027,43 +28225,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkSpreadExpression(node: ts.SpreadElement, checkMode?: CheckMode): ts.Type { - if (languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ts.ExternalEmitHelpers.SpreadIncludes : ts.ExternalEmitHelpers.SpreadArray); + function checkSpreadExpression(node: SpreadElement, checkMode?: CheckMode): Type { + if (languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(node, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray); } const arrayOrIterableType = checkExpression(node.expression, checkMode); return checkIteratedTypeOrElementType(IterationUse.Spread, arrayOrIterableType, undefinedType, node.expression); } - function checkSyntheticExpression(node: ts.SyntheticExpression): ts.Type { + function checkSyntheticExpression(node: SyntheticExpression): Type { return node.isSpread ? getIndexedAccessType(node.type, numberType) : node.type; } - function hasDefaultValue(node: ts.BindingElement | ts.Expression): boolean { - return (node.kind === ts.SyntaxKind.BindingElement && !!(node as ts.BindingElement).initializer) || - (node.kind === ts.SyntaxKind.BinaryExpression && (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken); + function hasDefaultValue(node: BindingElement | Expression): boolean { + return (node.kind === SyntaxKind.BindingElement && !!(node as BindingElement).initializer) || + (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken); } - function checkArrayLiteral(node: ts.ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): ts.Type { + function checkArrayLiteral(node: ArrayLiteralExpression, checkMode: CheckMode | undefined, forceTuple: boolean | undefined): Type { const elements = node.elements; const elementCount = elements.length; - const elementTypes: ts.Type[] = []; - const elementFlags: ts.ElementFlags[] = []; + const elementTypes: Type[] = []; + const elementFlags: ElementFlags[] = []; const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined); - const inDestructuringPattern = ts.isAssignmentTarget(node); + const inDestructuringPattern = isAssignmentTarget(node); const inConstContext = isConstContext(node); let hasOmittedExpression = false; for (let i = 0; i < elementCount; i++) { const e = elements[i]; - if (e.kind === ts.SyntaxKind.SpreadElement) { - if (languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(e, compilerOptions.downlevelIteration ? ts.ExternalEmitHelpers.SpreadIncludes : ts.ExternalEmitHelpers.SpreadArray); + if (e.kind === SyntaxKind.SpreadElement) { + if (languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(e, compilerOptions.downlevelIteration ? ExternalEmitHelpers.SpreadIncludes : ExternalEmitHelpers.SpreadArray); } - const spreadType = checkExpression((e as ts.SpreadElement).expression, checkMode, forceTuple); + const spreadType = checkExpression((e as SpreadElement).expression, checkMode, forceTuple); if (isArrayLikeType(spreadType)) { elementTypes.push(spreadType); - elementFlags.push(ts.ElementFlags.Variadic); + elementFlags.push(ElementFlags.Variadic); } else if (inDestructuringPattern) { // Given the following situation: @@ -28082,26 +28280,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getIteratedTypeOrElementType(IterationUse.Destructuring, spreadType, undefinedType, /*errorNode*/ undefined, /*checkAssignability*/ false) || unknownType; elementTypes.push(restElementType); - elementFlags.push(ts.ElementFlags.Rest); + elementFlags.push(ElementFlags.Rest); } else { - elementTypes.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, (e as ts.SpreadElement).expression)); - elementFlags.push(ts.ElementFlags.Rest); + elementTypes.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, (e as SpreadElement).expression)); + elementFlags.push(ElementFlags.Rest); } } - else if (exactOptionalPropertyTypes && e.kind === ts.SyntaxKind.OmittedExpression) { + else if (exactOptionalPropertyTypes && e.kind === SyntaxKind.OmittedExpression) { hasOmittedExpression = true; elementTypes.push(missingType); - elementFlags.push(ts.ElementFlags.Optional); + elementFlags.push(ElementFlags.Optional); } else { const elementContextualType = getContextualTypeForElementExpression(contextualType, elementTypes.length); const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple); elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression)); - elementFlags.push(hasOmittedExpression ? ts.ElementFlags.Optional : ts.ElementFlags.Required); + elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required); if (contextualType && someType(contextualType, isTupleLikeType) && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) { const inferenceContext = getInferenceContext(node); - ts.Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context + Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context addIntraExpressionInferenceSite(inferenceContext, e, type); } } @@ -28113,90 +28311,90 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext)); } return createArrayLiteralType(createArrayType(elementTypes.length ? - getUnionType(ts.sameMap(elementTypes, (t, i) => elementFlags[i] & ts.ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), ts.UnionReduction.Subtype) : + getUnionType(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), UnionReduction.Subtype) : strictNullChecks ? implicitNeverType : undefinedWideningType, inConstContext)); } - function createArrayLiteralType(type: ts.Type) { - if (!(ts.getObjectFlags(type) & ts.ObjectFlags.Reference)) { + function createArrayLiteralType(type: Type) { + if (!(getObjectFlags(type) & ObjectFlags.Reference)) { return type; } - let literalType = (type as ts.TypeReference).literalType; + let literalType = (type as TypeReference).literalType; if (!literalType) { - literalType = (type as ts.TypeReference).literalType = cloneTypeReference(type as ts.TypeReference); - literalType.objectFlags |= ts.ObjectFlags.ArrayLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral; + literalType = (type as TypeReference).literalType = cloneTypeReference(type as TypeReference); + literalType.objectFlags |= ObjectFlags.ArrayLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; } return literalType; } - function isNumericName(name: ts.DeclarationName): boolean { + function isNumericName(name: DeclarationName): boolean { switch (name.kind) { - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.ComputedPropertyName: return isNumericComputedName(name); - case ts.SyntaxKind.Identifier: - return ts.isNumericLiteralName(name.escapedText); - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.StringLiteral: - return ts.isNumericLiteralName(name.text); + case SyntaxKind.Identifier: + return isNumericLiteralName(name.escapedText); + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + return isNumericLiteralName(name.text); default: return false; } } - function isNumericComputedName(name: ts.ComputedPropertyName): boolean { + function isNumericComputedName(name: ComputedPropertyName): boolean { // It seems odd to consider an expression of type Any to result in a numeric name, // but this behavior is consistent with checkIndexedAccess - return isTypeAssignableToKind(checkComputedPropertyName(name), ts.TypeFlags.NumberLike); + return isTypeAssignableToKind(checkComputedPropertyName(name), TypeFlags.NumberLike); } - function checkComputedPropertyName(node: ts.ComputedPropertyName): ts.Type { + function checkComputedPropertyName(node: ComputedPropertyName): Type { const links = getNodeLinks(node.expression); if (!links.resolvedType) { - if ((ts.isTypeLiteralNode(node.parent.parent) || ts.isClassLike(node.parent.parent) || ts.isInterfaceDeclaration(node.parent.parent)) - && ts.isBinaryExpression(node.expression) && node.expression.operatorToken.kind === ts.SyntaxKind.InKeyword - && node.parent.kind !== ts.SyntaxKind.GetAccessor && node.parent.kind !== ts.SyntaxKind.SetAccessor) { + if ((isTypeLiteralNode(node.parent.parent) || isClassLike(node.parent.parent) || isInterfaceDeclaration(node.parent.parent)) + && isBinaryExpression(node.expression) && node.expression.operatorToken.kind === SyntaxKind.InKeyword + && node.parent.kind !== SyntaxKind.GetAccessor && node.parent.kind !== SyntaxKind.SetAccessor) { return links.resolvedType = errorType; } links.resolvedType = checkExpression(node.expression); // The computed property name of a non-static class field within a loop must be stored in a block-scoped binding. // (It needs to be bound at class evaluation time.) - if (ts.isPropertyDeclaration(node.parent) && !ts.hasStaticModifier(node.parent) && ts.isClassExpression(node.parent.parent)) { - const container = ts.getEnclosingBlockScopeContainer(node.parent.parent); + if (isPropertyDeclaration(node.parent) && !hasStaticModifier(node.parent) && isClassExpression(node.parent.parent)) { + const container = getEnclosingBlockScopeContainer(node.parent.parent); const enclosingIterationStatement = getEnclosingIterationStatement(container); if (enclosingIterationStatement) { // The computed field name will use a block scoped binding which can be unique for each iteration of the loop. - getNodeLinks(enclosingIterationStatement).flags |= ts.NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; // The generated variable which stores the computed field name must be block-scoped. - getNodeLinks(node).flags |= ts.NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(node).flags |= NodeCheckFlags.BlockScopedBindingInLoop; // The generated variable which stores the class must be block-scoped. - getNodeLinks(node.parent.parent).flags |= ts.NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(node.parent.parent).flags |= NodeCheckFlags.BlockScopedBindingInLoop; } } // This will allow types number, string, symbol or any. It will also allow enums, the unknown // type, and any union of these types (like string | number). - if (links.resolvedType.flags & ts.TypeFlags.Nullable || - !isTypeAssignableToKind(links.resolvedType, ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.ESSymbolLike) && + if (links.resolvedType.flags & TypeFlags.Nullable || + !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike) && !isTypeAssignableTo(links.resolvedType, stringNumberSymbolType)) { - error(node, ts.Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); + error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any); } } return links.resolvedType; } - function isSymbolWithNumericName(symbol: ts.Symbol) { + function isSymbolWithNumericName(symbol: Symbol) { const firstDecl = symbol.declarations?.[0]; - return ts.isNumericLiteralName(symbol.escapedName) || (firstDecl && ts.isNamedDeclaration(firstDecl) && isNumericName(firstDecl.name)); + return isNumericLiteralName(symbol.escapedName) || (firstDecl && isNamedDeclaration(firstDecl) && isNumericName(firstDecl.name)); } - function isSymbolWithSymbolName(symbol: ts.Symbol) { + function isSymbolWithSymbolName(symbol: Symbol) { const firstDecl = symbol.declarations?.[0]; - return ts.isKnownSymbol(symbol) || (firstDecl && ts.isNamedDeclaration(firstDecl) && ts.isComputedPropertyName(firstDecl.name) && - isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), ts.TypeFlags.ESSymbol)); + return isKnownSymbol(symbol) || (firstDecl && isNamedDeclaration(firstDecl) && isComputedPropertyName(firstDecl.name) && + isTypeAssignableToKind(checkComputedPropertyName(firstDecl.name), TypeFlags.ESSymbol)); } - function getObjectLiteralIndexInfo(node: ts.ObjectLiteralExpression, offset: number, properties: ts.Symbol[], keyType: ts.Type): ts.IndexInfo { - const propTypes: ts.Type[] = []; + function getObjectLiteralIndexInfo(node: ObjectLiteralExpression, offset: number, properties: Symbol[], keyType: Type): IndexInfo { + const propTypes: Type[] = []; for (let i = offset; i < properties.length; i++) { const prop = properties[i]; if (keyType === stringType && !isSymbolWithSymbolName(prop) || @@ -28205,41 +28403,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { propTypes.push(getTypeOfSymbol(properties[i])); } } - const unionType = propTypes.length ? getUnionType(propTypes, ts.UnionReduction.Subtype) : undefinedType; + const unionType = propTypes.length ? getUnionType(propTypes, UnionReduction.Subtype) : undefinedType; return createIndexInfo(keyType, unionType, isConstContext(node)); } - function getImmediateAliasedSymbol(symbol: ts.Symbol): ts.Symbol | undefined { - ts.Debug.assert((symbol.flags & ts.SymbolFlags.Alias) !== 0, "Should only get Alias here."); + function getImmediateAliasedSymbol(symbol: Symbol): Symbol | undefined { + Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here."); const links = getSymbolLinks(symbol); if (!links.immediateTarget) { const node = getDeclarationOfAliasSymbol(symbol); - if (!node) return ts.Debug.fail(); + if (!node) return Debug.fail(); links.immediateTarget = getTargetOfAliasDeclaration(node, /*dontRecursivelyResolve*/ true); } return links.immediateTarget; } - function checkObjectLiteral(node: ts.ObjectLiteralExpression, checkMode?: CheckMode): ts.Type { - const inDestructuringPattern = ts.isAssignmentTarget(node); + function checkObjectLiteral(node: ObjectLiteralExpression, checkMode?: CheckMode): Type { + const inDestructuringPattern = isAssignmentTarget(node); // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); - const allPropertiesTable = strictNullChecks ? ts.createSymbolTable() : undefined; - let propertiesTable = ts.createSymbolTable(); - let propertiesArray: ts.Symbol[] = []; - let spread: ts.Type = emptyObjectType; + const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined; + let propertiesTable = createSymbolTable(); + let propertiesArray: Symbol[] = []; + let spread: Type = emptyObjectType; const contextualType = getApparentTypeOfContextualType(node, /*contextFlags*/ undefined); const contextualTypeHasPattern = contextualType && contextualType.pattern && - (contextualType.pattern.kind === ts.SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === ts.SyntaxKind.ObjectLiteralExpression); + (contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression); const inConstContext = isConstContext(node); - const checkFlags = inConstContext ? ts.CheckFlags.Readonly : 0; - const isInJavascript = ts.isInJSFile(node) && !ts.isInJsonFile(node); - const enumTag = ts.getJSDocEnumTag(node); + const checkFlags = inConstContext ? CheckFlags.Readonly : 0; + const isInJavascript = isInJSFile(node) && !isInJsonFile(node); + const enumTag = getJSDocEnumTag(node); const isJSObjectLiteral = !contextualType && isInJavascript && !enumTag; - let objectFlags: ts.ObjectFlags = freshObjectLiteralFlag; + let objectFlags: ObjectFlags = freshObjectLiteralFlag; let patternWithComputedProperties = false; let hasComputedStringProperty = false; let hasComputedNumberProperty = false; @@ -28249,7 +28447,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // As otherwise they may not be checked until exports for the type at this position are retrieved, // which may never occur. for (const elem of node.properties) { - if (elem.name && ts.isComputedPropertyName(elem.name)) { + if (elem.name && isComputedPropertyName(elem.name)) { checkComputedPropertyName(elem.name); } } @@ -28257,16 +28455,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let offset = 0; for (const memberDecl of node.properties) { let member = getSymbolOfNode(memberDecl); - const computedNameType = memberDecl.name && memberDecl.name.kind === ts.SyntaxKind.ComputedPropertyName ? + const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName ? checkComputedPropertyName(memberDecl.name) : undefined; - if (memberDecl.kind === ts.SyntaxKind.PropertyAssignment || - memberDecl.kind === ts.SyntaxKind.ShorthandPropertyAssignment || - ts.isObjectLiteralMethod(memberDecl)) { - let type = memberDecl.kind === ts.SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) : + if (memberDecl.kind === SyntaxKind.PropertyAssignment || + memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment || + isObjectLiteralMethod(memberDecl)) { + let type = memberDecl.kind === SyntaxKind.PropertyAssignment ? checkPropertyAssignment(memberDecl, checkMode) : // avoid resolving the left side of the ShorthandPropertyAssignment outside of the destructuring // for error recovery purposes. For example, if a user wrote `{ a = 100 }` instead of `{ a: 100 }`. // we don't want to say "could not find 'a'". - memberDecl.kind === ts.SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) : + memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment ? checkExpressionForMutableLocation(!inDestructuringPattern && memberDecl.objectAssignmentInitializer ? memberDecl.objectAssignmentInitializer : memberDecl.name, checkMode) : checkObjectLiteralMethod(memberDecl, checkMode); if (isInJavascript) { const jsDocType = getTypeForDeclarationFromJSDocComment(memberDecl); @@ -28278,11 +28476,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkTypeAssignableTo(type, getTypeFromTypeNode(enumTag.typeExpression), memberDecl); } } - objectFlags |= ts.getObjectFlags(type) & ts.ObjectFlags.PropagatingFlags; + objectFlags |= getObjectFlags(type) & ObjectFlags.PropagatingFlags; const nameType = computedNameType && isTypeUsableAsPropertyName(computedNameType) ? computedNameType : undefined; const prop = nameType ? - createSymbol(ts.SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | ts.CheckFlags.Late) : - createSymbol(ts.SymbolFlags.Property | member.flags, member.escapedName, checkFlags); + createSymbol(SymbolFlags.Property | member.flags, getPropertyNameFromType(nameType), checkFlags | CheckFlags.Late) : + createSymbol(SymbolFlags.Property | member.flags, member.escapedName, checkFlags); if (nameType) { prop.nameType = nameType; } @@ -28291,22 +28489,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If object literal is an assignment pattern and if the assignment pattern specifies a default value // for the property, make the property optional. const isOptional = - (memberDecl.kind === ts.SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) || - (memberDecl.kind === ts.SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer); + (memberDecl.kind === SyntaxKind.PropertyAssignment && hasDefaultValue(memberDecl.initializer)) || + (memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment && memberDecl.objectAssignmentInitializer); if (isOptional) { - prop.flags |= ts.SymbolFlags.Optional; + prop.flags |= SymbolFlags.Optional; } } - else if (contextualTypeHasPattern && !(ts.getObjectFlags(contextualType) & ts.ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { + else if (contextualTypeHasPattern && !(getObjectFlags(contextualType) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { // If object literal is contextually typed by the implied type of a binding pattern, and if the // binding pattern specifies a default value for the property, make the property optional. const impliedProp = getPropertyOfType(contextualType, member.escapedName); if (impliedProp) { - prop.flags |= impliedProp.flags & ts.SymbolFlags.Optional; + prop.flags |= impliedProp.flags & SymbolFlags.Optional; } else if (!compilerOptions.suppressExcessPropertyErrors && !getIndexInfoOfType(contextualType, stringType)) { - error(memberDecl.name, ts.Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, + error(memberDecl.name, Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(member), typeToString(contextualType)); } } @@ -28323,21 +28521,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { allPropertiesTable?.set(prop.escapedName, prop); if (contextualType && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && - (memberDecl.kind === ts.SyntaxKind.PropertyAssignment || memberDecl.kind === ts.SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) { + (memberDecl.kind === SyntaxKind.PropertyAssignment || memberDecl.kind === SyntaxKind.MethodDeclaration) && isContextSensitive(memberDecl)) { const inferenceContext = getInferenceContext(node); - ts.Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context - const inferenceNode = memberDecl.kind === ts.SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl; + Debug.assert(inferenceContext); // In CheckMode.Inferential we should always have an inference context + const inferenceNode = memberDecl.kind === SyntaxKind.PropertyAssignment ? memberDecl.initializer : memberDecl; addIntraExpressionInferenceSite(inferenceContext, inferenceNode, type); } } - else if (memberDecl.kind === ts.SyntaxKind.SpreadAssignment) { - if (languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(memberDecl, ts.ExternalEmitHelpers.Assign); + else if (memberDecl.kind === SyntaxKind.SpreadAssignment) { + if (languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(memberDecl, ExternalEmitHelpers.Assign); } if (propertiesArray.length > 0) { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; - propertiesTable = ts.createSymbolTable(); + propertiesTable = createSymbolTable(); hasComputedStringProperty = false; hasComputedNumberProperty = false; hasComputedSymbolProperty = false; @@ -28355,7 +28553,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { spread = getSpreadType(spread, mergedType, node.symbol, objectFlags, inConstContext); } else { - error(memberDecl, ts.Diagnostics.Spread_types_may_only_be_created_from_object_types); + error(memberDecl, Diagnostics.Spread_types_may_only_be_created_from_object_types); spread = errorType; } continue; @@ -28366,11 +28564,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // an ordinary function declaration(section 6.1) with no parameters. // A set accessor declaration is processed in the same manner // as an ordinary function declaration with a single parameter and a Void return type. - ts.Debug.assert(memberDecl.kind === ts.SyntaxKind.GetAccessor || memberDecl.kind === ts.SyntaxKind.SetAccessor); + Debug.assert(memberDecl.kind === SyntaxKind.GetAccessor || memberDecl.kind === SyntaxKind.SetAccessor); checkNodeDeferred(memberDecl); } - if (computedNameType && !(computedNameType.flags & ts.TypeFlags.StringOrNumberLiteralOrUnique)) { + if (computedNameType && !(computedNameType.flags & TypeFlags.StringOrNumberLiteralOrUnique)) { if (isTypeAssignableTo(computedNameType, stringNumberSymbolType)) { if (isTypeAssignableTo(computedNameType, numberType)) { hasComputedNumberProperty = true; @@ -28400,22 +28598,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // It's not possible to check if the immediate parent node is a spread assignment // since the type flows in non-obvious ways through conditional expressions, IIFEs and more. if (contextualTypeHasPattern) { - const rootPatternParent = ts.findAncestor(contextualType.pattern!.parent, n => - n.kind === ts.SyntaxKind.VariableDeclaration || - n.kind === ts.SyntaxKind.BinaryExpression || - n.kind === ts.SyntaxKind.Parameter + const rootPatternParent = findAncestor(contextualType.pattern!.parent, n => + n.kind === SyntaxKind.VariableDeclaration || + n.kind === SyntaxKind.BinaryExpression || + n.kind === SyntaxKind.Parameter ); - const spreadOrOutsideRootObject = ts.findAncestor(node, n => + const spreadOrOutsideRootObject = findAncestor(node, n => n === rootPatternParent || - n.kind === ts.SyntaxKind.SpreadAssignment + n.kind === SyntaxKind.SpreadAssignment )!; - if (spreadOrOutsideRootObject.kind !== ts.SyntaxKind.SpreadAssignment) { + if (spreadOrOutsideRootObject.kind !== SyntaxKind.SpreadAssignment) { for (const prop of getPropertiesOfType(contextualType)) { if (!propertiesTable.get(prop.escapedName) && !getPropertyOfType(spread, prop.escapedName)) { - if (!(prop.flags & ts.SymbolFlags.Optional)) { - error(prop.valueDeclaration || (prop as ts.TransientSymbol).bindingElement, - ts.Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); + if (!(prop.flags & SymbolFlags.Optional)) { + error(prop.valueDeclaration || (prop as TransientSymbol).bindingElement, + Diagnostics.Initializer_provides_no_value_for_this_binding_element_and_the_binding_element_has_no_default_value); } propertiesTable.set(prop.escapedName, prop); propertiesArray.push(prop); @@ -28432,7 +28630,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (propertiesArray.length > 0) { spread = getSpreadType(spread, createObjectLiteralType(), node.symbol, objectFlags, inConstContext); propertiesArray = []; - propertiesTable = ts.createSymbolTable(); + propertiesTable = createSymbolTable(); hasComputedStringProperty = false; hasComputedNumberProperty = false; } @@ -28447,13 +28645,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (hasComputedStringProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, stringType)); if (hasComputedNumberProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, numberType)); if (hasComputedSymbolProperty) indexInfos.push(getObjectLiteralIndexInfo(node, offset, propertiesArray, esSymbolType)); - const result = createAnonymousType(node.symbol, propertiesTable, ts.emptyArray, ts.emptyArray, indexInfos); - result.objectFlags |= objectFlags | ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral; + const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, indexInfos); + result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; if (isJSObjectLiteral) { - result.objectFlags |= ts.ObjectFlags.JSLiteral; + result.objectFlags |= ObjectFlags.JSLiteral; } if (patternWithComputedProperties) { - result.objectFlags |= ts.ObjectFlags.ObjectLiteralPatternWithComputedProperties; + result.objectFlags |= ObjectFlags.ObjectLiteralPatternWithComputedProperties; } if (inDestructuringPattern) { result.pattern = node; @@ -28462,22 +28660,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isValidSpreadType(type: ts.Type): boolean { + function isValidSpreadType(type: Type): boolean { const t = removeDefinitelyFalsyTypes(mapType(type, getBaseConstraintOrType)); - return !!(t.flags & (ts.TypeFlags.Any | ts.TypeFlags.NonPrimitive | ts.TypeFlags.Object | ts.TypeFlags.InstantiableNonPrimitive) || - t.flags & ts.TypeFlags.UnionOrIntersection && ts.every((t as ts.UnionOrIntersectionType).types, isValidSpreadType)); + return !!(t.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) || + t.flags & TypeFlags.UnionOrIntersection && every((t as UnionOrIntersectionType).types, isValidSpreadType)); } - function checkJsxSelfClosingElementDeferred(node: ts.JsxSelfClosingElement) { + function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) { checkJsxOpeningLikeElementOrOpeningFragment(node); } - function checkJsxSelfClosingElement(node: ts.JsxSelfClosingElement, _checkMode: CheckMode | undefined): ts.Type { + function checkJsxSelfClosingElement(node: JsxSelfClosingElement, _checkMode: CheckMode | undefined): Type { checkNodeDeferred(node); return getJsxElementTypeAt(node) || anyType; } - function checkJsxElementDeferred(node: ts.JsxElement) { + function checkJsxElementDeferred(node: JsxElement) { // Check attributes checkJsxOpeningLikeElementOrOpeningFragment(node.openingElement); @@ -28492,41 +28690,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkJsxChildren(node); } - function checkJsxElement(node: ts.JsxElement, _checkMode: CheckMode | undefined): ts.Type { + function checkJsxElement(node: JsxElement, _checkMode: CheckMode | undefined): Type { checkNodeDeferred(node); return getJsxElementTypeAt(node) || anyType; } - function checkJsxFragment(node: ts.JsxFragment): ts.Type { + function checkJsxFragment(node: JsxFragment): Type { checkJsxOpeningLikeElementOrOpeningFragment(node.openingFragment); // by default, jsx:'react' will use jsxFactory = React.createElement and jsxFragmentFactory = React.Fragment // if jsxFactory compiler option is provided, ensure jsxFragmentFactory compiler option or @jsxFrag pragma is provided too - const nodeSourceFile = ts.getSourceFileOfNode(node); - if (ts.getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx")) + const nodeSourceFile = getSourceFileOfNode(node); + if (getJSXTransformEnabled(compilerOptions) && (compilerOptions.jsxFactory || nodeSourceFile.pragmas.has("jsx")) && !compilerOptions.jsxFragmentFactory && !nodeSourceFile.pragmas.has("jsxfrag")) { error(node, compilerOptions.jsxFactory - ? ts.Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option - : ts.Diagnostics.An_jsxFrag_pragma_is_required_when_using_an_jsx_pragma_with_JSX_fragments); + ? Diagnostics.The_jsxFragmentFactory_compiler_option_must_be_provided_to_use_JSX_fragments_with_the_jsxFactory_compiler_option + : Diagnostics.An_jsxFrag_pragma_is_required_when_using_an_jsx_pragma_with_JSX_fragments); } checkJsxChildren(node); return getJsxElementTypeAt(node) || anyType; } - function isHyphenatedJsxName(name: string | ts.__String) { - return ts.stringContains(name as string, "-"); + function isHyphenatedJsxName(name: string | __String) { + return stringContains(name as string, "-"); } /** * Returns true iff React would emit this tag name as a string rather than an identifier or qualified name */ - function isJsxIntrinsicIdentifier(tagName: ts.JsxTagNameExpression): boolean { - return tagName.kind === ts.SyntaxKind.Identifier && ts.isIntrinsicJsxName(tagName.escapedText); + function isJsxIntrinsicIdentifier(tagName: JsxTagNameExpression): boolean { + return tagName.kind === SyntaxKind.Identifier && isIntrinsicJsxName(tagName.escapedText); } - function checkJsxAttribute(node: ts.JsxAttribute, checkMode?: CheckMode) { + function checkJsxAttribute(node: JsxAttribute, checkMode?: CheckMode) { return node.initializer ? checkExpressionForMutableLocation(node.initializer, checkMode) : trueType; // is sugar for @@ -28541,25 +28739,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @remarks Because this function calls getSpreadType, it needs to use the same checks as checkObjectLiteral, * which also calls getSpreadType. */ - function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: ts.JsxOpeningLikeElement, checkMode: CheckMode | undefined) { + function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) { const attributes = openingLikeElement.attributes; - const attributesType = getContextualType(attributes, ts.ContextFlags.None); - const allAttributesTable = strictNullChecks ? ts.createSymbolTable() : undefined; - let attributesTable = ts.createSymbolTable(); - let spread: ts.Type = emptyJsxObjectType; + const attributesType = getContextualType(attributes, ContextFlags.None); + const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined; + let attributesTable = createSymbolTable(); + let spread: Type = emptyJsxObjectType; let hasSpreadAnyType = false; - let typeToIntersect: ts.Type | undefined; + let typeToIntersect: Type | undefined; let explicitlySpecifyChildrenAttribute = false; - let objectFlags: ts.ObjectFlags = ts.ObjectFlags.JsxAttributes; + let objectFlags: ObjectFlags = ObjectFlags.JsxAttributes; const jsxChildrenPropertyName = getJsxElementChildrenPropertyName(getJsxNamespaceAt(openingLikeElement)); for (const attributeDecl of attributes.properties) { const member = attributeDecl.symbol; - if (ts.isJsxAttribute(attributeDecl)) { + if (isJsxAttribute(attributeDecl)) { const exprType = checkJsxAttribute(attributeDecl, checkMode); - objectFlags |= ts.getObjectFlags(exprType) & ts.ObjectFlags.PropagatingFlags; + objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags; - const attributeSymbol = createSymbol(ts.SymbolFlags.Property | member.flags, member.escapedName); + const attributeSymbol = createSymbol(SymbolFlags.Property | member.flags, member.escapedName); attributeSymbol.declarations = member.declarations; attributeSymbol.parent = member.parent; if (member.valueDeclaration) { @@ -28580,10 +28778,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else { - ts.Debug.assert(attributeDecl.kind === ts.SyntaxKind.JsxSpreadAttribute); + Debug.assert(attributeDecl.kind === SyntaxKind.JsxSpreadAttribute); if (attributesTable.size > 0) { spread = getSpreadType(spread, createJsxAttributesType(), attributes.symbol, objectFlags, /*readonly*/ false); - attributesTable = ts.createSymbolTable(); + attributesTable = createSymbolTable(); } const exprType = getReducedType(checkExpressionCached(attributeDecl.expression, checkMode)); if (isTypeAny(exprType)) { @@ -28596,7 +28794,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else { - error(attributeDecl.expression, ts.Diagnostics.Spread_types_may_only_be_created_from_object_types); + error(attributeDecl.expression, Diagnostics.Spread_types_may_only_be_created_from_object_types); typeToIntersect = typeToIntersect ? getIntersectionType([typeToIntersect, exprType]) : exprType; } } @@ -28609,33 +28807,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Handle children attribute - const parent = openingLikeElement.parent.kind === ts.SyntaxKind.JsxElement ? openingLikeElement.parent as ts.JsxElement : undefined; + const parent = openingLikeElement.parent.kind === SyntaxKind.JsxElement ? openingLikeElement.parent as JsxElement : undefined; // We have to check that openingElement of the parent is the one we are visiting as this may not be true for selfClosingElement if (parent && parent.openingElement === openingLikeElement && parent.children.length > 0) { - const childrenTypes: ts.Type[] = checkJsxChildren(parent, checkMode); + const childrenTypes: Type[] = checkJsxChildren(parent, checkMode); if (!hasSpreadAnyType && jsxChildrenPropertyName && jsxChildrenPropertyName !== "") { // Error if there is a attribute named "children" explicitly specified and children element. // This is because children element will overwrite the value from attributes. // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if (explicitlySpecifyChildrenAttribute) { - error(attributes, ts.Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, ts.unescapeLeadingUnderscores(jsxChildrenPropertyName)); + error(attributes, Diagnostics._0_are_specified_twice_The_attribute_named_0_will_be_overwritten, unescapeLeadingUnderscores(jsxChildrenPropertyName)); } const contextualType = getApparentTypeOfContextualType(openingLikeElement.attributes, /*contextFlags*/ undefined); const childrenContextualType = contextualType && getTypeOfPropertyOfContextualType(contextualType, jsxChildrenPropertyName); // If there are children in the body of JSX element, create dummy attribute "children" with the union of children types so that it will pass the attribute checking process - const childrenPropSymbol = createSymbol(ts.SymbolFlags.Property, jsxChildrenPropertyName); + const childrenPropSymbol = createSymbol(SymbolFlags.Property, jsxChildrenPropertyName); childrenPropSymbol.type = childrenTypes.length === 1 ? childrenTypes[0] : childrenContextualType && someType(childrenContextualType, isTupleLikeType) ? createTupleType(childrenTypes) : createArrayType(getUnionType(childrenTypes)); // Fake up a property declaration for the children - childrenPropSymbol.valueDeclaration = ts.factory.createPropertySignature(/*modifiers*/ undefined, ts.unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); - ts.setParent(childrenPropSymbol.valueDeclaration, attributes); + childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); + setParent(childrenPropSymbol.valueDeclaration, attributes); childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol; - const childPropMap = ts.createSymbolTable(); + const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); - spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, ts.emptyArray, ts.emptyArray, ts.emptyArray), + spread = getSpreadType(spread, createAnonymousType(attributes.symbol, childPropMap, emptyArray, emptyArray, emptyArray), attributes.symbol, objectFlags, /*readonly*/ false); } @@ -28656,23 +28854,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { */ function createJsxAttributesType() { objectFlags |= freshObjectLiteralFlag; - const result = createAnonymousType(attributes.symbol, attributesTable, ts.emptyArray, ts.emptyArray, ts.emptyArray); - result.objectFlags |= objectFlags | ts.ObjectFlags.ObjectLiteral | ts.ObjectFlags.ContainsObjectOrArrayLiteral; + const result = createAnonymousType(attributes.symbol, attributesTable, emptyArray, emptyArray, emptyArray); + result.objectFlags |= objectFlags | ObjectFlags.ObjectLiteral | ObjectFlags.ContainsObjectOrArrayLiteral; return result; } } - function checkJsxChildren(node: ts.JsxElement | ts.JsxFragment, checkMode?: CheckMode) { - const childrenTypes: ts.Type[] = []; + function checkJsxChildren(node: JsxElement | JsxFragment, checkMode?: CheckMode) { + const childrenTypes: Type[] = []; for (const child of node.children) { // In React, JSX text that contains only whitespaces will be ignored so we don't want to type-check that // because then type of children property will have constituent of string type. - if (child.kind === ts.SyntaxKind.JsxText) { + if (child.kind === SyntaxKind.JsxText) { if (!child.containsOnlyTriviaWhiteSpaces) { childrenTypes.push(stringType); } } - else if (child.kind === ts.SyntaxKind.JsxExpression && !child.expression) { + else if (child.kind === SyntaxKind.JsxExpression && !child.expression) { continue; // empty jsx expressions don't *really* count as present children } else { @@ -28682,13 +28880,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return childrenTypes; } - function checkSpreadPropOverrides(type: ts.Type, props: ts.SymbolTable, spread: ts.SpreadAssignment | ts.JsxSpreadAttribute) { + function checkSpreadPropOverrides(type: Type, props: SymbolTable, spread: SpreadAssignment | JsxSpreadAttribute) { for (const right of getPropertiesOfType(type)) { - if (!(right.flags & ts.SymbolFlags.Optional)) { + if (!(right.flags & SymbolFlags.Optional)) { const left = props.get(right.escapedName); if (left) { - const diagnostic = error(left.valueDeclaration, ts.Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, ts.unescapeLeadingUnderscores(left.escapedName)); - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(spread, ts.Diagnostics.This_spread_always_overwrites_this_property)); + const diagnostic = error(left.valueDeclaration, Diagnostics._0_is_specified_more_than_once_so_this_usage_will_be_overwritten, unescapeLeadingUnderscores(left.escapedName)); + addRelatedInfo(diagnostic, createDiagnosticForNode(spread, Diagnostics.This_spread_always_overwrites_this_property)); } } } @@ -28699,14 +28897,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * (See "checkApplicableSignatureForJsxOpeningLikeElement" for how the function is used) * @param node a JSXAttributes to be resolved of its type */ - function checkJsxAttributes(node: ts.JsxAttributes, checkMode: CheckMode | undefined) { + function checkJsxAttributes(node: JsxAttributes, checkMode: CheckMode | undefined) { return createJsxAttributesTypeFromAttributesProperty(node.parent, checkMode); } - function getJsxType(name: ts.__String, location: ts.Node | undefined) { + function getJsxType(name: __String, location: Node | undefined) { const namespace = getJsxNamespaceAt(location); const exports = namespace && getExportsOfSymbol(namespace); - const typeSymbol = exports && getSymbol(exports, name, ts.SymbolFlags.Type); + const typeSymbol = exports && getSymbol(exports, name, SymbolFlags.Type); return typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType; } @@ -28716,33 +28914,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * string index signature (in which case nodeLinks.jsxFlags will be IntrinsicIndexedElement). * May also return unknownSymbol if both of these lookups fail. */ - function getIntrinsicTagSymbol(node: ts.JsxOpeningLikeElement | ts.JsxClosingElement): ts.Symbol { + function getIntrinsicTagSymbol(node: JsxOpeningLikeElement | JsxClosingElement): Symbol { const links = getNodeLinks(node); if (!links.resolvedSymbol) { const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, node); if (!isErrorType(intrinsicElementsType)) { // Property case - if (!ts.isIdentifier(node.tagName)) return ts.Debug.fail(); + if (!isIdentifier(node.tagName)) return Debug.fail(); const intrinsicProp = getPropertyOfType(intrinsicElementsType, node.tagName.escapedText); if (intrinsicProp) { - links.jsxFlags |= ts.JsxFlags.IntrinsicNamedElement; + links.jsxFlags |= JsxFlags.IntrinsicNamedElement; return links.resolvedSymbol = intrinsicProp; } // Intrinsic string indexer case const indexSignatureType = getIndexTypeOfType(intrinsicElementsType, stringType); if (indexSignatureType) { - links.jsxFlags |= ts.JsxFlags.IntrinsicIndexedElement; + links.jsxFlags |= JsxFlags.IntrinsicIndexedElement; return links.resolvedSymbol = intrinsicElementsType.symbol; } // Wasn't found - error(node, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.idText(node.tagName), "JSX." + JsxNames.IntrinsicElements); + error(node, Diagnostics.Property_0_does_not_exist_on_type_1, idText(node.tagName), "JSX." + JsxNames.IntrinsicElements); return links.resolvedSymbol = unknownSymbol; } else { if (noImplicitAny) { - error(node, ts.Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, ts.unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); + error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); } return links.resolvedSymbol = unknownSymbol; } @@ -28750,8 +28948,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedSymbol; } - function getJsxNamespaceContainerForImplicitImport(location: ts.Node | undefined): ts.Symbol | undefined { - const file = location && ts.getSourceFileOfNode(location); + function getJsxNamespaceContainerForImplicitImport(location: Node | undefined): Symbol | undefined { + const file = location && getSourceFileOfNode(location); const links = file && getNodeLinks(file); if (links && links.jsxImplicitImportContainer === false) { return undefined; @@ -28759,14 +28957,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (links && links.jsxImplicitImportContainer) { return links.jsxImplicitImportContainer; } - const runtimeImportSpecifier = ts.getJSXRuntimeImport(ts.getJSXImplicitImportBase(compilerOptions, file), compilerOptions); + const runtimeImportSpecifier = getJSXRuntimeImport(getJSXImplicitImportBase(compilerOptions, file), compilerOptions); if (!runtimeImportSpecifier) { return undefined; } - const isClassic = ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Classic; + const isClassic = getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Classic; const errorMessage = isClassic - ? ts.Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option - : ts.Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; + ? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option + : Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations; const mod = resolveExternalModule(location!, runtimeImportSpecifier, errorMessage, location!); const result = mod && mod !== unknownSymbol ? getMergedSymbol(resolveSymbol(mod)) : undefined; if (links) { @@ -28775,7 +28973,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function getJsxNamespaceAt(location: ts.Node | undefined): ts.Symbol { + function getJsxNamespaceAt(location: Node | undefined): Symbol { const links = location && getNodeLinks(location); if (links && links.jsxNamespace) { return links.jsxNamespace; @@ -28785,11 +28983,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!resolvedNamespace || resolvedNamespace === unknownSymbol) { const namespaceName = getJsxNamespace(location); - resolvedNamespace = resolveName(location, namespaceName, ts.SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false); + resolvedNamespace = resolveName(location, namespaceName, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined, namespaceName, /*isUse*/ false); } if (resolvedNamespace) { - const candidate = resolveSymbol(getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, ts.SymbolFlags.Namespace)); + const candidate = resolveSymbol(getSymbol(getExportsOfSymbol(resolveSymbol(resolvedNamespace)), JsxNames.JSX, SymbolFlags.Namespace)); if (candidate && candidate !== unknownSymbol) { if (links) { links.jsxNamespace = candidate; @@ -28802,7 +29000,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } // JSX global fallback - const s = resolveSymbol(getGlobalSymbol(JsxNames.JSX, ts.SymbolFlags.Namespace, /*diagnosticMessage*/ undefined)); + const s = resolveSymbol(getGlobalSymbol(JsxNames.JSX, SymbolFlags.Namespace, /*diagnosticMessage*/ undefined)); if (s === unknownSymbol) { return undefined!; // TODO: GH#18217 } @@ -28816,9 +29014,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer * if other string is given or the container doesn't exist, return undefined. */ - function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: ts.__String, jsxNamespace: ts.Symbol): ts.__String | undefined { + function getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer: __String, jsxNamespace: Symbol): __String | undefined { // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] - const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, ts.SymbolFlags.Type); + const jsxElementAttribPropInterfaceSym = jsxNamespace && getSymbol(jsxNamespace.exports!, nameOfAttribPropContainer, SymbolFlags.Type); // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [type] const jsxElementAttribPropInterfaceType = jsxElementAttribPropInterfaceSym && getDeclaredTypeOfSymbol(jsxElementAttribPropInterfaceSym); // The properties of JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute @@ -28826,7 +29024,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (propertiesOfJsxElementAttribPropInterface) { // Element Attributes has zero properties, so the element attributes type will be the class instance type if (propertiesOfJsxElementAttribPropInterface.length === 0) { - return "" as ts.__String; + return "" as __String; } // Element Attributes has one property, so the element attributes type will be the type of the corresponding // property of the class instance type @@ -28835,15 +29033,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else if (propertiesOfJsxElementAttribPropInterface.length > 1 && jsxElementAttribPropInterfaceSym.declarations) { // More than one property on ElementAttributesProperty is an error - error(jsxElementAttribPropInterfaceSym.declarations[0], ts.Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, ts.unescapeLeadingUnderscores(nameOfAttribPropContainer)); + error(jsxElementAttribPropInterfaceSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, unescapeLeadingUnderscores(nameOfAttribPropContainer)); } } return undefined; } - function getJsxLibraryManagedAttributes(jsxNamespace: ts.Symbol) { + function getJsxLibraryManagedAttributes(jsxNamespace: Symbol) { // JSX.LibraryManagedAttributes [symbol] - return jsxNamespace && getSymbol(jsxNamespace.exports!, JsxNames.LibraryManagedAttributes, ts.SymbolFlags.Type); + return jsxNamespace && getSymbol(jsxNamespace.exports!, JsxNames.LibraryManagedAttributes, SymbolFlags.Type); } /// e.g. "props" for React.d.ts, @@ -28851,23 +29049,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /// non-intrinsic elements' attributes type is 'any'), /// or '' if it has 0 properties (which means every /// non-intrinsic elements' attributes type is the element instance type) - function getJsxElementPropertiesName(jsxNamespace: ts.Symbol) { + function getJsxElementPropertiesName(jsxNamespace: Symbol) { return getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace); } - function getJsxElementChildrenPropertyName(jsxNamespace: ts.Symbol): ts.__String | undefined { + function getJsxElementChildrenPropertyName(jsxNamespace: Symbol): __String | undefined { return getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace); } - function getUninstantiatedJsxSignaturesOfType(elementType: ts.Type, caller: ts.JsxOpeningLikeElement): readonly ts.Signature[] { - if (elementType.flags & ts.TypeFlags.String) { + function getUninstantiatedJsxSignaturesOfType(elementType: Type, caller: JsxOpeningLikeElement): readonly Signature[] { + if (elementType.flags & TypeFlags.String) { return [anySignature]; } - else if (elementType.flags & ts.TypeFlags.StringLiteral) { - const intrinsicType = getIntrinsicAttributesTypeFromStringLiteralType(elementType as ts.StringLiteralType, caller); + else if (elementType.flags & TypeFlags.StringLiteral) { + const intrinsicType = getIntrinsicAttributesTypeFromStringLiteralType(elementType as StringLiteralType, caller); if (!intrinsicType) { - error(caller, ts.Diagnostics.Property_0_does_not_exist_on_type_1, (elementType as ts.StringLiteralType).value, "JSX." + JsxNames.IntrinsicElements); - return ts.emptyArray; + error(caller, Diagnostics.Property_0_does_not_exist_on_type_1, (elementType as StringLiteralType).value, "JSX." + JsxNames.IntrinsicElements); + return emptyArray; } else { const fakeSignature = createSignatureForJSXIntrinsic(caller, intrinsicType); @@ -28876,19 +29074,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const apparentElemType = getApparentType(elementType); // Resolve the signatures, preferring constructor - let signatures = getSignaturesOfType(apparentElemType, ts.SignatureKind.Construct); + let signatures = getSignaturesOfType(apparentElemType, SignatureKind.Construct); if (signatures.length === 0) { // No construct signatures, try call signatures - signatures = getSignaturesOfType(apparentElemType, ts.SignatureKind.Call); + signatures = getSignaturesOfType(apparentElemType, SignatureKind.Call); } - if (signatures.length === 0 && apparentElemType.flags & ts.TypeFlags.Union) { + if (signatures.length === 0 && apparentElemType.flags & TypeFlags.Union) { // If each member has some combination of new/call signatures; make a union signature list for those - signatures = getUnionSignatures(ts.map((apparentElemType as ts.UnionType).types, t => getUninstantiatedJsxSignaturesOfType(t, caller))); + signatures = getUnionSignatures(map((apparentElemType as UnionType).types, t => getUninstantiatedJsxSignaturesOfType(t, caller))); } return signatures; } - function getIntrinsicAttributesTypeFromStringLiteralType(type: ts.StringLiteralType, location: ts.Node): ts.Type | undefined { + function getIntrinsicAttributesTypeFromStringLiteralType(type: StringLiteralType, location: Node): Type | undefined { // If the elemType is a stringLiteral type, we can then provide a check to make sure that the string literal type is one of the Jsx intrinsic element type // For example: // var CustomTag: "h1" = "h1"; @@ -28896,7 +29094,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const intrinsicElementsType = getJsxType(JsxNames.IntrinsicElements, location); if (!isErrorType(intrinsicElementsType)) { const stringLiteralTypeName = type.value; - const intrinsicProp = getPropertyOfType(intrinsicElementsType, ts.escapeLeadingUnderscores(stringLiteralTypeName)); + const intrinsicProp = getPropertyOfType(intrinsicElementsType, escapeLeadingUnderscores(stringLiteralTypeName)); if (intrinsicProp) { return getTypeOfSymbol(intrinsicProp); } @@ -28910,18 +29108,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return anyType; } - function checkJsxReturnAssignableToAppropriateBound(refKind: ts.JsxReferenceKind, elemInstanceType: ts.Type, openingLikeElement: ts.JsxOpeningLikeElement) { - if (refKind === ts.JsxReferenceKind.Function) { + function checkJsxReturnAssignableToAppropriateBound(refKind: JsxReferenceKind, elemInstanceType: Type, openingLikeElement: JsxOpeningLikeElement) { + if (refKind === JsxReferenceKind.Function) { const sfcReturnConstraint = getJsxStatelessElementTypeAt(openingLikeElement); if (sfcReturnConstraint) { - checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement.tagName, ts.Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo(elemInstanceType, sfcReturnConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_return_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); } } - else if (refKind === ts.JsxReferenceKind.Component) { + else if (refKind === JsxReferenceKind.Component) { const classConstraint = getJsxElementClassTypeAt(openingLikeElement); if (classConstraint) { // Issue an error if this return type isn't assignable to JSX.ElementClass, failing that - checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement.tagName, ts.Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo(elemInstanceType, classConstraint, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_instance_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); } } else { // Mixed @@ -28931,12 +29129,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } const combined = getUnionType([sfcReturnConstraint, classConstraint]); - checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement.tagName, ts.Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); + checkTypeRelatedTo(elemInstanceType, combined, assignableRelation, openingLikeElement.tagName, Diagnostics.Its_element_type_0_is_not_a_valid_JSX_element, generateInitialErrorChain); } - function generateInitialErrorChain(): ts.DiagnosticMessageChain { - const componentName = ts.getTextOfNode(openingLikeElement.tagName); - return ts.chainDiagnosticMessages(/* details */ undefined, ts.Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName); + function generateInitialErrorChain(): DiagnosticMessageChain { + const componentName = getTextOfNode(openingLikeElement.tagName); + return chainDiagnosticMessages(/* details */ undefined, Diagnostics._0_cannot_be_used_as_a_JSX_component, componentName); } } @@ -28945,15 +29143,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * The function is intended to be called from a function which has checked that the opening element is an intrinsic element. * @param node an intrinsic JSX opening-like element */ - function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node: ts.JsxOpeningLikeElement): ts.Type { - ts.Debug.assert(isJsxIntrinsicIdentifier(node.tagName)); + function getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node: JsxOpeningLikeElement): Type { + Debug.assert(isJsxIntrinsicIdentifier(node.tagName)); const links = getNodeLinks(node); if (!links.resolvedJsxElementAttributesType) { const symbol = getIntrinsicTagSymbol(node); - if (links.jsxFlags & ts.JsxFlags.IntrinsicNamedElement) { + if (links.jsxFlags & JsxFlags.IntrinsicNamedElement) { return links.resolvedJsxElementAttributesType = getTypeOfSymbol(symbol) || errorType; } - else if (links.jsxFlags & ts.JsxFlags.IntrinsicIndexedElement) { + else if (links.jsxFlags & JsxFlags.IntrinsicIndexedElement) { return links.resolvedJsxElementAttributesType = getIndexTypeOfType(getJsxType(JsxNames.IntrinsicElements, node), stringType) || errorType; } @@ -28964,17 +29162,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedJsxElementAttributesType; } - function getJsxElementClassTypeAt(location: ts.Node): ts.Type | undefined { + function getJsxElementClassTypeAt(location: Node): Type | undefined { const type = getJsxType(JsxNames.ElementClass, location); if (isErrorType(type)) return undefined; return type; } - function getJsxElementTypeAt(location: ts.Node): ts.Type { + function getJsxElementTypeAt(location: Node): Type { return getJsxType(JsxNames.Element, location); } - function getJsxStatelessElementTypeAt(location: ts.Node): ts.Type | undefined { + function getJsxStatelessElementTypeAt(location: Node): Type | undefined { const jsxElementType = getJsxElementTypeAt(location); if (jsxElementType) { return getUnionType([jsxElementType, nullType]); @@ -28984,26 +29182,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Returns all the properties of the Jsx.IntrinsicElements interface */ - function getJsxIntrinsicTagNamesAt(location: ts.Node): ts.Symbol[] { + function getJsxIntrinsicTagNamesAt(location: Node): Symbol[] { const intrinsics = getJsxType(JsxNames.IntrinsicElements, location); - return intrinsics ? getPropertiesOfType(intrinsics) : ts.emptyArray; + return intrinsics ? getPropertiesOfType(intrinsics) : emptyArray; } - function checkJsxPreconditions(errorNode: ts.Node) { + function checkJsxPreconditions(errorNode: Node) { // Preconditions for using JSX - if ((compilerOptions.jsx || ts.JsxEmit.None) === ts.JsxEmit.None) { - error(errorNode, ts.Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided); + if ((compilerOptions.jsx || JsxEmit.None) === JsxEmit.None) { + error(errorNode, Diagnostics.Cannot_use_JSX_unless_the_jsx_flag_is_provided); } if (getJsxElementTypeAt(errorNode) === undefined) { if (noImplicitAny) { - error(errorNode, ts.Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist); + error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist); } } } - function checkJsxOpeningLikeElementOrOpeningFragment(node: ts.JsxOpeningLikeElement | ts.JsxOpeningFragment) { - const isNodeOpeningLikeElement = ts.isJsxOpeningLikeElement(node); + function checkJsxOpeningLikeElementOrOpeningFragment(node: JsxOpeningLikeElement | JsxOpeningFragment) { + const isNodeOpeningLikeElement = isJsxOpeningLikeElement(node); if (isNodeOpeningLikeElement) { checkGrammarJsxElement(node); @@ -29014,33 +29212,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!getJsxNamespaceContainerForImplicitImport(node)) { // The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import. // And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error. - const jsxFactoryRefErr = diagnostics && compilerOptions.jsx === ts.JsxEmit.React ? ts.Diagnostics.Cannot_find_name_0 : undefined; + const jsxFactoryRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined; const jsxFactoryNamespace = getJsxNamespace(node); const jsxFactoryLocation = isNodeOpeningLikeElement ? node.tagName : node; // allow null as jsxFragmentFactory - let jsxFactorySym: ts.Symbol | undefined; - if (!(ts.isJsxOpeningFragment(node) && jsxFactoryNamespace === "null")) { - jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, ts.SymbolFlags.Value, jsxFactoryRefErr, jsxFactoryNamespace, /*isUse*/ true); + let jsxFactorySym: Symbol | undefined; + if (!(isJsxOpeningFragment(node) && jsxFactoryNamespace === "null")) { + jsxFactorySym = resolveName(jsxFactoryLocation, jsxFactoryNamespace, SymbolFlags.Value, jsxFactoryRefErr, jsxFactoryNamespace, /*isUse*/ true); } if (jsxFactorySym) { // Mark local symbol as referenced here because it might not have been marked // if jsx emit was not jsxFactory as there wont be error being emitted - jsxFactorySym.isReferenced = ts.SymbolFlags.All; + jsxFactorySym.isReferenced = SymbolFlags.All; // If react/jsxFactory symbol is alias, mark it as refereced - if (jsxFactorySym.flags & ts.SymbolFlags.Alias && !getTypeOnlyAliasDeclaration(jsxFactorySym)) { + if (jsxFactorySym.flags & SymbolFlags.Alias && !getTypeOnlyAliasDeclaration(jsxFactorySym)) { markAliasSymbolAsReferenced(jsxFactorySym); } } // For JsxFragment, mark jsx pragma as referenced via resolveName - if (ts.isJsxOpeningFragment(node)) { - const file = ts.getSourceFileOfNode(node); + if (isJsxOpeningFragment(node)) { + const file = getSourceFileOfNode(node); const localJsxNamespace = getLocalJsxNamespace(file); if (localJsxNamespace) { - resolveName(jsxFactoryLocation, localJsxNamespace, ts.SymbolFlags.Value, jsxFactoryRefErr, localJsxNamespace, /*isUse*/ true); + resolveName(jsxFactoryLocation, localJsxNamespace, SymbolFlags.Value, jsxFactoryRefErr, localJsxNamespace, /*isUse*/ true); } } } @@ -29066,8 +29264,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType */ - function isKnownProperty(targetType: ts.Type, name: ts.__String, isComparingJsxAttributes: boolean): boolean { - if (targetType.flags & ts.TypeFlags.Object) { + function isKnownProperty(targetType: Type, name: __String, isComparingJsxAttributes: boolean): boolean { + if (targetType.flags & TypeFlags.Object) { // For backwards compatibility a symbol-named property is satisfied by a string index signature. This // is incorrect and inconsistent with element access expressions, where it is an error, so eventually // we should remove this exception. @@ -29079,8 +29277,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } } - else if (targetType.flags & ts.TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) { - for (const t of (targetType as ts.UnionOrIntersectionType).types) { + else if (targetType.flags & TypeFlags.UnionOrIntersection && isExcessPropertyCheckTarget(targetType)) { + for (const t of (targetType as UnionOrIntersectionType).types) { if (isKnownProperty(t, name, isComparingJsxAttributes)) { return true; } @@ -29089,19 +29287,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isExcessPropertyCheckTarget(type: ts.Type): boolean { - return !!(type.flags & ts.TypeFlags.Object && !(ts.getObjectFlags(type) & ts.ObjectFlags.ObjectLiteralPatternWithComputedProperties) || - type.flags & ts.TypeFlags.NonPrimitive || - type.flags & ts.TypeFlags.Union && ts.some((type as ts.UnionType).types, isExcessPropertyCheckTarget) || - type.flags & ts.TypeFlags.Intersection && ts.every((type as ts.IntersectionType).types, isExcessPropertyCheckTarget)); + function isExcessPropertyCheckTarget(type: Type): boolean { + return !!(type.flags & TypeFlags.Object && !(getObjectFlags(type) & ObjectFlags.ObjectLiteralPatternWithComputedProperties) || + type.flags & TypeFlags.NonPrimitive || + type.flags & TypeFlags.Union && some((type as UnionType).types, isExcessPropertyCheckTarget) || + type.flags & TypeFlags.Intersection && every((type as IntersectionType).types, isExcessPropertyCheckTarget)); } - function checkJsxExpression(node: ts.JsxExpression, checkMode?: CheckMode) { + function checkJsxExpression(node: JsxExpression, checkMode?: CheckMode) { checkGrammarJsxExpression(node); if (node.expression) { const type = checkExpression(node.expression, checkMode); if (node.dotDotDotToken && type !== anyType && !isArrayType(type)) { - error(node, ts.Diagnostics.JSX_spread_child_must_be_an_array_type); + error(node, Diagnostics.JSX_spread_child_must_be_an_array_type); } return type; } @@ -29110,22 +29308,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getDeclarationNodeFlagsFromSymbol(s: ts.Symbol): ts.NodeFlags { - return s.valueDeclaration ? ts.getCombinedNodeFlags(s.valueDeclaration) : 0; + function getDeclarationNodeFlagsFromSymbol(s: Symbol): NodeFlags { + return s.valueDeclaration ? getCombinedNodeFlags(s.valueDeclaration) : 0; } /** * Return whether this symbol is a member of a prototype somewhere * Note that this is not tracked well within the compiler, so the answer may be incorrect. */ - function isPrototypeProperty(symbol: ts.Symbol) { - if (symbol.flags & ts.SymbolFlags.Method || ts.getCheckFlags(symbol) & ts.CheckFlags.SyntheticMethod) { + function isPrototypeProperty(symbol: Symbol) { + if (symbol.flags & SymbolFlags.Method || getCheckFlags(symbol) & CheckFlags.SyntheticMethod) { return true; } - if (ts.isInJSFile(symbol.valueDeclaration)) { + if (isInJSFile(symbol.valueDeclaration)) { const parent = symbol.valueDeclaration!.parent; - return parent && ts.isBinaryExpression(parent) && - ts.getAssignmentDeclarationKind(parent) === ts.AssignmentDeclarationKind.PrototypeProperty; + return parent && isBinaryExpression(parent) && + getAssignmentDeclarationKind(parent) === AssignmentDeclarationKind.PrototypeProperty; } } @@ -29138,13 +29336,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param prop The symbol for the property being accessed. */ function checkPropertyAccessibility( - node: ts.PropertyAccessExpression | ts.QualifiedName | ts.PropertyAccessExpression | ts.VariableDeclaration | ts.ParameterDeclaration | ts.ImportTypeNode | ts.PropertyAssignment | ts.ShorthandPropertyAssignment | ts.BindingElement, - isSuper: boolean, writing: boolean, type: ts.Type, prop: ts.Symbol, reportError = true): boolean { + node: PropertyAccessExpression | QualifiedName | PropertyAccessExpression | VariableDeclaration | ParameterDeclaration | ImportTypeNode | PropertyAssignment | ShorthandPropertyAssignment | BindingElement, + isSuper: boolean, writing: boolean, type: Type, prop: Symbol, reportError = true): boolean { const errorNode = !reportError ? undefined : - node.kind === ts.SyntaxKind.QualifiedName ? node.right : - node.kind === ts.SyntaxKind.ImportType ? node : - node.kind === ts.SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name; + node.kind === SyntaxKind.QualifiedName ? node.right : + node.kind === SyntaxKind.ImportType ? node : + node.kind === SyntaxKind.BindingElement && node.propertyName ? node.propertyName : node.name; return checkPropertyAccessibilityAtLocation(node, isSuper, writing, type, prop, errorNode); } @@ -29159,11 +29357,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param prop The symbol for the property being accessed. * @param errorNode The node where we should report an invalid property access error, or undefined if we should not report errors. */ - function checkPropertyAccessibilityAtLocation(location: ts.Node, + function checkPropertyAccessibilityAtLocation(location: Node, isSuper: boolean, writing: boolean, - containingType: ts.Type, prop: ts.Symbol, errorNode?: ts.Node): boolean { + containingType: Type, prop: Symbol, errorNode?: Node): boolean { - const flags = ts.getDeclarationModifierFlagsFromSymbol(prop, writing); + const flags = getDeclarationModifierFlagsFromSymbol(prop, writing); if (isSuper) { // TS 1.0 spec (April 2014): 4.8.2 @@ -29173,22 +29371,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // - In a static member function or static member accessor // where this references the constructor function object of a derived class, // a super property access is permitted and must specify a public static member function of the base class. - if (languageVersion < ts.ScriptTarget.ES2015) { + if (languageVersion < ScriptTarget.ES2015) { if (symbolHasNonMethodDeclaration(prop)) { if (errorNode) { - error(errorNode, ts.Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); + error(errorNode, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword); } return false; } } - if (flags & ts.ModifierFlags.Abstract) { + if (flags & ModifierFlags.Abstract) { // A method cannot be accessed in a super property access if the method is abstract. // This error could mask a private property access error. But, a member // cannot simultaneously be private and abstract, so this will trigger an // additional error elsewhere. if (errorNode) { error(errorNode, - ts.Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, + Diagnostics.Abstract_method_0_in_class_1_cannot_be_accessed_via_super_expression, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); } @@ -29197,34 +29395,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Referencing abstract properties within their own constructors is not allowed - if ((flags & ts.ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) && - (ts.isThisProperty(location) || ts.isThisInitializedObjectBindingExpression(location) || ts.isObjectBindingPattern(location.parent) && ts.isThisInitializedDeclaration(location.parent.parent))) { - const declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!); + if ((flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) && + (isThisProperty(location) || isThisInitializedObjectBindingExpression(location) || isObjectBindingPattern(location.parent) && isThisInitializedDeclaration(location.parent.parent))) { + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!); if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(location)) { if (errorNode) { error(errorNode, - ts.Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, + Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), - ts.getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); + getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!)); } return false; } } // Public properties are otherwise accessible. - if (!(flags & ts.ModifierFlags.NonPublicAccessibilityModifier)) { + if (!(flags & ModifierFlags.NonPublicAccessibilityModifier)) { return true; } // Property is known to be private or protected at this point // Private property is accessible if the property is within the declaring class - if (flags & ts.ModifierFlags.Private) { - const declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!; + if (flags & ModifierFlags.Private) { + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!)!; if (!isNodeWithinClass(location, declaringClassDeclaration)) { if (errorNode) { error(errorNode, - ts.Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, + Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop)!)); } @@ -29243,7 +29441,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Find the first enclosing class that has the declaring classes of the protected constituents // of the property as base classes let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => { - const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as ts.InterfaceType; + const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as InterfaceType; return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing); }); // A protected property is accessible if the property is within the declaring class or classes derived from it @@ -29252,10 +29450,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // static member access is disallowed enclosingClass = getEnclosingClassFromThisParameter(location); enclosingClass = enclosingClass && isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing); - if (flags & ts.ModifierFlags.Static || !enclosingClass) { + if (flags & ModifierFlags.Static || !enclosingClass) { if (errorNode) { error(errorNode, - ts.Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, + Diagnostics.Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses, symbolToString(prop), typeToString(getDeclaringClass(prop) || containingType)); } @@ -29263,17 +29461,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } // No further restrictions for static properties - if (flags & ts.ModifierFlags.Static) { + if (flags & ModifierFlags.Static) { return true; } - if (containingType.flags & ts.TypeFlags.TypeParameter) { + if (containingType.flags & TypeFlags.TypeParameter) { // get the original type -- represented as the type constraint of the 'this' type - containingType = (containingType as ts.TypeParameter).isThisType ? getConstraintOfTypeParameter(containingType as ts.TypeParameter)! : getBaseConstraintOfType(containingType as ts.TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined + containingType = (containingType as TypeParameter).isThisType ? getConstraintOfTypeParameter(containingType as TypeParameter)! : getBaseConstraintOfType(containingType as TypeParameter)!; // TODO: GH#18217 Use a different variable that's allowed to be undefined } if (!containingType || !hasBaseType(containingType, enclosingClass)) { if (errorNode) { error(errorNode, - ts.Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2, + Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1_This_is_an_instance_of_class_2, symbolToString(prop), typeToString(enclosingClass), typeToString(containingType)); } return false; @@ -29281,150 +29479,150 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function getEnclosingClassFromThisParameter(node: ts.Node): ts.InterfaceType | undefined { + function getEnclosingClassFromThisParameter(node: Node): InterfaceType | undefined { const thisParameter = getThisParameterFromNodeContext(node); let thisType = thisParameter?.type && getTypeFromTypeNode(thisParameter.type); - if (thisType && thisType.flags & ts.TypeFlags.TypeParameter) { - thisType = getConstraintOfTypeParameter(thisType as ts.TypeParameter); + if (thisType && thisType.flags & TypeFlags.TypeParameter) { + thisType = getConstraintOfTypeParameter(thisType as TypeParameter); } - if (thisType && ts.getObjectFlags(thisType) & (ts.ObjectFlags.ClassOrInterface | ts.ObjectFlags.Reference)) { - return getTargetType(thisType) as ts.InterfaceType; + if (thisType && getObjectFlags(thisType) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference)) { + return getTargetType(thisType) as InterfaceType; } return undefined; } - function getThisParameterFromNodeContext(node: ts.Node) { - const thisContainer = ts.getThisContainer(node, /* includeArrowFunctions */ false); - return thisContainer && ts.isFunctionLike(thisContainer) ? ts.getThisParameter(thisContainer) : undefined; + function getThisParameterFromNodeContext(node: Node) { + const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false); + return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined; } - function symbolHasNonMethodDeclaration(symbol: ts.Symbol) { - return !!forEachProperty(symbol, prop => !(prop.flags & ts.SymbolFlags.Method)); + function symbolHasNonMethodDeclaration(symbol: Symbol) { + return !!forEachProperty(symbol, prop => !(prop.flags & SymbolFlags.Method)); } - function checkNonNullExpression(node: ts.Expression | ts.QualifiedName) { + function checkNonNullExpression(node: Expression | QualifiedName) { return checkNonNullType(checkExpression(node), node); } - function isNullableType(type: ts.Type) { + function isNullableType(type: Type) { return !!(getTypeFacts(type) & TypeFacts.IsUndefinedOrNull); } - function getNonNullableTypeIfNeeded(type: ts.Type) { + function getNonNullableTypeIfNeeded(type: Type) { return isNullableType(type) ? getNonNullableType(type) : type; } - function reportObjectPossiblyNullOrUndefinedError(node: ts.Node, facts: TypeFacts) { - const nodeText = ts.isEntityNameExpression(node) ? ts.entityNameToString(node) : undefined; - if (node.kind === ts.SyntaxKind.NullKeyword) { - error(node, ts.Diagnostics.The_value_0_cannot_be_used_here, "null"); + function reportObjectPossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { + const nodeText = isEntityNameExpression(node) ? entityNameToString(node) : undefined; + if (node.kind === SyntaxKind.NullKeyword) { + error(node, Diagnostics.The_value_0_cannot_be_used_here, "null"); return; } if (nodeText !== undefined && nodeText.length < 100) { - if (ts.isIdentifier(node) && nodeText === "undefined") { - error(node, ts.Diagnostics.The_value_0_cannot_be_used_here, "undefined"); + if (isIdentifier(node) && nodeText === "undefined") { + error(node, Diagnostics.The_value_0_cannot_be_used_here, "undefined"); return; } error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - ts.Diagnostics._0_is_possibly_null_or_undefined : - ts.Diagnostics._0_is_possibly_undefined : - ts.Diagnostics._0_is_possibly_null, + Diagnostics._0_is_possibly_null_or_undefined : + Diagnostics._0_is_possibly_undefined : + Diagnostics._0_is_possibly_null, nodeText ); } else { error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - ts.Diagnostics.Object_is_possibly_null_or_undefined : - ts.Diagnostics.Object_is_possibly_undefined : - ts.Diagnostics.Object_is_possibly_null + Diagnostics.Object_is_possibly_null_or_undefined : + Diagnostics.Object_is_possibly_undefined : + Diagnostics.Object_is_possibly_null ); } } - function reportCannotInvokePossiblyNullOrUndefinedError(node: ts.Node, facts: TypeFacts) { + function reportCannotInvokePossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { error(node, facts & TypeFacts.IsUndefined ? facts & TypeFacts.IsNull ? - ts.Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined : - ts.Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined : - ts.Diagnostics.Cannot_invoke_an_object_which_is_possibly_null + Diagnostics.Cannot_invoke_an_object_which_is_possibly_null_or_undefined : + Diagnostics.Cannot_invoke_an_object_which_is_possibly_undefined : + Diagnostics.Cannot_invoke_an_object_which_is_possibly_null ); } function checkNonNullTypeWithReporter( - type: ts.Type, - node: ts.Node, - reportError: (node: ts.Node, facts: TypeFacts) => void - ): ts.Type { - if (strictNullChecks && type.flags & ts.TypeFlags.Unknown) { - if (ts.isEntityNameExpression(node)) { - const nodeText = ts.entityNameToString(node); + type: Type, + node: Node, + reportError: (node: Node, facts: TypeFacts) => void + ): Type { + if (strictNullChecks && type.flags & TypeFlags.Unknown) { + if (isEntityNameExpression(node)) { + const nodeText = entityNameToString(node); if (nodeText.length < 100) { - error(node, ts.Diagnostics._0_is_of_type_unknown, nodeText); + error(node, Diagnostics._0_is_of_type_unknown, nodeText); return errorType; } } - error(node, ts.Diagnostics.Object_is_of_type_unknown); + error(node, Diagnostics.Object_is_of_type_unknown); return errorType; } const facts = getTypeFacts(type); if (facts & TypeFacts.IsUndefinedOrNull) { reportError(node, facts); const t = getNonNullableType(type); - return t.flags & (ts.TypeFlags.Nullable | ts.TypeFlags.Never) ? errorType : t; + return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t; } return type; } - function checkNonNullType(type: ts.Type, node: ts.Node) { + function checkNonNullType(type: Type, node: Node) { return checkNonNullTypeWithReporter(type, node, reportObjectPossiblyNullOrUndefinedError); } - function checkNonNullNonVoidType(type: ts.Type, node: ts.Node): ts.Type { + function checkNonNullNonVoidType(type: Type, node: Node): Type { const nonNullType = checkNonNullType(type, node); - if (nonNullType.flags & ts.TypeFlags.Void) { - if (ts.isEntityNameExpression(node)) { - const nodeText = ts.entityNameToString(node); - if (ts.isIdentifier(node) && nodeText === "undefined") { - error(node, ts.Diagnostics.The_value_0_cannot_be_used_here, nodeText); + if (nonNullType.flags & TypeFlags.Void) { + if (isEntityNameExpression(node)) { + const nodeText = entityNameToString(node); + if (isIdentifier(node) && nodeText === "undefined") { + error(node, Diagnostics.The_value_0_cannot_be_used_here, nodeText); return nonNullType; } if (nodeText.length < 100) { - error(node, ts.Diagnostics._0_is_possibly_undefined, nodeText); + error(node, Diagnostics._0_is_possibly_undefined, nodeText); return nonNullType; } } - error(node, ts.Diagnostics.Object_is_possibly_undefined); + error(node, Diagnostics.Object_is_possibly_undefined); } return nonNullType; } - function checkPropertyAccessExpression(node: ts.PropertyAccessExpression, checkMode: CheckMode | undefined) { - return node.flags & ts.NodeFlags.OptionalChain ? checkPropertyAccessChain(node as ts.PropertyAccessChain, checkMode) : + function checkPropertyAccessExpression(node: PropertyAccessExpression, checkMode: CheckMode | undefined) { + return node.flags & NodeFlags.OptionalChain ? checkPropertyAccessChain(node as PropertyAccessChain, checkMode) : checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullExpression(node.expression), node.name, checkMode); } - function checkPropertyAccessChain(node: ts.PropertyAccessChain, checkMode: CheckMode | undefined) { + function checkPropertyAccessChain(node: PropertyAccessChain, checkMode: CheckMode | undefined) { const leftType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(leftType, node.expression); return propagateOptionalTypeMarker(checkPropertyAccessExpressionOrQualifiedName(node, node.expression, checkNonNullType(nonOptionalType, node.expression), node.name, checkMode), node, nonOptionalType !== leftType); } - function checkQualifiedName(node: ts.QualifiedName, checkMode: CheckMode | undefined) { - const leftType = ts.isPartOfTypeQuery(node) && ts.isThisIdentifier(node.left) ? checkNonNullType(checkThisExpression(node.left), node.left) : checkNonNullExpression(node.left); + function checkQualifiedName(node: QualifiedName, checkMode: CheckMode | undefined) { + const leftType = isPartOfTypeQuery(node) && isThisIdentifier(node.left) ? checkNonNullType(checkThisExpression(node.left), node.left) : checkNonNullExpression(node.left); return checkPropertyAccessExpressionOrQualifiedName(node, node.left, leftType, node.right, checkMode); } - function isMethodAccessForCall(node: ts.Node) { - while (node.parent.kind === ts.SyntaxKind.ParenthesizedExpression) { + function isMethodAccessForCall(node: Node) { + while (node.parent.kind === SyntaxKind.ParenthesizedExpression) { node = node.parent; } - return ts.isCallOrNewExpression(node.parent) && node.parent.expression === node; + return isCallOrNewExpression(node.parent) && node.parent.expression === node; } // Lookup the private identifier lexically. - function lookupSymbolForPrivateIdentifierDeclaration(propName: ts.__String, location: ts.Node): ts.Symbol | undefined { - for (let containingClass = ts.getContainingClass(location); !!containingClass; containingClass = ts.getContainingClass(containingClass)) { + function lookupSymbolForPrivateIdentifierDeclaration(propName: __String, location: Node): Symbol | undefined { + for (let containingClass = getContainingClass(location); !!containingClass; containingClass = getContainingClass(containingClass)) { const { symbol } = containingClass; - const name = ts.getSymbolNameForPrivateIdentifier(symbol, propName); + const name = getSymbolNameForPrivateIdentifier(symbol, propName); const prop = (symbol.members && symbol.members.get(name)) || (symbol.exports && symbol.exports.get(name)); if (prop) { return prop; @@ -29432,26 +29630,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkGrammarPrivateIdentifierExpression(privId: ts.PrivateIdentifier): boolean { - if (!ts.getContainingClass(privId)) { - return grammarErrorOnNode(privId, ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + function checkGrammarPrivateIdentifierExpression(privId: PrivateIdentifier): boolean { + if (!getContainingClass(privId)) { + return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); } - if (!ts.isForInStatement(privId.parent)) { - if (!ts.isExpressionNode(privId)) { - return grammarErrorOnNode(privId, ts.Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression); + if (!isForInStatement(privId.parent)) { + if (!isExpressionNode(privId)) { + return grammarErrorOnNode(privId, Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression); } - const isInOperation = ts.isBinaryExpression(privId.parent) && privId.parent.operatorToken.kind === ts.SyntaxKind.InKeyword; + const isInOperation = isBinaryExpression(privId.parent) && privId.parent.operatorToken.kind === SyntaxKind.InKeyword; if (!getSymbolForPrivateIdentifierExpression(privId) && !isInOperation) { - return grammarErrorOnNode(privId, ts.Diagnostics.Cannot_find_name_0, ts.idText(privId)); + return grammarErrorOnNode(privId, Diagnostics.Cannot_find_name_0, idText(privId)); } } return false; } - function checkPrivateIdentifierExpression(privId: ts.PrivateIdentifier): ts.Type { + function checkPrivateIdentifierExpression(privId: PrivateIdentifier): Type { checkGrammarPrivateIdentifierExpression(privId); const symbol = getSymbolForPrivateIdentifierExpression(privId); if (symbol) { @@ -29460,8 +29658,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return anyType; } - function getSymbolForPrivateIdentifierExpression(privId: ts.PrivateIdentifier): ts.Symbol | undefined { - if (!ts.isExpressionNode(privId)) { + function getSymbolForPrivateIdentifierExpression(privId: PrivateIdentifier): Symbol | undefined { + if (!isExpressionNode(privId)) { return undefined; } @@ -29472,19 +29670,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedSymbol; } - function getPrivateIdentifierPropertyOfType(leftType: ts.Type, lexicallyScopedIdentifier: ts.Symbol): ts.Symbol | undefined { + function getPrivateIdentifierPropertyOfType(leftType: Type, lexicallyScopedIdentifier: Symbol): Symbol | undefined { return getPropertyOfType(leftType, lexicallyScopedIdentifier.escapedName); } - function checkPrivateIdentifierPropertyAccess(leftType: ts.Type, right: ts.PrivateIdentifier, lexicallyScopedIdentifier: ts.Symbol | undefined): boolean { + function checkPrivateIdentifierPropertyAccess(leftType: Type, right: PrivateIdentifier, lexicallyScopedIdentifier: Symbol | undefined): boolean { // Either the identifier could not be looked up in the lexical scope OR the lexically scoped identifier did not exist on the type. // Find a private identifier with the same description on the type. - let propertyOnType: ts.Symbol | undefined; + let propertyOnType: Symbol | undefined; const properties = getPropertiesOfType(leftType); if (properties) { - ts.forEach(properties, (symbol: ts.Symbol) => { + forEach(properties, (symbol: Symbol) => { const decl = symbol.valueDeclaration; - if (decl && ts.isNamedDeclaration(decl) && ts.isPrivateIdentifier(decl.name) && decl.name.escapedText === right.escapedText) { + if (decl && isNamedDeclaration(decl) && isPrivateIdentifier(decl.name) && decl.name.escapedText === right.escapedText) { propertyOnType = symbol; return true; } @@ -29492,34 +29690,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const diagName = diagnosticName(right); if (propertyOnType) { - const typeValueDecl = ts.Debug.checkDefined(propertyOnType.valueDeclaration); - const typeClass = ts.Debug.checkDefined(ts.getContainingClass(typeValueDecl)); + const typeValueDecl = Debug.checkDefined(propertyOnType.valueDeclaration); + const typeClass = Debug.checkDefined(getContainingClass(typeValueDecl)); // We found a private identifier property with the same description. // Either: // - There is a lexically scoped private identifier AND it shadows the one we found on the type. // - It is an attempt to access the private identifier outside of the class. if (lexicallyScopedIdentifier?.valueDeclaration) { const lexicalValueDecl = lexicallyScopedIdentifier.valueDeclaration; - const lexicalClass = ts.getContainingClass(lexicalValueDecl); - ts.Debug.assert(!!lexicalClass); - if (ts.findAncestor(lexicalClass, n => typeClass === n)) { + const lexicalClass = getContainingClass(lexicalValueDecl); + Debug.assert(!!lexicalClass); + if (findAncestor(lexicalClass, n => typeClass === n)) { const diagnostic = error( right, - ts.Diagnostics.The_property_0_cannot_be_accessed_on_type_1_within_this_class_because_it_is_shadowed_by_another_private_identifier_with_the_same_spelling, + Diagnostics.The_property_0_cannot_be_accessed_on_type_1_within_this_class_because_it_is_shadowed_by_another_private_identifier_with_the_same_spelling, diagName, typeToString(leftType) ); - ts.addRelatedInfo( + addRelatedInfo( diagnostic, - ts.createDiagnosticForNode( + createDiagnosticForNode( lexicalValueDecl, - ts.Diagnostics.The_shadowing_declaration_of_0_is_defined_here, + Diagnostics.The_shadowing_declaration_of_0_is_defined_here, diagName ), - ts.createDiagnosticForNode( + createDiagnosticForNode( typeValueDecl, - ts.Diagnostics.The_declaration_of_0_that_you_probably_intended_to_use_is_defined_here, + Diagnostics.The_declaration_of_0_that_you_probably_intended_to_use_is_defined_here, diagName ) ); @@ -29528,7 +29726,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } error( right, - ts.Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier, + Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier, diagName, diagnosticName(typeClass.name || anon) ); @@ -29537,38 +29735,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isThisPropertyAccessInConstructor(node: ts.ElementAccessExpression | ts.PropertyAccessExpression | ts.QualifiedName, prop: ts.Symbol) { - return (isConstructorDeclaredProperty(prop) || ts.isThisProperty(node) && isAutoTypedProperty(prop)) - && ts.getThisContainer(node, /*includeArrowFunctions*/ true) === getDeclaringConstructor(prop); + function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { + return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop)) + && getThisContainer(node, /*includeArrowFunctions*/ true) === getDeclaringConstructor(prop); } - function checkPropertyAccessExpressionOrQualifiedName(node: ts.PropertyAccessExpression | ts.QualifiedName, left: ts.Expression | ts.QualifiedName, leftType: ts.Type, right: ts.Identifier | ts.PrivateIdentifier, checkMode: CheckMode | undefined) { + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined) { const parentSymbol = getNodeLinks(left).resolvedSymbol; - const assignmentKind = ts.getAssignmentTargetKind(node); - const apparentType = getApparentType(assignmentKind !== ts.AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType); + const assignmentKind = getAssignmentTargetKind(node); + const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType); const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType; - let prop: ts.Symbol | undefined; - if (ts.isPrivateIdentifier(right)) { - if (languageVersion < ts.ScriptTarget.ESNext) { - if (assignmentKind !== ts.AssignmentKind.None) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ClassPrivateFieldSet); + let prop: Symbol | undefined; + if (isPrivateIdentifier(right)) { + if (languageVersion < ScriptTarget.ESNext) { + if (assignmentKind !== AssignmentKind.None) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldSet); } - if (assignmentKind !== ts.AssignmentKind.Definite) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ClassPrivateFieldGet); + if (assignmentKind !== AssignmentKind.Definite) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ClassPrivateFieldGet); } } const lexicallyScopedSymbol = lookupSymbolForPrivateIdentifierDeclaration(right.escapedText, right); - if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && ts.isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) { - grammarErrorOnNode(right, ts.Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, ts.idText(right)); + if (assignmentKind && lexicallyScopedSymbol && lexicallyScopedSymbol.valueDeclaration && isMethodDeclaration(lexicallyScopedSymbol.valueDeclaration)) { + grammarErrorOnNode(right, Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, idText(right)); } if (isAnyLike) { if (lexicallyScopedSymbol) { return isErrorType(apparentType) ? errorType : apparentType; } - if (!ts.getContainingClass(right)) { - grammarErrorOnNode(right, ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + if (!getContainingClass(right)) { + grammarErrorOnNode(right, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); return anyType; } } @@ -29578,20 +29776,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return errorType; } else { - const isSetonlyAccessor = prop && prop.flags & ts.SymbolFlags.SetAccessor && !(prop.flags & ts.SymbolFlags.GetAccessor); - if (isSetonlyAccessor && assignmentKind !== ts.AssignmentKind.Definite) { - error(node, ts.Diagnostics.Private_accessor_was_defined_without_a_getter); + const isSetonlyAccessor = prop && prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor); + if (isSetonlyAccessor && assignmentKind !== AssignmentKind.Definite) { + error(node, Diagnostics.Private_accessor_was_defined_without_a_getter); } } } else { if (isAnyLike) { - if (ts.isIdentifier(left) && parentSymbol) { + if (isIdentifier(left) && parentSymbol) { markAliasReferenced(parentSymbol, node); } return isErrorType(apparentType) ? errorType : apparentType; } - prop = getPropertyOfType(apparentType, right.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ node.kind === ts.SyntaxKind.QualifiedName); + prop = getPropertyOfType(apparentType, right.escapedText, /*skipObjectFunctionPropertyAugment*/ false, /*includeTypeOnlyMembers*/ node.kind === SyntaxKind.QualifiedName); } // In `Foo.Bar.Baz`, 'Foo' is not referenced if 'Bar' is a const enum or a module containing only const enums. // `Foo` is also not referenced in `enum FooCopy { Bar = Foo.Bar }`, because the enum member value gets inlined @@ -29600,17 +29798,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The exceptions are: // 1. if 'isolatedModules' is enabled, because the const enum value will not be inlined, and // 2. if 'preserveConstEnums' is enabled and the expression is itself an export, e.g. `export = Foo.Bar.Baz`. - if (ts.isIdentifier(left) && parentSymbol && ( + if (isIdentifier(left) && parentSymbol && ( compilerOptions.isolatedModules || - !(prop && (isConstEnumOrConstEnumOnlyModule(prop) || prop.flags & ts.SymbolFlags.EnumMember && node.parent.kind === ts.SyntaxKind.EnumMember)) || - ts.shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(node) + !(prop && (isConstEnumOrConstEnumOnlyModule(prop) || prop.flags & SymbolFlags.EnumMember && node.parent.kind === SyntaxKind.EnumMember)) || + shouldPreserveConstEnums(compilerOptions) && isExportOrExportExpression(node) )) { markAliasReferenced(parentSymbol, node); } - let propType: ts.Type; + let propType: Type; if (!prop) { - const indexInfo = !ts.isPrivateIdentifier(right) && (assignmentKind === ts.AssignmentKind.None || !isGenericObjectType(leftType) || ts.isThisTypeParameter(leftType)) ? + const indexInfo = !isPrivateIdentifier(right) && (assignmentKind === AssignmentKind.None || !isGenericObjectType(leftType) || isThisTypeParameter(leftType)) ? getApplicableIndexInfoForName(apparentType, right.escapedText) : undefined; if (!(indexInfo && indexInfo.type)) { const isUncheckedJS = isUncheckedJSSuggestion(node, leftType.symbol, /*excludeClasses*/ true); @@ -29618,28 +29816,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return anyType; } if (leftType.symbol === globalThisSymbol) { - if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & ts.SymbolFlags.BlockScoped)) { - error(right, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.unescapeLeadingUnderscores(right.escapedText), typeToString(leftType)); + if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped)) { + error(right, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(right.escapedText), typeToString(leftType)); } else if (noImplicitAny) { - error(right, ts.Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType)); + error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType)); } return anyType; } if (right.escapedText && !checkAndReportErrorForExtendingInterface(node)) { - reportNonexistentProperty(right, ts.isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS); + reportNonexistentProperty(right, isThisTypeParameter(leftType) ? apparentType : leftType, isUncheckedJS); } return errorType; } - if (indexInfo.isReadonly && (ts.isAssignmentTarget(node) || ts.isDeleteTarget(node))) { - error(node, ts.Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); + if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) { + error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - propType = (compilerOptions.noUncheckedIndexedAccess && !ts.isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; - if (compilerOptions.noPropertyAccessFromIndexSignature && ts.isPropertyAccessExpression(node)) { - error(right, ts.Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, ts.unescapeLeadingUnderscores(right.escapedText)); + propType = (compilerOptions.noUncheckedIndexedAccess && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; + if (compilerOptions.noPropertyAccessFromIndexSignature && isPropertyAccessExpression(node)) { + error(right, Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, unescapeLeadingUnderscores(right.escapedText)); } - if (indexInfo.declaration && ts.getCombinedNodeFlags(indexInfo.declaration) & ts.NodeFlags.Deprecated) { + if (indexInfo.declaration && getCombinedNodeFlags(indexInfo.declaration) & NodeFlags.Deprecated) { addDeprecatedSuggestion(right, [indexInfo.declaration], right.escapedText as string); } } @@ -29650,10 +29848,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkPropertyNotUsedBeforeDeclaration(prop, node, right); markPropertyAsReferenced(prop, node, isSelfTypeAccess(left, parentSymbol)); getNodeLinks(node).resolvedSymbol = prop; - const writing = ts.isWriteAccess(node); - checkPropertyAccessibility(node, left.kind === ts.SyntaxKind.SuperKeyword, writing, apparentType, prop); - if (isAssignmentToReadonlyEntity(node as ts.Expression, prop, assignmentKind)) { - error(right, ts.Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, ts.idText(right)); + const writing = isWriteAccess(node); + checkPropertyAccessibility(node, left.kind === SyntaxKind.SuperKeyword, writing, apparentType, prop); + if (isAssignmentToReadonlyEntity(node as Expression, prop, assignmentKind)) { + error(right, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, idText(right)); return errorType; } @@ -29670,30 +29868,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * - Is from a global file that is different from the reference file, or * - (optionally) Is a class, or is a this.x property access expression */ - function isUncheckedJSSuggestion(node: ts.Node | undefined, suggestion: ts.Symbol | undefined, excludeClasses: boolean): boolean { - const file = ts.getSourceFileOfNode(node); + function isUncheckedJSSuggestion(node: Node | undefined, suggestion: Symbol | undefined, excludeClasses: boolean): boolean { + const file = getSourceFileOfNode(node); if (file) { - if (compilerOptions.checkJs === undefined && file.checkJsDirective === undefined && (file.scriptKind === ts.ScriptKind.JS || file.scriptKind === ts.ScriptKind.JSX)) { - const declarationFile = ts.forEach(suggestion?.declarations, ts.getSourceFileOfNode); + if (compilerOptions.checkJs === undefined && file.checkJsDirective === undefined && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX)) { + const declarationFile = forEach(suggestion?.declarations, getSourceFileOfNode); return !(file !== declarationFile && !!declarationFile && isGlobalSourceFile(declarationFile)) - && !(excludeClasses && suggestion && suggestion.flags & ts.SymbolFlags.Class) - && !(!!node && excludeClasses && ts.isPropertyAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword); + && !(excludeClasses && suggestion && suggestion.flags & SymbolFlags.Class) + && !(!!node && excludeClasses && isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword); } } return false; } - function getFlowTypeOfAccessExpression(node: ts.ElementAccessExpression | ts.PropertyAccessExpression | ts.QualifiedName, prop: ts.Symbol | undefined, propType: ts.Type, errorNode: ts.Node, checkMode: CheckMode | undefined) { + function getFlowTypeOfAccessExpression(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol | undefined, propType: Type, errorNode: Node, checkMode: CheckMode | undefined) { // Only compute control flow type if this is a property access expression that isn't an // assignment target, and the referenced property was declared as a variable, property, // accessor, or optional method. - const assignmentKind = ts.getAssignmentTargetKind(node); - if (assignmentKind === ts.AssignmentKind.Definite) { - return removeMissingType(propType, !!(prop && prop.flags & ts.SymbolFlags.Optional)); + const assignmentKind = getAssignmentTargetKind(node); + if (assignmentKind === AssignmentKind.Definite) { + return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional)); } if (prop && - !(prop.flags & (ts.SymbolFlags.Variable | ts.SymbolFlags.Property | ts.SymbolFlags.Accessor)) - && !(prop.flags & ts.SymbolFlags.Method && propType.flags & ts.TypeFlags.Union) + !(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) + && !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union) && !isDuplicatedCommonJSExport(prop.declarations)) { return propType; } @@ -29706,87 +29904,87 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // and if we are in a constructor of the same class as the property declaration, assume that // the property is uninitialized at the top of the control flow. let assumeUninitialized = false; - if (strictNullChecks && strictPropertyInitialization && ts.isAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword) { + if (strictNullChecks && strictPropertyInitialization && isAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword) { const declaration = prop && prop.valueDeclaration; if (declaration && isPropertyWithoutInitializer(declaration)) { - if (!ts.isStatic(declaration)) { + if (!isStatic(declaration)) { const flowContainer = getControlFlowContainer(node); - if (flowContainer.kind === ts.SyntaxKind.Constructor && flowContainer.parent === declaration.parent && !(declaration.flags & ts.NodeFlags.Ambient)) { + if (flowContainer.kind === SyntaxKind.Constructor && flowContainer.parent === declaration.parent && !(declaration.flags & NodeFlags.Ambient)) { assumeUninitialized = true; } } } } else if (strictNullChecks && prop && prop.valueDeclaration && - ts.isPropertyAccessExpression(prop.valueDeclaration) && - ts.getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) && + isPropertyAccessExpression(prop.valueDeclaration) && + getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) && getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration)) { assumeUninitialized = true; } const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); if (assumeUninitialized && !containsUndefinedType(propType) && containsUndefinedType(flowType)) { - error(errorNode, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 + error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 // Return the declared type to reduce follow-on errors return propType; } return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } - function checkPropertyNotUsedBeforeDeclaration(prop: ts.Symbol, node: ts.PropertyAccessExpression | ts.QualifiedName, right: ts.Identifier | ts.PrivateIdentifier): void { + function checkPropertyNotUsedBeforeDeclaration(prop: Symbol, node: PropertyAccessExpression | QualifiedName, right: Identifier | PrivateIdentifier): void { const { valueDeclaration } = prop; - if (!valueDeclaration || ts.getSourceFileOfNode(node).isDeclarationFile) { + if (!valueDeclaration || getSourceFileOfNode(node).isDeclarationFile) { return; } let diagnosticMessage; - const declarationName = ts.idText(right); + const declarationName = idText(right); if (isInPropertyInitializerOrClassStaticBlock(node) && !isOptionalPropertyDeclaration(valueDeclaration) - && !(ts.isAccessExpression(node) && ts.isAccessExpression(node.expression)) + && !(isAccessExpression(node) && isAccessExpression(node.expression)) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) - && !(ts.isMethodDeclaration(valueDeclaration) && ts.getCombinedModifierFlags(valueDeclaration) & ts.ModifierFlags.Static) + && !(isMethodDeclaration(valueDeclaration) && getCombinedModifierFlags(valueDeclaration) & ModifierFlags.Static) && (compilerOptions.useDefineForClassFields || !isPropertyDeclaredInAncestorClass(prop))) { - diagnosticMessage = error(right, ts.Diagnostics.Property_0_is_used_before_its_initialization, declarationName); + diagnosticMessage = error(right, Diagnostics.Property_0_is_used_before_its_initialization, declarationName); } - else if (valueDeclaration.kind === ts.SyntaxKind.ClassDeclaration && - node.parent.kind !== ts.SyntaxKind.TypeReference && - !(valueDeclaration.flags & ts.NodeFlags.Ambient) && + else if (valueDeclaration.kind === SyntaxKind.ClassDeclaration && + node.parent.kind !== SyntaxKind.TypeReference && + !(valueDeclaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)) { - diagnosticMessage = error(right, ts.Diagnostics.Class_0_used_before_its_declaration, declarationName); + diagnosticMessage = error(right, Diagnostics.Class_0_used_before_its_declaration, declarationName); } if (diagnosticMessage) { - ts.addRelatedInfo(diagnosticMessage, - ts.createDiagnosticForNode(valueDeclaration, ts.Diagnostics._0_is_declared_here, declarationName) + addRelatedInfo(diagnosticMessage, + createDiagnosticForNode(valueDeclaration, Diagnostics._0_is_declared_here, declarationName) ); } } - function isInPropertyInitializerOrClassStaticBlock(node: ts.Node): boolean { - return !!ts.findAncestor(node, node => { + function isInPropertyInitializerOrClassStaticBlock(node: Node): boolean { + return !!findAncestor(node, node => { switch (node.kind) { - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyDeclaration: return true; - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.SpreadAssignment: - case ts.SyntaxKind.ComputedPropertyName: - case ts.SyntaxKind.TemplateSpan: - case ts.SyntaxKind.JsxExpression: - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.JsxAttributes: - case ts.SyntaxKind.JsxSpreadAttribute: - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.ExpressionWithTypeArguments: - case ts.SyntaxKind.HeritageClause: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TemplateSpan: + case SyntaxKind.JsxExpression: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxAttributes: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.HeritageClause: return false; - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.ExpressionStatement: - return ts.isBlock(node.parent) && ts.isClassStaticBlockDeclaration(node.parent.parent) ? true : "quit"; + case SyntaxKind.ArrowFunction: + case SyntaxKind.ExpressionStatement: + return isBlock(node.parent) && isClassStaticBlockDeclaration(node.parent.parent) ? true : "quit"; default: - return ts.isExpressionNode(node) ? false : "quit"; + return isExpressionNode(node) ? false : "quit"; } }); } @@ -29795,13 +29993,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass. * In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration. */ - function isPropertyDeclaredInAncestorClass(prop: ts.Symbol): boolean { - if (!(prop.parent!.flags & ts.SymbolFlags.Class)) { + function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean { + if (!(prop.parent!.flags & SymbolFlags.Class)) { return false; } - let classType: ts.InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as ts.InterfaceType; + let classType: InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as InterfaceType; while (true) { - classType = classType.symbol && getSuperClass(classType) as ts.InterfaceType | undefined; + classType = classType.symbol && getSuperClass(classType) as InterfaceType | undefined; if (!classType) { return false; } @@ -29812,7 +30010,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getSuperClass(classType: ts.InterfaceType): ts.Type | undefined { + function getSuperClass(classType: InterfaceType): Type | undefined { const x = getBaseTypes(classType); if (x.length === 0) { return undefined; @@ -29820,172 +30018,172 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getIntersectionType(x); } - function reportNonexistentProperty(propNode: ts.Identifier | ts.PrivateIdentifier, containingType: ts.Type, isUncheckedJS: boolean) { - let errorInfo: ts.DiagnosticMessageChain | undefined; - let relatedInfo: ts.Diagnostic | undefined; - if (!ts.isPrivateIdentifier(propNode) && containingType.flags & ts.TypeFlags.Union && !(containingType.flags & ts.TypeFlags.Primitive)) { - for (const subtype of (containingType as ts.UnionType).types) { + function reportNonexistentProperty(propNode: Identifier | PrivateIdentifier, containingType: Type, isUncheckedJS: boolean) { + let errorInfo: DiagnosticMessageChain | undefined; + let relatedInfo: Diagnostic | undefined; + if (!isPrivateIdentifier(propNode) && containingType.flags & TypeFlags.Union && !(containingType.flags & TypeFlags.Primitive)) { + for (const subtype of (containingType as UnionType).types) { if (!getPropertyOfType(subtype, propNode.escapedText) && !getApplicableIndexInfoForName(subtype, propNode.escapedText)) { - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(subtype)); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(subtype)); break; } } } if (typeHasStaticProperty(propNode.escapedText, containingType)) { - const propName = ts.declarationNameToString(propNode); + const propName = declarationNameToString(propNode); const typeName = typeToString(containingType); - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName, typeName, typeName + "." + propName); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName, typeName, typeName + "." + propName); } else { const promisedType = getPromisedTypeOfPromise(containingType); if (promisedType && getPropertyOfType(promisedType, propNode.escapedText)) { - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1, ts.declarationNameToString(propNode), typeToString(containingType)); - relatedInfo = ts.createDiagnosticForNode(propNode, ts.Diagnostics.Did_you_forget_to_use_await); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(propNode), typeToString(containingType)); + relatedInfo = createDiagnosticForNode(propNode, Diagnostics.Did_you_forget_to_use_await); } else { - const missingProperty = ts.declarationNameToString(propNode); + const missingProperty = declarationNameToString(propNode); const container = typeToString(containingType); const libSuggestion = getSuggestedLibForNonExistentProperty(missingProperty, containingType); if (libSuggestion !== undefined) { - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Property_0_does_not_exist_on_type_1_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2_or_later, missingProperty, container, libSuggestion); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Property_0_does_not_exist_on_type_1_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_2_or_later, missingProperty, container, libSuggestion); } else { const suggestion = getSuggestedSymbolForNonexistentProperty(propNode, containingType); if (suggestion !== undefined) { - const suggestedName = ts.symbolName(suggestion); - const message = isUncheckedJS ? ts.Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2 : ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2; - errorInfo = ts.chainDiagnosticMessages(errorInfo, message, missingProperty, container, suggestedName); - relatedInfo = suggestion.valueDeclaration && ts.createDiagnosticForNode(suggestion.valueDeclaration, ts.Diagnostics._0_is_declared_here, suggestedName); + const suggestedName = symbolName(suggestion); + const message = isUncheckedJS ? Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2 : Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2; + errorInfo = chainDiagnosticMessages(errorInfo, message, missingProperty, container, suggestedName); + relatedInfo = suggestion.valueDeclaration && createDiagnosticForNode(suggestion.valueDeclaration, Diagnostics._0_is_declared_here, suggestedName); } else { const diagnostic = containerSeemsToBeEmptyDomElement(containingType) - ? ts.Diagnostics.Property_0_does_not_exist_on_type_1_Try_changing_the_lib_compiler_option_to_include_dom - : ts.Diagnostics.Property_0_does_not_exist_on_type_1; - errorInfo = ts.chainDiagnosticMessages(elaborateNeverIntersection(errorInfo, containingType), diagnostic, missingProperty, container); + ? Diagnostics.Property_0_does_not_exist_on_type_1_Try_changing_the_lib_compiler_option_to_include_dom + : Diagnostics.Property_0_does_not_exist_on_type_1; + errorInfo = chainDiagnosticMessages(elaborateNeverIntersection(errorInfo, containingType), diagnostic, missingProperty, container); } } } } - const resultDiagnostic = ts.createDiagnosticForNodeFromMessageChain(propNode, errorInfo); + const resultDiagnostic = createDiagnosticForNodeFromMessageChain(propNode, errorInfo); if (relatedInfo) { - ts.addRelatedInfo(resultDiagnostic, relatedInfo); + addRelatedInfo(resultDiagnostic, relatedInfo); } - addErrorOrSuggestion(!isUncheckedJS || errorInfo.code !== ts.Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, resultDiagnostic); + addErrorOrSuggestion(!isUncheckedJS || errorInfo.code !== Diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2.code, resultDiagnostic); } - function containerSeemsToBeEmptyDomElement(containingType: ts.Type) { + function containerSeemsToBeEmptyDomElement(containingType: Type) { return (compilerOptions.lib && !compilerOptions.lib.includes("dom")) && - everyContainedType(containingType, type => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(ts.unescapeLeadingUnderscores(type.symbol.escapedName))) && + everyContainedType(containingType, type => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) && isEmptyObjectType(containingType); } - function typeHasStaticProperty(propName: ts.__String, containingType: ts.Type): boolean { + function typeHasStaticProperty(propName: __String, containingType: Type): boolean { const prop = containingType.symbol && getPropertyOfType(getTypeOfSymbol(containingType.symbol), propName); - return prop !== undefined && !!prop.valueDeclaration && ts.isStatic(prop.valueDeclaration); + return prop !== undefined && !!prop.valueDeclaration && isStatic(prop.valueDeclaration); } - function getSuggestedLibForNonExistentName(name: ts.__String | ts.Identifier) { + function getSuggestedLibForNonExistentName(name: __String | Identifier) { const missingName = diagnosticName(name); - const allFeatures = ts.getScriptTargetFeatures(); - const libTargets = ts.getOwnKeys(allFeatures); + const allFeatures = getScriptTargetFeatures(); + const libTargets = getOwnKeys(allFeatures); for (const libTarget of libTargets) { - const containingTypes = ts.getOwnKeys(allFeatures[libTarget]); - if (containingTypes !== undefined && ts.contains(containingTypes, missingName)) { + const containingTypes = getOwnKeys(allFeatures[libTarget]); + if (containingTypes !== undefined && contains(containingTypes, missingName)) { return libTarget; } } } - function getSuggestedLibForNonExistentProperty(missingProperty: string, containingType: ts.Type) { + function getSuggestedLibForNonExistentProperty(missingProperty: string, containingType: Type) { const container = getApparentType(containingType).symbol; if (!container) { return undefined; } - const allFeatures = ts.getScriptTargetFeatures(); - const libTargets = ts.getOwnKeys(allFeatures); + const allFeatures = getScriptTargetFeatures(); + const libTargets = getOwnKeys(allFeatures); for (const libTarget of libTargets) { const featuresOfLib = allFeatures[libTarget]; - const featuresOfContainingType = featuresOfLib[ts.symbolName(container)]; - if (featuresOfContainingType !== undefined && ts.contains(featuresOfContainingType, missingProperty)) { + const featuresOfContainingType = featuresOfLib[symbolName(container)]; + if (featuresOfContainingType !== undefined && contains(featuresOfContainingType, missingProperty)) { return libTarget; } } } - function getSuggestedSymbolForNonexistentClassMember(name: string, baseType: ts.Type): ts.Symbol | undefined { - return getSpellingSuggestionForName(name, getPropertiesOfType(baseType), ts.SymbolFlags.ClassMember); + function getSuggestedSymbolForNonexistentClassMember(name: string, baseType: Type): Symbol | undefined { + return getSpellingSuggestionForName(name, getPropertiesOfType(baseType), SymbolFlags.ClassMember); } - function getSuggestedSymbolForNonexistentProperty(name: ts.Identifier | ts.PrivateIdentifier | string, containingType: ts.Type): ts.Symbol | undefined { + function getSuggestedSymbolForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined { let props = getPropertiesOfType(containingType); if (typeof name !== "string") { const parent = name.parent; - if (ts.isPropertyAccessExpression(parent)) { - props = ts.filter(props, prop => isValidPropertyAccessForCompletions(parent, containingType, prop)); + if (isPropertyAccessExpression(parent)) { + props = filter(props, prop => isValidPropertyAccessForCompletions(parent, containingType, prop)); } - name = ts.idText(name); + name = idText(name); } - return getSpellingSuggestionForName(name, props, ts.SymbolFlags.Value); + return getSpellingSuggestionForName(name, props, SymbolFlags.Value); } - function getSuggestedSymbolForNonexistentJSXAttribute(name: ts.Identifier | ts.PrivateIdentifier | string, containingType: ts.Type): ts.Symbol | undefined { - const strName = ts.isString(name) ? name : ts.idText(name); + function getSuggestedSymbolForNonexistentJSXAttribute(name: Identifier | PrivateIdentifier | string, containingType: Type): Symbol | undefined { + const strName = isString(name) ? name : idText(name); const properties = getPropertiesOfType(containingType); - const jsxSpecific = strName === "for" ? ts.find(properties, x => ts.symbolName(x) === "htmlFor") - : strName === "class" ? ts.find(properties, x => ts.symbolName(x) === "className") + const jsxSpecific = strName === "for" ? find(properties, x => symbolName(x) === "htmlFor") + : strName === "class" ? find(properties, x => symbolName(x) === "className") : undefined; - return jsxSpecific ?? getSpellingSuggestionForName(strName, properties, ts.SymbolFlags.Value); + return jsxSpecific ?? getSpellingSuggestionForName(strName, properties, SymbolFlags.Value); } - function getSuggestionForNonexistentProperty(name: ts.Identifier | ts.PrivateIdentifier | string, containingType: ts.Type): string | undefined { + function getSuggestionForNonexistentProperty(name: Identifier | PrivateIdentifier | string, containingType: Type): string | undefined { const suggestion = getSuggestedSymbolForNonexistentProperty(name, containingType); - return suggestion && ts.symbolName(suggestion); + return suggestion && symbolName(suggestion); } - function getSuggestedSymbolForNonexistentSymbol(location: ts.Node | undefined, outerName: ts.__String, meaning: ts.SymbolFlags): ts.Symbol | undefined { - ts.Debug.assert(outerName !== undefined, "outername should always be defined"); + function getSuggestedSymbolForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined { + Debug.assert(outerName !== undefined, "outername should always be defined"); const result = resolveNameHelper(location, outerName, meaning, /*nameNotFoundMessage*/ undefined, outerName, /*isUse*/ false, /*excludeGlobals*/ false, /*getSpellingSuggestions*/ true, (symbols, name, meaning) => { - ts.Debug.assertEqual(outerName, name, "name should equal outerName"); + Debug.assertEqual(outerName, name, "name should equal outerName"); const symbol = getSymbol(symbols, name, meaning); // Sometimes the symbol is found when location is a return type of a function: `typeof x` and `x` is declared in the body of the function // So the table *contains* `x` but `x` isn't actually in scope. // However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion. if (symbol) return symbol; - let candidates: ts.Symbol[]; + let candidates: Symbol[]; if (symbols === globals) { - const primitives = ts.mapDefined( + const primitives = mapDefined( ["string", "number", "boolean", "object", "bigint", "symbol"], - s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as ts.__String) - ? createSymbol(ts.SymbolFlags.TypeAlias, s as ts.__String) as ts.Symbol + s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String) + ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol : undefined); - candidates = primitives.concat(ts.arrayFrom(symbols.values())); + candidates = primitives.concat(arrayFrom(symbols.values())); } else { - candidates = ts.arrayFrom(symbols.values()); + candidates = arrayFrom(symbols.values()); } - return getSpellingSuggestionForName(ts.unescapeLeadingUnderscores(name), candidates, meaning); + return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning); }); return result; } - function getSuggestionForNonexistentSymbol(location: ts.Node | undefined, outerName: ts.__String, meaning: ts.SymbolFlags): string | undefined { + function getSuggestionForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): string | undefined { const symbolResult = getSuggestedSymbolForNonexistentSymbol(location, outerName, meaning); - return symbolResult && ts.symbolName(symbolResult); + return symbolResult && symbolName(symbolResult); } - function getSuggestedSymbolForNonexistentModule(name: ts.Identifier, targetModule: ts.Symbol): ts.Symbol | undefined { - return targetModule.exports && getSpellingSuggestionForName(ts.idText(name), getExportsOfModuleAsArray(targetModule), ts.SymbolFlags.ModuleMember); + function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined { + return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule), SymbolFlags.ModuleMember); } - function getSuggestionForNonexistentExport(name: ts.Identifier, targetModule: ts.Symbol): string | undefined { + function getSuggestionForNonexistentExport(name: Identifier, targetModule: Symbol): string | undefined { const suggestion = getSuggestedSymbolForNonexistentModule(name, targetModule); - return suggestion && ts.symbolName(suggestion); + return suggestion && symbolName(suggestion); } - function getSuggestionForNonexistentIndexSignature(objectType: ts.Type, expr: ts.ElementAccessExpression, keyedType: ts.Type): string | undefined { + function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression, keyedType: Type): string | undefined { // check if object type has setter or getter function hasProp(name: "set" | "get") { - const prop = getPropertyOfObjectType(objectType, name as ts.__String); + const prop = getPropertyOfObjectType(objectType, name as __String); if (prop) { const s = getSingleCallSignature(getTypeOfSymbol(prop)); return !!s && getMinArgumentCount(s) >= 1 && isTypeAssignableTo(keyedType, getTypeAtPosition(s, 0)); @@ -29993,12 +30191,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - const suggestedMethod = ts.isAssignmentTarget(expr) ? "set" : "get"; + const suggestedMethod = isAssignmentTarget(expr) ? "set" : "get"; if (!hasProp(suggestedMethod)) { return undefined; } - let suggestion = ts.tryGetPropertyAccessOrIdentifierToString(expr.expression); + let suggestion = tryGetPropertyAccessOrIdentifierToString(expr.expression); if (suggestion === undefined) { suggestion = suggestedMethod; } @@ -30009,9 +30207,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return suggestion; } - function getSuggestedTypeForNonexistentStringLiteralType(source: ts.StringLiteralType, target: ts.UnionType): ts.StringLiteralType | undefined { - const candidates = target.types.filter((type): type is ts.StringLiteralType => !!(type.flags & ts.TypeFlags.StringLiteral)); - return ts.getSpellingSuggestion(source.value, candidates, type => type.value); + function getSuggestedTypeForNonexistentStringLiteralType(source: StringLiteralType, target: UnionType): StringLiteralType | undefined { + const candidates = target.types.filter((type): type is StringLiteralType => !!(type.flags & TypeFlags.StringLiteral)); + return getSpellingSuggestion(source.value, candidates, type => type.value); } /** @@ -30029,12 +30227,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * (0.4 allows 1 substitution/transposition for every 5 characters, * and 1 insertion/deletion at 3 characters) */ - function getSpellingSuggestionForName(name: string, symbols: ts.Symbol[], meaning: ts.SymbolFlags): ts.Symbol | undefined { - return ts.getSpellingSuggestion(name, symbols, getCandidateName); + function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags): Symbol | undefined { + return getSpellingSuggestion(name, symbols, getCandidateName); - function getCandidateName(candidate: ts.Symbol) { - const candidateName = ts.symbolName(candidate); - if (ts.startsWith(candidateName, "\"")) { + function getCandidateName(candidate: Symbol) { + const candidateName = symbolName(candidate); + if (startsWith(candidateName, "\"")) { return undefined; } @@ -30042,7 +30240,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return candidateName; } - if (candidate.flags & ts.SymbolFlags.Alias) { + if (candidate.flags & SymbolFlags.Alias) { const alias = tryResolveAlias(candidate); if (alias && alias.flags & meaning) { return candidateName; @@ -30053,42 +30251,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function markPropertyAsReferenced(prop: ts.Symbol, nodeForCheckWriteOnly: ts.Node | undefined, isSelfTypeAccess: boolean) { - const valueDeclaration = prop && (prop.flags & ts.SymbolFlags.ClassMember) && prop.valueDeclaration; + function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isSelfTypeAccess: boolean) { + const valueDeclaration = prop && (prop.flags & SymbolFlags.ClassMember) && prop.valueDeclaration; if (!valueDeclaration) { return; } - const hasPrivateModifier = ts.hasEffectiveModifier(valueDeclaration, ts.ModifierFlags.Private); - const hasPrivateIdentifier = prop.valueDeclaration && ts.isNamedDeclaration(prop.valueDeclaration) && ts.isPrivateIdentifier(prop.valueDeclaration.name); + const hasPrivateModifier = hasEffectiveModifier(valueDeclaration, ModifierFlags.Private); + const hasPrivateIdentifier = prop.valueDeclaration && isNamedDeclaration(prop.valueDeclaration) && isPrivateIdentifier(prop.valueDeclaration.name); if (!hasPrivateModifier && !hasPrivateIdentifier) { return; } - if (nodeForCheckWriteOnly && ts.isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & ts.SymbolFlags.SetAccessor)) { + if (nodeForCheckWriteOnly && isWriteOnlyAccess(nodeForCheckWriteOnly) && !(prop.flags & SymbolFlags.SetAccessor)) { return; } if (isSelfTypeAccess) { // Find any FunctionLikeDeclaration because those create a new 'this' binding. But this should only matter for methods (or getters/setters). - const containingMethod = ts.findAncestor(nodeForCheckWriteOnly, ts.isFunctionLikeDeclaration); + const containingMethod = findAncestor(nodeForCheckWriteOnly, isFunctionLikeDeclaration); if (containingMethod && containingMethod.symbol === prop) { return; } } - (ts.getCheckFlags(prop) & ts.CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = ts.SymbolFlags.All; + (getCheckFlags(prop) & CheckFlags.Instantiated ? getSymbolLinks(prop).target : prop)!.isReferenced = SymbolFlags.All; } - function isSelfTypeAccess(name: ts.Expression | ts.QualifiedName, parent: ts.Symbol | undefined) { - return name.kind === ts.SyntaxKind.ThisKeyword - || !!parent && ts.isEntityNameExpression(name) && parent === getResolvedSymbol(ts.getFirstIdentifier(name)); + function isSelfTypeAccess(name: Expression | QualifiedName, parent: Symbol | undefined) { + return name.kind === SyntaxKind.ThisKeyword + || !!parent && isEntityNameExpression(name) && parent === getResolvedSymbol(getFirstIdentifier(name)); } - function isValidPropertyAccess(node: ts.PropertyAccessExpression | ts.QualifiedName | ts.ImportTypeNode, propertyName: ts.__String): boolean { + function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName | ImportTypeNode, propertyName: __String): boolean { switch (node.kind) { - case ts.SyntaxKind.PropertyAccessExpression: - return isValidPropertyAccessWithType(node, node.expression.kind === ts.SyntaxKind.SuperKeyword, propertyName, getWidenedType(checkExpression(node.expression))); - case ts.SyntaxKind.QualifiedName: + case SyntaxKind.PropertyAccessExpression: + return isValidPropertyAccessWithType(node, node.expression.kind === SyntaxKind.SuperKeyword, propertyName, getWidenedType(checkExpression(node.expression))); + case SyntaxKind.QualifiedName: return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getWidenedType(checkExpression(node.left))); - case ts.SyntaxKind.ImportType: + case SyntaxKind.ImportType: return isValidPropertyAccessWithType(node, /*isSuper*/ false, propertyName, getTypeFromTypeNode(node)); } } @@ -30103,9 +30301,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param type the type whose property we are checking. * @param property the accessed property's symbol. */ - function isValidPropertyAccessForCompletions(node: ts.PropertyAccessExpression | ts.ImportTypeNode | ts.QualifiedName, type: ts.Type, property: ts.Symbol): boolean { + function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean { return isPropertyAccessible(node, - node.kind === ts.SyntaxKind.PropertyAccessExpression && node.expression.kind === ts.SyntaxKind.SuperKeyword, + node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, /* isWrite */ false, type, property); @@ -30113,10 +30311,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function isValidPropertyAccessWithType( - node: ts.PropertyAccessExpression | ts.QualifiedName | ts.ImportTypeNode, + node: PropertyAccessExpression | QualifiedName | ImportTypeNode, isSuper: boolean, - propertyName: ts.__String, - type: ts.Type): boolean { + propertyName: __String, + type: Type): boolean { // Short-circuiting for improved performance. if (isTypeAny(type)) { @@ -30138,11 +30336,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param property property symbol. */ function isPropertyAccessible( - node: ts.Node, + node: Node, isSuper: boolean, isWrite: boolean, - containingType: ts.Type, - property: ts.Symbol): boolean { + containingType: Type, + property: Symbol): boolean { // Short-circuiting for improved performance. if (isTypeAny(containingType)) { @@ -30151,9 +30349,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // A #private property access in an optional chain is an error dealt with by the parser. // The checker does not check for it, so we need to do our own check here. - if (property.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(property.valueDeclaration)) { - const declClass = ts.getContainingClass(property.valueDeclaration); - return !ts.isOptionalChain(node) && !!ts.findAncestor(node, parent => parent === declClass); + if (property.valueDeclaration && isPrivateIdentifierClassElementDeclaration(property.valueDeclaration)) { + const declClass = getContainingClass(property.valueDeclaration); + return !isOptionalChain(node) && !!findAncestor(node, parent => parent === declClass); } return checkPropertyAccessibilityAtLocation(node, isSuper, isWrite, containingType, property); @@ -30162,16 +30360,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Return the symbol of the for-in variable declared or referenced by the given for-in statement. */ - function getForInVariableSymbol(node: ts.ForInStatement): ts.Symbol | undefined { + function getForInVariableSymbol(node: ForInStatement): Symbol | undefined { const initializer = node.initializer; - if (initializer.kind === ts.SyntaxKind.VariableDeclarationList) { - const variable = (initializer as ts.VariableDeclarationList).declarations[0]; - if (variable && !ts.isBindingPattern(variable.name)) { + if (initializer.kind === SyntaxKind.VariableDeclarationList) { + const variable = (initializer as VariableDeclarationList).declarations[0]; + if (variable && !isBindingPattern(variable.name)) { return getSymbolOfNode(variable); } } - else if (initializer.kind === ts.SyntaxKind.Identifier) { - return getResolvedSymbol(initializer as ts.Identifier); + else if (initializer.kind === SyntaxKind.Identifier) { + return getResolvedSymbol(initializer as Identifier); } return undefined; } @@ -30179,7 +30377,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Return true if the given type is considered to have numeric property names. */ - function hasNumericPropertyNames(type: ts.Type) { + function hasNumericPropertyNames(type: Type) { return getIndexInfosOfType(type).length === 1 && !!getIndexInfoOfType(type, numberType); } @@ -30187,18 +30385,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Return true if given node is an expression consisting of an identifier (possibly parenthesized) * that references a for-in variable for an object with numeric property names. */ - function isForInVariableForNumericPropertyNames(expr: ts.Expression) { - const e = ts.skipParentheses(expr); - if (e.kind === ts.SyntaxKind.Identifier) { - const symbol = getResolvedSymbol(e as ts.Identifier); - if (symbol.flags & ts.SymbolFlags.Variable) { - let child: ts.Node = expr; + function isForInVariableForNumericPropertyNames(expr: Expression) { + const e = skipParentheses(expr); + if (e.kind === SyntaxKind.Identifier) { + const symbol = getResolvedSymbol(e as Identifier); + if (symbol.flags & SymbolFlags.Variable) { + let child: Node = expr; let node = expr.parent; while (node) { - if (node.kind === ts.SyntaxKind.ForInStatement && - child === (node as ts.ForInStatement).statement && - getForInVariableSymbol(node as ts.ForInStatement) === symbol && - hasNumericPropertyNames(getTypeOfExpression((node as ts.ForInStatement).expression))) { + if (node.kind === SyntaxKind.ForInStatement && + child === (node as ForInStatement).statement && + getForInVariableSymbol(node as ForInStatement) === symbol && + hasNumericPropertyNames(getTypeOfExpression((node as ForInStatement).expression))) { return true; } child = node; @@ -30209,19 +30407,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkIndexedAccess(node: ts.ElementAccessExpression, checkMode: CheckMode | undefined): ts.Type { - return node.flags & ts.NodeFlags.OptionalChain ? checkElementAccessChain(node as ts.ElementAccessChain, checkMode) : + function checkIndexedAccess(node: ElementAccessExpression, checkMode: CheckMode | undefined): Type { + return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) : checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode); } - function checkElementAccessChain(node: ts.ElementAccessChain, checkMode: CheckMode | undefined) { + function checkElementAccessChain(node: ElementAccessChain, checkMode: CheckMode | undefined) { const exprType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(exprType, node.expression); return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), node, nonOptionalType !== exprType); } - function checkElementAccessExpression(node: ts.ElementAccessExpression, exprType: ts.Type, checkMode: CheckMode | undefined): ts.Type { - const objectType = ts.getAssignmentTargetKind(node) !== ts.AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(exprType) : exprType; + function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type, checkMode: CheckMode | undefined): Type { + const objectType = getAssignmentTargetKind(node) !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(exprType) : exprType; const indexExpression = node.argumentExpression; const indexType = checkExpression(indexExpression); @@ -30229,45 +30427,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return objectType; } - if (isConstEnumObjectType(objectType) && !ts.isStringLiteralLike(indexExpression)) { - error(indexExpression, ts.Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal); + if (isConstEnumObjectType(objectType) && !isStringLiteralLike(indexExpression)) { + error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal); return errorType; } const effectiveIndexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType; - const accessFlags = ts.isAssignmentTarget(node) ? - ts.AccessFlags.Writing | (isGenericObjectType(objectType) && !ts.isThisTypeParameter(objectType) ? ts.AccessFlags.NoIndexSignatures : 0) : - ts.AccessFlags.ExpressionPosition; + const accessFlags = isAssignmentTarget(node) ? + AccessFlags.Writing | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures : 0) : + AccessFlags.ExpressionPosition; const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, accessFlags, node) || errorType; return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, getNodeLinks(node).resolvedSymbol, indexedAccessType, indexExpression, checkMode), node); } - function callLikeExpressionMayHaveTypeArguments(node: ts.CallLikeExpression): node is ts.CallExpression | ts.NewExpression | ts.TaggedTemplateExpression | ts.JsxOpeningElement { - return ts.isCallOrNewExpression(node) || ts.isTaggedTemplateExpression(node) || ts.isJsxOpeningLikeElement(node); + function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement { + return isCallOrNewExpression(node) || isTaggedTemplateExpression(node) || isJsxOpeningLikeElement(node); } - function resolveUntypedCall(node: ts.CallLikeExpression): ts.Signature { + function resolveUntypedCall(node: CallLikeExpression): Signature { if (callLikeExpressionMayHaveTypeArguments(node)) { // Check type arguments even though we will give an error that untyped calls may not accept type arguments. // This gets us diagnostics for the type arguments and marks them as referenced. - ts.forEach(node.typeArguments, checkSourceElement); + forEach(node.typeArguments, checkSourceElement); } - if (node.kind === ts.SyntaxKind.TaggedTemplateExpression) { + if (node.kind === SyntaxKind.TaggedTemplateExpression) { checkExpression(node.template); } - else if (ts.isJsxOpeningLikeElement(node)) { + else if (isJsxOpeningLikeElement(node)) { checkExpression(node.attributes); } - else if (node.kind !== ts.SyntaxKind.Decorator) { - ts.forEach((node as ts.CallExpression).arguments, argument => { + else if (node.kind !== SyntaxKind.Decorator) { + forEach((node as CallExpression).arguments, argument => { checkExpression(argument); }); } return anySignature; } - function resolveErrorCall(node: ts.CallLikeExpression): ts.Signature { + function resolveErrorCall(node: CallLikeExpression): Signature { resolveUntypedCall(node); return unknownSignature; } @@ -30280,14 +30478,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // interface B extends A { (x: 'foo'): string } // const b: B; // b('foo') // <- here overloads should be processed as [(x:'foo'): string, (x: string): void] - function reorderCandidates(signatures: readonly ts.Signature[], result: ts.Signature[], callChainFlags: ts.SignatureFlags): void { - let lastParent: ts.Node | undefined; - let lastSymbol: ts.Symbol | undefined; + function reorderCandidates(signatures: readonly Signature[], result: Signature[], callChainFlags: SignatureFlags): void { + let lastParent: Node | undefined; + let lastSymbol: Symbol | undefined; let cutoffIndex = 0; let index: number | undefined; let specializedIndex = -1; let spliceIndex: number; - ts.Debug.assert(!result.length); + Debug.assert(!result.length); for (const signature of signatures) { const symbol = signature.declaration && getSymbolOfNode(signature.declaration); const parent = signature.declaration && signature.declaration.parent; @@ -30326,49 +30524,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isSpreadArgument(arg: ts.Expression | undefined): arg is ts.Expression { - return !!arg && (arg.kind === ts.SyntaxKind.SpreadElement || arg.kind === ts.SyntaxKind.SyntheticExpression && (arg as ts.SyntheticExpression).isSpread); + function isSpreadArgument(arg: Expression | undefined): arg is Expression { + return !!arg && (arg.kind === SyntaxKind.SpreadElement || arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).isSpread); } - function getSpreadArgumentIndex(args: readonly ts.Expression[]): number { - return ts.findIndex(args, isSpreadArgument); + function getSpreadArgumentIndex(args: readonly Expression[]): number { + return findIndex(args, isSpreadArgument); } - function acceptsVoid(t: ts.Type): boolean { - return !!(t.flags & ts.TypeFlags.Void); + function acceptsVoid(t: Type): boolean { + return !!(t.flags & TypeFlags.Void); } - function acceptsVoidUndefinedUnknownOrAny(t: ts.Type): boolean { - return !!(t.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Unknown | ts.TypeFlags.Any)); + function acceptsVoidUndefinedUnknownOrAny(t: Type): boolean { + return !!(t.flags & (TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Unknown | TypeFlags.Any)); } - function hasCorrectArity(node: ts.CallLikeExpression, args: readonly ts.Expression[], signature: ts.Signature, signatureHelpTrailingComma = false) { + function hasCorrectArity(node: CallLikeExpression, args: readonly Expression[], signature: Signature, signatureHelpTrailingComma = false) { let argCount: number; let callIsIncomplete = false; // In incomplete call we want to be lenient when we have too few arguments let effectiveParameterCount = getParameterCount(signature); let effectiveMinimumArguments = getMinArgumentCount(signature); - if (node.kind === ts.SyntaxKind.TaggedTemplateExpression) { + if (node.kind === SyntaxKind.TaggedTemplateExpression) { argCount = args.length; - if (node.template.kind === ts.SyntaxKind.TemplateExpression) { + if (node.template.kind === SyntaxKind.TemplateExpression) { // If a tagged template expression lacks a tail literal, the call is incomplete. // Specifically, a template only can end in a TemplateTail or a Missing literal. - const lastSpan = ts.last(node.template.templateSpans); // we should always have at least one span. - callIsIncomplete = ts.nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated; + const lastSpan = last(node.template.templateSpans); // we should always have at least one span. + callIsIncomplete = nodeIsMissing(lastSpan.literal) || !!lastSpan.literal.isUnterminated; } else { // If the template didn't end in a backtick, or its beginning occurred right prior to EOF, // then this might actually turn out to be a TemplateHead in the future; // so we consider the call to be incomplete. - const templateLiteral = node.template as ts.LiteralExpression; - ts.Debug.assert(templateLiteral.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral); + const templateLiteral = node.template as LiteralExpression; + Debug.assert(templateLiteral.kind === SyntaxKind.NoSubstitutionTemplateLiteral); callIsIncomplete = !!templateLiteral.isUnterminated; } } - else if (node.kind === ts.SyntaxKind.Decorator) { + else if (node.kind === SyntaxKind.Decorator) { argCount = getDecoratorArgumentCount(node, signature); } - else if (ts.isJsxOpeningLikeElement(node)) { + else if (isJsxOpeningLikeElement(node)) { callIsIncomplete = node.attributes.end === node.end; if (callIsIncomplete) { return true; @@ -30379,7 +30577,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else if (!node.arguments) { // This only happens when we have something of the form: 'new C' - ts.Debug.assert(node.kind === ts.SyntaxKind.NewExpression); + Debug.assert(node.kind === SyntaxKind.NewExpression); return getMinArgumentCount(signature) === 0; } else { @@ -30407,40 +30605,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } for (let i = argCount; i < effectiveMinimumArguments; i++) { const type = getTypeAtPosition(signature, i); - if (filterType(type, ts.isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & ts.TypeFlags.Never) { + if (filterType(type, isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & TypeFlags.Never) { return false; } } return true; } - function hasCorrectTypeArgumentArity(signature: ts.Signature, typeArguments: ts.NodeArray | undefined) { + function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray | undefined) { // If the user supplied type arguments, but the number of type arguments does not match // the declared number of type parameters, the call has an incorrect arity. - const numTypeParameters = ts.length(signature.typeParameters); + const numTypeParameters = length(signature.typeParameters); const minTypeArgumentCount = getMinTypeArgumentCount(signature.typeParameters); - return !ts.some(typeArguments) || + return !some(typeArguments) || (typeArguments.length >= minTypeArgumentCount && typeArguments.length <= numTypeParameters); } // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. - function getSingleCallSignature(type: ts.Type): ts.Signature | undefined { - return getSingleSignature(type, ts.SignatureKind.Call, /*allowMembers*/ false); + function getSingleCallSignature(type: Type): Signature | undefined { + return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false); } - function getSingleCallOrConstructSignature(type: ts.Type): ts.Signature | undefined { - return getSingleSignature(type, ts.SignatureKind.Call, /*allowMembers*/ false) || - getSingleSignature(type, ts.SignatureKind.Construct, /*allowMembers*/ false); + function getSingleCallOrConstructSignature(type: Type): Signature | undefined { + return getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ false) || + getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ false); } - function getSingleSignature(type: ts.Type, kind: ts.SignatureKind, allowMembers: boolean): ts.Signature | undefined { - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function getSingleSignature(type: Type, kind: SignatureKind, allowMembers: boolean): Signature | undefined { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); if (allowMembers || resolved.properties.length === 0 && resolved.indexInfos.length === 0) { - if (kind === ts.SignatureKind.Call && resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0) { + if (kind === SignatureKind.Call && resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0) { return resolved.callSignatures[0]; } - if (kind === ts.SignatureKind.Construct && resolved.constructSignatures.length === 1 && resolved.callSignatures.length === 0) { + if (kind === SignatureKind.Construct && resolved.constructSignatures.length === 1 && resolved.callSignatures.length === 0) { return resolved.constructSignatures[0]; } } @@ -30449,13 +30647,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) - function instantiateSignatureInContextOf(signature: ts.Signature, contextualSignature: ts.Signature, inferenceContext?: ts.InferenceContext, compareTypes?: ts.TypeComparer): ts.Signature { - const context = createInferenceContext(signature.typeParameters!, signature, ts.InferenceFlags.None, compareTypes); + function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, inferenceContext?: InferenceContext, compareTypes?: TypeComparer): Signature { + const context = createInferenceContext(signature.typeParameters!, signature, InferenceFlags.None, compareTypes); // We clone the inferenceContext to avoid fixing. For example, when the source signature is (x: T) => T[] and // the contextual signature is (...args: A) => B, we want to infer the element type of A's constraint (say 'any') // for T but leave it possible to later infer '[any]' back to A. const restType = getEffectiveRestType(contextualSignature); - const mapper = inferenceContext && (restType && restType.flags & ts.TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper); + const mapper = inferenceContext && (restType && restType.flags & TypeFlags.TypeParameter ? inferenceContext.nonFixingMapper : inferenceContext.mapper); const sourceSignature = mapper ? instantiateSignature(contextualSignature, mapper) : contextualSignature; applyToParameterTypes(sourceSignature, signature, (source, target) => { // Type parameters from outer context referenced by source type are fixed by instantiation of the source type @@ -30463,31 +30661,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); if (!inferenceContext) { applyToReturnTypes(contextualSignature, signature, (source, target) => { - inferTypes(context.inferences, source, target, ts.InferencePriority.ReturnType); + inferTypes(context.inferences, source, target, InferencePriority.ReturnType); }); } - return getSignatureInstantiation(signature, getInferredTypes(context), ts.isInJSFile(contextualSignature.declaration)); + return getSignatureInstantiation(signature, getInferredTypes(context), isInJSFile(contextualSignature.declaration)); } - function inferJsxTypeArguments(node: ts.JsxOpeningLikeElement, signature: ts.Signature, checkMode: CheckMode, context: ts.InferenceContext): ts.Type[] { + function inferJsxTypeArguments(node: JsxOpeningLikeElement, signature: Signature, checkMode: CheckMode, context: InferenceContext): Type[] { const paramType = getEffectiveFirstArgumentForJsxSignature(signature, node); const checkAttrType = checkExpressionWithContextualType(node.attributes, paramType, context, checkMode); inferTypes(context.inferences, checkAttrType, paramType); return getInferredTypes(context); } - function getThisArgumentType(thisArgumentNode: ts.LeftHandSideExpression | undefined) { + function getThisArgumentType(thisArgumentNode: LeftHandSideExpression | undefined) { if (!thisArgumentNode) { return voidType; } const thisArgumentType = checkExpression(thisArgumentNode); - return ts.isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) : - ts.isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) : + return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) : + isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) : thisArgumentType; } - function inferTypeArguments(node: ts.CallLikeExpression, signature: ts.Signature, args: readonly ts.Expression[], checkMode: CheckMode, context: ts.InferenceContext): ts.Type[] { - if (ts.isJsxOpeningLikeElement(node)) { + function inferTypeArguments(node: CallLikeExpression, signature: Signature, args: readonly Expression[], checkMode: CheckMode, context: InferenceContext): Type[] { + if (isJsxOpeningLikeElement(node)) { return inferJsxTypeArguments(node, signature, checkMode, context); } @@ -30495,14 +30693,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // example, given a 'function wrap(cb: (x: T) => U): (x: T) => U' and a call expression // 'let f: (x: string) => number = wrap(s => s.length)', we infer from the declared type of 'f' to the // return type of 'wrap'. - if (node.kind !== ts.SyntaxKind.Decorator) { - const skipBindingPatterns = ts.every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)); - const contextualType = getContextualType(node, skipBindingPatterns ? ts.ContextFlags.SkipBindingPatterns : ts.ContextFlags.None); + if (node.kind !== SyntaxKind.Decorator) { + const skipBindingPatterns = every(signature.typeParameters, p => !!getDefaultFromTypeParameter(p)); + const contextualType = getContextualType(node, skipBindingPatterns ? ContextFlags.SkipBindingPatterns : ContextFlags.None); if (contextualType) { const inferenceTargetType = getReturnTypeOfSignature(signature); if (couldContainTypeVariables(inferenceTargetType)) { const outerContext = getInferenceContext(node); - const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ts.ContextFlags.SkipBindingPatterns) !== contextualType; + const isFromBindingPattern = !skipBindingPatterns && getContextualType(node, ContextFlags.SkipBindingPatterns) !== contextualType; // A return type inference from a binding pattern can be used in instantiating the contextual // type of an argument later in inference, but cannot stand on its own as the final return type. // It is incorporated into `context.returnMapper` which is used in `instantiateContextualType`, @@ -30517,7 +30715,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We clone the inference context to avoid disturbing a resolution in progress for an // outer call expression. Effectively we just want a snapshot of whatever has been // inferred for any outer call expression so far. - const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, ts.InferenceFlags.NoDefault)); + const outerMapper = getMapperFromContext(cloneInferenceContext(outerContext, InferenceFlags.NoDefault)); const instantiatedType = instantiateType(contextualType, outerMapper); // If the contextual type is a generic function type with a single call signature, we // instantiate the type with its own type parameters and type arguments. This ensures that @@ -30531,7 +30729,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getOrCreateTypeFromSignature(getSignatureInstantiationWithoutFillingInTypeArguments(contextualSignature, contextualSignature.typeParameters)) : instantiatedType; // Inferences made from return types have lower priority than all other inferences. - inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, ts.InferencePriority.ReturnType); + inferTypes(context.inferences, inferenceSourceType, inferenceTargetType, InferencePriority.ReturnType); } // Create a type mapper for instantiating generic contextual types using the inferences made // from the return type. We need a separate inference pass here because (a) instantiation of @@ -30540,17 +30738,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const returnContext = createInferenceContext(signature.typeParameters!, signature, context.flags); const returnSourceType = instantiateType(contextualType, outerContext && outerContext.returnMapper); inferTypes(returnContext.inferences, returnSourceType, inferenceTargetType); - context.returnMapper = ts.some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined; + context.returnMapper = some(returnContext.inferences, hasInferenceCandidates) ? getMapperFromContext(cloneInferredPartOfContext(returnContext)) : undefined; } } } const restType = getNonArrayRestType(signature); const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; - if (restType && restType.flags & ts.TypeFlags.TypeParameter) { - const info = ts.find(context.inferences, info => info.typeParameter === restType); + if (restType && restType.flags & TypeFlags.TypeParameter) { + const info = find(context.inferences, info => info.typeParameter === restType); if (info) { - info.impliedArity = ts.findIndex(args, isSpreadArgument, argCount) < 0 ? args.length - argCount : undefined; + info.impliedArity = findIndex(args, isSpreadArgument, argCount) < 0 ? args.length - argCount : undefined; } } @@ -30562,7 +30760,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = 0; i < argCount; i++) { const arg = args[i]; - if (arg.kind !== ts.SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg))) { + if (arg.kind !== SyntaxKind.OmittedExpression && !(checkMode & CheckMode.IsForStringLiteralArgumentCompletions && hasSkipDirectInferenceFlag(arg))) { const paramType = getTypeAtPosition(signature, i); if (couldContainTypeVariables(paramType)) { const argType = checkExpressionWithContextualType(arg, paramType, context, checkMode); @@ -30579,21 +30777,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getInferredTypes(context); } - function getMutableArrayOrTupleType(type: ts.Type) { - return type.flags & ts.TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) : - type.flags & ts.TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type : + function getMutableArrayOrTupleType(type: Type) { + return type.flags & TypeFlags.Union ? mapType(type, getMutableArrayOrTupleType) : + type.flags & TypeFlags.Any || isMutableArrayOrTuple(getBaseConstraintOfType(type) || type) ? type : isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.elementFlags, /*readonly*/ false, type.target.labeledElementDeclarations) : - createTupleType([type], [ts.ElementFlags.Variadic]); + createTupleType([type], [ElementFlags.Variadic]); } - function getSpreadArgumentType(args: readonly ts.Expression[], index: number, argCount: number, restType: ts.Type, context: ts.InferenceContext | undefined, checkMode: CheckMode) { + function getSpreadArgumentType(args: readonly Expression[], index: number, argCount: number, restType: Type, context: InferenceContext | undefined, checkMode: CheckMode) { if (index >= argCount - 1) { const arg = args[argCount - 1]; if (isSpreadArgument(arg)) { // We are inferring from a spread expression in the last argument position, i.e. both the parameter // and the argument are ...x forms. - return getMutableArrayOrTupleType(arg.kind === ts.SyntaxKind.SyntheticExpression ? (arg as ts.SyntheticExpression).type : - checkExpressionWithContextualType((arg as ts.SpreadElement).expression, restType, context, checkMode)); + return getMutableArrayOrTupleType(arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type : + checkExpressionWithContextualType((arg as SpreadElement).expression, restType, context, checkMode)); } } const types = []; @@ -30602,41 +30800,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = index; i < argCount; i++) { const arg = args[i]; if (isSpreadArgument(arg)) { - const spreadType = arg.kind === ts.SyntaxKind.SyntheticExpression ? (arg as ts.SyntheticExpression).type : checkExpression((arg as ts.SpreadElement).expression); + const spreadType = arg.kind === SyntaxKind.SyntheticExpression ? (arg as SyntheticExpression).type : checkExpression((arg as SpreadElement).expression); if (isArrayLikeType(spreadType)) { types.push(spreadType); - flags.push(ts.ElementFlags.Variadic); + flags.push(ElementFlags.Variadic); } else { - types.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === ts.SyntaxKind.SpreadElement ? (arg as ts.SpreadElement).expression : arg)); - flags.push(ts.ElementFlags.Rest); + types.push(checkIteratedTypeOrElementType(IterationUse.Spread, spreadType, undefinedType, arg.kind === SyntaxKind.SpreadElement ? (arg as SpreadElement).expression : arg)); + flags.push(ElementFlags.Rest); } } else { - const contextualType = getIndexedAccessType(restType, getNumberLiteralType(i - index), ts.AccessFlags.Contextual); + const contextualType = getIndexedAccessType(restType, getNumberLiteralType(i - index), AccessFlags.Contextual); const argType = checkExpressionWithContextualType(arg, contextualType, context, checkMode); - const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, ts.TypeFlags.Primitive | ts.TypeFlags.Index | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping); + const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping); types.push(hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType)); - flags.push(ts.ElementFlags.Required); + flags.push(ElementFlags.Required); } - if (arg.kind === ts.SyntaxKind.SyntheticExpression && (arg as ts.SyntheticExpression).tupleNameSource) { - names.push((arg as ts.SyntheticExpression).tupleNameSource!); + if (arg.kind === SyntaxKind.SyntheticExpression && (arg as SyntheticExpression).tupleNameSource) { + names.push((arg as SyntheticExpression).tupleNameSource!); } } - return createTupleType(types, flags, /*readonly*/ false, ts.length(names) === ts.length(types) ? names : undefined); + return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined); } - function checkTypeArguments(signature: ts.Signature, typeArgumentNodes: readonly ts.TypeNode[], reportErrors: boolean, headMessage?: ts.DiagnosticMessage): ts.Type[] | undefined { - const isJavascript = ts.isInJSFile(signature.declaration); + function checkTypeArguments(signature: Signature, typeArgumentNodes: readonly TypeNode[], reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined { + const isJavascript = isInJSFile(signature.declaration); const typeParameters = signature.typeParameters!; - const typeArgumentTypes = fillMissingTypeArguments(ts.map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); - let mapper: ts.TypeMapper | undefined; + const typeArgumentTypes = fillMissingTypeArguments(map(typeArgumentNodes, getTypeFromTypeNode), typeParameters, getMinTypeArgumentCount(typeParameters), isJavascript); + let mapper: TypeMapper | undefined; for (let i = 0; i < typeArgumentNodes.length; i++) { - ts.Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments"); + Debug.assert(typeParameters[i] !== undefined, "Should not call checkTypeArguments with too many type arguments"); const constraint = getConstraintOfTypeParameter(typeParameters[i]); if (constraint) { - const errorInfo = reportErrors && headMessage ? (() => ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1)) : undefined; - const typeArgumentHeadMessage = headMessage || ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1; + const errorInfo = reportErrors && headMessage ? (() => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Type_0_does_not_satisfy_the_constraint_1)) : undefined; + const typeArgumentHeadMessage = headMessage || Diagnostics.Type_0_does_not_satisfy_the_constraint_1; if (!mapper) { mapper = createTypeMapper(typeParameters, typeArgumentTypes); } @@ -30654,18 +30852,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeArgumentTypes; } - function getJsxReferenceKind(node: ts.JsxOpeningLikeElement): ts.JsxReferenceKind { + function getJsxReferenceKind(node: JsxOpeningLikeElement): JsxReferenceKind { if (isJsxIntrinsicIdentifier(node.tagName)) { - return ts.JsxReferenceKind.Mixed; + return JsxReferenceKind.Mixed; } const tagType = getApparentType(checkExpression(node.tagName)); - if (ts.length(getSignaturesOfType(tagType, ts.SignatureKind.Construct))) { - return ts.JsxReferenceKind.Component; + if (length(getSignaturesOfType(tagType, SignatureKind.Construct))) { + return JsxReferenceKind.Component; } - if (ts.length(getSignaturesOfType(tagType, ts.SignatureKind.Call))) { - return ts.JsxReferenceKind.Function; + if (length(getSignaturesOfType(tagType, SignatureKind.Call))) { + return JsxReferenceKind.Function; } - return ts.JsxReferenceKind.Mixed; + return JsxReferenceKind.Mixed; } /** @@ -30675,13 +30873,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param relation a relationship to check parameter and argument type */ function checkApplicableSignatureForJsxOpeningLikeElement( - node: ts.JsxOpeningLikeElement, - signature: ts.Signature, - relation: ts.ESMap, + node: JsxOpeningLikeElement, + signature: Signature, + relation: ESMap, checkMode: CheckMode, reportErrors: boolean, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } ) { // Stateless function components can have maximum of three arguments: "props", "context", and "updater". // However "context" and "updater" are implicit and can't be specify by users. Only the first parameter, props, @@ -30702,26 +30900,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (getJsxNamespaceContainerForImplicitImport(node)) { return true; // factory is implicitly jsx/jsxdev - assume it fits the bill, since we don't strongly look for the jsx/jsxs/jsxDEV factory APIs anywhere else (at least not yet) } - const tagType = ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node) && !isJsxIntrinsicIdentifier(node.tagName) ? checkExpression(node.tagName) : undefined; + const tagType = isJsxOpeningElement(node) || isJsxSelfClosingElement(node) && !isJsxIntrinsicIdentifier(node.tagName) ? checkExpression(node.tagName) : undefined; if (!tagType) { return true; } - const tagCallSignatures = getSignaturesOfType(tagType, ts.SignatureKind.Call); - if (!ts.length(tagCallSignatures)) { + const tagCallSignatures = getSignaturesOfType(tagType, SignatureKind.Call); + if (!length(tagCallSignatures)) { return true; } const factory = getJsxFactoryEntity(node); if (!factory) { return true; } - const factorySymbol = resolveEntityName(factory, ts.SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, node); + const factorySymbol = resolveEntityName(factory, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, node); if (!factorySymbol) { return true; } const factoryType = getTypeOfSymbol(factorySymbol); - const callSignatures = getSignaturesOfType(factoryType, ts.SignatureKind.Call); - if (!ts.length(callSignatures)) { + const callSignatures = getSignaturesOfType(factoryType, SignatureKind.Call); + if (!length(callSignatures)) { return true; } @@ -30730,8 +30928,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Check that _some_ first parameter expects a FC-like thing, and that some overload of the SFC expects an acceptable number of arguments for (const sig of callSignatures) { const firstparam = getTypeAtPosition(sig, 0); - const signaturesOfParam = getSignaturesOfType(firstparam, ts.SignatureKind.Call); - if (!ts.length(signaturesOfParam)) continue; + const signaturesOfParam = getSignaturesOfType(firstparam, SignatureKind.Call); + if (!length(signaturesOfParam)) continue; for (const paramSig of signaturesOfParam) { hasFirstParamSignatures = true; if (hasEffectiveRestParameter(paramSig)) { @@ -30760,10 +30958,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (reportErrors) { - const diag = ts.createDiagnosticForNode(node.tagName, ts.Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, ts.entityNameToString(node.tagName), absoluteMinArgCount, ts.entityNameToString(factory), maxParamCount); + const diag = createDiagnosticForNode(node.tagName, Diagnostics.Tag_0_expects_at_least_1_arguments_but_the_JSX_factory_2_provides_at_most_3, entityNameToString(node.tagName), absoluteMinArgCount, entityNameToString(factory), maxParamCount); const tagNameDeclaration = getSymbolAtLocation(node.tagName)?.valueDeclaration; if (tagNameDeclaration) { - ts.addRelatedInfo(diag, ts.createDiagnosticForNode(tagNameDeclaration, ts.Diagnostics._0_is_declared_here, ts.entityNameToString(node.tagName))); + addRelatedInfo(diag, createDiagnosticForNode(tagNameDeclaration, Diagnostics._0_is_declared_here, entityNameToString(node.tagName))); } if (errorOutputContainer && errorOutputContainer.skipLogging) { (errorOutputContainer.errors || (errorOutputContainer.errors = [])).push(diag); @@ -30777,43 +30975,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function getSignatureApplicabilityError( - node: ts.CallLikeExpression, - args: readonly ts.Expression[], - signature: ts.Signature, - relation: ts.ESMap, + node: CallLikeExpression, + args: readonly Expression[], + signature: Signature, + relation: ESMap, checkMode: CheckMode, reportErrors: boolean, - containingMessageChain: (() => ts.DiagnosticMessageChain | undefined) | undefined, - ): readonly ts.Diagnostic[] | undefined { + containingMessageChain: (() => DiagnosticMessageChain | undefined) | undefined, + ): readonly Diagnostic[] | undefined { - const errorOutputContainer: { errors?: ts.Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true }; - if (ts.isJsxOpeningLikeElement(node)) { + const errorOutputContainer: { errors?: Diagnostic[], skipLogging?: boolean } = { errors: undefined, skipLogging: true }; + if (isJsxOpeningLikeElement(node)) { if (!checkApplicableSignatureForJsxOpeningLikeElement(node, signature, relation, checkMode, reportErrors, containingMessageChain, errorOutputContainer)) { - ts.Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors"); - return errorOutputContainer.errors || ts.emptyArray; + Debug.assert(!reportErrors || !!errorOutputContainer.errors, "jsx should have errors when reporting errors"); + return errorOutputContainer.errors || emptyArray; } return undefined; } const thisType = getThisTypeOfSignature(signature); - if (thisType && thisType !== voidType && node.kind !== ts.SyntaxKind.NewExpression) { + if (thisType && thisType !== voidType && node.kind !== SyntaxKind.NewExpression) { // If the called expression is not of the form `x.f` or `x["f"]`, then sourceType = voidType // If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible. // If the expression is a new expression, then the check is skipped. const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = getThisArgumentType(thisArgumentNode); const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - const headMessage = ts.Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; + const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1; if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) { - ts.Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors"); - return errorOutputContainer.errors || ts.emptyArray; + Debug.assert(!reportErrors || !!errorOutputContainer.errors, "this parameter should have errors when reporting errors"); + return errorOutputContainer.errors || emptyArray; } } - const headMessage = ts.Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; + const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1; const restType = getNonArrayRestType(signature); const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length; for (let i = 0; i < argCount; i++) { const arg = args[i]; - if (arg.kind !== ts.SyntaxKind.OmittedExpression) { + if (arg.kind !== SyntaxKind.OmittedExpression) { const paramType = getTypeAtPosition(signature, i); const argType = checkExpressionWithContextualType(arg, paramType, /*inferenceContext*/ undefined, checkMode); // If one or more arguments are still excluded (as indicated by CheckMode.SkipContextSensitive), @@ -30821,9 +31019,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // parameter types yet and therefore excess property checks may yield false positives (see #17041). const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType; if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) { - ts.Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors"); + Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors"); maybeAddMissingAwaitInfo(arg, checkArgType, paramType); - return errorOutputContainer.errors || ts.emptyArray; + return errorOutputContainer.errors || emptyArray; } } } @@ -30833,16 +31031,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const errorNode = !reportErrors ? undefined : restArgCount === 0 ? node : restArgCount === 1 ? args[argCount] : - ts.setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end); + setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end); if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) { - ts.Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); + Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); maybeAddMissingAwaitInfo(errorNode, spreadType, restType); - return errorOutputContainer.errors || ts.emptyArray; + return errorOutputContainer.errors || emptyArray; } } return undefined; - function maybeAddMissingAwaitInfo(errorNode: ts.Node | undefined, source: ts.Type, target: ts.Type) { + function maybeAddMissingAwaitInfo(errorNode: Node | undefined, source: Type, target: Type) { if (errorNode && reportErrors && errorOutputContainer.errors && errorOutputContainer.errors.length) { // Bail if target is Promise-like---something else is wrong if (getAwaitedTypeOfPromise(target)) { @@ -30850,7 +31048,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const awaitedTypeOfSource = getAwaitedTypeOfPromise(source); if (awaitedTypeOfSource && isTypeRelatedTo(awaitedTypeOfSource, target, relation)) { - ts.addRelatedInfo(errorOutputContainer.errors[0], ts.createDiagnosticForNode(errorNode, ts.Diagnostics.Did_you_forget_to_use_await)); + addRelatedInfo(errorOutputContainer.errors[0], createDiagnosticForNode(errorNode, Diagnostics.Did_you_forget_to_use_await)); } } } @@ -30859,45 +31057,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Returns the this argument in calls like x.f(...) and x[f](...). Undefined otherwise. */ - function getThisArgumentOfCall(node: ts.CallLikeExpression): ts.LeftHandSideExpression | undefined { - const expression = node.kind === ts.SyntaxKind.CallExpression ? node.expression : - node.kind === ts.SyntaxKind.TaggedTemplateExpression ? node.tag : undefined; + function getThisArgumentOfCall(node: CallLikeExpression): LeftHandSideExpression | undefined { + const expression = node.kind === SyntaxKind.CallExpression ? node.expression : + node.kind === SyntaxKind.TaggedTemplateExpression ? node.tag : undefined; if (expression) { - const callee = ts.skipOuterExpressions(expression); - if (ts.isAccessExpression(callee)) { + const callee = skipOuterExpressions(expression); + if (isAccessExpression(callee)) { return callee.expression; } } } - function createSyntheticExpression(parent: ts.Node, type: ts.Type, isSpread?: boolean, tupleNameSource?: ts.ParameterDeclaration | ts.NamedTupleMember) { - const result = ts.parseNodeFactory.createSyntheticExpression(type, isSpread, tupleNameSource); - ts.setTextRange(result, parent); - ts.setParent(result, parent); + function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember) { + const result = parseNodeFactory.createSyntheticExpression(type, isSpread, tupleNameSource); + setTextRange(result, parent); + setParent(result, parent); return result; } /** * Returns the effective arguments for an expression that works like a function invocation. */ - function getEffectiveCallArguments(node: ts.CallLikeExpression): readonly ts.Expression[] { - if (node.kind === ts.SyntaxKind.TaggedTemplateExpression) { + function getEffectiveCallArguments(node: CallLikeExpression): readonly Expression[] { + if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = node.template; - const args: ts.Expression[] = [createSyntheticExpression(template, getGlobalTemplateStringsArrayType())]; - if (template.kind === ts.SyntaxKind.TemplateExpression) { - ts.forEach(template.templateSpans, span => { + const args: Expression[] = [createSyntheticExpression(template, getGlobalTemplateStringsArrayType())]; + if (template.kind === SyntaxKind.TemplateExpression) { + forEach(template.templateSpans, span => { args.push(span.expression); }); } return args; } - if (node.kind === ts.SyntaxKind.Decorator) { + if (node.kind === SyntaxKind.Decorator) { return getEffectiveDecoratorArguments(node); } - if (ts.isJsxOpeningLikeElement(node)) { - return node.attributes.properties.length > 0 || (ts.isJsxOpeningElement(node) && node.parent.children.length > 0) ? [node.attributes] : ts.emptyArray; + if (isJsxOpeningLikeElement(node)) { + return node.attributes.properties.length > 0 || (isJsxOpeningElement(node) && node.parent.children.length > 0) ? [node.attributes] : emptyArray; } - const args = node.arguments || ts.emptyArray; + const args = node.arguments || emptyArray; const spreadIndex = getSpreadArgumentIndex(args); if (spreadIndex >= 0) { // Create synthetic arguments from spreads of tuple types. @@ -30905,12 +31103,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = spreadIndex; i < args.length; i++) { const arg = args[i]; // We can call checkExpressionCached because spread expressions never have a contextual type. - const spreadType = arg.kind === ts.SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as ts.SpreadElement).expression) : checkExpressionCached((arg as ts.SpreadElement).expression)); + const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg as SpreadElement).expression) : checkExpressionCached((arg as SpreadElement).expression)); if (spreadType && isTupleType(spreadType)) { - ts.forEach(getTypeArguments(spreadType), (t, i) => { + forEach(getTypeArguments(spreadType), (t, i) => { const flags = spreadType.target.elementFlags[i]; - const syntheticArg = createSyntheticExpression(arg, flags & ts.ElementFlags.Rest ? createArrayType(t) : t, - !!(flags & ts.ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]); + const syntheticArg = createSyntheticExpression(arg, flags & ElementFlags.Rest ? createArrayType(t) : t, + !!(flags & ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]); effectiveArgs.push(syntheticArg); }); } @@ -30926,97 +31124,97 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Returns the synthetic argument list for a decorator invocation. */ - function getEffectiveDecoratorArguments(node: ts.Decorator): readonly ts.Expression[] { + function getEffectiveDecoratorArguments(node: Decorator): readonly Expression[] { const parent = node.parent; const expr = node.expression; switch (parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: // For a class decorator, the `target` is the type of the class (e.g. the // "static" or "constructor" side of the class). return [ createSyntheticExpression(expr, getTypeOfSymbol(getSymbolOfNode(parent))) ]; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: // A parameter declaration decorator will have three arguments (see // `ParameterDecorator` in core.d.ts). - const func = parent.parent as ts.FunctionLikeDeclaration; + const func = parent.parent as FunctionLikeDeclaration; return [ - createSyntheticExpression(expr, parent.parent.kind === ts.SyntaxKind.Constructor ? getTypeOfSymbol(getSymbolOfNode(func)) : errorType), + createSyntheticExpression(expr, parent.parent.kind === SyntaxKind.Constructor ? getTypeOfSymbol(getSymbolOfNode(func)) : errorType), createSyntheticExpression(expr, anyType), createSyntheticExpression(expr, numberType) ]; - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: // A method or accessor declaration decorator will have two or three arguments (see // `PropertyDecorator` and `MethodDecorator` in core.d.ts). If we are emitting decorators // for ES3, we will only pass two arguments. - const hasPropDesc = languageVersion !== ts.ScriptTarget.ES3 && (!ts.isPropertyDeclaration(parent) || ts.hasAccessorModifier(parent)); + const hasPropDesc = languageVersion !== ScriptTarget.ES3 && (!isPropertyDeclaration(parent) || hasAccessorModifier(parent)); return [ - createSyntheticExpression(expr, getParentTypeOfClassElement(parent as ts.ClassElement)), - createSyntheticExpression(expr, getClassElementPropertyKeyType(parent as ts.ClassElement)), + createSyntheticExpression(expr, getParentTypeOfClassElement(parent as ClassElement)), + createSyntheticExpression(expr, getClassElementPropertyKeyType(parent as ClassElement)), createSyntheticExpression(expr, hasPropDesc ? createTypedPropertyDescriptorType(getTypeOfNode(parent)) : anyType) ]; } - return ts.Debug.fail(); + return Debug.fail(); } /** * Returns the argument count for a decorator node that works like a function invocation. */ - function getDecoratorArgumentCount(node: ts.Decorator, signature: ts.Signature) { + function getDecoratorArgumentCount(node: Decorator, signature: Signature) { switch (node.parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: return 1; - case ts.SyntaxKind.PropertyDeclaration: - return ts.hasAccessorModifier(node.parent) ? 3 : 2; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + return hasAccessorModifier(node.parent) ? 3 : 2; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: // For ES3 or decorators with only two parameters we supply only two arguments - return languageVersion === ts.ScriptTarget.ES3 || signature.parameters.length <= 2 ? 2 : 3; - case ts.SyntaxKind.Parameter: + return languageVersion === ScriptTarget.ES3 || signature.parameters.length <= 2 ? 2 : 3; + case SyntaxKind.Parameter: return 3; default: - return ts.Debug.fail(); + return Debug.fail(); } } - function getDiagnosticSpanForCallNode(node: ts.CallExpression, doNotIncludeArguments?: boolean) { + function getDiagnosticSpanForCallNode(node: CallExpression, doNotIncludeArguments?: boolean) { let start: number; let length: number; - const sourceFile = ts.getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(node); - if (ts.isPropertyAccessExpression(node.expression)) { - const nameSpan = ts.getErrorSpanForNode(sourceFile, node.expression.name); + if (isPropertyAccessExpression(node.expression)) { + const nameSpan = getErrorSpanForNode(sourceFile, node.expression.name); start = nameSpan.start; length = doNotIncludeArguments ? nameSpan.length : node.end - start; } else { - const expressionSpan = ts.getErrorSpanForNode(sourceFile, node.expression); + const expressionSpan = getErrorSpanForNode(sourceFile, node.expression); start = expressionSpan.start; length = doNotIncludeArguments ? expressionSpan.length : node.end - start; } return { start, length, sourceFile }; } - function getDiagnosticForCallNode(node: ts.CallLikeExpression, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): ts.DiagnosticWithLocation { - if (ts.isCallExpression(node)) { + function getDiagnosticForCallNode(node: CallLikeExpression, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number): DiagnosticWithLocation { + if (isCallExpression(node)) { const { sourceFile, start, length } = getDiagnosticSpanForCallNode(node); - return ts.createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2, arg3); + return createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2, arg3); } else { - return ts.createDiagnosticForNode(node, message, arg0, arg1, arg2, arg3); + return createDiagnosticForNode(node, message, arg0, arg1, arg2, arg3); } } - function isPromiseResolveArityError(node: ts.CallLikeExpression) { - if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression)) return false; + function isPromiseResolveArityError(node: CallLikeExpression) { + if (!isCallExpression(node) || !isIdentifier(node.expression)) return false; - const symbol = resolveName(node.expression, node.expression.escapedText, ts.SymbolFlags.Value, undefined, undefined, false); + const symbol = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, undefined, undefined, false); const decl = symbol?.valueDeclaration; - if (!decl || !ts.isParameter(decl) || !ts.isFunctionExpressionOrArrowFunction(decl.parent) || !ts.isNewExpression(decl.parent.parent) || !ts.isIdentifier(decl.parent.parent.expression)) { + if (!decl || !isParameter(decl) || !isFunctionExpressionOrArrowFunction(decl.parent) || !isNewExpression(decl.parent.parent) || !isIdentifier(decl.parent.parent.expression)) { return false; } @@ -31027,17 +31225,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return constructorSymbol === globalPromiseSymbol; } - function getArgumentArityError(node: ts.CallLikeExpression, signatures: readonly ts.Signature[], args: readonly ts.Expression[]) { + function getArgumentArityError(node: CallLikeExpression, signatures: readonly Signature[], args: readonly Expression[]) { const spreadIndex = getSpreadArgumentIndex(args); if (spreadIndex > -1) { - return ts.createDiagnosticForNode(args[spreadIndex], ts.Diagnostics.A_spread_argument_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter); + return createDiagnosticForNode(args[spreadIndex], Diagnostics.A_spread_argument_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter); } let min = Number.POSITIVE_INFINITY; // smallest parameter count let max = Number.NEGATIVE_INFINITY; // largest parameter count let maxBelow = Number.NEGATIVE_INFINITY; // largest parameter count that is smaller than the number of arguments let minAbove = Number.POSITIVE_INFINITY; // smallest parameter count that is larger than the number of arguments - let closestSignature: ts.Signature | undefined; + let closestSignature: Signature | undefined; for (const sig of signatures) { const minParameter = getMinArgumentCount(sig); const maxParameter = getParameterCount(sig); @@ -31051,67 +31249,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (minParameter < args.length && minParameter > maxBelow) maxBelow = minParameter; if (args.length < maxParameter && maxParameter < minAbove) minAbove = maxParameter; } - const hasRestParameter = ts.some(signatures, hasEffectiveRestParameter); + const hasRestParameter = some(signatures, hasEffectiveRestParameter); const parameterRange = hasRestParameter ? min : min < max ? min + "-" + max : min; const isVoidPromiseError = !hasRestParameter && parameterRange === 1 && args.length === 0 && isPromiseResolveArityError(node); - if (isVoidPromiseError && ts.isInJSFile(node)) { - return getDiagnosticForCallNode(node, ts.Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments); + if (isVoidPromiseError && isInJSFile(node)) { + return getDiagnosticForCallNode(node, Diagnostics.Expected_1_argument_but_got_0_new_Promise_needs_a_JSDoc_hint_to_produce_a_resolve_that_can_be_called_without_arguments); } const error = hasRestParameter - ? ts.Diagnostics.Expected_at_least_0_arguments_but_got_1 + ? Diagnostics.Expected_at_least_0_arguments_but_got_1 : isVoidPromiseError - ? ts.Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise - : ts.Diagnostics.Expected_0_arguments_but_got_1; + ? Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise + : Diagnostics.Expected_0_arguments_but_got_1; if (min < args.length && args.length < max) { // between min and max, but with no matching overload - return getDiagnosticForCallNode(node, ts.Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove); + return getDiagnosticForCallNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove); } else if (args.length < min) { // too short: put the error span on the call expression, not any of the args const diagnostic = getDiagnosticForCallNode(node, error, parameterRange, args.length); const parameter = closestSignature?.declaration?.parameters[closestSignature.thisParameter ? args.length + 1 : args.length]; if (parameter) { - const parameterError = ts.createDiagnosticForNode( + const parameterError = createDiagnosticForNode( parameter, - ts.isBindingPattern(parameter.name) ? ts.Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided - : ts.isRestParameter(parameter) ? ts.Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided - : ts.Diagnostics.An_argument_for_0_was_not_provided, - !parameter.name ? args.length : !ts.isBindingPattern(parameter.name) ? ts.idText(ts.getFirstIdentifier(parameter.name)) : undefined + isBindingPattern(parameter.name) ? Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided + : isRestParameter(parameter) ? Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided + : Diagnostics.An_argument_for_0_was_not_provided, + !parameter.name ? args.length : !isBindingPattern(parameter.name) ? idText(getFirstIdentifier(parameter.name)) : undefined ); - return ts.addRelatedInfo(diagnostic, parameterError); + return addRelatedInfo(diagnostic, parameterError); } return diagnostic; } else { // too long; error goes on the excess parameters - const errorSpan = ts.factory.createNodeArray(args.slice(max)); - const pos = ts.first(errorSpan).pos; - let end = ts.last(errorSpan).end; + const errorSpan = factory.createNodeArray(args.slice(max)); + const pos = first(errorSpan).pos; + let end = last(errorSpan).end; if (end === pos) { end++; } - ts.setTextRangePosEnd(errorSpan, pos, end); - return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), errorSpan, error, parameterRange, args.length); + setTextRangePosEnd(errorSpan, pos, end); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), errorSpan, error, parameterRange, args.length); } } - function getTypeArgumentArityError(node: ts.Node, signatures: readonly ts.Signature[], typeArguments: ts.NodeArray) { + function getTypeArgumentArityError(node: Node, signatures: readonly Signature[], typeArguments: NodeArray) { const argCount = typeArguments.length; // No overloads exist if (signatures.length === 1) { const sig = signatures[0]; const min = getMinTypeArgumentCount(sig.typeParameters); - const max = ts.length(sig.typeParameters); - return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min , argCount); + const max = length(sig.typeParameters); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, min < max ? min + "-" + max : min , argCount); } // Overloads exist let belowArgCount = -Infinity; let aboveArgCount = Infinity; for (const sig of signatures) { const min = getMinTypeArgumentCount(sig.typeParameters); - const max = ts.length(sig.typeParameters); + const max = length(sig.typeParameters); if (min > argCount) { aboveArgCount = Math.min(aboveArgCount, min); } @@ -31120,25 +31318,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (belowArgCount !== -Infinity && aboveArgCount !== Infinity) { - return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.No_overload_expects_0_type_arguments_but_overloads_do_exist_that_expect_either_1_or_2_type_arguments, argCount, belowArgCount, aboveArgCount); } - return ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Expected_0_type_arguments_but_got_1, belowArgCount === -Infinity ? aboveArgCount : belowArgCount, argCount); } - function resolveCall(node: ts.CallLikeExpression, signatures: readonly ts.Signature[], candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode, callChainFlags: ts.SignatureFlags, fallbackError?: ts.DiagnosticMessage): ts.Signature { - const isTaggedTemplate = node.kind === ts.SyntaxKind.TaggedTemplateExpression; - const isDecorator = node.kind === ts.SyntaxKind.Decorator; - const isJsxOpeningOrSelfClosingElement = ts.isJsxOpeningLikeElement(node); + function resolveCall(node: CallLikeExpression, signatures: readonly Signature[], candidatesOutArray: Signature[] | undefined, checkMode: CheckMode, callChainFlags: SignatureFlags, fallbackError?: DiagnosticMessage): Signature { + const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression; + const isDecorator = node.kind === SyntaxKind.Decorator; + const isJsxOpeningOrSelfClosingElement = isJsxOpeningLikeElement(node); const reportErrors = !candidatesOutArray; - let typeArguments: ts.NodeArray | undefined; + let typeArguments: NodeArray | undefined; - if (!isDecorator && !ts.isSuperCall(node)) { - typeArguments = (node as ts.CallExpression).typeArguments; + if (!isDecorator && !isSuperCall(node)) { + typeArguments = (node as CallExpression).typeArguments; // We already perform checking on the type arguments on the class declaration itself. - if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (node as ts.CallExpression).expression.kind !== ts.SyntaxKind.SuperKeyword) { - ts.forEach(typeArguments, checkSourceElement); + if (isTaggedTemplate || isJsxOpeningOrSelfClosingElement || (node as CallExpression).expression.kind !== SyntaxKind.SuperKeyword) { + forEach(typeArguments, checkSourceElement); } } @@ -31147,7 +31345,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { reorderCandidates(signatures, candidates, callChainFlags); if (!candidates.length) { if (reportErrors) { - diagnostics.add(getDiagnosticForCallNode(node, ts.Diagnostics.Call_target_does_not_contain_any_signatures)); + diagnostics.add(getDiagnosticForCallNode(node, Diagnostics.Call_target_does_not_contain_any_signatures)); } return resolveErrorCall(node); } @@ -31167,7 +31365,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. const isSingleNonGenericCandidate = candidates.length === 1 && !candidates[0].typeParameters; - let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && ts.some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; + let argCheckMode = !isDecorator && !isSingleNonGenericCandidate && some(args, isContextSensitive) ? CheckMode.SkipContextSensitive : CheckMode.Normal; argCheckMode |= checkMode & CheckMode.IsForStringLiteralArgumentCompletions; // The following variables are captured and modified by calls to chooseOverload. @@ -31191,15 +31389,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // function foo(): void; // foo(0); // - let candidatesForArgumentError: ts.Signature[] | undefined; - let candidateForArgumentArityError: ts.Signature | undefined; - let candidateForTypeArgumentError: ts.Signature | undefined; - let result: ts.Signature | undefined; + let candidatesForArgumentError: Signature[] | undefined; + let candidateForArgumentArityError: Signature | undefined; + let candidateForTypeArgumentError: Signature | undefined; + let result: Signature | undefined; // If we are in signature help, a trailing comma indicates that we intend to provide another argument, // so we will only accept overloads with arity at least 1 higher than the current number of provided arguments. const signatureHelpTrailingComma = - !!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === ts.SyntaxKind.CallExpression && node.arguments.hasTrailingComma; + !!(checkMode & CheckMode.IsForSignatureHelp) && node.kind === SyntaxKind.CallExpression && node.arguments.hasTrailingComma; // Section 4.12.1: // if the candidate list contains one or more signatures for which the type of each argument @@ -31239,33 +31437,33 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (candidatesForArgumentError) { if (candidatesForArgumentError.length === 1 || candidatesForArgumentError.length > 3) { const last = candidatesForArgumentError[candidatesForArgumentError.length - 1]; - let chain: ts.DiagnosticMessageChain | undefined; + let chain: DiagnosticMessageChain | undefined; if (candidatesForArgumentError.length > 3) { - chain = ts.chainDiagnosticMessages(chain, ts.Diagnostics.The_last_overload_gave_the_following_error); - chain = ts.chainDiagnosticMessages(chain, ts.Diagnostics.No_overload_matches_this_call); + chain = chainDiagnosticMessages(chain, Diagnostics.The_last_overload_gave_the_following_error); + chain = chainDiagnosticMessages(chain, Diagnostics.No_overload_matches_this_call); } const diags = getSignatureApplicabilityError(node, args, last, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, () => chain); if (diags) { for (const d of diags) { if (last.declaration && candidatesForArgumentError.length > 3) { - ts.addRelatedInfo(d, ts.createDiagnosticForNode(last.declaration, ts.Diagnostics.The_last_overload_is_declared_here)); + addRelatedInfo(d, createDiagnosticForNode(last.declaration, Diagnostics.The_last_overload_is_declared_here)); } addImplementationSuccessElaboration(last, d); diagnostics.add(d); } } else { - ts.Debug.fail("No error for last overload signature"); + Debug.fail("No error for last overload signature"); } } else { - const allDiagnostics: (readonly ts.DiagnosticRelatedInformation[])[] = []; + const allDiagnostics: (readonly DiagnosticRelatedInformation[])[] = []; let max = 0; let min = Number.MAX_VALUE; let minIndex = 0; let i = 0; for (const c of candidatesForArgumentError) { - const chain = () => ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, candidates.length, signatureToString(c)); + const chain = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Overload_0_of_1_2_gave_the_following_error, i + 1, candidates.length, signatureToString(c)); const diags = getSignatureApplicabilityError(node, args, c, assignableRelation, CheckMode.Normal, /*reportErrors*/ true, chain); if (diags) { if (diags.length <= min) { @@ -31276,26 +31474,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { allDiagnostics.push(diags); } else { - ts.Debug.fail("No error for 3 or fewer overload signatures"); + Debug.fail("No error for 3 or fewer overload signatures"); } i++; } - const diags = max > 1 ? allDiagnostics[minIndex] : ts.flatten(allDiagnostics); - ts.Debug.assert(diags.length > 0, "No errors reported for 3 or fewer overload signatures"); - const chain = ts.chainDiagnosticMessages( - ts.map(diags, ts.createDiagnosticMessageChainFromDiagnostic), - ts.Diagnostics.No_overload_matches_this_call); + const diags = max > 1 ? allDiagnostics[minIndex] : flatten(allDiagnostics); + Debug.assert(diags.length > 0, "No errors reported for 3 or fewer overload signatures"); + const chain = chainDiagnosticMessages( + map(diags, createDiagnosticMessageChainFromDiagnostic), + Diagnostics.No_overload_matches_this_call); // The below is a spread to guarantee we get a new (mutable) array - our `flatMap` helper tries to do "smart" optimizations where it reuses input // arrays and the emptyArray singleton where possible, which is decidedly not what we want while we're still constructing this diagnostic - const related = [...ts.flatMap(diags, d => (d as ts.Diagnostic).relatedInformation) as ts.DiagnosticRelatedInformation[]]; - let diag: ts.Diagnostic; - if (ts.every(diags, d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file)) { + const related = [...flatMap(diags, d => (d as Diagnostic).relatedInformation) as DiagnosticRelatedInformation[]]; + let diag: Diagnostic; + if (every(diags, d => d.start === diags[0].start && d.length === diags[0].length && d.file === diags[0].file)) { const { file, start, length } = diags[0]; diag = { file, start, length, code: chain.code, category: chain.category, messageText: chain, relatedInformation: related }; } else { - diag = ts.createDiagnosticForNodeFromMessageChain(node, chain, related); + diag = createDiagnosticForNodeFromMessageChain(node, chain, related); } addImplementationSuccessElaboration(candidatesForArgumentError[0], diag); diagnostics.add(diag); @@ -31305,10 +31503,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { diagnostics.add(getArgumentArityError(node, [candidateForArgumentArityError], args)); } else if (candidateForTypeArgumentError) { - checkTypeArguments(candidateForTypeArgumentError, (node as ts.CallExpression | ts.TaggedTemplateExpression | ts.JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, fallbackError); + checkTypeArguments(candidateForTypeArgumentError, (node as CallExpression | TaggedTemplateExpression | JsxOpeningLikeElement).typeArguments!, /*reportErrors*/ true, fallbackError); } else { - const signaturesWithCorrectTypeArgumentArity = ts.filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments)); + const signaturesWithCorrectTypeArgumentArity = filter(signatures, s => hasCorrectTypeArgumentArity(s, typeArguments)); if (signaturesWithCorrectTypeArgumentArity.length === 0) { diagnostics.add(getTypeArgumentArityError(node, signatures, typeArguments!)); } @@ -31323,19 +31521,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; - function addImplementationSuccessElaboration(failed: ts.Signature, diagnostic: ts.Diagnostic) { + function addImplementationSuccessElaboration(failed: Signature, diagnostic: Diagnostic) { const oldCandidatesForArgumentError = candidatesForArgumentError; const oldCandidateForArgumentArityError = candidateForArgumentArityError; const oldCandidateForTypeArgumentError = candidateForTypeArgumentError; - const failedSignatureDeclarations = failed.declaration?.symbol?.declarations || ts.emptyArray; + const failedSignatureDeclarations = failed.declaration?.symbol?.declarations || emptyArray; const isOverload = failedSignatureDeclarations.length > 1; - const implDecl = isOverload ? ts.find(failedSignatureDeclarations, d => ts.isFunctionLikeDeclaration(d) && ts.nodeIsPresent(d.body)) : undefined; + const implDecl = isOverload ? find(failedSignatureDeclarations, d => isFunctionLikeDeclaration(d) && nodeIsPresent(d.body)) : undefined; if (implDecl) { - const candidate = getSignatureFromDeclaration(implDecl as ts.FunctionLikeDeclaration); + const candidate = getSignatureFromDeclaration(implDecl as FunctionLikeDeclaration); const isSingleNonGenericCandidate = !candidate.typeParameters; if (chooseOverload([candidate], assignableRelation, isSingleNonGenericCandidate)) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(implDecl, ts.Diagnostics.The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible)); + addRelatedInfo(diagnostic, createDiagnosticForNode(implDecl, Diagnostics.The_call_would_have_succeeded_against_this_implementation_but_implementation_signatures_of_overloads_are_not_externally_visible)); } } @@ -31344,14 +31542,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { candidateForTypeArgumentError = oldCandidateForTypeArgumentError; } - function chooseOverload(candidates: ts.Signature[], relation: ts.ESMap, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) { + function chooseOverload(candidates: Signature[], relation: ESMap, isSingleNonGenericCandidate: boolean, signatureHelpTrailingComma = false) { candidatesForArgumentError = undefined; candidateForArgumentArityError = undefined; candidateForTypeArgumentError = undefined; if (isSingleNonGenericCandidate) { const candidate = candidates[0]; - if (ts.some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { + if (some(typeArguments) || !hasCorrectArity(node, args, candidate, signatureHelpTrailingComma)) { return undefined; } if (getSignatureApplicabilityError(node, args, candidate, relation, CheckMode.Normal, /*reportErrors*/ false, /*containingMessageChain*/ undefined)) { @@ -31367,12 +31565,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { continue; } - let checkCandidate: ts.Signature; - let inferenceContext: ts.InferenceContext | undefined; + let checkCandidate: Signature; + let inferenceContext: InferenceContext | undefined; if (candidate.typeParameters) { - let typeArgumentTypes: ts.Type[] | undefined; - if (ts.some(typeArguments)) { + let typeArgumentTypes: Type[] | undefined; + if (some(typeArguments)) { typeArgumentTypes = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false); if (!typeArgumentTypes) { candidateForTypeArgumentError = candidate; @@ -31380,11 +31578,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else { - inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? ts.InferenceFlags.AnyDefault : ts.InferenceFlags.None); + inferenceContext = createInferenceContext(candidate.typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode | CheckMode.SkipGenericFunctions, inferenceContext); - argCheckMode |= inferenceContext.flags & ts.InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal; + argCheckMode |= inferenceContext.flags & InferenceFlags.SkippedGenericFunction ? CheckMode.SkipGenericFunctions : CheckMode.Normal; } - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext && inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -31407,7 +31605,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { argCheckMode = checkMode & CheckMode.IsForStringLiteralArgumentCompletions; if (inferenceContext) { const typeArgumentTypes = inferTypeArguments(node, candidate, args, argCheckMode, inferenceContext); - checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, ts.isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters); + checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJSFile(candidate.declaration), inferenceContext.inferredTypeParameters); // If the original signature has a generic rest type, instantiation may produce a // signature with different arity and we need to perform another arity check. if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) { @@ -31431,13 +31629,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // No signature was applicable. We have already reported the errors for the invalid signature. function getCandidateForOverloadFailure( - node: ts.CallLikeExpression, - candidates: ts.Signature[], - args: readonly ts.Expression[], + node: CallLikeExpression, + candidates: Signature[], + args: readonly Expression[], hasCandidatesOutArray: boolean, checkMode: CheckMode, - ): ts.Signature { - ts.Debug.assert(candidates.length > 0); // Else should not have called this. + ): Signature { + Debug.assert(candidates.length > 0); // Else should not have called this. checkNodeDeferred(node); // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine. // Don't do this if there is a `candidatesOutArray`, @@ -31447,30 +31645,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { : createUnionOfSignaturesForOverloadFailure(candidates); } - function createUnionOfSignaturesForOverloadFailure(candidates: readonly ts.Signature[]): ts.Signature { - const thisParameters = ts.mapDefined(candidates, c => c.thisParameter); - let thisParameter: ts.Symbol | undefined; + function createUnionOfSignaturesForOverloadFailure(candidates: readonly Signature[]): Signature { + const thisParameters = mapDefined(candidates, c => c.thisParameter); + let thisParameter: Symbol | undefined; if (thisParameters.length) { thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter)); } - const { min: minArgumentCount, max: maxNonRestParam } = ts.minAndMax(candidates, getNumNonRestParameters); - const parameters: ts.Symbol[] = []; + const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters); + const parameters: Symbol[] = []; for (let i = 0; i < maxNonRestParam; i++) { - const symbols = ts.mapDefined(candidates, s => signatureHasRestParameter(s) ? - i < s.parameters.length - 1 ? s.parameters[i] : ts.last(s.parameters) : + const symbols = mapDefined(candidates, s => signatureHasRestParameter(s) ? + i < s.parameters.length - 1 ? s.parameters[i] : last(s.parameters) : i < s.parameters.length ? s.parameters[i] : undefined); - ts.Debug.assert(symbols.length !== 0); - parameters.push(createCombinedSymbolFromTypes(symbols, ts.mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i)))); + Debug.assert(symbols.length !== 0); + parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i)))); } - const restParameterSymbols = ts.mapDefined(candidates, c => signatureHasRestParameter(c) ? ts.last(c.parameters) : undefined); - let flags = ts.SignatureFlags.None; + const restParameterSymbols = mapDefined(candidates, c => signatureHasRestParameter(c) ? last(c.parameters) : undefined); + let flags = SignatureFlags.None; if (restParameterSymbols.length !== 0) { - const type = createArrayType(getUnionType(ts.mapDefined(candidates, tryGetRestTypeOfSignature), ts.UnionReduction.Subtype)); + const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype)); parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type)); - flags |= ts.SignatureFlags.HasRestParameter; + flags |= SignatureFlags.HasRestParameter; } if (candidates.some(signatureHasLiteralTypes)) { - flags |= ts.SignatureFlags.HasLiteralTypes; + flags |= SignatureFlags.HasLiteralTypes; } return createSignature( candidates[0].declaration, @@ -31483,21 +31681,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { flags); } - function getNumNonRestParameters(signature: ts.Signature): number { + function getNumNonRestParameters(signature: Signature): number { const numParams = signature.parameters.length; return signatureHasRestParameter(signature) ? numParams - 1 : numParams; } - function createCombinedSymbolFromTypes(sources: readonly ts.Symbol[], types: ts.Type[]): ts.Symbol { - return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, ts.UnionReduction.Subtype)); + function createCombinedSymbolFromTypes(sources: readonly Symbol[], types: Type[]): Symbol { + return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype)); } - function createCombinedSymbolForOverloadFailure(sources: readonly ts.Symbol[], type: ts.Type): ts.Symbol { + function createCombinedSymbolForOverloadFailure(sources: readonly Symbol[], type: Type): Symbol { // This function is currently only used for erroneous overloads, so it's good enough to just use the first source. - return createSymbolWithType(ts.first(sources), type); + return createSymbolWithType(first(sources), type); } - function pickLongestCandidateSignature(node: ts.CallLikeExpression, candidates: ts.Signature[], args: readonly ts.Expression[], checkMode: CheckMode): ts.Signature { + function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: readonly Expression[], checkMode: CheckMode): Signature { // Pick the longest signature. This way we can get a contextual type for cases like: // declare function f(a: { xa: number; xb: number; }, b: number); // f({ | @@ -31511,15 +31709,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return candidate; } - const typeArgumentNodes: readonly ts.TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined; + const typeArgumentNodes: readonly TypeNode[] | undefined = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments : undefined; const instantiated = typeArgumentNodes - ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, ts.isInJSFile(node))) + ? createSignatureInstantiation(candidate, getTypeArgumentsFromNodes(typeArgumentNodes, typeParameters, isInJSFile(node))) : inferSignatureInstantiationForOverloadFailure(node, typeParameters, candidate, args, checkMode); candidates[bestIndex] = instantiated; return instantiated; } - function getTypeArgumentsFromNodes(typeArgumentNodes: readonly ts.TypeNode[], typeParameters: readonly ts.TypeParameter[], isJs: boolean): readonly ts.Type[] { + function getTypeArgumentsFromNodes(typeArgumentNodes: readonly TypeNode[], typeParameters: readonly TypeParameter[], isJs: boolean): readonly Type[] { const typeArguments = typeArgumentNodes.map(getTypeOfNode); while (typeArguments.length > typeParameters.length) { typeArguments.pop(); @@ -31530,13 +31728,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeArguments; } - function inferSignatureInstantiationForOverloadFailure(node: ts.CallLikeExpression, typeParameters: readonly ts.TypeParameter[], candidate: ts.Signature, args: readonly ts.Expression[], checkMode: CheckMode): ts.Signature { - const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ ts.isInJSFile(node) ? ts.InferenceFlags.AnyDefault : ts.InferenceFlags.None); + function inferSignatureInstantiationForOverloadFailure(node: CallLikeExpression, typeParameters: readonly TypeParameter[], candidate: Signature, args: readonly Expression[], checkMode: CheckMode): Signature { + const inferenceContext = createInferenceContext(typeParameters, candidate, /*flags*/ isInJSFile(node) ? InferenceFlags.AnyDefault : InferenceFlags.None); const typeArgumentTypes = inferTypeArguments(node, candidate, args, checkMode | CheckMode.SkipContextSensitive | CheckMode.SkipGenericFunctions, inferenceContext); return createSignatureInstantiation(candidate, typeArgumentTypes); } - function getLongestCandidateIndex(candidates: ts.Signature[], argsCount: number): number { + function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number { let maxParamsIndex = -1; let maxParams = -1; @@ -31555,8 +31753,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return maxParamsIndex; } - function resolveCallExpression(node: ts.CallExpression, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { - if (node.expression.kind === ts.SyntaxKind.SuperKeyword) { + function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + if (node.expression.kind === SyntaxKind.SuperKeyword) { const superType = checkSuperExpression(node.expression); if (isTypeAny(superType)) { for (const arg of node.arguments) { @@ -31567,26 +31765,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isErrorType(superType)) { // In super call, the candidate signatures are the matching arity signatures of the base constructor function instantiated // with the type arguments specified in the extends clause. - const baseTypeNode = ts.getEffectiveBaseTypeNode(ts.getContainingClass(node)!); + const baseTypeNode = getEffectiveBaseTypeNode(getContainingClass(node)!); if (baseTypeNode) { const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments, baseTypeNode); - return resolveCall(node, baseConstructors, candidatesOutArray, checkMode, ts.SignatureFlags.None); + return resolveCall(node, baseConstructors, candidatesOutArray, checkMode, SignatureFlags.None); } } return resolveUntypedCall(node); } - let callChainFlags: ts.SignatureFlags; + let callChainFlags: SignatureFlags; let funcType = checkExpression(node.expression); - if (ts.isCallChain(node)) { + if (isCallChain(node)) { const nonOptionalType = getOptionalExpressionType(funcType, node.expression); - callChainFlags = nonOptionalType === funcType ? ts.SignatureFlags.None : - ts.isOutermostOptionalChain(node) ? ts.SignatureFlags.IsOuterCallChain : - ts.SignatureFlags.IsInnerCallChain; + callChainFlags = nonOptionalType === funcType ? SignatureFlags.None : + isOutermostOptionalChain(node) ? SignatureFlags.IsOuterCallChain : + SignatureFlags.IsInnerCallChain; funcType = nonOptionalType; } else { - callChainFlags = ts.SignatureFlags.None; + callChainFlags = SignatureFlags.None; } funcType = checkNonNullTypeWithReporter( @@ -31609,8 +31807,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // but we are not including call signatures that may have been added to the Object or // Function interface, since they have none by default. This is a bit of a leap of faith // that the user will not add any. - const callSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Call); - const numConstructSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Construct).length; + const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); + const numConstructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct).length; // TS 1.0 Spec: 4.12 // In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual @@ -31619,7 +31817,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The unknownType indicates that an error already occurred (and was reported). No // need to report another error in this case. if (!isErrorType(funcType) && node.typeArguments) { - error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); + error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } @@ -31628,17 +31826,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // with multiple call signatures. if (!callSignatures.length) { if (numConstructSignatures) { - error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); + error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); } else { - let relatedInformation: ts.DiagnosticRelatedInformation | undefined; + let relatedInformation: DiagnosticRelatedInformation | undefined; if (node.arguments.length === 1) { - const text = ts.getSourceFileOfNode(node).text; - if (ts.isLineBreak(text.charCodeAt(ts.skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) { - relatedInformation = ts.createDiagnosticForNode(node.expression, ts.Diagnostics.Are_you_missing_a_semicolon); + const text = getSourceFileOfNode(node).text; + if (isLineBreak(text.charCodeAt(skipTrivia(text, node.expression.end, /* stopAfterLineBreak */ true) - 1))) { + relatedInformation = createDiagnosticForNode(node.expression, Diagnostics.Are_you_missing_a_semicolon); } } - invocationError(node.expression, apparentType, ts.SignatureKind.Call, relatedInformation); + invocationError(node.expression, apparentType, SignatureKind.Call, relatedInformation); } return resolveErrorCall(node); } @@ -31659,15 +31857,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolvingSignature; } // If the function is explicitly marked with `@class`, then it must be constructed. - if (callSignatures.some(sig => ts.isInJSFile(sig.declaration) && !!ts.getJSDocClassTag(sig.declaration!))) { - error(node, ts.Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); + if (callSignatures.some(sig => isInJSFile(sig.declaration) && !!getJSDocClassTag(sig.declaration!))) { + error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType)); return resolveErrorCall(node); } return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunction(signature: ts.Signature) { + function isGenericFunctionReturningFunction(signature: Signature) { return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } @@ -31676,17 +31874,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * If FuncExpr is of type Any, or of an object type that has no call or construct signatures * but is a subtype of the Function interface, the call is an untyped function call. */ - function isUntypedFunctionCall(funcType: ts.Type, apparentFuncType: ts.Type, numCallSignatures: number, numConstructSignatures: number): boolean { + function isUntypedFunctionCall(funcType: Type, apparentFuncType: Type, numCallSignatures: number, numConstructSignatures: number): boolean { // We exclude union types because we may have a union of function types that happen to have no common signatures. - return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & ts.TypeFlags.TypeParameter) || - !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & ts.TypeFlags.Union) && !(getReducedType(apparentFuncType).flags & ts.TypeFlags.Never) && isTypeAssignableTo(funcType, globalFunctionType); + return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & TypeFlags.TypeParameter) || + !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & TypeFlags.Union) && !(getReducedType(apparentFuncType).flags & TypeFlags.Never) && isTypeAssignableTo(funcType, globalFunctionType); } - function resolveNewExpression(node: ts.NewExpression, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { - if (node.arguments && languageVersion < ts.ScriptTarget.ES5) { + function resolveNewExpression(node: NewExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { + if (node.arguments && languageVersion < ScriptTarget.ES5) { const spreadIndex = getSpreadArgumentIndex(node.arguments); if (spreadIndex >= 0) { - error(node.arguments[spreadIndex], ts.Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher); + error(node.arguments[spreadIndex], Diagnostics.Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_5_and_higher); } } @@ -31711,7 +31909,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // list and the result of the operation is of type Any. if (isTypeAny(expressionType)) { if (node.typeArguments) { - error(node, ts.Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); + error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments); } return resolveUntypedCall(node); } @@ -31720,7 +31918,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // but we are not including construct signatures that may have been added to the Object or // Function interface, since they have none by default. This is a bit of a leap of faith // that the user will not add any. - const constructSignatures = getSignaturesOfType(expressionType, ts.SignatureKind.Construct); + const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct); if (constructSignatures.length) { if (!isConstructorAccessible(node, constructSignatures[0])) { return resolveErrorCall(node); @@ -31729,66 +31927,66 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // then it cannot be instantiated. // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. - if (someSignature(constructSignatures, signature => !!(signature.flags & ts.SignatureFlags.Abstract))) { - error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); + if (someSignature(constructSignatures, signature => !!(signature.flags & SignatureFlags.Abstract))) { + error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - const valueDecl = expressionType.symbol && ts.getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && ts.hasSyntacticModifier(valueDecl, ts.ModifierFlags.Abstract)) { - error(node, ts.Diagnostics.Cannot_create_an_instance_of_an_abstract_class); + const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); + if (valueDecl && hasSyntacticModifier(valueDecl, ModifierFlags.Abstract)) { + error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } - return resolveCall(node, constructSignatures, candidatesOutArray, checkMode, ts.SignatureFlags.None); + return resolveCall(node, constructSignatures, candidatesOutArray, checkMode, SignatureFlags.None); } // If expressionType's apparent type is an object type with no construct signatures but // one or more call signatures, the expression is processed as a function call. A compile-time // error occurs if the result of the function call is not Void. The type of the result of the // operation is Any. It is an error to have a Void this type. - const callSignatures = getSignaturesOfType(expressionType, ts.SignatureKind.Call); + const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call); if (callSignatures.length) { - const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode, ts.SignatureFlags.None); + const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None); if (!noImplicitAny) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { - error(node, ts.Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); + error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } if (getThisTypeOfSignature(signature) === voidType) { - error(node, ts.Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); + error(node, Diagnostics.A_function_that_is_called_with_the_new_keyword_cannot_have_a_this_type_that_is_void); } } return signature; } - invocationError(node.expression, expressionType, ts.SignatureKind.Construct); + invocationError(node.expression, expressionType, SignatureKind.Construct); return resolveErrorCall(node); } - function someSignature(signatures: ts.Signature | readonly ts.Signature[], f: (s: ts.Signature) => boolean): boolean { - if (ts.isArray(signatures)) { - return ts.some(signatures, signature => someSignature(signature, f)); + function someSignature(signatures: Signature | readonly Signature[], f: (s: Signature) => boolean): boolean { + if (isArray(signatures)) { + return some(signatures, signature => someSignature(signature, f)); } - return signatures.compositeKind === ts.TypeFlags.Union ? ts.some(signatures.compositeSignatures, f) : f(signatures); + return signatures.compositeKind === TypeFlags.Union ? some(signatures.compositeSignatures, f) : f(signatures); } - function typeHasProtectedAccessibleBase(target: ts.Symbol, type: ts.InterfaceType): boolean { + function typeHasProtectedAccessibleBase(target: Symbol, type: InterfaceType): boolean { const baseTypes = getBaseTypes(type); - if (!ts.length(baseTypes)) { + if (!length(baseTypes)) { return false; } const firstBase = baseTypes[0]; - if (firstBase.flags & ts.TypeFlags.Intersection) { - const types = (firstBase as ts.IntersectionType).types; + if (firstBase.flags & TypeFlags.Intersection) { + const types = (firstBase as IntersectionType).types; const mixinFlags = findMixins(types); let i = 0; - for (const intersectionMember of (firstBase as ts.IntersectionType).types) { + for (const intersectionMember of (firstBase as IntersectionType).types) { // We want to ignore mixin ctors if (!mixinFlags[i]) { - if (ts.getObjectFlags(intersectionMember) & (ts.ObjectFlags.Class | ts.ObjectFlags.Interface)) { + if (getObjectFlags(intersectionMember) & (ObjectFlags.Class | ObjectFlags.Interface)) { if (intersectionMember.symbol === target) { return true; } - if (typeHasProtectedAccessibleBase(target, intersectionMember as ts.InterfaceType)) { + if (typeHasProtectedAccessibleBase(target, intersectionMember as InterfaceType)) { return true; } } @@ -31800,39 +31998,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (firstBase.symbol === target) { return true; } - return typeHasProtectedAccessibleBase(target, firstBase as ts.InterfaceType); + return typeHasProtectedAccessibleBase(target, firstBase as InterfaceType); } - function isConstructorAccessible(node: ts.NewExpression, signature: ts.Signature) { + function isConstructorAccessible(node: NewExpression, signature: Signature) { if (!signature || !signature.declaration) { return true; } const declaration = signature.declaration; - const modifiers = ts.getSelectedEffectiveModifierFlags(declaration, ts.ModifierFlags.NonPublicAccessibilityModifier); + const modifiers = getSelectedEffectiveModifierFlags(declaration, ModifierFlags.NonPublicAccessibilityModifier); // (1) Public constructors and (2) constructor functions are always accessible. - if (!modifiers || declaration.kind !== ts.SyntaxKind.Constructor) { + if (!modifiers || declaration.kind !== SyntaxKind.Constructor) { return true; } - const declaringClassDeclaration = ts.getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!; - const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol) as ts.InterfaceType; + const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol)!; + const declaringClass = getDeclaredTypeOfSymbol(declaration.parent.symbol) as InterfaceType; // A private or protected constructor can only be instantiated within its own class (or a subclass, for protected) if (!isNodeWithinClass(node, declaringClassDeclaration)) { - const containingClass = ts.getContainingClass(node); - if (containingClass && modifiers & ts.ModifierFlags.Protected) { + const containingClass = getContainingClass(node); + if (containingClass && modifiers & ModifierFlags.Protected) { const containingType = getTypeOfNode(containingClass); - if (typeHasProtectedAccessibleBase(declaration.parent.symbol, containingType as ts.InterfaceType)) { + if (typeHasProtectedAccessibleBase(declaration.parent.symbol, containingType as InterfaceType)) { return true; } } - if (modifiers & ts.ModifierFlags.Private) { - error(node, ts.Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); + if (modifiers & ModifierFlags.Private) { + error(node, Diagnostics.Constructor_of_class_0_is_private_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } - if (modifiers & ts.ModifierFlags.Protected) { - error(node, ts.Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); + if (modifiers & ModifierFlags.Protected) { + error(node, Diagnostics.Constructor_of_class_0_is_protected_and_only_accessible_within_the_class_declaration, typeToString(declaringClass)); } return false; } @@ -31840,13 +32038,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function invocationErrorDetails(errorTarget: ts.Node, apparentType: ts.Type, kind: ts.SignatureKind): { messageChain: ts.DiagnosticMessageChain, relatedMessage: ts.DiagnosticMessage | undefined } { - let errorInfo: ts.DiagnosticMessageChain | undefined; - const isCall = kind === ts.SignatureKind.Call; + function invocationErrorDetails(errorTarget: Node, apparentType: Type, kind: SignatureKind): { messageChain: DiagnosticMessageChain, relatedMessage: DiagnosticMessage | undefined } { + let errorInfo: DiagnosticMessageChain | undefined; + const isCall = kind === SignatureKind.Call; const awaitedType = getAwaitedType(apparentType); const maybeMissingAwait = awaitedType && getSignaturesOfType(awaitedType, kind).length > 0; - if (apparentType.flags & ts.TypeFlags.Union) { - const types = (apparentType as ts.UnionType).types; + if (apparentType.flags & TypeFlags.Union) { + const types = (apparentType as UnionType).types; let hasSignatures = false; for (const constituent of types) { const signatures = getSignaturesOfType(constituent, kind); @@ -31860,18 +32058,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // Error on the first non callable constituent only if (!errorInfo) { - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( errorInfo, isCall ? - ts.Diagnostics.Type_0_has_no_call_signatures : - ts.Diagnostics.Type_0_has_no_construct_signatures, + Diagnostics.Type_0_has_no_call_signatures : + Diagnostics.Type_0_has_no_construct_signatures, typeToString(constituent) ); - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( errorInfo, isCall ? - ts.Diagnostics.Not_all_constituents_of_type_0_are_callable : - ts.Diagnostics.Not_all_constituents_of_type_0_are_constructable, + Diagnostics.Not_all_constituents_of_type_0_are_callable : + Diagnostics.Not_all_constituents_of_type_0_are_constructable, typeToString(apparentType) ); } @@ -31882,82 +32080,82 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (!hasSignatures) { - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( /* detials */ undefined, isCall ? - ts.Diagnostics.No_constituent_of_type_0_is_callable : - ts.Diagnostics.No_constituent_of_type_0_is_constructable, + Diagnostics.No_constituent_of_type_0_is_callable : + Diagnostics.No_constituent_of_type_0_is_constructable, typeToString(apparentType) ); } if (!errorInfo) { - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( errorInfo, isCall ? - ts.Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other : - ts.Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other, + Diagnostics.Each_member_of_the_union_type_0_has_signatures_but_none_of_those_signatures_are_compatible_with_each_other : + Diagnostics.Each_member_of_the_union_type_0_has_construct_signatures_but_none_of_those_signatures_are_compatible_with_each_other, typeToString(apparentType) ); } } else { - errorInfo = ts.chainDiagnosticMessages( + errorInfo = chainDiagnosticMessages( errorInfo, isCall ? - ts.Diagnostics.Type_0_has_no_call_signatures : - ts.Diagnostics.Type_0_has_no_construct_signatures, + Diagnostics.Type_0_has_no_call_signatures : + Diagnostics.Type_0_has_no_construct_signatures, typeToString(apparentType) ); } - let headMessage = isCall ? ts.Diagnostics.This_expression_is_not_callable : ts.Diagnostics.This_expression_is_not_constructable; + let headMessage = isCall ? Diagnostics.This_expression_is_not_callable : Diagnostics.This_expression_is_not_constructable; // Diagnose get accessors incorrectly called as functions - if (ts.isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) { + if (isCallExpression(errorTarget.parent) && errorTarget.parent.arguments.length === 0) { const { resolvedSymbol } = getNodeLinks(errorTarget); - if (resolvedSymbol && resolvedSymbol.flags & ts.SymbolFlags.GetAccessor) { - headMessage = ts.Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without; + if (resolvedSymbol && resolvedSymbol.flags & SymbolFlags.GetAccessor) { + headMessage = Diagnostics.This_expression_is_not_callable_because_it_is_a_get_accessor_Did_you_mean_to_use_it_without; } } return { - messageChain: ts.chainDiagnosticMessages(errorInfo, headMessage), - relatedMessage: maybeMissingAwait ? ts.Diagnostics.Did_you_forget_to_use_await : undefined, + messageChain: chainDiagnosticMessages(errorInfo, headMessage), + relatedMessage: maybeMissingAwait ? Diagnostics.Did_you_forget_to_use_await : undefined, }; } - function invocationError(errorTarget: ts.Node, apparentType: ts.Type, kind: ts.SignatureKind, relatedInformation?: ts.DiagnosticRelatedInformation) { + function invocationError(errorTarget: Node, apparentType: Type, kind: SignatureKind, relatedInformation?: DiagnosticRelatedInformation) { const { messageChain, relatedMessage: relatedInfo } = invocationErrorDetails(errorTarget, apparentType, kind); - const diagnostic = ts.createDiagnosticForNodeFromMessageChain(errorTarget, messageChain); + const diagnostic = createDiagnosticForNodeFromMessageChain(errorTarget, messageChain); if (relatedInfo) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(errorTarget, relatedInfo)); + addRelatedInfo(diagnostic, createDiagnosticForNode(errorTarget, relatedInfo)); } - if (ts.isCallExpression(errorTarget.parent)) { + if (isCallExpression(errorTarget.parent)) { const { start, length } = getDiagnosticSpanForCallNode(errorTarget.parent, /* doNotIncludeArguments */ true); diagnostic.start = start; diagnostic.length = length; } diagnostics.add(diagnostic); - invocationErrorRecovery(apparentType, kind, relatedInformation ? ts.addRelatedInfo(diagnostic, relatedInformation) : diagnostic); + invocationErrorRecovery(apparentType, kind, relatedInformation ? addRelatedInfo(diagnostic, relatedInformation) : diagnostic); } - function invocationErrorRecovery(apparentType: ts.Type, kind: ts.SignatureKind, diagnostic: ts.Diagnostic) { + function invocationErrorRecovery(apparentType: Type, kind: SignatureKind, diagnostic: Diagnostic) { if (!apparentType.symbol) { return; } const importNode = getSymbolLinks(apparentType.symbol).originatingImport; // Create a diagnostic on the originating import if possible onto which we can attach a quickfix // An import call expression cannot be rewritten into another form to correct the error - the only solution is to use `.default` at the use-site - if (importNode && !ts.isImportCall(importNode)) { + if (importNode && !isImportCall(importNode)) { const sigs = getSignaturesOfType(getTypeOfSymbol(getSymbolLinks(apparentType.symbol).target!), kind); if (!sigs || !sigs.length) return; - ts.addRelatedInfo(diagnostic, - ts.createDiagnosticForNode(importNode, ts.Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead) + addRelatedInfo(diagnostic, + createDiagnosticForNode(importNode, Diagnostics.Type_originates_at_this_import_A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime_Consider_using_a_default_import_or_import_require_here_instead) ); } } - function resolveTaggedTemplateExpression(node: ts.TaggedTemplateExpression, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { + function resolveTaggedTemplateExpression(node: TaggedTemplateExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { const tagType = checkExpression(node.tag); const apparentType = getApparentType(tagType); @@ -31966,102 +32164,102 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolveErrorCall(node); } - const callSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Call); - const numConstructSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Construct).length; + const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); + const numConstructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct).length; if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, numConstructSignatures)) { return resolveUntypedCall(node); } if (!callSignatures.length) { - if (ts.isArrayLiteralExpression(node.parent)) { - const diagnostic = ts.createDiagnosticForNode(node.tag, ts.Diagnostics.It_is_likely_that_you_are_missing_a_comma_to_separate_these_two_template_expressions_They_form_a_tagged_template_expression_which_cannot_be_invoked); + if (isArrayLiteralExpression(node.parent)) { + const diagnostic = createDiagnosticForNode(node.tag, Diagnostics.It_is_likely_that_you_are_missing_a_comma_to_separate_these_two_template_expressions_They_form_a_tagged_template_expression_which_cannot_be_invoked); diagnostics.add(diagnostic); return resolveErrorCall(node); } - invocationError(node.tag, apparentType, ts.SignatureKind.Call); + invocationError(node.tag, apparentType, SignatureKind.Call); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, checkMode, ts.SignatureFlags.None); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None); } /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. */ - function getDiagnosticHeadMessageForDecoratorResolution(node: ts.Decorator) { + function getDiagnosticHeadMessageForDecoratorResolution(node: Decorator) { switch (node.parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - return ts.Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return Diagnostics.Unable_to_resolve_signature_of_class_decorator_when_called_as_an_expression; - case ts.SyntaxKind.Parameter: - return ts.Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression; + case SyntaxKind.Parameter: + return Diagnostics.Unable_to_resolve_signature_of_parameter_decorator_when_called_as_an_expression; - case ts.SyntaxKind.PropertyDeclaration: - return ts.Diagnostics.Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression; + case SyntaxKind.PropertyDeclaration: + return Diagnostics.Unable_to_resolve_signature_of_property_decorator_when_called_as_an_expression; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return ts.Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return Diagnostics.Unable_to_resolve_signature_of_method_decorator_when_called_as_an_expression; default: - return ts.Debug.fail(); + return Debug.fail(); } } /** * Resolves a decorator as if it were a call expression. */ - function resolveDecorator(node: ts.Decorator, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { + function resolveDecorator(node: Decorator, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { const funcType = checkExpression(node.expression); const apparentType = getApparentType(funcType); if (isErrorType(apparentType)) { return resolveErrorCall(node); } - const callSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Call); - const numConstructSignatures = getSignaturesOfType(apparentType, ts.SignatureKind.Construct).length; + const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call); + const numConstructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct).length; if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, numConstructSignatures)) { return resolveUntypedCall(node); } if (isPotentiallyUncalledDecorator(node, callSignatures)) { - const nodeStr = ts.getTextOfNode(node.expression, /*includeTrivia*/ false); - error(node, ts.Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); + const nodeStr = getTextOfNode(node.expression, /*includeTrivia*/ false); + error(node, Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0, nodeStr); return resolveErrorCall(node); } const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node); if (!callSignatures.length) { - const errorDetails = invocationErrorDetails(node.expression, apparentType, ts.SignatureKind.Call); - const messageChain = ts.chainDiagnosticMessages(errorDetails.messageChain, headMessage); - const diag = ts.createDiagnosticForNodeFromMessageChain(node.expression, messageChain); + const errorDetails = invocationErrorDetails(node.expression, apparentType, SignatureKind.Call); + const messageChain = chainDiagnosticMessages(errorDetails.messageChain, headMessage); + const diag = createDiagnosticForNodeFromMessageChain(node.expression, messageChain); if (errorDetails.relatedMessage) { - ts.addRelatedInfo(diag, ts.createDiagnosticForNode(node.expression, errorDetails.relatedMessage)); + addRelatedInfo(diag, createDiagnosticForNode(node.expression, errorDetails.relatedMessage)); } diagnostics.add(diag); - invocationErrorRecovery(apparentType, ts.SignatureKind.Call, diag); + invocationErrorRecovery(apparentType, SignatureKind.Call, diag); return resolveErrorCall(node); } - return resolveCall(node, callSignatures, candidatesOutArray, checkMode, ts.SignatureFlags.None, headMessage); + return resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None, headMessage); } - function createSignatureForJSXIntrinsic(node: ts.JsxOpeningLikeElement, result: ts.Type): ts.Signature { + function createSignatureForJSXIntrinsic(node: JsxOpeningLikeElement, result: Type): Signature { const namespace = getJsxNamespaceAt(node); const exports = namespace && getExportsOfSymbol(namespace); // We fake up a SFC signature for each intrinsic, however a more specific per-element signature drawn from the JSX declaration // file would probably be preferable. - const typeSymbol = exports && getSymbol(exports, JsxNames.Element, ts.SymbolFlags.Type); - const returnNode = typeSymbol && nodeBuilder.symbolToEntityName(typeSymbol, ts.SymbolFlags.Type, node); - const declaration = ts.factory.createFunctionTypeNode(/*typeParameters*/ undefined, - [ts.factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotdotdot*/ undefined, "props", /*questionMark*/ undefined, nodeBuilder.typeToTypeNode(result, node))], - returnNode ? ts.factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + const typeSymbol = exports && getSymbol(exports, JsxNames.Element, SymbolFlags.Type); + const returnNode = typeSymbol && nodeBuilder.symbolToEntityName(typeSymbol, SymbolFlags.Type, node); + const declaration = factory.createFunctionTypeNode(/*typeParameters*/ undefined, + [factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotdotdot*/ undefined, "props", /*questionMark*/ undefined, nodeBuilder.typeToTypeNode(result, node))], + returnNode ? factory.createTypeReferenceNode(returnNode, /*typeArguments*/ undefined) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ); - const parameterSymbol = createSymbol(ts.SymbolFlags.FunctionScopedVariable, "props" as ts.__String); + const parameterSymbol = createSymbol(SymbolFlags.FunctionScopedVariable, "props" as __String); parameterSymbol.type = result; return createSignature( declaration, @@ -32071,18 +32269,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { typeSymbol ? getDeclaredTypeOfSymbol(typeSymbol) : errorType, /*returnTypePredicate*/ undefined, 1, - ts.SignatureFlags.None + SignatureFlags.None ); } - function resolveJsxOpeningLikeElement(node: ts.JsxOpeningLikeElement, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { + function resolveJsxOpeningLikeElement(node: JsxOpeningLikeElement, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { if (isJsxIntrinsicIdentifier(node.tagName)) { const result = getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node); const fakeSignature = createSignatureForJSXIntrinsic(node, result); checkTypeAssignableToAndOptionallyElaborate(checkExpressionWithContextualType(node.attributes, getEffectiveFirstArgumentForJsxSignature(fakeSignature, node), /*mapper*/ undefined, CheckMode.Normal), result, node.tagName, node.attributes); - if (ts.length(node.typeArguments)) { - ts.forEach(node.typeArguments, checkSourceElement); - diagnostics.add(ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), node.typeArguments!, ts.Diagnostics.Expected_0_type_arguments_but_got_1, 0, ts.length(node.typeArguments))); + if (length(node.typeArguments)) { + forEach(node.typeArguments, checkSourceElement); + diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), node.typeArguments!, Diagnostics.Expected_0_type_arguments_but_got_1, 0, length(node.typeArguments))); } return fakeSignature; } @@ -32099,11 +32297,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (signatures.length === 0) { // We found no signatures at all, which is an error - error(node.tagName, ts.Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, ts.getTextOfNode(node.tagName)); + error(node.tagName, Diagnostics.JSX_element_type_0_does_not_have_any_construct_or_call_signatures, getTextOfNode(node.tagName)); return resolveErrorCall(node); } - return resolveCall(node, signatures, candidatesOutArray, checkMode, ts.SignatureFlags.None); + return resolveCall(node, signatures, candidatesOutArray, checkMode, SignatureFlags.None); } /** @@ -32111,28 +32309,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * but is receiving too many arguments as part of the decorator invocation. * In those cases, a user may have meant to *call* the expression before using it as a decorator. */ - function isPotentiallyUncalledDecorator(decorator: ts.Decorator, signatures: readonly ts.Signature[]) { - return signatures.length && ts.every(signatures, signature => + function isPotentiallyUncalledDecorator(decorator: Decorator, signatures: readonly Signature[]) { + return signatures.length && every(signatures, signature => signature.minArgumentCount === 0 && !signatureHasRestParameter(signature) && signature.parameters.length < getDecoratorArgumentCount(decorator, signature)); } - function resolveSignature(node: ts.CallLikeExpression, candidatesOutArray: ts.Signature[] | undefined, checkMode: CheckMode): ts.Signature { + function resolveSignature(node: CallLikeExpression, candidatesOutArray: Signature[] | undefined, checkMode: CheckMode): Signature { switch (node.kind) { - case ts.SyntaxKind.CallExpression: + case SyntaxKind.CallExpression: return resolveCallExpression(node, candidatesOutArray, checkMode); - case ts.SyntaxKind.NewExpression: + case SyntaxKind.NewExpression: return resolveNewExpression(node, candidatesOutArray, checkMode); - case ts.SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TaggedTemplateExpression: return resolveTaggedTemplateExpression(node, candidatesOutArray, checkMode); - case ts.SyntaxKind.Decorator: + case SyntaxKind.Decorator: return resolveDecorator(node, candidatesOutArray, checkMode); - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxSelfClosingElement: return resolveJsxOpeningLikeElement(node, candidatesOutArray, checkMode); } - throw ts.Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); + throw Debug.assertNever(node, "Branch in 'resolveSignature' should be unreachable."); } /** @@ -32142,7 +32340,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * the function will fill it up with appropriate candidate signatures * @return a signature of the call-like expression or undefined if one can't be found */ - function getResolvedSignature(node: ts.CallLikeExpression, candidatesOutArray?: ts.Signature[] | undefined, checkMode?: CheckMode): ts.Signature { + function getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[] | undefined, checkMode?: CheckMode): Signature { const links = getNodeLinks(node); // If getResolvedSignature has already been called, we will have cached the resolvedSignature. // However, it is possible that either candidatesOutArray was not passed in the first time, @@ -32169,19 +32367,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Indicates whether a declaration can be treated as a constructor in a JavaScript * file. */ - function isJSConstructor(node: ts.Node | undefined): node is ts.FunctionDeclaration | ts.FunctionExpression { - if (!node || !ts.isInJSFile(node)) { + function isJSConstructor(node: Node | undefined): node is FunctionDeclaration | FunctionExpression { + if (!node || !isInJSFile(node)) { return false; } - const func = ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) ? node : - (ts.isVariableDeclaration(node) || ts.isPropertyAssignment(node)) && node.initializer && ts.isFunctionExpression(node.initializer) ? node.initializer : + const func = isFunctionDeclaration(node) || isFunctionExpression(node) ? node : + (isVariableDeclaration(node) || isPropertyAssignment(node)) && node.initializer && isFunctionExpression(node.initializer) ? node.initializer : undefined; if (func) { // If the node has a @class or @constructor tag, treat it like a constructor. - if (ts.getJSDocClassTag(node)) return true; + if (getJSDocClassTag(node)) return true; // If the node is a property of an object literal. - if (ts.isPropertyAssignment(ts.walkUpParenthesizedExpressions(func.parent))) return false; + if (isPropertyAssignment(walkUpParenthesizedExpressions(func.parent))) return false; // If the symbol of the node has members, treat it like a constructor. const symbol = getSymbolOfNode(func); @@ -32190,92 +32388,92 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function mergeJSSymbols(target: ts.Symbol, source: ts.Symbol | undefined) { + function mergeJSSymbols(target: Symbol, source: Symbol | undefined) { if (source) { const links = getSymbolLinks(source); if (!links.inferredClassSymbol || !links.inferredClassSymbol.has(getSymbolId(target))) { - const inferred = ts.isTransientSymbol(target) ? target : cloneSymbol(target) as ts.TransientSymbol; - inferred.exports = inferred.exports || ts.createSymbolTable(); - inferred.members = inferred.members || ts.createSymbolTable(); - inferred.flags |= source.flags & ts.SymbolFlags.Class; + const inferred = isTransientSymbol(target) ? target : cloneSymbol(target) as TransientSymbol; + inferred.exports = inferred.exports || createSymbolTable(); + inferred.members = inferred.members || createSymbolTable(); + inferred.flags |= source.flags & SymbolFlags.Class; if (source.exports?.size) { mergeSymbolTable(inferred.exports, source.exports); } if (source.members?.size) { mergeSymbolTable(inferred.members, source.members); } - (links.inferredClassSymbol || (links.inferredClassSymbol = new ts.Map())).set(getSymbolId(inferred), inferred); + (links.inferredClassSymbol || (links.inferredClassSymbol = new Map())).set(getSymbolId(inferred), inferred); return inferred; } return links.inferredClassSymbol.get(getSymbolId(target)); } } - function getAssignedClassSymbol(decl: ts.Declaration): ts.Symbol | undefined { + function getAssignedClassSymbol(decl: Declaration): Symbol | undefined { const assignmentSymbol = decl && getSymbolOfExpando(decl, /*allowDeclaration*/ true); - const prototype = assignmentSymbol?.exports?.get("prototype" as ts.__String); + const prototype = assignmentSymbol?.exports?.get("prototype" as __String); const init = prototype?.valueDeclaration && getAssignedJSPrototype(prototype.valueDeclaration); return init ? getSymbolOfNode(init) : undefined; } - function getSymbolOfExpando(node: ts.Node, allowDeclaration: boolean): ts.Symbol | undefined { + function getSymbolOfExpando(node: Node, allowDeclaration: boolean): Symbol | undefined { if (!node.parent) { return undefined; } - let name: ts.Expression | ts.BindingName | undefined; - let decl: ts.Node | undefined; - if (ts.isVariableDeclaration(node.parent) && node.parent.initializer === node) { - if (!ts.isInJSFile(node) && !(ts.isVarConst(node.parent) && ts.isFunctionLikeDeclaration(node))) { + let name: Expression | BindingName | undefined; + let decl: Node | undefined; + if (isVariableDeclaration(node.parent) && node.parent.initializer === node) { + if (!isInJSFile(node) && !(isVarConst(node.parent) && isFunctionLikeDeclaration(node))) { return undefined; } name = node.parent.name; decl = node.parent; } - else if (ts.isBinaryExpression(node.parent)) { + else if (isBinaryExpression(node.parent)) { const parentNode = node.parent; const parentNodeOperator = node.parent.operatorToken.kind; - if (parentNodeOperator === ts.SyntaxKind.EqualsToken && (allowDeclaration || parentNode.right === node)) { + if (parentNodeOperator === SyntaxKind.EqualsToken && (allowDeclaration || parentNode.right === node)) { name = parentNode.left; decl = name; } - else if (parentNodeOperator === ts.SyntaxKind.BarBarToken || parentNodeOperator === ts.SyntaxKind.QuestionQuestionToken) { - if (ts.isVariableDeclaration(parentNode.parent) && parentNode.parent.initializer === parentNode) { + else if (parentNodeOperator === SyntaxKind.BarBarToken || parentNodeOperator === SyntaxKind.QuestionQuestionToken) { + if (isVariableDeclaration(parentNode.parent) && parentNode.parent.initializer === parentNode) { name = parentNode.parent.name; decl = parentNode.parent; } - else if (ts.isBinaryExpression(parentNode.parent) && parentNode.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && (allowDeclaration || parentNode.parent.right === parentNode)) { + else if (isBinaryExpression(parentNode.parent) && parentNode.parent.operatorToken.kind === SyntaxKind.EqualsToken && (allowDeclaration || parentNode.parent.right === parentNode)) { name = parentNode.parent.left; decl = name; } - if (!name || !ts.isBindableStaticNameExpression(name) || !ts.isSameEntityName(name, parentNode.left)) { + if (!name || !isBindableStaticNameExpression(name) || !isSameEntityName(name, parentNode.left)) { return undefined; } } } - else if (allowDeclaration && ts.isFunctionDeclaration(node)) { + else if (allowDeclaration && isFunctionDeclaration(node)) { name = node.name; decl = node; } - if (!decl || !name || (!allowDeclaration && !ts.getExpandoInitializer(node, ts.isPrototypeAccess(name)))) { + if (!decl || !name || (!allowDeclaration && !getExpandoInitializer(node, isPrototypeAccess(name)))) { return undefined; } return getSymbolOfNode(decl); } - function getAssignedJSPrototype(node: ts.Node) { + function getAssignedJSPrototype(node: Node) { if (!node.parent) { return false; } - let parent: ts.Node = node.parent; - while (parent && parent.kind === ts.SyntaxKind.PropertyAccessExpression) { + let parent: Node = node.parent; + while (parent && parent.kind === SyntaxKind.PropertyAccessExpression) { parent = parent.parent; } - if (parent && ts.isBinaryExpression(parent) && ts.isPrototypeAccess(parent.left) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { - const right = ts.getInitializerOfBinaryExpression(parent); - return ts.isObjectLiteralExpression(right) && right; + if (parent && isBinaryExpression(parent) && isPrototypeAccess(parent.left) && parent.operatorToken.kind === SyntaxKind.EqualsToken) { + const right = getInitializerOfBinaryExpression(parent); + return isObjectLiteralExpression(right) && right; } } @@ -32284,7 +32482,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param node The call/new expression to be checked. * @returns On success, the expression's signature's return type. On failure, anyType. */ - function checkCallExpression(node: ts.CallExpression | ts.NewExpression, checkMode?: CheckMode): ts.Type { + function checkCallExpression(node: CallExpression | NewExpression, checkMode?: CheckMode): Type { checkGrammarTypeArguments(node, node.typeArguments); const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode); @@ -32296,55 +32494,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkDeprecatedSignature(signature, node); - if (node.expression.kind === ts.SyntaxKind.SuperKeyword) { + if (node.expression.kind === SyntaxKind.SuperKeyword) { return voidType; } - if (node.kind === ts.SyntaxKind.NewExpression) { + if (node.kind === SyntaxKind.NewExpression) { const declaration = signature.declaration; if (declaration && - declaration.kind !== ts.SyntaxKind.Constructor && - declaration.kind !== ts.SyntaxKind.ConstructSignature && - declaration.kind !== ts.SyntaxKind.ConstructorType && - !ts.isJSDocConstructSignature(declaration) && + declaration.kind !== SyntaxKind.Constructor && + declaration.kind !== SyntaxKind.ConstructSignature && + declaration.kind !== SyntaxKind.ConstructorType && + !isJSDocConstructSignature(declaration) && !isJSConstructor(declaration)) { // When resolved signature is a call signature (and not a construct signature) the result type is any if (noImplicitAny) { - error(node, ts.Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); + error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } return anyType; } } // In JavaScript files, calls to any identifier 'require' are treated as external module imports - if (ts.isInJSFile(node) && isCommonJsRequire(node)) { - return resolveExternalModuleTypeByLiteral(node.arguments![0] as ts.StringLiteral); + if (isInJSFile(node) && isCommonJsRequire(node)) { + return resolveExternalModuleTypeByLiteral(node.arguments![0] as StringLiteral); } const returnType = getReturnTypeOfSignature(signature); // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property // as a fresh unique symbol literal type. - if (returnType.flags & ts.TypeFlags.ESSymbolLike && isSymbolOrSymbolForCall(node)) { - return getESSymbolLikeTypeForNode(ts.walkUpParenthesizedExpressions(node.parent)); + if (returnType.flags & TypeFlags.ESSymbolLike && isSymbolOrSymbolForCall(node)) { + return getESSymbolLikeTypeForNode(walkUpParenthesizedExpressions(node.parent)); } - if (node.kind === ts.SyntaxKind.CallExpression && !node.questionDotToken && node.parent.kind === ts.SyntaxKind.ExpressionStatement && - returnType.flags & ts.TypeFlags.Void && getTypePredicateOfSignature(signature)) { - if (!ts.isDottedName(node.expression)) { - error(node.expression, ts.Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name); + if (node.kind === SyntaxKind.CallExpression && !node.questionDotToken && node.parent.kind === SyntaxKind.ExpressionStatement && + returnType.flags & TypeFlags.Void && getTypePredicateOfSignature(signature)) { + if (!isDottedName(node.expression)) { + error(node.expression, Diagnostics.Assertions_require_the_call_target_to_be_an_identifier_or_qualified_name); } else if (!getEffectsSignature(node)) { - const diagnostic = error(node.expression, ts.Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation); + const diagnostic = error(node.expression, Diagnostics.Assertions_require_every_name_in_the_call_target_to_be_declared_with_an_explicit_type_annotation); getTypeOfDottedName(node.expression, diagnostic); } } - if (ts.isInJSFile(node)) { + if (isInJSFile(node)) { const jsSymbol = getSymbolOfExpando(node, /*allowDeclaration*/ false); if (jsSymbol?.exports?.size) { - const jsAssignmentType = createAnonymousType(jsSymbol, jsSymbol.exports, ts.emptyArray, ts.emptyArray, ts.emptyArray); - jsAssignmentType.objectFlags |= ts.ObjectFlags.JSLiteral; + const jsAssignmentType = createAnonymousType(jsSymbol, jsSymbol.exports, emptyArray, emptyArray, emptyArray); + jsAssignmentType.objectFlags |= ObjectFlags.JSLiteral; return getIntersectionType([returnType, jsAssignmentType]); } } @@ -32352,45 +32550,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return returnType; } - function checkDeprecatedSignature(signature: ts.Signature, node: ts.CallLikeExpression) { - if (signature.declaration && signature.declaration.flags & ts.NodeFlags.Deprecated) { + function checkDeprecatedSignature(signature: Signature, node: CallLikeExpression) { + if (signature.declaration && signature.declaration.flags & NodeFlags.Deprecated) { const suggestionNode = getDeprecatedSuggestionNode(node); - const name = ts.tryGetPropertyAccessOrIdentifierToString(ts.getInvokedExpression(node)); + const name = tryGetPropertyAccessOrIdentifierToString(getInvokedExpression(node)); addDeprecatedSuggestionWithSignature(suggestionNode, signature.declaration, name, signatureToString(signature)); } } - function getDeprecatedSuggestionNode(node: ts.Node): ts.Node { - node = ts.skipParentheses(node); + function getDeprecatedSuggestionNode(node: Node): Node { + node = skipParentheses(node); switch (node.kind) { - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.Decorator: - case ts.SyntaxKind.NewExpression: - return getDeprecatedSuggestionNode((node as ts.Decorator | ts.CallExpression | ts.NewExpression).expression); - case ts.SyntaxKind.TaggedTemplateExpression: - return getDeprecatedSuggestionNode((node as ts.TaggedTemplateExpression).tag); - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxSelfClosingElement: - return getDeprecatedSuggestionNode((node as ts.JsxOpeningLikeElement).tagName); - case ts.SyntaxKind.ElementAccessExpression: - return (node as ts.ElementAccessExpression).argumentExpression; - case ts.SyntaxKind.PropertyAccessExpression: - return (node as ts.PropertyAccessExpression).name; - case ts.SyntaxKind.TypeReference: - const typeReference = node as ts.TypeReferenceNode; - return ts.isQualifiedName(typeReference.typeName) ? typeReference.typeName.right : typeReference; + case SyntaxKind.CallExpression: + case SyntaxKind.Decorator: + case SyntaxKind.NewExpression: + return getDeprecatedSuggestionNode((node as Decorator | CallExpression | NewExpression).expression); + case SyntaxKind.TaggedTemplateExpression: + return getDeprecatedSuggestionNode((node as TaggedTemplateExpression).tag); + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxSelfClosingElement: + return getDeprecatedSuggestionNode((node as JsxOpeningLikeElement).tagName); + case SyntaxKind.ElementAccessExpression: + return (node as ElementAccessExpression).argumentExpression; + case SyntaxKind.PropertyAccessExpression: + return (node as PropertyAccessExpression).name; + case SyntaxKind.TypeReference: + const typeReference = node as TypeReferenceNode; + return isQualifiedName(typeReference.typeName) ? typeReference.typeName.right : typeReference; default: return node; } } - function isSymbolOrSymbolForCall(node: ts.Node) { - if (!ts.isCallExpression(node)) return false; + function isSymbolOrSymbolForCall(node: Node) { + if (!isCallExpression(node)) return false; let left = node.expression; - if (ts.isPropertyAccessExpression(left) && left.name.escapedText === "for") { + if (isPropertyAccessExpression(left) && left.name.escapedText === "for") { left = left.expression; } - if (!ts.isIdentifier(left) || left.escapedText !== "Symbol") { + if (!isIdentifier(left) || left.escapedText !== "Symbol") { return false; } @@ -32400,10 +32598,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - return globalESSymbol === resolveName(left, "Symbol" as ts.__String, ts.SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + return globalESSymbol === resolveName(left, "Symbol" as __String, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); } - function checkImportCallExpression(node: ts.ImportCall): ts.Type { + function checkImportCallExpression(node: ImportCall): Type { // Check grammar of dynamic import checkGrammarImportCallExpression(node); @@ -32419,14 +32617,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkExpressionCached(node.arguments[i]); } - if (specifierType.flags & ts.TypeFlags.Undefined || specifierType.flags & ts.TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) { - error(specifier, ts.Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); + if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) { + error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType)); } if (optionsType) { const importCallOptionsType = getGlobalImportCallOptionsType(/*reportErrors*/ true); if (importCallOptionsType !== emptyObjectType) { - checkTypeAssignableTo(optionsType, getNullableType(importCallOptionsType, ts.TypeFlags.Undefined), node.arguments[1]); + checkTypeAssignableTo(optionsType, getNullableType(importCallOptionsType, TypeFlags.Undefined), node.arguments[1]); } } @@ -32444,20 +32642,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createPromiseReturnType(node, anyType); } - function createDefaultPropertyWrapperForModule(symbol: ts.Symbol, originalSymbol: ts.Symbol, anonymousSymbol?: ts.Symbol | undefined) { - const memberTable = ts.createSymbolTable(); - const newSymbol = createSymbol(ts.SymbolFlags.Alias, ts.InternalSymbolName.Default); + function createDefaultPropertyWrapperForModule(symbol: Symbol, originalSymbol: Symbol, anonymousSymbol?: Symbol | undefined) { + const memberTable = createSymbolTable(); + const newSymbol = createSymbol(SymbolFlags.Alias, InternalSymbolName.Default); newSymbol.parent = originalSymbol; newSymbol.nameType = getStringLiteralType("default"); newSymbol.aliasTarget = resolveSymbol(symbol); - memberTable.set(ts.InternalSymbolName.Default, newSymbol); - return createAnonymousType(anonymousSymbol, memberTable, ts.emptyArray, ts.emptyArray, ts.emptyArray); + memberTable.set(InternalSymbolName.Default, newSymbol); + return createAnonymousType(anonymousSymbol, memberTable, emptyArray, emptyArray, emptyArray); } - function getTypeWithSyntheticDefaultOnly(type: ts.Type, symbol: ts.Symbol, originalSymbol: ts.Symbol, moduleSpecifier: ts.Expression) { + function getTypeWithSyntheticDefaultOnly(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression) { const hasDefaultOnly = isOnlyImportedAsDefault(moduleSpecifier); if (hasDefaultOnly && type && !isErrorType(type)) { - const synthType = type as ts.SyntheticDefaultModuleType; + const synthType = type as SyntheticDefaultModuleType; if (!synthType.defaultOnlyType) { const type = createDefaultPropertyWrapperForModule(symbol, originalSymbol); synthType.defaultOnlyType = type; @@ -32467,14 +32665,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getTypeWithSyntheticDefaultImportType(type: ts.Type, symbol: ts.Symbol, originalSymbol: ts.Symbol, moduleSpecifier: ts.Expression): ts.Type { + function getTypeWithSyntheticDefaultImportType(type: Type, symbol: Symbol, originalSymbol: Symbol, moduleSpecifier: Expression): Type { if (allowSyntheticDefaultImports && type && !isErrorType(type)) { - const synthType = type as ts.SyntheticDefaultModuleType; + const synthType = type as SyntheticDefaultModuleType; if (!synthType.syntheticType) { - const file = originalSymbol.declarations?.find(ts.isSourceFile); + const file = originalSymbol.declarations?.find(isSourceFile); const hasSyntheticDefault = canHaveSyntheticDefault(file, originalSymbol, /*dontResolveAlias*/ false, moduleSpecifier); if (hasSyntheticDefault) { - const anonymousSymbol = createSymbol(ts.SymbolFlags.TypeLiteral, ts.InternalSymbolName.Type); + const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); const defaultContainingObject = createDefaultPropertyWrapperForModule(symbol, originalSymbol, anonymousSymbol); anonymousSymbol.type = defaultContainingObject; synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; @@ -32488,91 +32686,91 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function isCommonJsRequire(node: ts.Node): boolean { - if (!ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { + function isCommonJsRequire(node: Node): boolean { + if (!isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { return false; } // Make sure require is not a local function - if (!ts.isIdentifier(node.expression)) return ts.Debug.fail(); - const resolvedRequire = resolveName(node.expression, node.expression.escapedText, ts.SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true)!; // TODO: GH#18217 + if (!isIdentifier(node.expression)) return Debug.fail(); + const resolvedRequire = resolveName(node.expression, node.expression.escapedText, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true)!; // TODO: GH#18217 if (resolvedRequire === requireSymbol) { return true; } // project includes symbol named 'require' - make sure that it is ambient and local non-alias - if (resolvedRequire.flags & ts.SymbolFlags.Alias) { + if (resolvedRequire.flags & SymbolFlags.Alias) { return false; } - const targetDeclarationKind = resolvedRequire.flags & ts.SymbolFlags.Function - ? ts.SyntaxKind.FunctionDeclaration - : resolvedRequire.flags & ts.SymbolFlags.Variable - ? ts.SyntaxKind.VariableDeclaration - : ts.SyntaxKind.Unknown; - if (targetDeclarationKind !== ts.SyntaxKind.Unknown) { - const decl = ts.getDeclarationOfKind(resolvedRequire, targetDeclarationKind)!; + const targetDeclarationKind = resolvedRequire.flags & SymbolFlags.Function + ? SyntaxKind.FunctionDeclaration + : resolvedRequire.flags & SymbolFlags.Variable + ? SyntaxKind.VariableDeclaration + : SyntaxKind.Unknown; + if (targetDeclarationKind !== SyntaxKind.Unknown) { + const decl = getDeclarationOfKind(resolvedRequire, targetDeclarationKind)!; // function/variable declaration should be ambient - return !!decl && !!(decl.flags & ts.NodeFlags.Ambient); + return !!decl && !!(decl.flags & NodeFlags.Ambient); } return false; } - function checkTaggedTemplateExpression(node: ts.TaggedTemplateExpression): ts.Type { + function checkTaggedTemplateExpression(node: TaggedTemplateExpression): Type { if (!checkGrammarTaggedTemplateChain(node)) checkGrammarTypeArguments(node, node.typeArguments); - if (languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.MakeTemplateObject); + if (languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.MakeTemplateObject); } const signature = getResolvedSignature(node); checkDeprecatedSignature(signature, node); return getReturnTypeOfSignature(signature); } - function checkAssertion(node: ts.AssertionExpression) { - if (node.kind === ts.SyntaxKind.TypeAssertionExpression) { - const file = ts.getSourceFileOfNode(node); - if (file && ts.fileExtensionIsOneOf(file.fileName, [ts.Extension.Cts, ts.Extension.Mts])) { - grammarErrorOnNode(node, ts.Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead); + function checkAssertion(node: AssertionExpression) { + if (node.kind === SyntaxKind.TypeAssertionExpression) { + const file = getSourceFileOfNode(node); + if (file && fileExtensionIsOneOf(file.fileName, [Extension.Cts, Extension.Mts])) { + grammarErrorOnNode(node, Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Use_an_as_expression_instead); } } return checkAssertionWorker(node, node.type, node.expression); } - function isValidConstAssertionArgument(node: ts.Node): boolean { + function isValidConstAssertionArgument(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.ArrayLiteralExpression: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.TemplateExpression: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TemplateExpression: return true; - case ts.SyntaxKind.ParenthesizedExpression: - return isValidConstAssertionArgument((node as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.PrefixUnaryExpression: - const op = (node as ts.PrefixUnaryExpression).operator; - const arg = (node as ts.PrefixUnaryExpression).operand; - return op === ts.SyntaxKind.MinusToken && (arg.kind === ts.SyntaxKind.NumericLiteral || arg.kind === ts.SyntaxKind.BigIntLiteral) || - op === ts.SyntaxKind.PlusToken && arg.kind === ts.SyntaxKind.NumericLiteral; - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - const expr = (node as ts.PropertyAccessExpression | ts.ElementAccessExpression).expression; + case SyntaxKind.ParenthesizedExpression: + return isValidConstAssertionArgument((node as ParenthesizedExpression).expression); + case SyntaxKind.PrefixUnaryExpression: + const op = (node as PrefixUnaryExpression).operator; + const arg = (node as PrefixUnaryExpression).operand; + return op === SyntaxKind.MinusToken && (arg.kind === SyntaxKind.NumericLiteral || arg.kind === SyntaxKind.BigIntLiteral) || + op === SyntaxKind.PlusToken && arg.kind === SyntaxKind.NumericLiteral; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + const expr = (node as PropertyAccessExpression | ElementAccessExpression).expression; let symbol = getTypeOfNode(expr).symbol; - if (symbol && symbol.flags & ts.SymbolFlags.Alias) { + if (symbol && symbol.flags & SymbolFlags.Alias) { symbol = resolveAlias(symbol); } - return !!(symbol && getAllSymbolFlags(symbol) & ts.SymbolFlags.Enum); + return !!(symbol && getAllSymbolFlags(symbol) & SymbolFlags.Enum); } return false; } - function checkAssertionWorker(errNode: ts.Node, type: ts.TypeNode, expression: ts.UnaryExpression | ts.Expression, checkMode?: CheckMode) { + function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) { let exprType = checkExpression(expression, checkMode); - if (ts.isConstTypeReference(type)) { + if (isConstTypeReference(type)) { if (!isValidConstAssertionArgument(expression)) { - error(expression, ts.Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals); + error(expression, Diagnostics.A_const_assertions_can_only_be_applied_to_references_to_enum_members_or_string_number_boolean_array_or_object_literals); } return getRegularTypeOfLiteralType(exprType); } @@ -32584,43 +32782,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const widenedType = getWidenedType(exprType); if (!isTypeComparableTo(targetType, widenedType)) { checkTypeComparableTo(exprType, targetType, errNode, - ts.Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first); + Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first); } }); } return targetType; } - function checkNonNullChain(node: ts.NonNullChain) { + function checkNonNullChain(node: NonNullChain) { const leftType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(leftType, node.expression); return propagateOptionalTypeMarker(getNonNullableType(nonOptionalType), node, nonOptionalType !== leftType); } - function checkNonNullAssertion(node: ts.NonNullExpression) { - return node.flags & ts.NodeFlags.OptionalChain ? checkNonNullChain(node as ts.NonNullChain) : + function checkNonNullAssertion(node: NonNullExpression) { + return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) : getNonNullableType(checkExpression(node.expression)); } - function checkExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments | ts.TypeQueryNode) { + function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { checkGrammarExpressionWithTypeArguments(node); - const exprType = node.kind === ts.SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) : - ts.isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) : + const exprType = node.kind === SyntaxKind.ExpressionWithTypeArguments ? checkExpression(node.expression) : + isThisIdentifier(node.exprName) ? checkThisExpression(node.exprName) : checkExpression(node.exprName); const typeArguments = node.typeArguments; - if (exprType === silentNeverType || isErrorType(exprType) || !ts.some(typeArguments)) { + if (exprType === silentNeverType || isErrorType(exprType) || !some(typeArguments)) { return exprType; } let hasSomeApplicableSignature = false; - let nonApplicableType: ts.Type | undefined; + let nonApplicableType: Type | undefined; const result = getInstantiatedType(exprType); const errorType = hasSomeApplicableSignature ? nonApplicableType : exprType; if (errorType) { - diagnostics.add(ts.createDiagnosticForNodeArray(ts.getSourceFileOfNode(node), typeArguments, ts.Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, typeToString(errorType))); + diagnostics.add(createDiagnosticForNodeArray(getSourceFileOfNode(node), typeArguments, Diagnostics.Type_0_has_no_signatures_for_which_the_type_argument_list_is_applicable, typeToString(errorType))); } return result; - function getInstantiatedType(type: ts.Type): ts.Type { + function getInstantiatedType(type: Type): Type { let hasSignatures = false; let hasApplicableSignature = false; const result = getInstantiatedTypePart(type); @@ -32630,21 +32828,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return result; - function getInstantiatedTypePart(type: ts.Type): ts.Type { - if (type.flags & ts.TypeFlags.Object) { - const resolved = resolveStructuredTypeMembers(type as ts.ObjectType); + function getInstantiatedTypePart(type: Type): Type { + if (type.flags & TypeFlags.Object) { + const resolved = resolveStructuredTypeMembers(type as ObjectType); const callSignatures = getInstantiatedSignatures(resolved.callSignatures); const constructSignatures = getInstantiatedSignatures(resolved.constructSignatures); hasSignatures ||= resolved.callSignatures.length !== 0 || resolved.constructSignatures.length !== 0; hasApplicableSignature ||= callSignatures.length !== 0 || constructSignatures.length !== 0; if (callSignatures !== resolved.callSignatures || constructSignatures !== resolved.constructSignatures) { - const result = createAnonymousType(undefined, resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ts.ResolvedType & ts.InstantiationExpressionType; - result.objectFlags |= ts.ObjectFlags.InstantiationExpressionType; + const result = createAnonymousType(undefined, resolved.members, callSignatures, constructSignatures, resolved.indexInfos) as ResolvedType & InstantiationExpressionType; + result.objectFlags |= ObjectFlags.InstantiationExpressionType; result.node = node; return result; } } - else if (type.flags & ts.TypeFlags.InstantiableNonPrimitive) { + else if (type.flags & TypeFlags.InstantiableNonPrimitive) { const constraint = getBaseConstraintOfType(type); if (constraint) { const instantiated = getInstantiatedTypePart(constraint); @@ -32653,26 +32851,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (type.flags & ts.TypeFlags.Union) { + else if (type.flags & TypeFlags.Union) { return mapType(type, getInstantiatedType); } - else if (type.flags & ts.TypeFlags.Intersection) { - return getIntersectionType(ts.sameMap((type as ts.IntersectionType).types, getInstantiatedTypePart)); + else if (type.flags & TypeFlags.Intersection) { + return getIntersectionType(sameMap((type as IntersectionType).types, getInstantiatedTypePart)); } return type; } } - function getInstantiatedSignatures(signatures: readonly ts.Signature[]) { - const applicableSignatures = ts.filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments)); - return ts.sameMap(applicableSignatures, sig => { + function getInstantiatedSignatures(signatures: readonly Signature[]) { + const applicableSignatures = filter(signatures, sig => !!sig.typeParameters && hasCorrectTypeArgumentArity(sig, typeArguments)); + return sameMap(applicableSignatures, sig => { const typeArgumentTypes = checkTypeArguments(sig, typeArguments!, /*reportErrors*/ true); - return typeArgumentTypes ? getSignatureInstantiation(sig, typeArgumentTypes, ts.isInJSFile(sig.declaration)) : sig; + return typeArgumentTypes ? getSignatureInstantiation(sig, typeArgumentTypes, isInJSFile(sig.declaration)) : sig; }); } } - function checkSatisfiesExpression(node: ts.SatisfiesExpression) { + function checkSatisfiesExpression(node: SatisfiesExpression) { checkSourceElement(node.type); const targetType = getTypeFromTypeNode(node.type); @@ -32681,45 +32879,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const exprType = checkExpression(node.expression); - checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, node.type, node.expression, ts.Diagnostics.Type_0_does_not_satisfy_the_expected_type_1); + checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, node.type, node.expression, Diagnostics.Type_0_does_not_satisfy_the_expected_type_1); return exprType; } - function checkMetaProperty(node: ts.MetaProperty): ts.Type { + function checkMetaProperty(node: MetaProperty): Type { checkGrammarMetaProperty(node); - if (node.keywordToken === ts.SyntaxKind.NewKeyword) { + if (node.keywordToken === SyntaxKind.NewKeyword) { return checkNewTargetMetaProperty(node); } - if (node.keywordToken === ts.SyntaxKind.ImportKeyword) { + if (node.keywordToken === SyntaxKind.ImportKeyword) { return checkImportMetaProperty(node); } - return ts.Debug.assertNever(node.keywordToken); + return Debug.assertNever(node.keywordToken); } - function checkMetaPropertyKeyword(node: ts.MetaProperty): ts.Type { + function checkMetaPropertyKeyword(node: MetaProperty): Type { switch (node.keywordToken) { - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: return getGlobalImportMetaExpressionType(); - case ts.SyntaxKind.NewKeyword: + case SyntaxKind.NewKeyword: const type = checkNewTargetMetaProperty(node); return isErrorType(type) ? errorType : createNewTargetExpressionType(type); default: - ts.Debug.assertNever(node.keywordToken); + Debug.assertNever(node.keywordToken); } } - function checkNewTargetMetaProperty(node: ts.MetaProperty) { - const container = ts.getNewTargetContainer(node); + function checkNewTargetMetaProperty(node: MetaProperty) { + const container = getNewTargetContainer(node); if (!container) { - error(node, ts.Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); + error(node, Diagnostics.Meta_property_0_is_only_allowed_in_the_body_of_a_function_declaration_function_expression_or_constructor, "new.target"); return errorType; } - else if (container.kind === ts.SyntaxKind.Constructor) { - const symbol = getSymbolOfNode(container.parent as ts.ClassLikeDeclaration); + else if (container.kind === SyntaxKind.Constructor) { + const symbol = getSymbolOfNode(container.parent as ClassLikeDeclaration); return getTypeOfSymbol(symbol); } else { @@ -32728,37 +32926,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkImportMetaProperty(node: ts.MetaProperty) { - if (moduleKind === ts.ModuleKind.Node16 || moduleKind === ts.ModuleKind.NodeNext) { - if (ts.getSourceFileOfNode(node).impliedNodeFormat !== ts.ModuleKind.ESNext) { - error(node, ts.Diagnostics.The_import_meta_meta_property_is_not_allowed_in_files_which_will_build_into_CommonJS_output); + function checkImportMetaProperty(node: MetaProperty) { + if (moduleKind === ModuleKind.Node16 || moduleKind === ModuleKind.NodeNext) { + if (getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.ESNext) { + error(node, Diagnostics.The_import_meta_meta_property_is_not_allowed_in_files_which_will_build_into_CommonJS_output); } } - else if (moduleKind < ts.ModuleKind.ES2020 && moduleKind !== ts.ModuleKind.System) { - error(node, ts.Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_or_nodenext); + else if (moduleKind < ModuleKind.ES2020 && moduleKind !== ModuleKind.System) { + error(node, Diagnostics.The_import_meta_meta_property_is_only_allowed_when_the_module_option_is_es2020_es2022_esnext_system_node16_or_nodenext); } - const file = ts.getSourceFileOfNode(node); - ts.Debug.assert(!!(file.flags & ts.NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag."); + const file = getSourceFileOfNode(node); + Debug.assert(!!(file.flags & NodeFlags.PossiblyContainsImportMeta), "Containing file is missing import meta node flag."); return node.name.escapedText === "meta" ? getGlobalImportMetaType() : errorType; } - function getTypeOfParameter(symbol: ts.Symbol) { + function getTypeOfParameter(symbol: Symbol) { const type = getTypeOfSymbol(symbol); if (strictNullChecks) { const declaration = symbol.valueDeclaration; - if (declaration && ts.hasInitializer(declaration)) { + if (declaration && hasInitializer(declaration)) { return getOptionalType(type); } } return type; } - function getTupleElementLabel(d: ts.ParameterDeclaration | ts.NamedTupleMember) { - ts.Debug.assert(ts.isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names + function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) { + Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names return d.name.escapedText; } - function getParameterNameAtPosition(signature: ts.Signature, pos: number, overrideRestType?: ts.Type) { + function getParameterNameAtPosition(signature: Signature, pos: number, overrideRestType?: Type) { const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); if (pos < paramCount) { return signature.parameters[pos].escapedName; @@ -32766,15 +32964,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const restParameter = signature.parameters[paramCount] || unknownSymbol; const restType = overrideRestType || getTypeOfSymbol(restParameter); if (isTupleType(restType)) { - const associatedNames = ((restType as ts.TypeReference).target as ts.TupleType).labeledElementDeclarations; + const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations; const index = pos - paramCount; - return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as ts.__String; + return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String; } return restParameter.escapedName; } - function getParameterIdentifierNameAtPosition(signature: ts.Signature, pos: number): [parameterName: ts.__String, isRestParameter: boolean] | undefined { - if (signature.declaration?.kind === ts.SyntaxKind.JSDocFunctionType) { + function getParameterIdentifierNameAtPosition(signature: Signature, pos: number): [parameterName: __String, isRestParameter: boolean] | undefined { + if (signature.declaration?.kind === SyntaxKind.JSDocFunctionType) { return undefined; } const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); @@ -32790,7 +32988,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const restType = getTypeOfSymbol(restParameter); if (isTupleType(restType)) { - const associatedNames = ((restType as ts.TypeReference).target as ts.TupleType).labeledElementDeclarations; + const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations; const index = pos - paramCount; const associatedName = associatedNames?.[index]; const isRestTupleElement = !!associatedName?.dotDotDotToken; @@ -32806,14 +33004,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isParameterDeclarationWithIdentifierName(symbol: ts.Symbol) { - return symbol.valueDeclaration && ts.isParameter(symbol.valueDeclaration) && ts.isIdentifier(symbol.valueDeclaration.name); + function isParameterDeclarationWithIdentifierName(symbol: Symbol) { + return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isIdentifier(symbol.valueDeclaration.name); } - function isValidDeclarationForTupleLabel(d: ts.Declaration): d is ts.NamedTupleMember | (ts.ParameterDeclaration & { name: ts.Identifier }) { - return d.kind === ts.SyntaxKind.NamedTupleMember || (ts.isParameter(d) && d.name && ts.isIdentifier(d.name)); + function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) { + return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && d.name && isIdentifier(d.name)); } - function getNameableDeclarationAtPosition(signature: ts.Signature, pos: number) { + function getNameableDeclarationAtPosition(signature: Signature, pos: number) { const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); if (pos < paramCount) { const decl = signature.parameters[pos].valueDeclaration; @@ -32822,18 +33020,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const restParameter = signature.parameters[paramCount] || unknownSymbol; const restType = getTypeOfSymbol(restParameter); if (isTupleType(restType)) { - const associatedNames = ((restType as ts.TypeReference).target as ts.TupleType).labeledElementDeclarations; + const associatedNames = ((restType as TypeReference).target as TupleType).labeledElementDeclarations; const index = pos - paramCount; return associatedNames && associatedNames[index]; } return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined; } - function getTypeAtPosition(signature: ts.Signature, pos: number): ts.Type { + function getTypeAtPosition(signature: Signature, pos: number): Type { return tryGetTypeAtPosition(signature, pos) || anyType; } - function tryGetTypeAtPosition(signature: ts.Signature, pos: number): ts.Type | undefined { + function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined { const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); if (pos < paramCount) { return getTypeOfParameter(signature.parameters[pos]); @@ -32851,7 +33049,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getRestTypeAtPosition(source: ts.Signature, pos: number): ts.Type { + function getRestTypeAtPosition(source: Signature, pos: number): Type { const parameterCount = getParameterCount(source); const minArgumentCount = getMinArgumentCount(source); const restType = getEffectiveRestType(source); @@ -32864,25 +33062,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (let i = pos; i < parameterCount; i++) { if (!restType || i < parameterCount - 1) { types.push(getTypeAtPosition(source, i)); - flags.push(i < minArgumentCount ? ts.ElementFlags.Required : ts.ElementFlags.Optional); + flags.push(i < minArgumentCount ? ElementFlags.Required : ElementFlags.Optional); } else { types.push(restType); - flags.push(ts.ElementFlags.Variadic); + flags.push(ElementFlags.Variadic); } const name = getNameableDeclarationAtPosition(source, i); if (name) { names.push(name); } } - return createTupleType(types, flags, /*readonly*/ false, ts.length(names) === ts.length(types) ? names : undefined); + return createTupleType(types, flags, /*readonly*/ false, length(names) === length(types) ? names : undefined); } // Return the number of parameters in a signature. The rest parameter, if present, counts as one // parameter. For example, the parameter count of (x: number, y: number, ...z: string[]) is 3 and // the parameter count of (x: number, ...args: [number, ...string[], boolean])) is also 3. In the // latter example, the effective rest type is [...string[], boolean]. - function getParameterCount(signature: ts.Signature) { + function getParameterCount(signature: Signature) { const length = signature.parameters.length; if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[length - 1]); @@ -32893,7 +33091,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return length; } - function getMinArgumentCount(signature: ts.Signature, flags?: MinArgumentCountFlags) { + function getMinArgumentCount(signature: Signature, flags?: MinArgumentCountFlags) { const strongArityForUntypedJS = flags! & MinArgumentCountFlags.StrongArityForUntypedJS; const voidIsNonOptional = flags! & MinArgumentCountFlags.VoidIsNonOptional; if (voidIsNonOptional || signature.resolvedMinArgumentCount === undefined) { @@ -32901,7 +33099,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); if (isTupleType(restType)) { - const firstOptionalIndex = ts.findIndex(restType.target.elementFlags, f => !(f & ts.ElementFlags.Required)); + const firstOptionalIndex = findIndex(restType.target.elementFlags, f => !(f & ElementFlags.Required)); const requiredCount = firstOptionalIndex < 0 ? restType.target.fixedLength : firstOptionalIndex; if (requiredCount > 0) { minArgumentCount = signature.parameters.length - 1 + requiredCount; @@ -32909,7 +33107,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } if (minArgumentCount === undefined) { - if (!strongArityForUntypedJS && signature.flags & ts.SignatureFlags.IsUntypedSignatureInJSFile) { + if (!strongArityForUntypedJS && signature.flags & SignatureFlags.IsUntypedSignatureInJSFile) { return 0; } minArgumentCount = signature.minArgumentCount; @@ -32919,7 +33117,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } for (let i = minArgumentCount - 1; i >= 0; i--) { const type = getTypeAtPosition(signature, i); - if (filterType(type, acceptsVoid).flags & ts.TypeFlags.Never) { + if (filterType(type, acceptsVoid).flags & TypeFlags.Never) { break; } minArgumentCount = i; @@ -32929,7 +33127,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return signature.resolvedMinArgumentCount; } - function hasEffectiveRestParameter(signature: ts.Signature) { + function hasEffectiveRestParameter(signature: Signature) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); return !isTupleType(restType) || restType.target.hasRestElement; @@ -32937,7 +33135,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function getEffectiveRestType(signature: ts.Signature) { + function getEffectiveRestType(signature: Signature) { if (signatureHasRestParameter(signature)) { const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]); if (!isTupleType(restType)) { @@ -32950,25 +33148,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function getNonArrayRestType(signature: ts.Signature) { + function getNonArrayRestType(signature: Signature) { const restType = getEffectiveRestType(signature); - return restType && !isArrayType(restType) && !isTypeAny(restType) && (getReducedType(restType).flags & ts.TypeFlags.Never) === 0 ? restType : undefined; + return restType && !isArrayType(restType) && !isTypeAny(restType) && (getReducedType(restType).flags & TypeFlags.Never) === 0 ? restType : undefined; } - function getTypeOfFirstParameterOfSignature(signature: ts.Signature) { + function getTypeOfFirstParameterOfSignature(signature: Signature) { return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType); } - function getTypeOfFirstParameterOfSignatureWithFallback(signature: ts.Signature, fallbackType: ts.Type) { + function getTypeOfFirstParameterOfSignatureWithFallback(signature: Signature, fallbackType: Type) { return signature.parameters.length > 0 ? getTypeAtPosition(signature, 0) : fallbackType; } - function inferFromAnnotatedParameters(signature: ts.Signature, context: ts.Signature, inferenceContext: ts.InferenceContext) { + function inferFromAnnotatedParameters(signature: Signature, context: Signature, inferenceContext: InferenceContext) { const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); for (let i = 0; i < len; i++) { - const declaration = signature.parameters[i].valueDeclaration as ts.ParameterDeclaration; + const declaration = signature.parameters[i].valueDeclaration as ParameterDeclaration; if (declaration.type) { - const typeNode = ts.getEffectiveTypeAnnotationNode(declaration); + const typeNode = getEffectiveTypeAnnotationNode(declaration); if (typeNode) { inferTypes(inferenceContext.inferences, getTypeFromTypeNode(typeNode), getTypeAtPosition(context, i)); } @@ -32976,7 +33174,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function assignContextualParameterTypes(signature: ts.Signature, context: ts.Signature) { + function assignContextualParameterTypes(signature: Signature, context: Signature) { if (context.typeParameters) { if (!signature.typeParameters) { signature.typeParameters = context.typeParameters; @@ -32987,7 +33185,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (context.thisParameter) { const parameter = signature.thisParameter; - if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration as ts.ParameterDeclaration).type) { + if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration as ParameterDeclaration).type) { if (!parameter) { signature.thisParameter = createSymbolWithType(context.thisParameter, /*type*/ undefined); } @@ -32997,19 +33195,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const len = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0); for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; - if (!ts.getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ts.ParameterDeclaration)) { + if (!getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration)) { const contextualParameterType = tryGetTypeAtPosition(context, i); assignParameterType(parameter, contextualParameterType); } } if (signatureHasRestParameter(signature)) { // parameter might be a transient symbol generated by use of `arguments` in the function body. - const parameter = ts.last(signature.parameters); + const parameter = last(signature.parameters); if (parameter.valueDeclaration - ? !ts.getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ts.ParameterDeclaration) + ? !getEffectiveTypeAnnotationNode(parameter.valueDeclaration as ParameterDeclaration) // a declarationless parameter may still have a `.type` already set by its construction logic // (which may pull a type from a jsdoc) - only allow fixing on `DeferredType` parameters with a fallback type - : !!(ts.getCheckFlags(parameter) & ts.CheckFlags.DeferredType) + : !!(getCheckFlags(parameter) & CheckFlags.DeferredType) ) { const contextualParameterType = getRestTypeAtPosition(context, len); assignParameterType(parameter, contextualParameterType); @@ -33017,7 +33215,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function assignNonContextualParameterTypes(signature: ts.Signature) { + function assignNonContextualParameterTypes(signature: Signature) { if (signature.thisParameter) { assignParameterType(signature.thisParameter); } @@ -33026,12 +33224,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function assignParameterType(parameter: ts.Symbol, type?: ts.Type) { + function assignParameterType(parameter: Symbol, type?: Type) { const links = getSymbolLinks(parameter); if (!links.type) { - const declaration = parameter.valueDeclaration as ts.ParameterDeclaration | undefined; + const declaration = parameter.valueDeclaration as ParameterDeclaration | undefined; links.type = type || (declaration ? getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true) : getTypeOfSymbol(parameter)); - if (declaration && declaration.name.kind !== ts.SyntaxKind.Identifier) { + if (declaration && declaration.name.kind !== SyntaxKind.Identifier) { // if inference didn't come up with anything but unknown, fall back to the binding pattern if present. if (links.type === unknownType) { links.type = getTypeFromBindingPattern(declaration.name); @@ -33040,17 +33238,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } else if (type) { - ts.Debug.assertEqual(links.type, type, "Parameter symbol already has a cached type which differs from newly assigned type"); + Debug.assertEqual(links.type, type, "Parameter symbol already has a cached type which differs from newly assigned type"); } } // When contextual typing assigns a type to a parameter that contains a binding pattern, we also need to push // the destructured type into the contained binding elements. - function assignBindingElementTypes(pattern: ts.BindingPattern, parentType: ts.Type) { + function assignBindingElementTypes(pattern: BindingPattern, parentType: Type) { for (const element of pattern.elements) { - if (!ts.isOmittedExpression(element)) { + if (!isOmittedExpression(element)) { const type = getBindingElementTypeFromParentType(element, parentType); - if (element.name.kind === ts.SyntaxKind.Identifier) { + if (element.name.kind === SyntaxKind.Identifier) { getSymbolLinks(getSymbolOfNode(element)).type = type; } else { @@ -33060,7 +33258,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function createPromiseType(promisedType: ts.Type): ts.Type { + function createPromiseType(promisedType: Type): Type { // creates a `Promise` type where `T` is the promisedType argument const globalPromiseType = getGlobalPromiseType(/*reportErrors*/ true); if (globalPromiseType !== emptyGenericType) { @@ -33073,7 +33271,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return unknownType; } - function createPromiseLikeType(promisedType: ts.Type): ts.Type { + function createPromiseLikeType(promisedType: Type): Type { // creates a `PromiseLike` type where `T` is the promisedType argument const globalPromiseLikeType = getGlobalPromiseLikeType(/*reportErrors*/ true); if (globalPromiseLikeType !== emptyGenericType) { @@ -33086,57 +33284,57 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return unknownType; } - function createPromiseReturnType(func: ts.FunctionLikeDeclaration | ts.ImportCall, promisedType: ts.Type) { + function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) { const promiseType = createPromiseType(promisedType); if (promiseType === unknownType) { - error(func, ts.isImportCall(func) ? - ts.Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option : - ts.Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); + error(func, isImportCall(func) ? + Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option : + Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option); return errorType; } else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) { - error(func, ts.isImportCall(func) ? - ts.Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : - ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); + error(func, isImportCall(func) ? + Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option : + Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } return promiseType; } - function createNewTargetExpressionType(targetType: ts.Type): ts.Type { + function createNewTargetExpressionType(targetType: Type): Type { // Create a synthetic type `NewTargetExpression { target: TargetType; }` - const symbol = createSymbol(ts.SymbolFlags.None, "NewTargetExpression" as ts.__String); + const symbol = createSymbol(SymbolFlags.None, "NewTargetExpression" as __String); - const targetPropertySymbol = createSymbol(ts.SymbolFlags.Property, "target" as ts.__String, ts.CheckFlags.Readonly); + const targetPropertySymbol = createSymbol(SymbolFlags.Property, "target" as __String, CheckFlags.Readonly); targetPropertySymbol.parent = symbol; targetPropertySymbol.type = targetType; - const members = ts.createSymbolTable([targetPropertySymbol]); + const members = createSymbolTable([targetPropertySymbol]); symbol.members = members; - return createAnonymousType(symbol, members, ts.emptyArray, ts.emptyArray, ts.emptyArray); + return createAnonymousType(symbol, members, emptyArray, emptyArray, emptyArray); } - function getReturnTypeFromBody(func: ts.FunctionLikeDeclaration, checkMode?: CheckMode): ts.Type { + function getReturnTypeFromBody(func: FunctionLikeDeclaration, checkMode?: CheckMode): Type { if (!func.body) { return errorType; } - const functionFlags = ts.getFunctionFlags(func); - const isAsync = (functionFlags & ts.FunctionFlags.Async) !== 0; - const isGenerator = (functionFlags & ts.FunctionFlags.Generator) !== 0; + const functionFlags = getFunctionFlags(func); + const isAsync = (functionFlags & FunctionFlags.Async) !== 0; + const isGenerator = (functionFlags & FunctionFlags.Generator) !== 0; - let returnType: ts.Type | undefined; - let yieldType: ts.Type | undefined; - let nextType: ts.Type | undefined; - let fallbackReturnType: ts.Type = voidType; - if (func.body.kind !== ts.SyntaxKind.Block) { // Async or normal arrow function + let returnType: Type | undefined; + let yieldType: Type | undefined; + let nextType: Type | undefined; + let fallbackReturnType: Type = voidType; + if (func.body.kind !== SyntaxKind.Block) { // Async or normal arrow function returnType = checkExpressionCached(func.body, checkMode && checkMode & ~CheckMode.SkipGenericFunctions); if (isAsync) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the // return type of the body should be unwrapped to its awaited type, which we will wrap in // the native Promise type later in this function. - returnType = unwrapAwaitedType(checkAwaitedType(returnType, /*withAlias*/ false, /*errorNode*/ func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); + returnType = unwrapAwaitedType(checkAwaitedType(returnType, /*withAlias*/ false, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); } } else if (isGenerator) { // Generator or AsyncGenerator function @@ -33145,29 +33343,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { fallbackReturnType = neverType; } else if (returnTypes.length > 0) { - returnType = getUnionType(returnTypes, ts.UnionReduction.Subtype); + returnType = getUnionType(returnTypes, UnionReduction.Subtype); } const { yieldTypes, nextTypes } = checkAndAggregateYieldOperandTypes(func, checkMode); - yieldType = ts.some(yieldTypes) ? getUnionType(yieldTypes, ts.UnionReduction.Subtype) : undefined; - nextType = ts.some(nextTypes) ? getIntersectionType(nextTypes) : undefined; + yieldType = some(yieldTypes) ? getUnionType(yieldTypes, UnionReduction.Subtype) : undefined; + nextType = some(nextTypes) ? getIntersectionType(nextTypes) : undefined; } else { // Async or normal function const types = checkAndAggregateReturnExpressionTypes(func, checkMode); if (!types) { // For an async function, the return type will not be never, but rather a Promise for never. - return functionFlags & ts.FunctionFlags.Async + return functionFlags & FunctionFlags.Async ? createPromiseReturnType(func, neverType) // Async function : neverType; // Normal function } if (types.length === 0) { // For an async function, the return type will not be void, but rather a Promise for void. - return functionFlags & ts.FunctionFlags.Async + return functionFlags & FunctionFlags.Async ? createPromiseReturnType(func, voidType) // Async function : voidType; // Normal function } // Return a union of the return expression types. - returnType = getUnionType(types, ts.UnionReduction.Subtype); + returnType = getUnionType(types, UnionReduction.Subtype); } if (returnType || yieldType || nextType) { @@ -33213,7 +33411,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function createGeneratorReturnType(yieldType: ts.Type, returnType: ts.Type, nextType: ts.Type, isAsyncGenerator: boolean) { + function createGeneratorReturnType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean) { const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver; const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false); yieldType = resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || unknownType; @@ -33246,14 +33444,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createTypeFromGenericGlobalType(globalGeneratorType, [yieldType, returnType, nextType]); } - function checkAndAggregateYieldOperandTypes(func: ts.FunctionLikeDeclaration, checkMode: CheckMode | undefined) { - const yieldTypes: ts.Type[] = []; - const nextTypes: ts.Type[] = []; - const isAsync = (ts.getFunctionFlags(func) & ts.FunctionFlags.Async) !== 0; - ts.forEachYieldExpression(func.body as ts.Block, yieldExpression => { + function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined) { + const yieldTypes: Type[] = []; + const nextTypes: Type[] = []; + const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0; + forEachYieldExpression(func.body as Block, yieldExpression => { const yieldExpressionType = yieldExpression.expression ? checkExpression(yieldExpression.expression, checkMode) : undefinedWideningType; - ts.pushIfUnique(yieldTypes, getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync)); - let nextType: ts.Type | undefined; + pushIfUnique(yieldTypes, getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync)); + let nextType: Type | undefined; if (yieldExpression.asteriskToken) { const iterationTypes = getIterationTypesOfIterable( yieldExpressionType, @@ -33264,18 +33462,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { nextType = getContextualType(yieldExpression, /*contextFlags*/ undefined); } - if (nextType) ts.pushIfUnique(nextTypes, nextType); + if (nextType) pushIfUnique(nextTypes, nextType); }); return { yieldTypes, nextTypes }; } - function getYieldedTypeOfYieldExpression(node: ts.YieldExpression, expressionType: ts.Type, sentType: ts.Type, isAsync: boolean): ts.Type | undefined { + function getYieldedTypeOfYieldExpression(node: YieldExpression, expressionType: Type, sentType: Type, isAsync: boolean): Type | undefined { const errorNode = node.expression || node; // A `yield*` expression effectively yields everything that its operand yields const yieldedType = node.asteriskToken ? checkIteratedTypeOrElementType(isAsync ? IterationUse.AsyncYieldStar : IterationUse.YieldStar, expressionType, sentType, errorNode) : expressionType; return !isAsync ? yieldedType : getAwaitedType(yieldedType, errorNode, node.asteriskToken - ? ts.Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member - : ts.Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + ? Diagnostics.Type_of_iterated_elements_of_a_yield_Asterisk_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member + : Diagnostics.Type_of_yield_operand_in_an_async_generator_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } // Return the combined not-equal type facts for all cases except those between the start and end indices. @@ -33288,7 +33486,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return facts; } - function isExhaustiveSwitchStatement(node: ts.SwitchStatement): boolean { + function isExhaustiveSwitchStatement(node: SwitchStatement): boolean { const links = getNodeLinks(node); if (links.isExhaustive === undefined) { links.isExhaustive = 0; // Indicate resolution is in process @@ -33303,16 +33501,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.isExhaustive; } - function computeExhaustiveSwitchStatement(node: ts.SwitchStatement): boolean { - if (node.expression.kind === ts.SyntaxKind.TypeOfExpression) { + function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean { + if (node.expression.kind === SyntaxKind.TypeOfExpression) { const witnesses = getSwitchClauseTypeOfWitnesses(node); if (!witnesses) { return false; } - const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as ts.TypeOfExpression).expression)); + const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as TypeOfExpression).expression)); // Get the not-equal flags for all handled cases. const notEqualFacts = getNotEqualFactsFromTypeofSwitch(0, 0, witnesses); - if (operandConstraint.flags & ts.TypeFlags.AnyOrUnknown) { + if (operandConstraint.flags & TypeFlags.AnyOrUnknown) { // We special case the top types to be exhaustive when all cases are handled. return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE; } @@ -33324,37 +33522,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } const switchTypes = getSwitchClauseTypes(node); - if (!switchTypes.length || ts.some(switchTypes, isNeitherUnitTypeNorNever)) { + if (!switchTypes.length || some(switchTypes, isNeitherUnitTypeNorNever)) { return false; } return eachTypeContainedIn(mapType(type, getRegularTypeOfLiteralType), switchTypes); } - function functionHasImplicitReturn(func: ts.FunctionLikeDeclaration) { + function functionHasImplicitReturn(func: FunctionLikeDeclaration) { return func.endFlowNode && isReachableFlowNode(func.endFlowNode); } /** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */ - function checkAndAggregateReturnExpressionTypes(func: ts.FunctionLikeDeclaration, checkMode: CheckMode | undefined): ts.Type[] | undefined { - const functionFlags = ts.getFunctionFlags(func); - const aggregatedTypes: ts.Type[] = []; + function checkAndAggregateReturnExpressionTypes(func: FunctionLikeDeclaration, checkMode: CheckMode | undefined): Type[] | undefined { + const functionFlags = getFunctionFlags(func); + const aggregatedTypes: Type[] = []; let hasReturnWithNoExpression = functionHasImplicitReturn(func); let hasReturnOfTypeNever = false; - ts.forEachReturnStatement(func.body as ts.Block, returnStatement => { + forEachReturnStatement(func.body as Block, returnStatement => { const expr = returnStatement.expression; if (expr) { let type = checkExpressionCached(expr, checkMode && checkMode & ~CheckMode.SkipGenericFunctions); - if (functionFlags & ts.FunctionFlags.Async) { + if (functionFlags & FunctionFlags.Async) { // From within an async function you can return either a non-promise value or a promise. Any // Promise/A+ compatible implementation will always assimilate any foreign promise, so the // return type of the body should be unwrapped to its awaited type, which should be wrapped in // the native Promise type by the caller. - type = unwrapAwaitedType(checkAwaitedType(type, /*withAlias*/ false, func, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); + type = unwrapAwaitedType(checkAwaitedType(type, /*withAlias*/ false, func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member)); } - if (type.flags & ts.TypeFlags.Never) { + if (type.flags & TypeFlags.Never) { hasReturnOfTypeNever = true; } - ts.pushIfUnique(aggregatedTypes, type); + pushIfUnique(aggregatedTypes, type); } else { hasReturnWithNoExpression = true; @@ -33366,17 +33564,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol))) { // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined - ts.pushIfUnique(aggregatedTypes, undefinedType); + pushIfUnique(aggregatedTypes, undefinedType); } return aggregatedTypes; } - function mayReturnNever(func: ts.FunctionLikeDeclaration): boolean { + function mayReturnNever(func: FunctionLikeDeclaration): boolean { switch (func.kind) { - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: return true; - case ts.SyntaxKind.MethodDeclaration: - return func.parent.kind === ts.SyntaxKind.ObjectLiteralExpression; + case SyntaxKind.MethodDeclaration: + return func.parent.kind === SyntaxKind.ObjectLiteralExpression; default: return false; } @@ -33391,38 +33589,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * @param returnType - return type of the function, can be undefined if return type is not explicitly specified */ - function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: ts.FunctionLikeDeclaration | ts.MethodSignature, returnType: ts.Type | undefined) { + function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration | MethodSignature, returnType: Type | undefined) { addLazyDiagnostic(checkAllCodePathsInNonVoidFunctionReturnOrThrowDiagnostics); return; function checkAllCodePathsInNonVoidFunctionReturnOrThrowDiagnostics(): void { - const functionFlags = ts.getFunctionFlags(func); + const functionFlags = getFunctionFlags(func); const type = returnType && unwrapReturnType(returnType, functionFlags); // Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions. - if (type && maybeTypeOfKind(type, ts.TypeFlags.Any | ts.TypeFlags.Void)) { + if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) { return; } // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. // also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw - if (func.kind === ts.SyntaxKind.MethodSignature || ts.nodeIsMissing(func.body) || func.body!.kind !== ts.SyntaxKind.Block || !functionHasImplicitReturn(func)) { + if (func.kind === SyntaxKind.MethodSignature || nodeIsMissing(func.body) || func.body!.kind !== SyntaxKind.Block || !functionHasImplicitReturn(func)) { return; } - const hasExplicitReturn = func.flags & ts.NodeFlags.HasExplicitReturn; - const errorNode = ts.getEffectiveReturnTypeNode(func) || func; + const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; + const errorNode = getEffectiveReturnTypeNode(func) || func; - if (type && type.flags & ts.TypeFlags.Never) { - error(errorNode, ts.Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); + if (type && type.flags & TypeFlags.Never) { + error(errorNode, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } else if (type && !hasExplicitReturn) { // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. - error(errorNode, ts.Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); + error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { - error(errorNode, ts.Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); + error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } else if (compilerOptions.noImplicitReturns) { if (!type) { @@ -33437,23 +33635,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } } - error(errorNode, ts.Diagnostics.Not_all_code_paths_return_a_value); + error(errorNode, Diagnostics.Not_all_code_paths_return_a_value); } } } - function checkFunctionExpressionOrObjectLiteralMethod(node: ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration, checkMode?: CheckMode): ts.Type { - ts.Debug.assert(node.kind !== ts.SyntaxKind.MethodDeclaration || ts.isObjectLiteralMethod(node)); + function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode): Type { + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); checkNodeDeferred(node); - if (ts.isFunctionExpression(node)) { + if (isFunctionExpression(node)) { checkCollisionsForDeclarationName(node, node.name); } // The identityMapper object is used to indicate that function expressions are wildcards if (checkMode && checkMode & CheckMode.SkipContextSensitive && isContextSensitive(node)) { // Skip parameters, return signature with return type that retains noncontextual parts so inferences can still be drawn in an early stage - if (!ts.getEffectiveReturnTypeNode(node) && !ts.hasContextSensitiveParameters(node)) { + if (!getEffectiveReturnTypeNode(node) && !hasContextSensitiveParameters(node)) { // Return plain anyFunctionType if there is no possibility we'll make inferences from the return type const contextualSignature = getContextualSignature(node); if (contextualSignature && couldContainTypeVariables(getReturnTypeOfSignature(contextualSignature))) { @@ -33462,9 +33660,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.contextFreeType; } const returnType = getReturnTypeFromBody(node, checkMode); - const returnOnlySignature = createSignature(undefined, undefined, undefined, ts.emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, ts.SignatureFlags.None); - const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], ts.emptyArray, ts.emptyArray); - returnOnlyType.objectFlags |= ts.ObjectFlags.NonInferrableType; + const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, SignatureFlags.None); + const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, emptyArray); + returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType; return links.contextFreeType = returnOnlyType; } } @@ -33473,7 +33671,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Grammar checking const hasGrammarError = checkGrammarFunctionLikeDeclaration(node); - if (!hasGrammarError && node.kind === ts.SyntaxKind.FunctionExpression) { + if (!hasGrammarError && node.kind === SyntaxKind.FunctionExpression) { checkGrammarForGenerator(node); } @@ -33482,28 +33680,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getTypeOfSymbol(getSymbolOfNode(node)); } - function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: ts.FunctionExpression | ts.ArrowFunction | ts.MethodDeclaration, checkMode?: CheckMode) { + function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode) { const links = getNodeLinks(node); // Check if function expression is contextually typed and assign parameter types if so. - if (!(links.flags & ts.NodeCheckFlags.ContextChecked)) { + if (!(links.flags & NodeCheckFlags.ContextChecked)) { const contextualSignature = getContextualSignature(node); // If a type check is started at a function expression that is an argument of a function call, obtaining the // contextual type may recursively get back to here during overload resolution of the call. If so, we will have // already assigned contextual types. - if (!(links.flags & ts.NodeCheckFlags.ContextChecked)) { - links.flags |= ts.NodeCheckFlags.ContextChecked; - const signature = ts.firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfNode(node)), ts.SignatureKind.Call)); + if (!(links.flags & NodeCheckFlags.ContextChecked)) { + links.flags |= NodeCheckFlags.ContextChecked; + const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfNode(node)), SignatureKind.Call)); if (!signature) { return; } if (isContextSensitive(node)) { if (contextualSignature) { const inferenceContext = getInferenceContext(node); - let instantiatedContextualSignature: ts.Signature | undefined; + let instantiatedContextualSignature: Signature | undefined; if (checkMode && checkMode & CheckMode.Inferential) { inferFromAnnotatedParameters(signature, contextualSignature, inferenceContext!); const restType = getEffectiveRestType(contextualSignature); - if (restType && restType.flags & ts.TypeFlags.TypeParameter) { + if (restType && restType.flags & TypeFlags.TypeParameter) { instantiatedContextualSignature = instantiateSignature(contextualSignature, inferenceContext!.nonFixingMapper); } } @@ -33527,15 +33725,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration) { - ts.Debug.assert(node.kind !== ts.SyntaxKind.MethodDeclaration || ts.isObjectLiteralMethod(node)); + function checkFunctionExpressionOrObjectLiteralMethodDeferred(node: ArrowFunction | FunctionExpression | MethodDeclaration) { + Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); - const functionFlags = ts.getFunctionFlags(node); + const functionFlags = getFunctionFlags(node); const returnType = getReturnTypeFromAnnotation(node); checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); if (node.body) { - if (!ts.getEffectiveReturnTypeNode(node)) { + if (!getEffectiveReturnTypeNode(node)) { // There are some checks that are only performed in getReturnTypeFromBody, that may produce errors // we need. An example is the noImplicitAny errors resulting from widening the return expression // of a function. Because checking of function expression bodies is deferred, there was never an @@ -33544,7 +33742,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getReturnTypeOfSignature(getSignatureFromDeclaration(node)); } - if (node.body.kind === ts.SyntaxKind.Block) { + if (node.body.kind === SyntaxKind.Block) { checkSourceElement(node.body); } else { @@ -33556,8 +33754,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const exprType = checkExpression(node.body); const returnOrPromisedType = returnType && unwrapReturnType(returnType, functionFlags); if (returnOrPromisedType) { - if ((functionFlags & ts.FunctionFlags.AsyncGenerator) === ts.FunctionFlags.Async) { // Async function - const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, node.body, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function + const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, node.body, node.body); } else { // Normal function @@ -33568,7 +33766,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkArithmeticOperandType(operand: ts.Node, type: ts.Type, diagnostic: ts.DiagnosticMessage, isAwaitValid = false): boolean { + function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage, isAwaitValid = false): boolean { if (!isTypeAssignableTo(type, numberOrBigIntType)) { const awaitedType = isAwaitValid && getAwaitedTypeOfPromise(type); errorAndMaybeSuggestAwait( @@ -33580,17 +33778,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function isReadonlyAssignmentDeclaration(d: ts.Declaration) { - if (!ts.isCallExpression(d)) { + function isReadonlyAssignmentDeclaration(d: Declaration) { + if (!isCallExpression(d)) { return false; } - if (!ts.isBindableObjectDefinePropertyCall(d)) { + if (!isBindableObjectDefinePropertyCall(d)) { return false; } const objectLitType = checkExpressionCached(d.arguments[2]); - const valueType = getTypeOfPropertyOfType(objectLitType, "value" as ts.__String); + const valueType = getTypeOfPropertyOfType(objectLitType, "value" as __String); if (valueType) { - const writableProp = getPropertyOfType(objectLitType, "writable" as ts.__String); + const writableProp = getPropertyOfType(objectLitType, "writable" as __String); const writableType = writableProp && getTypeOfSymbol(writableProp); if (!writableType || writableType === falseType || writableType === regularFalseType) { return true; @@ -33598,7 +33796,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We include this definition whereupon we walk back and check the type at the declaration because // The usual definition of `Object.defineProperty` will _not_ cause literal types to be preserved in the // argument types, should the type be contextualized by the call itself. - if (writableProp && writableProp.valueDeclaration && ts.isPropertyAssignment(writableProp.valueDeclaration)) { + if (writableProp && writableProp.valueDeclaration && isPropertyAssignment(writableProp.valueDeclaration)) { const initializer = writableProp.valueDeclaration.initializer; const rawOriginalType = checkExpression(initializer); if (rawOriginalType === falseType || rawOriginalType === regularFalseType) { @@ -33607,11 +33805,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return false; } - const setProp = getPropertyOfType(objectLitType, "set" as ts.__String); + const setProp = getPropertyOfType(objectLitType, "set" as __String); return !setProp; } - function isReadonlySymbol(symbol: ts.Symbol): boolean { + function isReadonlySymbol(symbol: Symbol): boolean { // The following symbols are considered read-only: // Properties with a 'readonly' modifier // Variables declared with 'const' @@ -33619,32 +33817,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Enum members // Object.defineProperty assignments with writable false or no setter // Unions and intersections of the above (unions and intersections eagerly set isReadonly on creation) - return !!(ts.getCheckFlags(symbol) & ts.CheckFlags.Readonly || - symbol.flags & ts.SymbolFlags.Property && ts.getDeclarationModifierFlagsFromSymbol(symbol) & ts.ModifierFlags.Readonly || - symbol.flags & ts.SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & ts.NodeFlags.Const || - symbol.flags & ts.SymbolFlags.Accessor && !(symbol.flags & ts.SymbolFlags.SetAccessor) || - symbol.flags & ts.SymbolFlags.EnumMember || - ts.some(symbol.declarations, isReadonlyAssignmentDeclaration) + return !!(getCheckFlags(symbol) & CheckFlags.Readonly || + symbol.flags & SymbolFlags.Property && getDeclarationModifierFlagsFromSymbol(symbol) & ModifierFlags.Readonly || + symbol.flags & SymbolFlags.Variable && getDeclarationNodeFlagsFromSymbol(symbol) & NodeFlags.Const || + symbol.flags & SymbolFlags.Accessor && !(symbol.flags & SymbolFlags.SetAccessor) || + symbol.flags & SymbolFlags.EnumMember || + some(symbol.declarations, isReadonlyAssignmentDeclaration) ); } - function isAssignmentToReadonlyEntity(expr: ts.Expression, symbol: ts.Symbol, assignmentKind: ts.AssignmentKind) { - if (assignmentKind === ts.AssignmentKind.None) { + function isAssignmentToReadonlyEntity(expr: Expression, symbol: Symbol, assignmentKind: AssignmentKind) { + if (assignmentKind === AssignmentKind.None) { // no assigment means it doesn't matter whether the entity is readonly return false; } if (isReadonlySymbol(symbol)) { // Allow assignments to readonly properties within constructors of the same class declaration. - if (symbol.flags & ts.SymbolFlags.Property && - ts.isAccessExpression(expr) && - expr.expression.kind === ts.SyntaxKind.ThisKeyword) { + if (symbol.flags & SymbolFlags.Property && + isAccessExpression(expr) && + expr.expression.kind === SyntaxKind.ThisKeyword) { // Look for if this is the constructor for the class that `symbol` is a property of. - const ctor = ts.getContainingFunction(expr); - if (!(ctor && (ctor.kind === ts.SyntaxKind.Constructor || isJSConstructor(ctor)))) { + const ctor = getContainingFunction(expr); + if (!(ctor && (ctor.kind === SyntaxKind.Constructor || isJSConstructor(ctor)))) { return true; } if (symbol.valueDeclaration) { - const isAssignmentDeclaration = ts.isBinaryExpression(symbol.valueDeclaration); + const isAssignmentDeclaration = isBinaryExpression(symbol.valueDeclaration); const isLocalPropertyDeclaration = ctor.parent === symbol.valueDeclaration.parent; const isLocalParameterProperty = ctor === symbol.valueDeclaration.parent; const isLocalThisPropertyAssignment = isAssignmentDeclaration && symbol.parent?.valueDeclaration === ctor.parent; @@ -33659,114 +33857,114 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return true; } - if (ts.isAccessExpression(expr)) { + if (isAccessExpression(expr)) { // references through namespace import should be readonly - const node = ts.skipParentheses(expr.expression); - if (node.kind === ts.SyntaxKind.Identifier) { + const node = skipParentheses(expr.expression); + if (node.kind === SyntaxKind.Identifier) { const symbol = getNodeLinks(node).resolvedSymbol!; - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { const declaration = getDeclarationOfAliasSymbol(symbol); - return !!declaration && declaration.kind === ts.SyntaxKind.NamespaceImport; + return !!declaration && declaration.kind === SyntaxKind.NamespaceImport; } } } return false; } - function checkReferenceExpression(expr: ts.Expression, invalidReferenceMessage: ts.DiagnosticMessage, invalidOptionalChainMessage: ts.DiagnosticMessage): boolean { + function checkReferenceExpression(expr: Expression, invalidReferenceMessage: DiagnosticMessage, invalidOptionalChainMessage: DiagnosticMessage): boolean { // References are combinations of identifiers, parentheses, and property accesses. - const node = ts.skipOuterExpressions(expr, ts.OuterExpressionKinds.Assertions | ts.OuterExpressionKinds.Parentheses); - if (node.kind !== ts.SyntaxKind.Identifier && !ts.isAccessExpression(node)) { + const node = skipOuterExpressions(expr, OuterExpressionKinds.Assertions | OuterExpressionKinds.Parentheses); + if (node.kind !== SyntaxKind.Identifier && !isAccessExpression(node)) { error(expr, invalidReferenceMessage); return false; } - if (node.flags & ts.NodeFlags.OptionalChain) { + if (node.flags & NodeFlags.OptionalChain) { error(expr, invalidOptionalChainMessage); return false; } return true; } - function checkDeleteExpression(node: ts.DeleteExpression): ts.Type { + function checkDeleteExpression(node: DeleteExpression): Type { checkExpression(node.expression); - const expr = ts.skipParentheses(node.expression); - if (!ts.isAccessExpression(expr)) { - error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); + const expr = skipParentheses(node.expression); + if (!isAccessExpression(expr)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_a_property_reference); return booleanType; } - if (ts.isPropertyAccessExpression(expr) && ts.isPrivateIdentifier(expr.name)) { - error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_identifier); + if (isPropertyAccessExpression(expr) && isPrivateIdentifier(expr.name)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_private_identifier); } const links = getNodeLinks(expr); const symbol = getExportSymbolOfValueSymbolIfExported(links.resolvedSymbol); if (symbol) { if (isReadonlySymbol(symbol)) { - error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); + error(expr, Diagnostics.The_operand_of_a_delete_operator_cannot_be_a_read_only_property); } checkDeleteExpressionMustBeOptional(expr, symbol); } return booleanType; } - function checkDeleteExpressionMustBeOptional(expr: ts.AccessExpression, symbol: ts.Symbol) { + function checkDeleteExpressionMustBeOptional(expr: AccessExpression, symbol: Symbol) { const type = getTypeOfSymbol(symbol); if (strictNullChecks && - !(type.flags & (ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Never)) && - !(exactOptionalPropertyTypes ? symbol.flags & ts.SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined)) { - error(expr, ts.Diagnostics.The_operand_of_a_delete_operator_must_be_optional); + !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) && + !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined)) { + error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); } } - function checkTypeOfExpression(node: ts.TypeOfExpression): ts.Type { + function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); return typeofType; } - function checkVoidExpression(node: ts.VoidExpression): ts.Type { + function checkVoidExpression(node: VoidExpression): Type { checkExpression(node.expression); return undefinedWideningType; } - function checkAwaitExpressionGrammar(node: ts.AwaitExpression): void { + function checkAwaitExpressionGrammar(node: AwaitExpression): void { // Grammar checking - const container = ts.getContainingFunctionOrClassStaticBlock(node); - if (container && ts.isClassStaticBlockDeclaration(container)) { - error(node, ts.Diagnostics.Await_expression_cannot_be_used_inside_a_class_static_block); + const container = getContainingFunctionOrClassStaticBlock(node); + if (container && isClassStaticBlockDeclaration(container)) { + error(node, Diagnostics.Await_expression_cannot_be_used_inside_a_class_static_block); } - else if (!(node.flags & ts.NodeFlags.AwaitContext)) { - if (ts.isInTopLevelContext(node)) { - const sourceFile = ts.getSourceFileOfNode(node); + else if (!(node.flags & NodeFlags.AwaitContext)) { + if (isInTopLevelContext(node)) { + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - let span: ts.TextSpan | undefined; - if (!ts.isEffectiveExternalModule(sourceFile, compilerOptions)) { - span ??= ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - const diagnostic = ts.createFileDiagnostic(sourceFile, span.start, span.length, - ts.Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module); + let span: TextSpan | undefined; + if (!isEffectiveExternalModule(sourceFile, compilerOptions)) { + span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); + const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, + Diagnostics.await_expressions_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module); diagnostics.add(diagnostic); } switch (moduleKind) { - case ts.ModuleKind.Node16: - case ts.ModuleKind.NodeNext: - if (sourceFile.impliedNodeFormat === ts.ModuleKind.CommonJS) { - span ??= ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + case ModuleKind.Node16: + case ModuleKind.NodeNext: + if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) { + span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); diagnostics.add( - ts.createFileDiagnostic(sourceFile, span.start, span.length, ts.Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level) + createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level) ); break; } // fallthrough - case ts.ModuleKind.ES2022: - case ts.ModuleKind.ESNext: - case ts.ModuleKind.System: - if (languageVersion >= ts.ScriptTarget.ES2017) { + case ModuleKind.ES2022: + case ModuleKind.ESNext: + case ModuleKind.System: + if (languageVersion >= ScriptTarget.ES2017) { break; } // fallthrough default: - span ??= ts.getSpanOfTokenAtPosition(sourceFile, node.pos); + span ??= getSpanOfTokenAtPosition(sourceFile, node.pos); diagnostics.add( - ts.createFileDiagnostic(sourceFile, span.start, span.length, - ts.Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + createFileDiagnostic(sourceFile, span.start, span.length, + Diagnostics.Top_level_await_expressions_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher ) ); break; @@ -33775,13 +33973,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { // use of 'await' in non-async function - const sourceFile = ts.getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - const span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - const diagnostic = ts.createFileDiagnostic(sourceFile, span.start, span.length, ts.Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); - if (container && container.kind !== ts.SyntaxKind.Constructor && (ts.getFunctionFlags(container) & ts.FunctionFlags.Async) === 0) { - const relatedInfo = ts.createDiagnosticForNode(container, ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async); - ts.addRelatedInfo(diagnostic, relatedInfo); + const span = getSpanOfTokenAtPosition(sourceFile, node.pos); + const diagnostic = createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); + if (container && container.kind !== SyntaxKind.Constructor && (getFunctionFlags(container) & FunctionFlags.Async) === 0) { + const relatedInfo = createDiagnosticForNode(container, Diagnostics.Did_you_mean_to_mark_this_function_as_async); + addRelatedInfo(diagnostic, relatedInfo); } diagnostics.add(diagnostic); } @@ -33789,81 +33987,81 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (isInParameterInitializerBeforeContainingFunction(node)) { - error(node, ts.Diagnostics.await_expressions_cannot_be_used_in_a_parameter_initializer); + error(node, Diagnostics.await_expressions_cannot_be_used_in_a_parameter_initializer); } } - function checkAwaitExpression(node: ts.AwaitExpression): ts.Type { + function checkAwaitExpression(node: AwaitExpression): Type { addLazyDiagnostic(() => checkAwaitExpressionGrammar(node)); const operandType = checkExpression(node.expression); - const awaitedType = checkAwaitedType(operandType, /*withAlias*/ true, node, ts.Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); - if (awaitedType === operandType && !isErrorType(awaitedType) && !(operandType.flags & ts.TypeFlags.AnyOrUnknown)) { - addErrorOrSuggestion(/*isError*/ false, ts.createDiagnosticForNode(node, ts.Diagnostics.await_has_no_effect_on_the_type_of_this_expression)); + const awaitedType = checkAwaitedType(operandType, /*withAlias*/ true, node, Diagnostics.Type_of_await_operand_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + if (awaitedType === operandType && !isErrorType(awaitedType) && !(operandType.flags & TypeFlags.AnyOrUnknown)) { + addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.await_has_no_effect_on_the_type_of_this_expression)); } return awaitedType; } - function checkPrefixUnaryExpression(node: ts.PrefixUnaryExpression): ts.Type { + function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type { const operandType = checkExpression(node.operand); if (operandType === silentNeverType) { return silentNeverType; } switch (node.operand.kind) { - case ts.SyntaxKind.NumericLiteral: + case SyntaxKind.NumericLiteral: switch (node.operator) { - case ts.SyntaxKind.MinusToken: - return getFreshTypeOfLiteralType(getNumberLiteralType(-(node.operand as ts.NumericLiteral).text)); - case ts.SyntaxKind.PlusToken: - return getFreshTypeOfLiteralType(getNumberLiteralType(+(node.operand as ts.NumericLiteral).text)); + case SyntaxKind.MinusToken: + return getFreshTypeOfLiteralType(getNumberLiteralType(-(node.operand as NumericLiteral).text)); + case SyntaxKind.PlusToken: + return getFreshTypeOfLiteralType(getNumberLiteralType(+(node.operand as NumericLiteral).text)); } break; - case ts.SyntaxKind.BigIntLiteral: - if (node.operator === ts.SyntaxKind.MinusToken) { + case SyntaxKind.BigIntLiteral: + if (node.operator === SyntaxKind.MinusToken) { return getFreshTypeOfLiteralType(getBigIntLiteralType({ negative: true, - base10Value: ts.parsePseudoBigInt((node.operand as ts.BigIntLiteral).text) + base10Value: parsePseudoBigInt((node.operand as BigIntLiteral).text) })); } } switch (node.operator) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.TildeToken: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: checkNonNullType(operandType, node.operand); - if (maybeTypeOfKindConsideringBaseConstraint(operandType, ts.TypeFlags.ESSymbolLike)) { - error(node.operand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(node.operator)); + if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.ESSymbolLike)) { + error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator)); } - if (node.operator === ts.SyntaxKind.PlusToken) { - if (maybeTypeOfKindConsideringBaseConstraint(operandType, ts.TypeFlags.BigIntLike)) { - error(node.operand, ts.Diagnostics.Operator_0_cannot_be_applied_to_type_1, ts.tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType))); + if (node.operator === SyntaxKind.PlusToken) { + if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.BigIntLike)) { + error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType))); } return numberType; } return getUnaryResultType(operandType); - case ts.SyntaxKind.ExclamationToken: + case SyntaxKind.ExclamationToken: checkTruthinessExpression(node.operand); const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy); return facts === TypeFacts.Truthy ? falseType : facts === TypeFacts.Falsy ? trueType : booleanType; - case ts.SyntaxKind.PlusPlusToken: - case ts.SyntaxKind.MinusMinusToken: + case SyntaxKind.PlusPlusToken: + case SyntaxKind.MinusMinusToken: const ok = checkArithmeticOperandType(node.operand, checkNonNullType(operandType, node.operand), - ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type); + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression( node.operand, - ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, - ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access); + Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, + Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access); } return getUnaryResultType(operandType); } return errorType; } - function checkPostfixUnaryExpression(node: ts.PostfixUnaryExpression): ts.Type { + function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type { const operandType = checkExpression(node.operand); if (operandType === silentNeverType) { return silentNeverType; @@ -33871,20 +34069,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const ok = checkArithmeticOperandType( node.operand, checkNonNullType(operandType, node.operand), - ts.Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type); + Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_bigint_or_an_enum_type); if (ok) { // run check only if former checks succeeded to avoid reporting cascading errors checkReferenceExpression( node.operand, - ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, - ts.Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access); + Diagnostics.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, + Diagnostics.The_operand_of_an_increment_or_decrement_operator_may_not_be_an_optional_property_access); } return getUnaryResultType(operandType); } - function getUnaryResultType(operandType: ts.Type): ts.Type { - if (maybeTypeOfKind(operandType, ts.TypeFlags.BigIntLike)) { - return isTypeAssignableToKind(operandType, ts.TypeFlags.AnyOrUnknown) || maybeTypeOfKind(operandType, ts.TypeFlags.NumberLike) + function getUnaryResultType(operandType: Type): Type { + if (maybeTypeOfKind(operandType, TypeFlags.BigIntLike)) { + return isTypeAssignableToKind(operandType, TypeFlags.AnyOrUnknown) || maybeTypeOfKind(operandType, TypeFlags.NumberLike) ? numberOrBigIntType : bigintType; } @@ -33892,7 +34090,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return numberType; } - function maybeTypeOfKindConsideringBaseConstraint(type: ts.Type, kind: ts.TypeFlags): boolean { + function maybeTypeOfKindConsideringBaseConstraint(type: Type, kind: TypeFlags): boolean { if (maybeTypeOfKind(type, kind)) { return true; } @@ -33903,12 +34101,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if type might be of the given kind. A union or intersection type might be of a given // kind if at least one constituent type is of the given kind. - function maybeTypeOfKind(type: ts.Type, kind: ts.TypeFlags): boolean { + function maybeTypeOfKind(type: Type, kind: TypeFlags): boolean { if (type.flags & kind) { return true; } - if (type.flags & ts.TypeFlags.UnionOrIntersection) { - const types = (type as ts.UnionOrIntersectionType).types; + if (type.flags & TypeFlags.UnionOrIntersection) { + const types = (type as UnionOrIntersectionType).types; for (const t of types) { if (maybeTypeOfKind(t, kind)) { return true; @@ -33918,40 +34116,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isTypeAssignableToKind(source: ts.Type, kind: ts.TypeFlags, strict?: boolean): boolean { + function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean { if (source.flags & kind) { return true; } - if (strict && source.flags & (ts.TypeFlags.AnyOrUnknown | ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Null)) { + if (strict && source.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) { return false; } - return !!(kind & ts.TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) || - !!(kind & ts.TypeFlags.BigIntLike) && isTypeAssignableTo(source, bigintType) || - !!(kind & ts.TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) || - !!(kind & ts.TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) || - !!(kind & ts.TypeFlags.Void) && isTypeAssignableTo(source, voidType) || - !!(kind & ts.TypeFlags.Never) && isTypeAssignableTo(source, neverType) || - !!(kind & ts.TypeFlags.Null) && isTypeAssignableTo(source, nullType) || - !!(kind & ts.TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) || - !!(kind & ts.TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) || - !!(kind & ts.TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType); - } - - function allTypesAssignableToKind(source: ts.Type, kind: ts.TypeFlags, strict?: boolean): boolean { - return source.flags & ts.TypeFlags.Union ? - ts.every((source as ts.UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) : + return !!(kind & TypeFlags.NumberLike) && isTypeAssignableTo(source, numberType) || + !!(kind & TypeFlags.BigIntLike) && isTypeAssignableTo(source, bigintType) || + !!(kind & TypeFlags.StringLike) && isTypeAssignableTo(source, stringType) || + !!(kind & TypeFlags.BooleanLike) && isTypeAssignableTo(source, booleanType) || + !!(kind & TypeFlags.Void) && isTypeAssignableTo(source, voidType) || + !!(kind & TypeFlags.Never) && isTypeAssignableTo(source, neverType) || + !!(kind & TypeFlags.Null) && isTypeAssignableTo(source, nullType) || + !!(kind & TypeFlags.Undefined) && isTypeAssignableTo(source, undefinedType) || + !!(kind & TypeFlags.ESSymbol) && isTypeAssignableTo(source, esSymbolType) || + !!(kind & TypeFlags.NonPrimitive) && isTypeAssignableTo(source, nonPrimitiveType); + } + + function allTypesAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean { + return source.flags & TypeFlags.Union ? + every((source as UnionType).types, subType => allTypesAssignableToKind(subType, kind, strict)) : isTypeAssignableToKind(source, kind, strict); } - function isConstEnumObjectType(type: ts.Type): boolean { - return !!(ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous) && !!type.symbol && isConstEnumSymbol(type.symbol); + function isConstEnumObjectType(type: Type): boolean { + return !!(getObjectFlags(type) & ObjectFlags.Anonymous) && !!type.symbol && isConstEnumSymbol(type.symbol); } - function isConstEnumSymbol(symbol: ts.Symbol): boolean { - return (symbol.flags & ts.SymbolFlags.ConstEnum) !== 0; + function isConstEnumSymbol(symbol: Symbol): boolean { + return (symbol.flags & SymbolFlags.ConstEnum) !== 0; } - function checkInstanceOfExpression(left: ts.Expression, right: ts.Expression, leftType: ts.Type, rightType: ts.Type): ts.Type { + function checkInstanceOfExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } @@ -33961,31 +34159,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported if (!isTypeAny(leftType) && - allTypesAssignableToKind(leftType, ts.TypeFlags.Primitive)) { - error(left, ts.Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); + allTypesAssignableToKind(leftType, TypeFlags.Primitive)) { + error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported if (!(isTypeAny(rightType) || typeHasCallOrConstructSignatures(rightType) || isTypeSubtypeOf(rightType, globalFunctionType))) { - error(right, ts.Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); + error(right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } return booleanType; } - function hasEmptyObjectIntersection(type: ts.Type): boolean { - return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & ts.TypeFlags.Intersection) && ts.some((t as ts.IntersectionType).types, isEmptyAnonymousObjectType)); + function hasEmptyObjectIntersection(type: Type): boolean { + return someType(type, t => t === unknownEmptyObjectType || !!(t.flags & TypeFlags.Intersection) && some((t as IntersectionType).types, isEmptyAnonymousObjectType)); } - function checkInExpression(left: ts.Expression, right: ts.Expression, leftType: ts.Type, rightType: ts.Type): ts.Type { + function checkInExpression(left: Expression, right: Expression, leftType: Type, rightType: Type): Type { if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } - if (ts.isPrivateIdentifier(left)) { - if (languageVersion < ts.ScriptTarget.ESNext) { - checkExternalEmitHelpers(left, ts.ExternalEmitHelpers.ClassPrivateFieldIn); + if (isPrivateIdentifier(left)) { + if (languageVersion < ScriptTarget.ESNext) { + checkExternalEmitHelpers(left, ExternalEmitHelpers.ClassPrivateFieldIn); } // Unlike in 'checkPrivateIdentifierExpression' we now have access to the RHS type // which provides us with the opportunity to emit more detailed errors - if (!getNodeLinks(left).resolvedSymbol && ts.getContainingClass(left)) { + if (!getNodeLinks(left).resolvedSymbol && getContainingClass(left)) { const isUncheckedJS = isUncheckedJSSuggestion(left, rightType.symbol, /*excludeClasses*/ true); reportNonexistentProperty(left, rightType, isUncheckedJS); } @@ -34001,14 +34199,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // that include {} (we know that the other types in such intersections are assignable to object // since we already checked for that). if (hasEmptyObjectIntersection(rightType)) { - error(right, ts.Diagnostics.Type_0_may_represent_a_primitive_value_which_is_not_permitted_as_the_right_operand_of_the_in_operator, typeToString(rightType)); + error(right, Diagnostics.Type_0_may_represent_a_primitive_value_which_is_not_permitted_as_the_right_operand_of_the_in_operator, typeToString(rightType)); } } // The result is always of the Boolean primitive type. return booleanType; } - function checkObjectLiteralAssignment(node: ts.ObjectLiteralExpression, sourceType: ts.Type, rightIsThis?: boolean): ts.Type { + function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, rightIsThis?: boolean): Type { const properties = node.properties; if (strictNullChecks && properties.length === 0) { return checkNonNullType(sourceType, node); @@ -34020,10 +34218,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** Note: If property cannot be a SpreadAssignment, then allProperties does not need to be provided */ - function checkObjectLiteralDestructuringPropertyAssignment(node: ts.ObjectLiteralExpression, objectLiteralType: ts.Type, propertyIndex: number, allProperties?: ts.NodeArray, rightIsThis = false) { + function checkObjectLiteralDestructuringPropertyAssignment(node: ObjectLiteralExpression, objectLiteralType: Type, propertyIndex: number, allProperties?: NodeArray, rightIsThis = false) { const properties = node.properties; const property = properties[propertyIndex]; - if (property.kind === ts.SyntaxKind.PropertyAssignment || property.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) { const name = property.name; const exprType = getLiteralTypeFromPropertyName(name); if (isTypeUsableAsPropertyName(exprType)) { @@ -34034,49 +34232,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkPropertyAccessibility(property, /*isSuper*/ false, /*writing*/ true, objectLiteralType, prop); } } - const elementType = getIndexedAccessType(objectLiteralType, exprType, ts.AccessFlags.ExpressionPosition, name); + const elementType = getIndexedAccessType(objectLiteralType, exprType, AccessFlags.ExpressionPosition, name); const type = getFlowTypeOfDestructuring(property, elementType); - return checkDestructuringAssignment(property.kind === ts.SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); + return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); } - else if (property.kind === ts.SyntaxKind.SpreadAssignment) { + else if (property.kind === SyntaxKind.SpreadAssignment) { if (propertyIndex < properties.length - 1) { - error(property, ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); + error(property, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } else { - if (languageVersion < ts.ScriptTarget.ESNext) { - checkExternalEmitHelpers(property, ts.ExternalEmitHelpers.Rest); + if (languageVersion < ScriptTarget.ESNext) { + checkExternalEmitHelpers(property, ExternalEmitHelpers.Rest); } - const nonRestNames: ts.PropertyName[] = []; + const nonRestNames: PropertyName[] = []; if (allProperties) { for (const otherProperty of allProperties) { - if (!ts.isSpreadAssignment(otherProperty)) { + if (!isSpreadAssignment(otherProperty)) { nonRestNames.push(otherProperty.name); } } } const type = getRestType(objectLiteralType, nonRestNames, objectLiteralType.symbol); - checkGrammarForDisallowedTrailingComma(allProperties, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma(allProperties, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); return checkDestructuringAssignment(property.expression, type); } } else { - error(property, ts.Diagnostics.Property_assignment_expected); + error(property, Diagnostics.Property_assignment_expected); } } - function checkArrayLiteralAssignment(node: ts.ArrayLiteralExpression, sourceType: ts.Type, checkMode?: CheckMode): ts.Type { + function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, checkMode?: CheckMode): Type { const elements = node.elements; - if (languageVersion < ts.ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Read); + if (languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } // This elementType will be used if the specific property corresponding to this index is not // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType; - let inBoundsType: ts.Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined: possiblyOutOfBoundsType; + let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined: possiblyOutOfBoundsType; for (let i = 0; i < elements.length; i++) { let type = possiblyOutOfBoundsType; - if (node.elements[i].kind === ts.SyntaxKind.SpreadElement) { + if (node.elements[i].kind === SyntaxKind.SpreadElement) { type = inBoundsType = inBoundsType ?? (checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) || errorType); } checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, type, checkMode); @@ -34084,17 +34282,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return sourceType; } - function checkArrayLiteralDestructuringElementAssignment(node: ts.ArrayLiteralExpression, sourceType: ts.Type, - elementIndex: number, elementType: ts.Type, checkMode?: CheckMode) { + function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type, + elementIndex: number, elementType: Type, checkMode?: CheckMode) { const elements = node.elements; const element = elements[elementIndex]; - if (element.kind !== ts.SyntaxKind.OmittedExpression) { - if (element.kind !== ts.SyntaxKind.SpreadElement) { + if (element.kind !== SyntaxKind.OmittedExpression) { + if (element.kind !== SyntaxKind.SpreadElement) { const indexType = getNumberLiteralType(elementIndex); if (isArrayLikeType(sourceType)) { // We create a synthetic expression so that getIndexedAccessType doesn't get confused // when the element is a SyntaxKind.ElementAccessExpression. - const accessFlags = ts.AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? ts.AccessFlags.NoTupleBoundsCheck : 0); + const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0); const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, accessFlags, createSyntheticExpression(element, indexType)) || errorType; const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType; const type = getFlowTypeOfDestructuring(element, assignedType); @@ -34103,17 +34301,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return checkDestructuringAssignment(element, elementType, checkMode); } if (elementIndex < elements.length - 1) { - error(element, ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); + error(element, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } else { - const restExpression = (element as ts.SpreadElement).expression; - if (restExpression.kind === ts.SyntaxKind.BinaryExpression && (restExpression as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken) { - error((restExpression as ts.BinaryExpression).operatorToken, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); + const restExpression = (element as SpreadElement).expression; + if (restExpression.kind === SyntaxKind.BinaryExpression && (restExpression as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + error((restExpression as BinaryExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer); } else { - checkGrammarForDisallowedTrailingComma(node.elements, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma(node.elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); const type = everyType(sourceType, isTupleType) ? - mapType(sourceType, t => sliceTupleType(t as ts.TupleTypeReference, elementIndex)) : + mapType(sourceType, t => sliceTupleType(t as TupleTypeReference, elementIndex)) : createArrayType(elementType); return checkDestructuringAssignment(restExpression, type, checkMode); } @@ -34122,10 +34320,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function checkDestructuringAssignment(exprOrAssignment: ts.Expression | ts.ShorthandPropertyAssignment, sourceType: ts.Type, checkMode?: CheckMode, rightIsThis?: boolean): ts.Type { - let target: ts.Expression; - if (exprOrAssignment.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { - const prop = exprOrAssignment as ts.ShorthandPropertyAssignment; + function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, checkMode?: CheckMode, rightIsThis?: boolean): Type { + let target: Expression; + if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { + const prop = exprOrAssignment as ShorthandPropertyAssignment; if (prop.objectAssignmentInitializer) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. @@ -34135,42 +34333,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } checkBinaryLikeExpression(prop.name, prop.equalsToken!, prop.objectAssignmentInitializer, checkMode); } - target = (exprOrAssignment as ts.ShorthandPropertyAssignment).name; + target = (exprOrAssignment as ShorthandPropertyAssignment).name; } else { target = exprOrAssignment; } - if (target.kind === ts.SyntaxKind.BinaryExpression && (target as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken) { - checkBinaryExpression(target as ts.BinaryExpression, checkMode); - target = (target as ts.BinaryExpression).left; + if (target.kind === SyntaxKind.BinaryExpression && (target as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + checkBinaryExpression(target as BinaryExpression, checkMode); + target = (target as BinaryExpression).left; // A default value is specified, so remove undefined from the final type. if (strictNullChecks) { sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); } } - if (target.kind === ts.SyntaxKind.ObjectLiteralExpression) { - return checkObjectLiteralAssignment(target as ts.ObjectLiteralExpression, sourceType, rightIsThis); + if (target.kind === SyntaxKind.ObjectLiteralExpression) { + return checkObjectLiteralAssignment(target as ObjectLiteralExpression, sourceType, rightIsThis); } - if (target.kind === ts.SyntaxKind.ArrayLiteralExpression) { - return checkArrayLiteralAssignment(target as ts.ArrayLiteralExpression, sourceType, checkMode); + if (target.kind === SyntaxKind.ArrayLiteralExpression) { + return checkArrayLiteralAssignment(target as ArrayLiteralExpression, sourceType, checkMode); } return checkReferenceAssignment(target, sourceType, checkMode); } - function checkReferenceAssignment(target: ts.Expression, sourceType: ts.Type, checkMode?: CheckMode): ts.Type { + function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type { const targetType = checkExpression(target, checkMode); - const error = target.parent.kind === ts.SyntaxKind.SpreadAssignment ? - ts.Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : - ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; - const optionalError = target.parent.kind === ts.SyntaxKind.SpreadAssignment ? - ts.Diagnostics.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access : - ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; + const error = target.parent.kind === SyntaxKind.SpreadAssignment ? + Diagnostics.The_target_of_an_object_rest_assignment_must_be_a_variable_or_a_property_access : + Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access; + const optionalError = target.parent.kind === SyntaxKind.SpreadAssignment ? + Diagnostics.The_target_of_an_object_rest_assignment_may_not_be_an_optional_property_access : + Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access; if (checkReferenceExpression(target, error, optionalError)) { checkTypeAssignableToAndOptionallyElaborate(sourceType, targetType, target, target); } - if (ts.isPrivateIdentifierPropertyAccessExpression(target)) { - checkExternalEmitHelpers(target.parent, ts.ExternalEmitHelpers.ClassPrivateFieldSet); + if (isPrivateIdentifierPropertyAccessExpression(target)) { + checkExternalEmitHelpers(target.parent, ExternalEmitHelpers.ClassPrivateFieldSet); } return sourceType; } @@ -34183,67 +34381,67 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * The intent is to "smell test" an expression for correctness in positions where * its value is discarded (e.g. the left side of the comma operator). */ - function isSideEffectFree(node: ts.Node): boolean { - node = ts.skipParentheses(node); + function isSideEffectFree(node: Node): boolean { + node = skipParentheses(node); switch (node.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.RegularExpressionLiteral: - case ts.SyntaxKind.TaggedTemplateExpression: - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.UndefinedKeyword: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.ArrayLiteralExpression: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.TypeOfExpression: - case ts.SyntaxKind.NonNullExpression: - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxElement: + case SyntaxKind.Identifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TemplateExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxElement: return true; - case ts.SyntaxKind.ConditionalExpression: - return isSideEffectFree((node as ts.ConditionalExpression).whenTrue) && - isSideEffectFree((node as ts.ConditionalExpression).whenFalse); + case SyntaxKind.ConditionalExpression: + return isSideEffectFree((node as ConditionalExpression).whenTrue) && + isSideEffectFree((node as ConditionalExpression).whenFalse); - case ts.SyntaxKind.BinaryExpression: - if (ts.isAssignmentOperator((node as ts.BinaryExpression).operatorToken.kind)) { + case SyntaxKind.BinaryExpression: + if (isAssignmentOperator((node as BinaryExpression).operatorToken.kind)) { return false; } - return isSideEffectFree((node as ts.BinaryExpression).left) && - isSideEffectFree((node as ts.BinaryExpression).right); + return isSideEffectFree((node as BinaryExpression).left) && + isSideEffectFree((node as BinaryExpression).right); - case ts.SyntaxKind.PrefixUnaryExpression: - case ts.SyntaxKind.PostfixUnaryExpression: + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: // Unary operators ~, !, +, and - have no side effects. // The rest do. - switch ((node as ts.PrefixUnaryExpression).operator) { - case ts.SyntaxKind.ExclamationToken: - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.TildeToken: + switch ((node as PrefixUnaryExpression).operator) { + case SyntaxKind.ExclamationToken: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: return true; } return false; // Some forms listed here for clarity - case ts.SyntaxKind.VoidExpression: // Explicit opt-out - case ts.SyntaxKind.TypeAssertionExpression: // Not SEF, but can produce useful type warnings - case ts.SyntaxKind.AsExpression: // Not SEF, but can produce useful type warnings + case SyntaxKind.VoidExpression: // Explicit opt-out + case SyntaxKind.TypeAssertionExpression: // Not SEF, but can produce useful type warnings + case SyntaxKind.AsExpression: // Not SEF, but can produce useful type warnings default: return false; } } - function isTypeEqualityComparableTo(source: ts.Type, target: ts.Type) { - return (target.flags & ts.TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); + function isTypeEqualityComparableTo(source: Type, target: Type) { + return (target.flags & TypeFlags.Nullable) !== 0 || isTypeComparableTo(source, target); } function createCheckBinaryExpression() { @@ -34256,18 +34454,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Holds the type of the result at stackIndex+1. This allows us to reuse existing stack entries * and avoid storing an extra property on the object (i.e., `lastResult`). */ - typeStack: (ts.Type | undefined)[]; + typeStack: (Type | undefined)[]; } - const trampoline = ts.createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, foldState); + const trampoline = createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, foldState); - return (node: ts.BinaryExpression, checkMode: CheckMode | undefined) => { + return (node: BinaryExpression, checkMode: CheckMode | undefined) => { const result = trampoline(node, checkMode); - ts.Debug.assertIsDefined(result); + Debug.assertIsDefined(result); return result; }; - function onEnter(node: ts.BinaryExpression, state: WorkArea | undefined, checkMode: CheckMode | undefined) { + function onEnter(node: BinaryExpression, state: WorkArea | undefined, checkMode: CheckMode | undefined) { if (state) { state.stackIndex++; state.skip = false; @@ -34283,7 +34481,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }; } - if (ts.isInJSFile(node) && ts.getAssignedExpandoInitializer(node)) { + if (isInJSFile(node) && getAssignedExpandoInitializer(node)) { state.skip = true; setLastResult(state, checkExpression(node.right, checkMode)); return state; @@ -34292,59 +34490,59 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkGrammarNullishCoalesceWithLogicalExpression(node); const operator = node.operatorToken.kind; - if (operator === ts.SyntaxKind.EqualsToken && (node.left.kind === ts.SyntaxKind.ObjectLiteralExpression || node.left.kind === ts.SyntaxKind.ArrayLiteralExpression)) { + if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) { state.skip = true; - setLastResult(state, checkDestructuringAssignment(node.left, checkExpression(node.right, checkMode), checkMode, node.right.kind === ts.SyntaxKind.ThisKeyword)); + setLastResult(state, checkDestructuringAssignment(node.left, checkExpression(node.right, checkMode), checkMode, node.right.kind === SyntaxKind.ThisKeyword)); return state; } return state; } - function onLeft(left: ts.Expression, state: WorkArea, _node: ts.BinaryExpression) { + function onLeft(left: Expression, state: WorkArea, _node: BinaryExpression) { if (!state.skip) { return maybeCheckExpression(state, left); } } - function onOperator(operatorToken: ts.BinaryOperatorToken, state: WorkArea, node: ts.BinaryExpression) { + function onOperator(operatorToken: BinaryOperatorToken, state: WorkArea, node: BinaryExpression) { if (!state.skip) { const leftType = getLastResult(state); - ts.Debug.assertIsDefined(leftType); + Debug.assertIsDefined(leftType); setLeftType(state, leftType); setLastResult(state, /*type*/ undefined); const operator = operatorToken.kind; - if (operator === ts.SyntaxKind.AmpersandAmpersandToken || operator === ts.SyntaxKind.BarBarToken || operator === ts.SyntaxKind.QuestionQuestionToken) { - if (operator === ts.SyntaxKind.AmpersandAmpersandToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { + if (operator === SyntaxKind.AmpersandAmpersandToken) { let parent = node.parent; - while (parent.kind === ts.SyntaxKind.ParenthesizedExpression - || ts.isBinaryExpression(parent) && (parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === ts.SyntaxKind.BarBarToken)) { + while (parent.kind === SyntaxKind.ParenthesizedExpression + || isBinaryExpression(parent) && (parent.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === SyntaxKind.BarBarToken)) { parent = parent.parent; } - checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, ts.isIfStatement(parent) ? parent.thenStatement : undefined); + checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined); } checkTruthinessOfType(leftType, node.left); } } } - function onRight(right: ts.Expression, state: WorkArea, _node: ts.BinaryExpression) { + function onRight(right: Expression, state: WorkArea, _node: BinaryExpression) { if (!state.skip) { return maybeCheckExpression(state, right); } } - function onExit(node: ts.BinaryExpression, state: WorkArea): ts.Type | undefined { - let result: ts.Type | undefined; + function onExit(node: BinaryExpression, state: WorkArea): Type | undefined { + let result: Type | undefined; if (state.skip) { result = getLastResult(state); } else { const leftType = getLeftType(state); - ts.Debug.assertIsDefined(leftType); + Debug.assertIsDefined(leftType); const rightType = getLastResult(state); - ts.Debug.assertIsDefined(rightType); + Debug.assertIsDefined(rightType); result = checkBinaryLikeExpressionWorker(node.left, node.operatorToken, node.right, leftType, rightType, node); } @@ -34356,13 +34554,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function foldState(state: WorkArea, result: ts.Type | undefined, _side: "left" | "right") { + function foldState(state: WorkArea, result: Type | undefined, _side: "left" | "right") { setLastResult(state, result); return state; } - function maybeCheckExpression(state: WorkArea, node: ts.Expression): ts.BinaryExpression | undefined { - if (ts.isBinaryExpression(node)) { + function maybeCheckExpression(state: WorkArea, node: Expression): BinaryExpression | undefined { + if (isBinaryExpression(node)) { return node; } setLastResult(state, checkExpression(node, state.checkMode)); @@ -34372,7 +34570,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return state.typeStack[state.stackIndex]; } - function setLeftType(state: WorkArea, type: ts.Type | undefined) { + function setLeftType(state: WorkArea, type: Type | undefined) { state.typeStack[state.stackIndex] = type; } @@ -34380,7 +34578,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return state.typeStack[state.stackIndex + 1]; } - function setLastResult(state: WorkArea, type: ts.Type | undefined) { + function setLastResult(state: WorkArea, type: Type | undefined) { // To reduce overhead, reuse the next stack entry to store the // last result. This avoids the overhead of an additional property // on `WorkArea` and reuses empty stack entries as we walk back up @@ -34389,27 +34587,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkGrammarNullishCoalesceWithLogicalExpression(node: ts.BinaryExpression) { + function checkGrammarNullishCoalesceWithLogicalExpression(node: BinaryExpression) { const { left, operatorToken, right } = node; - if (operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) { - if (ts.isBinaryExpression(left) && (left.operatorToken.kind === ts.SyntaxKind.BarBarToken || left.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)) { - grammarErrorOnNode(left, ts.Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, ts.tokenToString(left.operatorToken.kind), ts.tokenToString(operatorToken.kind)); + if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) { + if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { + grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind)); } - if (ts.isBinaryExpression(right) && (right.operatorToken.kind === ts.SyntaxKind.BarBarToken || right.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken)) { - grammarErrorOnNode(right, ts.Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, ts.tokenToString(right.operatorToken.kind), ts.tokenToString(operatorToken.kind)); + if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) { + grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind)); } } } // Note that this and `checkBinaryExpression` above should behave mostly the same, except this elides some // expression-wide checks and does not use a work stack to fold nested binary expressions into the same callstack frame - function checkBinaryLikeExpression(left: ts.Expression, operatorToken: ts.Node, right: ts.Expression, checkMode?: CheckMode, errorNode?: ts.Node): ts.Type { + function checkBinaryLikeExpression(left: Expression, operatorToken: Node, right: Expression, checkMode?: CheckMode, errorNode?: Node): Type { const operator = operatorToken.kind; - if (operator === ts.SyntaxKind.EqualsToken && (left.kind === ts.SyntaxKind.ObjectLiteralExpression || left.kind === ts.SyntaxKind.ArrayLiteralExpression)) { - return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === ts.SyntaxKind.ThisKeyword); + if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) { + return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword); } - let leftType: ts.Type; - if (operator === ts.SyntaxKind.AmpersandAmpersandToken || operator === ts.SyntaxKind.BarBarToken || operator === ts.SyntaxKind.QuestionQuestionToken) { + let leftType: Type; + if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) { leftType = checkTruthinessExpression(left, checkMode); } else { @@ -34421,37 +34619,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function checkBinaryLikeExpressionWorker( - left: ts.Expression, - operatorToken: ts.Node, - right: ts.Expression, - leftType: ts.Type, - rightType: ts.Type, - errorNode?: ts.Node - ): ts.Type { + left: Expression, + operatorToken: Node, + right: Expression, + leftType: Type, + rightType: Type, + errorNode?: Node + ): Type { const operator = operatorToken.kind; switch (operator) { - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.AsteriskAsteriskToken: - case ts.SyntaxKind.AsteriskEqualsToken: - case ts.SyntaxKind.AsteriskAsteriskEqualsToken: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.SlashEqualsToken: - case ts.SyntaxKind.PercentToken: - case ts.SyntaxKind.PercentEqualsToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.MinusEqualsToken: - case ts.SyntaxKind.LessThanLessThanToken: - case ts.SyntaxKind.LessThanLessThanEqualsToken: - case ts.SyntaxKind.GreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.BarEqualsToken: - case ts.SyntaxKind.CaretToken: - case ts.SyntaxKind.CaretEqualsToken: - case ts.SyntaxKind.AmpersandToken: - case ts.SyntaxKind.AmpersandEqualsToken: + case SyntaxKind.AsteriskToken: + case SyntaxKind.AsteriskAsteriskToken: + case SyntaxKind.AsteriskEqualsToken: + case SyntaxKind.AsteriskAsteriskEqualsToken: + case SyntaxKind.SlashToken: + case SyntaxKind.SlashEqualsToken: + case SyntaxKind.PercentToken: + case SyntaxKind.PercentEqualsToken: + case SyntaxKind.MinusToken: + case SyntaxKind.MinusEqualsToken: + case SyntaxKind.LessThanLessThanToken: + case SyntaxKind.LessThanLessThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.BarToken: + case SyntaxKind.BarEqualsToken: + case SyntaxKind.CaretToken: + case SyntaxKind.CaretEqualsToken: + case SyntaxKind.AmpersandToken: + case SyntaxKind.AmpersandEqualsToken: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } @@ -34459,38 +34657,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); - let suggestedOperator: ts.SyntaxKind | undefined; + let suggestedOperator: SyntaxKind | undefined; // if a user tries to apply a bitwise operator to 2 boolean operands // try and return them a helpful suggestion - if ((leftType.flags & ts.TypeFlags.BooleanLike) && - (rightType.flags & ts.TypeFlags.BooleanLike) && + if ((leftType.flags & TypeFlags.BooleanLike) && + (rightType.flags & TypeFlags.BooleanLike) && (suggestedOperator = getSuggestedBooleanOperator(operatorToken.kind)) !== undefined) { - error(errorNode || operatorToken, ts.Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, ts.tokenToString(operatorToken.kind), ts.tokenToString(suggestedOperator)); + error(errorNode || operatorToken, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(operatorToken.kind), tokenToString(suggestedOperator)); return numberType; } else { // otherwise just check each operand separately and report errors as normal - const leftOk = checkArithmeticOperandType(left, leftType, ts.Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); - const rightOk = checkArithmeticOperandType(right, rightType, ts.Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); - let resultType: ts.Type; + const leftOk = checkArithmeticOperandType(left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); + const rightOk = checkArithmeticOperandType(right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_bigint_or_an_enum_type, /*isAwaitValid*/ true); + let resultType: Type; // If both are any or unknown, allow operation; assume it will resolve to number - if ((isTypeAssignableToKind(leftType, ts.TypeFlags.AnyOrUnknown) && isTypeAssignableToKind(rightType, ts.TypeFlags.AnyOrUnknown)) || + if ((isTypeAssignableToKind(leftType, TypeFlags.AnyOrUnknown) && isTypeAssignableToKind(rightType, TypeFlags.AnyOrUnknown)) || // Or, if neither could be bigint, implicit coercion results in a number result - !(maybeTypeOfKind(leftType, ts.TypeFlags.BigIntLike) || maybeTypeOfKind(rightType, ts.TypeFlags.BigIntLike)) + !(maybeTypeOfKind(leftType, TypeFlags.BigIntLike) || maybeTypeOfKind(rightType, TypeFlags.BigIntLike)) ) { resultType = numberType; } // At least one is assignable to bigint, so check that both are else if (bothAreBigIntLike(leftType, rightType)) { switch (operator) { - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: reportOperatorError(); break; - case ts.SyntaxKind.AsteriskAsteriskToken: - case ts.SyntaxKind.AsteriskAsteriskEqualsToken: - if (languageVersion < ts.ScriptTarget.ES2016) { - error(errorNode, ts.Diagnostics.Exponentiation_cannot_be_performed_on_bigint_values_unless_the_target_option_is_set_to_es2016_or_later); + case SyntaxKind.AsteriskAsteriskToken: + case SyntaxKind.AsteriskAsteriskEqualsToken: + if (languageVersion < ScriptTarget.ES2016) { + error(errorNode, Diagnostics.Exponentiation_cannot_be_performed_on_bigint_values_unless_the_target_option_is_set_to_es2016_or_later); } } resultType = bigintType; @@ -34505,28 +34703,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return resultType; } - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.PlusEqualsToken: + case SyntaxKind.PlusToken: + case SyntaxKind.PlusEqualsToken: if (leftType === silentNeverType || rightType === silentNeverType) { return silentNeverType; } - if (!isTypeAssignableToKind(leftType, ts.TypeFlags.StringLike) && !isTypeAssignableToKind(rightType, ts.TypeFlags.StringLike)) { + if (!isTypeAssignableToKind(leftType, TypeFlags.StringLike) && !isTypeAssignableToKind(rightType, TypeFlags.StringLike)) { leftType = checkNonNullType(leftType, left); rightType = checkNonNullType(rightType, right); } - let resultType: ts.Type | undefined; - if (isTypeAssignableToKind(leftType, ts.TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, ts.TypeFlags.NumberLike, /*strict*/ true)) { + let resultType: Type | undefined; + if (isTypeAssignableToKind(leftType, TypeFlags.NumberLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.NumberLike, /*strict*/ true)) { // Operands of an enum type are treated as having the primitive type Number. // If both operands are of the Number primitive type, the result is of the Number primitive type. resultType = numberType; } - else if (isTypeAssignableToKind(leftType, ts.TypeFlags.BigIntLike, /*strict*/ true) && isTypeAssignableToKind(rightType, ts.TypeFlags.BigIntLike, /*strict*/ true)) { + else if (isTypeAssignableToKind(leftType, TypeFlags.BigIntLike, /*strict*/ true) && isTypeAssignableToKind(rightType, TypeFlags.BigIntLike, /*strict*/ true)) { // If both operands are of the BigInt primitive type, the result is of the BigInt primitive type. resultType = bigintType; } - else if (isTypeAssignableToKind(leftType, ts.TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, ts.TypeFlags.StringLike, /*strict*/ true)) { + else if (isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true)) { // If one or both operands are of the String primitive type, the result is of the String primitive type. resultType = stringType; } @@ -34546,21 +34744,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If both types have an awaited type of one of these, we'll assume the user // might be missing an await without doing an exhaustive check that inserting // await(s) will actually be a completely valid binary expression. - const closeEnoughKind = ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.StringLike | ts.TypeFlags.AnyOrUnknown; + const closeEnoughKind = TypeFlags.NumberLike | TypeFlags.BigIntLike | TypeFlags.StringLike | TypeFlags.AnyOrUnknown; reportOperatorError((left, right) => isTypeAssignableToKind(left, closeEnoughKind) && isTypeAssignableToKind(right, closeEnoughKind)); return anyType; } - if (operator === ts.SyntaxKind.PlusEqualsToken) { + if (operator === SyntaxKind.PlusEqualsToken) { checkAssignmentOperator(resultType); } return resultType; - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.GreaterThanToken: - case ts.SyntaxKind.LessThanEqualsToken: - case ts.SyntaxKind.GreaterThanEqualsToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.LessThanEqualsToken: + case SyntaxKind.GreaterThanEqualsToken: if (checkForDisallowedESSymbolOperand(operator)) { leftType = getBaseTypeOfLiteralType(checkNonNullType(leftType, left)); rightType = getBaseTypeOfLiteralType(checkNonNullType(rightType, right)); @@ -34569,62 +34767,62 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isTypeAssignableTo(left, numberOrBigIntType) && isTypeAssignableTo(right, numberOrBigIntType))); } return booleanType; - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - if (ts.isLiteralExpressionOfObject(left) || ts.isLiteralExpressionOfObject(right)) { - const eqType = operator === ts.SyntaxKind.EqualsEqualsToken || operator === ts.SyntaxKind.EqualsEqualsEqualsToken; - error(errorNode, ts.Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true"); + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + if (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) { + const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken; + error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true"); } checkNaNEquality(errorNode, operator, left, right); reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left)); return booleanType; - case ts.SyntaxKind.InstanceOfKeyword: + case SyntaxKind.InstanceOfKeyword: return checkInstanceOfExpression(left, right, leftType, rightType); - case ts.SyntaxKind.InKeyword: + case SyntaxKind.InKeyword: return checkInExpression(left, right, leftType, rightType); - case ts.SyntaxKind.AmpersandAmpersandToken: - case ts.SyntaxKind.AmpersandAmpersandEqualsToken: { + case SyntaxKind.AmpersandAmpersandToken: + case SyntaxKind.AmpersandAmpersandEqualsToken: { const resultType = getTypeFacts(leftType) & TypeFacts.Truthy ? getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; - if (operator === ts.SyntaxKind.AmpersandAmpersandEqualsToken) { + if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) { checkAssignmentOperator(rightType); } return resultType; } - case ts.SyntaxKind.BarBarToken: - case ts.SyntaxKind.BarBarEqualsToken: { + case SyntaxKind.BarBarToken: + case SyntaxKind.BarBarEqualsToken: { const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ? - getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], ts.UnionReduction.Subtype) : + getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], UnionReduction.Subtype) : leftType; - if (operator === ts.SyntaxKind.BarBarEqualsToken) { + if (operator === SyntaxKind.BarBarEqualsToken) { checkAssignmentOperator(rightType); } return resultType; } - case ts.SyntaxKind.QuestionQuestionToken: - case ts.SyntaxKind.QuestionQuestionEqualsToken: { + case SyntaxKind.QuestionQuestionToken: + case SyntaxKind.QuestionQuestionEqualsToken: { const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? - getUnionType([getNonNullableType(leftType), rightType], ts.UnionReduction.Subtype) : + getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : leftType; - if (operator === ts.SyntaxKind.QuestionQuestionEqualsToken) { + if (operator === SyntaxKind.QuestionQuestionEqualsToken) { checkAssignmentOperator(rightType); } return resultType; } - case ts.SyntaxKind.EqualsToken: - const declKind = ts.isBinaryExpression(left.parent) ? ts.getAssignmentDeclarationKind(left.parent) : ts.AssignmentDeclarationKind.None; + case SyntaxKind.EqualsToken: + const declKind = isBinaryExpression(left.parent) ? getAssignmentDeclarationKind(left.parent) : AssignmentDeclarationKind.None; checkAssignmentDeclaration(declKind, rightType); if (isAssignmentDeclaration(declKind)) { - if (!(rightType.flags & ts.TypeFlags.Object) || - declKind !== ts.AssignmentDeclarationKind.ModuleExports && - declKind !== ts.AssignmentDeclarationKind.Prototype && + if (!(rightType.flags & TypeFlags.Object) || + declKind !== AssignmentDeclarationKind.ModuleExports && + declKind !== AssignmentDeclarationKind.Prototype && !isEmptyObjectType(rightType) && - !isFunctionObjectType(rightType as ts.ObjectType) && - !(ts.getObjectFlags(rightType) & ts.ObjectFlags.Class)) { + !isFunctionObjectType(rightType as ObjectType) && + !(getObjectFlags(rightType) & ObjectFlags.Class)) { // don't check assignability of module.exports=, C.prototype=, or expando types because they will necessarily be incomplete checkAssignmentOperator(rightType); } @@ -34634,80 +34832,80 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkAssignmentOperator(rightType); return getRegularTypeOfObjectLiteral(rightType); } - case ts.SyntaxKind.CommaToken: + case SyntaxKind.CommaToken: if (!compilerOptions.allowUnreachableCode && isSideEffectFree(left) && !isEvalNode(right)) { - const sf = ts.getSourceFileOfNode(left); + const sf = getSourceFileOfNode(left); const sourceText = sf.text; - const start = ts.skipTrivia(sourceText, left.pos); + const start = skipTrivia(sourceText, left.pos); const isInDiag2657 = sf.parseDiagnostics.some(diag => { - if (diag.code !== ts.Diagnostics.JSX_expressions_must_have_one_parent_element.code) return false; - return ts.textSpanContainsPosition(diag, start); + if (diag.code !== Diagnostics.JSX_expressions_must_have_one_parent_element.code) return false; + return textSpanContainsPosition(diag, start); }); - if (!isInDiag2657) error(left, ts.Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); + if (!isInDiag2657) error(left, Diagnostics.Left_side_of_comma_operator_is_unused_and_has_no_side_effects); } return rightType; default: - return ts.Debug.fail(); + return Debug.fail(); } - function bothAreBigIntLike(left: ts.Type, right: ts.Type): boolean { - return isTypeAssignableToKind(left, ts.TypeFlags.BigIntLike) && isTypeAssignableToKind(right, ts.TypeFlags.BigIntLike); + function bothAreBigIntLike(left: Type, right: Type): boolean { + return isTypeAssignableToKind(left, TypeFlags.BigIntLike) && isTypeAssignableToKind(right, TypeFlags.BigIntLike); } - function checkAssignmentDeclaration(kind: ts.AssignmentDeclarationKind, rightType: ts.Type) { - if (kind === ts.AssignmentDeclarationKind.ModuleExports) { + function checkAssignmentDeclaration(kind: AssignmentDeclarationKind, rightType: Type) { + if (kind === AssignmentDeclarationKind.ModuleExports) { for (const prop of getPropertiesOfObjectType(rightType)) { const propType = getTypeOfSymbol(prop); - if (propType.symbol && propType.symbol.flags & ts.SymbolFlags.Class) { + if (propType.symbol && propType.symbol.flags & SymbolFlags.Class) { const name = prop.escapedName; - const symbol = resolveName(prop.valueDeclaration, name, ts.SymbolFlags.Type, undefined, name, /*isUse*/ false); - if (symbol?.declarations && symbol.declarations.some(ts.isJSDocTypedefTag)) { - addDuplicateDeclarationErrorsForSymbols(symbol, ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name), prop); - addDuplicateDeclarationErrorsForSymbols(prop, ts.Diagnostics.Duplicate_identifier_0, ts.unescapeLeadingUnderscores(name), symbol); + const symbol = resolveName(prop.valueDeclaration, name, SymbolFlags.Type, undefined, name, /*isUse*/ false); + if (symbol?.declarations && symbol.declarations.some(isJSDocTypedefTag)) { + addDuplicateDeclarationErrorsForSymbols(symbol, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), prop); + addDuplicateDeclarationErrorsForSymbols(prop, Diagnostics.Duplicate_identifier_0, unescapeLeadingUnderscores(name), symbol); } } } } } - function isEvalNode(node: ts.Expression) { - return node.kind === ts.SyntaxKind.Identifier && (node as ts.Identifier).escapedText === "eval"; + function isEvalNode(node: Expression) { + return node.kind === SyntaxKind.Identifier && (node as Identifier).escapedText === "eval"; } // Return true if there was no error, false if there was an error. - function checkForDisallowedESSymbolOperand(operator: ts.SyntaxKind): boolean { + function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { const offendingSymbolOperand = - maybeTypeOfKindConsideringBaseConstraint(leftType, ts.TypeFlags.ESSymbolLike) ? left : - maybeTypeOfKindConsideringBaseConstraint(rightType, ts.TypeFlags.ESSymbolLike) ? right : + maybeTypeOfKindConsideringBaseConstraint(leftType, TypeFlags.ESSymbolLike) ? left : + maybeTypeOfKindConsideringBaseConstraint(rightType, TypeFlags.ESSymbolLike) ? right : undefined; if (offendingSymbolOperand) { - error(offendingSymbolOperand, ts.Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, ts.tokenToString(operator)); + error(offendingSymbolOperand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(operator)); return false; } return true; } - function getSuggestedBooleanOperator(operator: ts.SyntaxKind): ts.SyntaxKind | undefined { + function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind | undefined { switch (operator) { - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.BarEqualsToken: - return ts.SyntaxKind.BarBarToken; - case ts.SyntaxKind.CaretToken: - case ts.SyntaxKind.CaretEqualsToken: - return ts.SyntaxKind.ExclamationEqualsEqualsToken; - case ts.SyntaxKind.AmpersandToken: - case ts.SyntaxKind.AmpersandEqualsToken: - return ts.SyntaxKind.AmpersandAmpersandToken; + case SyntaxKind.BarToken: + case SyntaxKind.BarEqualsToken: + return SyntaxKind.BarBarToken; + case SyntaxKind.CaretToken: + case SyntaxKind.CaretEqualsToken: + return SyntaxKind.ExclamationEqualsEqualsToken; + case SyntaxKind.AmpersandToken: + case SyntaxKind.AmpersandEqualsToken: + return SyntaxKind.AmpersandAmpersandToken; default: return undefined; } } - function checkAssignmentOperator(valueType: ts.Type): void { - if (ts.isAssignmentOperator(operator)) { + function checkAssignmentOperator(valueType: Type): void { + if (isAssignmentOperator(operator)) { addLazyDiagnostic(checkAssignmentOperatorWorker); } @@ -34720,15 +34918,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // and the type of the non-compound operation to be assignable to the type of VarExpr. if (checkReferenceExpression(left, - ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access, - ts.Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access) - && (!ts.isIdentifier(left) || ts.unescapeLeadingUnderscores(left.escapedText) !== "exports")) { + Diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access, + Diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access) + && (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) { - let headMessage: ts.DiagnosticMessage | undefined; - if (exactOptionalPropertyTypes && ts.isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, ts.TypeFlags.Undefined)) { + let headMessage: DiagnosticMessage | undefined; + if (exactOptionalPropertyTypes && isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, TypeFlags.Undefined)) { const target = getTypeOfPropertyOfType(getTypeOfExpression(left.expression), left.name.escapedText); if (isExactOptionalPropertyMismatch(valueType, target)) { - headMessage = ts.Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target; + headMessage = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target; } } // to avoid cascading errors check assignability only if 'isReference' check succeeded and no errors were reported @@ -34737,18 +34935,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isAssignmentDeclaration(kind: ts.AssignmentDeclarationKind) { + function isAssignmentDeclaration(kind: AssignmentDeclarationKind) { switch (kind) { - case ts.AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.ModuleExports: return true; - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.Property: - case ts.AssignmentDeclarationKind.Prototype: - case ts.AssignmentDeclarationKind.PrototypeProperty: - case ts.AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: + case AssignmentDeclarationKind.ThisProperty: const symbol = getSymbolOfNode(left); - const init = ts.getAssignedExpandoInitializer(right); - return !!init && ts.isObjectLiteralExpression(init) && + const init = getAssignedExpandoInitializer(right); + return !!init && isObjectLiteralExpression(init) && !!symbol?.exports?.size; default: return false; @@ -34758,7 +34956,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Returns true if an error is reported */ - function reportOperatorErrorUnless(typesAreCompatible: (left: ts.Type, right: ts.Type) => boolean): boolean { + function reportOperatorErrorUnless(typesAreCompatible: (left: Type, right: Type) => boolean): boolean { if (!typesAreCompatible(leftType, rightType)) { reportOperatorError(typesAreCompatible); return true; @@ -34766,7 +34964,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function reportOperatorError(isRelated?: (left: ts.Type, right: ts.Type) => boolean) { + function reportOperatorError(isRelated?: (left: Type, right: Type) => boolean) { let wouldWorkWithAwait = false; const errNode = errorNode || operatorToken; if (isRelated) { @@ -34787,47 +34985,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { errorAndMaybeSuggestAwait( errNode, wouldWorkWithAwait, - ts.Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, - ts.tokenToString(operatorToken.kind), + Diagnostics.Operator_0_cannot_be_applied_to_types_1_and_2, + tokenToString(operatorToken.kind), leftStr, rightStr, ); } } - function tryGiveBetterPrimaryError(errNode: ts.Node, maybeMissingAwait: boolean, leftStr: string, rightStr: string) { + function tryGiveBetterPrimaryError(errNode: Node, maybeMissingAwait: boolean, leftStr: string, rightStr: string) { switch (operatorToken.kind) { - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: return errorAndMaybeSuggestAwait( errNode, maybeMissingAwait, - ts.Diagnostics.This_comparison_appears_to_be_unintentional_because_the_types_0_and_1_have_no_overlap, + Diagnostics.This_comparison_appears_to_be_unintentional_because_the_types_0_and_1_have_no_overlap, leftStr, rightStr); default: return undefined; } } - function checkNaNEquality(errorNode: ts.Node | undefined, operator: ts.SyntaxKind, left: ts.Expression, right: ts.Expression) { - const isLeftNaN = isGlobalNaN(ts.skipParentheses(left)); - const isRightNaN = isGlobalNaN(ts.skipParentheses(right)); + function checkNaNEquality(errorNode: Node | undefined, operator: SyntaxKind, left: Expression, right: Expression) { + const isLeftNaN = isGlobalNaN(skipParentheses(left)); + const isRightNaN = isGlobalNaN(skipParentheses(right)); if (isLeftNaN || isRightNaN) { - const err = error(errorNode, ts.Diagnostics.This_condition_will_always_return_0, - ts.tokenToString(operator === ts.SyntaxKind.EqualsEqualsEqualsToken || operator === ts.SyntaxKind.EqualsEqualsToken ? ts.SyntaxKind.FalseKeyword : ts.SyntaxKind.TrueKeyword)); + const err = error(errorNode, Diagnostics.This_condition_will_always_return_0, + tokenToString(operator === SyntaxKind.EqualsEqualsEqualsToken || operator === SyntaxKind.EqualsEqualsToken ? SyntaxKind.FalseKeyword : SyntaxKind.TrueKeyword)); if (isLeftNaN && isRightNaN) return; - const operatorString = operator === ts.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts.SyntaxKind.ExclamationEqualsToken ? ts.tokenToString(ts.SyntaxKind.ExclamationToken) : ""; + const operatorString = operator === SyntaxKind.ExclamationEqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken ? tokenToString(SyntaxKind.ExclamationToken) : ""; const location = isLeftNaN ? right : left; - const expression = ts.skipParentheses(location); - ts.addRelatedInfo(err, ts.createDiagnosticForNode(location, ts.Diagnostics.Did_you_mean_0, - `${operatorString}Number.isNaN(${ts.isEntityNameExpression(expression) ? ts.entityNameToString(expression) : "..."})`)); + const expression = skipParentheses(location); + addRelatedInfo(err, createDiagnosticForNode(location, Diagnostics.Did_you_mean_0, + `${operatorString}Number.isNaN(${isEntityNameExpression(expression) ? entityNameToString(expression) : "..."})`)); } } - function isGlobalNaN(expr: ts.Expression): boolean { - if (ts.isIdentifier(expr) && expr.escapedText === "NaN") { + function isGlobalNaN(expr: Expression): boolean { + if (isIdentifier(expr) && expr.escapedText === "NaN") { const globalNaNSymbol = getGlobalNaNSymbol(); return !!globalNaNSymbol && globalNaNSymbol === getResolvedSymbol(expr); } @@ -34835,7 +35033,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getBaseTypesIfUnrelated(leftType: ts.Type, rightType: ts.Type, isRelated: (left: ts.Type, right: ts.Type) => boolean): [ts.Type, ts.Type] { + function getBaseTypesIfUnrelated(leftType: Type, rightType: Type, isRelated: (left: Type, right: Type) => boolean): [Type, Type] { let effectiveLeft = leftType; let effectiveRight = rightType; const leftBase = getBaseTypeOfLiteralType(leftType); @@ -34847,29 +35045,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return [ effectiveLeft, effectiveRight ]; } - function checkYieldExpression(node: ts.YieldExpression): ts.Type { + function checkYieldExpression(node: YieldExpression): Type { addLazyDiagnostic(checkYieldExpressionGrammar); - const func = ts.getContainingFunction(node); + const func = getContainingFunction(node); if (!func) return anyType; - const functionFlags = ts.getFunctionFlags(func); + const functionFlags = getFunctionFlags(func); - if (!(functionFlags & ts.FunctionFlags.Generator)) { + if (!(functionFlags & FunctionFlags.Generator)) { // If the user's code is syntactically correct, the func should always have a star. After all, we are in a yield context. return anyType; } - const isAsync = (functionFlags & ts.FunctionFlags.Async) !== 0; + const isAsync = (functionFlags & FunctionFlags.Async) !== 0; if (node.asteriskToken) { // Async generator functions prior to ESNext require the __await, __asyncDelegator, // and __asyncValues helpers - if (isAsync && languageVersion < ts.ScriptTarget.ESNext) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.AsyncDelegatorIncludes); + if (isAsync && languageVersion < ScriptTarget.ESNext) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncDelegatorIncludes); } // Generator functions prior to ES2015 require the __values helper - if (!isAsync && languageVersion < ts.ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Values); + if (!isAsync && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Values); } } @@ -34900,10 +35098,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!type) { type = anyType; addLazyDiagnostic(() => { - if (noImplicitAny && !ts.expressionResultIsUnused(node)) { + if (noImplicitAny && !expressionResultIsUnused(node)) { const contextualType = getContextualType(node, /*contextFlags*/ undefined); if (!contextualType || isTypeAny(contextualType)) { - error(node, ts.Diagnostics.yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation); + error(node, Diagnostics.yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation); } } }); @@ -34911,37 +35109,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; function checkYieldExpressionGrammar() { - if (!(node.flags & ts.NodeFlags.YieldContext)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); + if (!(node.flags & NodeFlags.YieldContext)) { + grammarErrorOnFirstToken(node, Diagnostics.A_yield_expression_is_only_allowed_in_a_generator_body); } if (isInParameterInitializerBeforeContainingFunction(node)) { - error(node, ts.Diagnostics.yield_expressions_cannot_be_used_in_a_parameter_initializer); + error(node, Diagnostics.yield_expressions_cannot_be_used_in_a_parameter_initializer); } } } - function checkConditionalExpression(node: ts.ConditionalExpression, checkMode?: CheckMode): ts.Type { + function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type { const type = checkTruthinessExpression(node.condition); checkTestingKnownTruthyCallableOrAwaitableType(node.condition, type, node.whenTrue); const type1 = checkExpression(node.whenTrue, checkMode); const type2 = checkExpression(node.whenFalse, checkMode); - return getUnionType([type1, type2], ts.UnionReduction.Subtype); + return getUnionType([type1, type2], UnionReduction.Subtype); } - function isTemplateLiteralContext(node: ts.Node): boolean { + function isTemplateLiteralContext(node: Node): boolean { const parent = node.parent; - return ts.isParenthesizedExpression(parent) && isTemplateLiteralContext(parent) || - ts.isElementAccessExpression(parent) && parent.argumentExpression === node; + return isParenthesizedExpression(parent) && isTemplateLiteralContext(parent) || + isElementAccessExpression(parent) && parent.argumentExpression === node; } - function checkTemplateExpression(node: ts.TemplateExpression): ts.Type { + function checkTemplateExpression(node: TemplateExpression): Type { const texts = [node.head.text]; const types = []; for (const span of node.templateSpans) { const type = checkExpression(span.expression); - if (maybeTypeOfKindConsideringBaseConstraint(type, ts.TypeFlags.ESSymbolLike)) { - error(span.expression, ts.Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String); + if (maybeTypeOfKindConsideringBaseConstraint(type, TypeFlags.ESSymbolLike)) { + error(span.expression, Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String); } texts.push(span.literal.text); types.push(isTypeAssignableTo(type, templateConstraintType) ? type : stringType); @@ -34949,19 +35147,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node, /*contextFlags*/ undefined) || unknownType, isTemplateLiteralContextualType) ? getTemplateLiteralType(texts, types) : stringType; } - function isTemplateLiteralContextualType(type: ts.Type): boolean { - return !!(type.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.TemplateLiteral) || - type.flags & ts.TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, ts.TypeFlags.StringLike)); + function isTemplateLiteralContextualType(type: Type): boolean { + return !!(type.flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral) || + type.flags & TypeFlags.InstantiableNonPrimitive && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.StringLike)); } - function getContextNode(node: ts.Expression): ts.Node { - if (node.kind === ts.SyntaxKind.JsxAttributes && !ts.isJsxSelfClosingElement(node.parent)) { + function getContextNode(node: Expression): Node { + if (node.kind === SyntaxKind.JsxAttributes && !isJsxSelfClosingElement(node.parent)) { return node.parent.parent; // Needs to be the root JsxElement, so it encompasses the attributes _and_ the children (which are essentially part of the attributes) } return node; } - function checkExpressionWithContextualType(node: ts.Expression, contextualType: ts.Type, inferenceContext: ts.InferenceContext | undefined, checkMode: CheckMode): ts.Type { + function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type { const context = getContextNode(node); const saveContextualType = context.contextualType; const saveInferenceContext = context.inferenceContext; @@ -34977,7 +35175,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We strip literal freshness when an appropriate contextual type is present such that contextually typed // literals always preserve their literal types (otherwise they might widen during type inference). An alternative // here would be to not mark contextually typed literals as fresh in the first place. - const result = maybeTypeOfKind(type, ts.TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node, /*contextFlags*/ undefined)) ? + const result = maybeTypeOfKind(type, TypeFlags.Literal) && isLiteralOfContextualType(type, instantiateContextualType(contextualType, node, /*contextFlags*/ undefined)) ? getRegularTypeOfLiteralType(type) : type; return result; } @@ -34990,7 +35188,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkExpressionCached(node: ts.Expression | ts.QualifiedName, checkMode?: CheckMode): ts.Type { + function checkExpressionCached(node: Expression | QualifiedName, checkMode?: CheckMode): Type { if (checkMode) { return checkExpression(node, checkMode); } @@ -35010,38 +35208,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return links.resolvedType; } - function isTypeAssertion(node: ts.Expression) { - node = ts.skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - return node.kind === ts.SyntaxKind.TypeAssertionExpression || - node.kind === ts.SyntaxKind.AsExpression || - ts.isJSDocTypeAssertion(node); + function isTypeAssertion(node: Expression) { + node = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); + return node.kind === SyntaxKind.TypeAssertionExpression || + node.kind === SyntaxKind.AsExpression || + isJSDocTypeAssertion(node); } function checkDeclarationInitializer( - declaration: ts.HasExpressionInitializer, + declaration: HasExpressionInitializer, checkMode: CheckMode, - contextualType?: ts.Type | undefined + contextualType?: Type | undefined ) { - const initializer = ts.getEffectiveInitializer(declaration)!; + const initializer = getEffectiveInitializer(declaration)!; const type = getQuickTypeOfExpression(initializer) || (contextualType ? checkExpressionWithContextualType(initializer, contextualType, /*inferenceContext*/ undefined, checkMode || CheckMode.Normal) : checkExpressionCached(initializer, checkMode)); - return ts.isParameter(declaration) && declaration.name.kind === ts.SyntaxKind.ArrayBindingPattern && + return isParameter(declaration) && declaration.name.kind === SyntaxKind.ArrayBindingPattern && isTupleType(type) && !type.target.hasRestElement && getTypeReferenceArity(type) < declaration.name.elements.length ? padTupleType(type, declaration.name) : type; } - function padTupleType(type: ts.TupleTypeReference, pattern: ts.ArrayBindingPattern) { + function padTupleType(type: TupleTypeReference, pattern: ArrayBindingPattern) { const patternElements = pattern.elements; const elementTypes = getTypeArguments(type).slice(); const elementFlags = type.target.elementFlags.slice(); for (let i = getTypeReferenceArity(type); i < patternElements.length; i++) { const e = patternElements[i]; - if (i < patternElements.length - 1 || !(e.kind === ts.SyntaxKind.BindingElement && e.dotDotDotToken)) { - elementTypes.push(!ts.isOmittedExpression(e) && hasDefaultValue(e) ? getTypeFromBindingElement(e, /*includePatternInType*/ false, /*reportErrors*/ false) : anyType); - elementFlags.push(ts.ElementFlags.Optional); - if (!ts.isOmittedExpression(e) && !hasDefaultValue(e)) { + if (i < patternElements.length - 1 || !(e.kind === SyntaxKind.BindingElement && e.dotDotDotToken)) { + elementTypes.push(!isOmittedExpression(e) && hasDefaultValue(e) ? getTypeFromBindingElement(e, /*includePatternInType*/ false, /*reportErrors*/ false) : anyType); + elementFlags.push(ElementFlags.Optional); + if (!isOmittedExpression(e) && !hasDefaultValue(e)) { reportImplicitAny(e, anyType); } } @@ -35049,9 +35247,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return createTupleType(elementTypes, elementFlags, type.target.readonly); } - function widenTypeInferredFromInitializer(declaration: ts.HasExpressionInitializer, type: ts.Type) { - const widened = ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const || ts.isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type); - if (ts.isInJSFile(declaration)) { + function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) { + const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type); + if (isInJSFile(declaration)) { if (isEmptyLiteralType(widened)) { reportImplicitAny(declaration, anyType); return anyType; @@ -35064,68 +35262,68 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return widened; } - function isLiteralOfContextualType(candidateType: ts.Type, contextualType: ts.Type | undefined): boolean { + function isLiteralOfContextualType(candidateType: Type, contextualType: Type | undefined): boolean { if (contextualType) { - if (contextualType.flags & ts.TypeFlags.UnionOrIntersection) { - const types = (contextualType as ts.UnionType).types; - return ts.some(types, t => isLiteralOfContextualType(candidateType, t)); + if (contextualType.flags & TypeFlags.UnionOrIntersection) { + const types = (contextualType as UnionType).types; + return some(types, t => isLiteralOfContextualType(candidateType, t)); } - if (contextualType.flags & ts.TypeFlags.InstantiableNonPrimitive) { + if (contextualType.flags & TypeFlags.InstantiableNonPrimitive) { // If the contextual type is a type variable constrained to a primitive type, consider // this a literal context for literals of that primitive type. For example, given a // type parameter 'T extends string', infer string literal types for T. const constraint = getBaseConstraintOfType(contextualType) || unknownType; - return maybeTypeOfKind(constraint, ts.TypeFlags.String) && maybeTypeOfKind(candidateType, ts.TypeFlags.StringLiteral) || - maybeTypeOfKind(constraint, ts.TypeFlags.Number) && maybeTypeOfKind(candidateType, ts.TypeFlags.NumberLiteral) || - maybeTypeOfKind(constraint, ts.TypeFlags.BigInt) && maybeTypeOfKind(candidateType, ts.TypeFlags.BigIntLiteral) || - maybeTypeOfKind(constraint, ts.TypeFlags.ESSymbol) && maybeTypeOfKind(candidateType, ts.TypeFlags.UniqueESSymbol) || + return maybeTypeOfKind(constraint, TypeFlags.String) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || + maybeTypeOfKind(constraint, TypeFlags.Number) && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || + maybeTypeOfKind(constraint, TypeFlags.BigInt) && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) || + maybeTypeOfKind(constraint, TypeFlags.ESSymbol) && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol) || isLiteralOfContextualType(candidateType, constraint); } // If the contextual type is a literal of a particular primitive type, we consider this a // literal context for all literals of that primitive type. - return !!(contextualType.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.Index | ts.TypeFlags.TemplateLiteral | ts.TypeFlags.StringMapping) && maybeTypeOfKind(candidateType, ts.TypeFlags.StringLiteral) || - contextualType.flags & ts.TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, ts.TypeFlags.NumberLiteral) || - contextualType.flags & ts.TypeFlags.BigIntLiteral && maybeTypeOfKind(candidateType, ts.TypeFlags.BigIntLiteral) || - contextualType.flags & ts.TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, ts.TypeFlags.BooleanLiteral) || - contextualType.flags & ts.TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, ts.TypeFlags.UniqueESSymbol)); + return !!(contextualType.flags & (TypeFlags.StringLiteral | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) || + contextualType.flags & TypeFlags.NumberLiteral && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) || + contextualType.flags & TypeFlags.BigIntLiteral && maybeTypeOfKind(candidateType, TypeFlags.BigIntLiteral) || + contextualType.flags & TypeFlags.BooleanLiteral && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) || + contextualType.flags & TypeFlags.UniqueESSymbol && maybeTypeOfKind(candidateType, TypeFlags.UniqueESSymbol)); } return false; } - function isConstContext(node: ts.Expression): boolean { + function isConstContext(node: Expression): boolean { const parent = node.parent; - return ts.isAssertionExpression(parent) && ts.isConstTypeReference(parent.type) || - ts.isJSDocTypeAssertion(parent) && ts.isConstTypeReference(ts.getJSDocTypeAssertionType(parent)) || - (ts.isParenthesizedExpression(parent) || ts.isArrayLiteralExpression(parent) || ts.isSpreadElement(parent)) && isConstContext(parent) || - (ts.isPropertyAssignment(parent) || ts.isShorthandPropertyAssignment(parent) || ts.isTemplateSpan(parent)) && isConstContext(parent.parent); + return isAssertionExpression(parent) && isConstTypeReference(parent.type) || + isJSDocTypeAssertion(parent) && isConstTypeReference(getJSDocTypeAssertionType(parent)) || + (isParenthesizedExpression(parent) || isArrayLiteralExpression(parent) || isSpreadElement(parent)) && isConstContext(parent) || + (isPropertyAssignment(parent) || isShorthandPropertyAssignment(parent) || isTemplateSpan(parent)) && isConstContext(parent.parent); } - function checkExpressionForMutableLocation(node: ts.Expression, checkMode: CheckMode | undefined, contextualType?: ts.Type, forceTuple?: boolean): ts.Type { + function checkExpressionForMutableLocation(node: Expression, checkMode: CheckMode | undefined, contextualType?: Type, forceTuple?: boolean): Type { const type = checkExpression(node, checkMode, forceTuple); - return isConstContext(node) || ts.isCommonJsExportedExpression(node) ? getRegularTypeOfLiteralType(type) : + return isConstContext(node) || isCommonJsExportedExpression(node) ? getRegularTypeOfLiteralType(type) : isTypeAssertion(node) ? type : getWidenedLiteralLikeTypeForContextualType(type, instantiateContextualType(arguments.length === 2 ? getContextualType(node, /*contextFlags*/ undefined) : contextualType, node, /*contextFlags*/ undefined)); } - function checkPropertyAssignment(node: ts.PropertyAssignment, checkMode?: CheckMode): ts.Type { + function checkPropertyAssignment(node: PropertyAssignment, checkMode?: CheckMode): Type { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. - if (node.name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.name.kind === SyntaxKind.ComputedPropertyName) { checkComputedPropertyName(node.name); } return checkExpressionForMutableLocation(node.initializer, checkMode); } - function checkObjectLiteralMethod(node: ts.MethodDeclaration, checkMode?: CheckMode): ts.Type { + function checkObjectLiteralMethod(node: MethodDeclaration, checkMode?: CheckMode): Type { // Grammar checking checkGrammarMethod(node); // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. - if (node.name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.name.kind === SyntaxKind.ComputedPropertyName) { checkComputedPropertyName(node.name); } @@ -35133,15 +35331,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); } - function instantiateTypeWithSingleGenericCallSignature(node: ts.Expression | ts.MethodDeclaration | ts.QualifiedName, type: ts.Type, checkMode?: CheckMode) { + function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration | QualifiedName, type: Type, checkMode?: CheckMode) { if (checkMode && checkMode & (CheckMode.Inferential | CheckMode.SkipGenericFunctions)) { - const callSignature = getSingleSignature(type, ts.SignatureKind.Call, /*allowMembers*/ true); - const constructSignature = getSingleSignature(type, ts.SignatureKind.Construct, /*allowMembers*/ true); + const callSignature = getSingleSignature(type, SignatureKind.Call, /*allowMembers*/ true); + const constructSignature = getSingleSignature(type, SignatureKind.Construct, /*allowMembers*/ true); const signature = callSignature || constructSignature; if (signature && signature.typeParameters) { - const contextualType = getApparentTypeOfContextualType(node as ts.Expression, ts.ContextFlags.NoConstraints); + const contextualType = getApparentTypeOfContextualType(node as Expression, ContextFlags.NoConstraints); if (contextualType) { - const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? ts.SignatureKind.Call : ts.SignatureKind.Construct, /*allowMembers*/ false); + const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers*/ false); if (contextualSignature && !contextualSignature.typeParameters) { if (checkMode & CheckMode.SkipGenericFunctions) { skippedGenericFunction(node, checkMode); @@ -35156,18 +35354,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // potentially add inferred type parameters to the outer function return type. const returnType = context.signature && getReturnTypeOfSignature(context.signature); const returnSignature = returnType && getSingleCallOrConstructSignature(returnType); - if (returnSignature && !returnSignature.typeParameters && !ts.every(context.inferences, hasInferenceCandidates)) { + if (returnSignature && !returnSignature.typeParameters && !every(context.inferences, hasInferenceCandidates)) { // Instantiate the signature with its own type parameters as type arguments, possibly // renaming the type parameters to ensure they have unique names. const uniqueTypeParameters = getUniqueTypeParameters(context, signature.typeParameters); const instantiatedSignature = getSignatureInstantiationWithoutFillingInTypeArguments(signature, uniqueTypeParameters); // Infer from the parameters of the instantiated signature to the parameters of the // contextual signature starting with an empty set of inference candidates. - const inferences = ts.map(context.inferences, info => createInferenceInfo(info.typeParameter)); + const inferences = map(context.inferences, info => createInferenceInfo(info.typeParameter)); applyToParameterTypes(instantiatedSignature, contextualSignature, (source, target) => { inferTypes(inferences, source, target, /*priority*/ 0, /*contravariant*/ true); }); - if (ts.some(inferences, hasInferenceCandidates)) { + if (some(inferences, hasInferenceCandidates)) { // We have inference candidates, indicating that one or more type parameters are referenced // in the parameter types of the contextual signature. Now also infer from the return type. applyToReturnTypes(instantiatedSignature, contextualSignature, (source, target) => { @@ -35178,7 +35376,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // to the set of inferred type parameters for the outer function return type. if (!hasOverlappingInferences(context.inferences, inferences)) { mergeInferences(context.inferences, inferences); - context.inferredTypeParameters = ts.concatenate(context.inferredTypeParameters, uniqueTypeParameters); + context.inferredTypeParameters = concatenate(context.inferredTypeParameters, uniqueTypeParameters); return getOrCreateTypeFromSignature(instantiatedSignature); } } @@ -35191,24 +35389,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return type; } - function skippedGenericFunction(node: ts.Node, checkMode: CheckMode) { + function skippedGenericFunction(node: Node, checkMode: CheckMode) { if (checkMode & CheckMode.Inferential) { // We have skipped a generic function during inferential typing. Obtain the inference context and // indicate this has occurred such that we know a second pass of inference is be needed. const context = getInferenceContext(node)!; - context.flags |= ts.InferenceFlags.SkippedGenericFunction; + context.flags |= InferenceFlags.SkippedGenericFunction; } } - function hasInferenceCandidates(info: ts.InferenceInfo) { + function hasInferenceCandidates(info: InferenceInfo) { return !!(info.candidates || info.contraCandidates); } - function hasInferenceCandidatesOrDefault(info: ts.InferenceInfo) { + function hasInferenceCandidatesOrDefault(info: InferenceInfo) { return !!(info.candidates || info.contraCandidates || hasTypeParameterDefault(info.typeParameter)); } - function hasOverlappingInferences(a: ts.InferenceInfo[], b: ts.InferenceInfo[]) { + function hasOverlappingInferences(a: InferenceInfo[], b: InferenceInfo[]) { for (let i = 0; i < a.length; i++) { if (hasInferenceCandidates(a[i]) && hasInferenceCandidates(b[i])) { return true; @@ -35217,7 +35415,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function mergeInferences(target: ts.InferenceInfo[], source: ts.InferenceInfo[]) { + function mergeInferences(target: InferenceInfo[], source: InferenceInfo[]) { for (let i = 0; i < target.length; i++) { if (!hasInferenceCandidates(target[i]) && hasInferenceCandidates(source[i])) { target[i] = source[i]; @@ -35225,19 +35423,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getUniqueTypeParameters(context: ts.InferenceContext, typeParameters: readonly ts.TypeParameter[]): readonly ts.TypeParameter[] { - const result: ts.TypeParameter[] = []; - let oldTypeParameters: ts.TypeParameter[] | undefined; - let newTypeParameters: ts.TypeParameter[] | undefined; + function getUniqueTypeParameters(context: InferenceContext, typeParameters: readonly TypeParameter[]): readonly TypeParameter[] { + const result: TypeParameter[] = []; + let oldTypeParameters: TypeParameter[] | undefined; + let newTypeParameters: TypeParameter[] | undefined; for (const tp of typeParameters) { const name = tp.symbol.escapedName; if (hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name)) { - const newName = getUniqueTypeParameterName(ts.concatenate(context.inferredTypeParameters, result), name); - const symbol = createSymbol(ts.SymbolFlags.TypeParameter, newName); + const newName = getUniqueTypeParameterName(concatenate(context.inferredTypeParameters, result), name); + const symbol = createSymbol(SymbolFlags.TypeParameter, newName); const newTypeParameter = createTypeParameter(symbol); newTypeParameter.target = tp; - oldTypeParameters = ts.append(oldTypeParameters, tp); - newTypeParameters = ts.append(newTypeParameters, newTypeParameter); + oldTypeParameters = append(oldTypeParameters, tp); + newTypeParameters = append(newTypeParameters, newTypeParameter); result.push(newTypeParameter); } else { @@ -35253,30 +35451,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function hasTypeParameterByName(typeParameters: readonly ts.TypeParameter[] | undefined, name: ts.__String) { - return ts.some(typeParameters, tp => tp.symbol.escapedName === name); + function hasTypeParameterByName(typeParameters: readonly TypeParameter[] | undefined, name: __String) { + return some(typeParameters, tp => tp.symbol.escapedName === name); } - function getUniqueTypeParameterName(typeParameters: readonly ts.TypeParameter[], baseName: ts.__String) { + function getUniqueTypeParameterName(typeParameters: readonly TypeParameter[], baseName: __String) { let len = (baseName as string).length; - while (len > 1 && (baseName as string).charCodeAt(len - 1) >= ts.CharacterCodes._0 && (baseName as string).charCodeAt(len - 1) <= ts.CharacterCodes._9) len--; + while (len > 1 && (baseName as string).charCodeAt(len - 1) >= CharacterCodes._0 && (baseName as string).charCodeAt(len - 1) <= CharacterCodes._9) len--; const s = (baseName as string).slice(0, len); for (let index = 1; true; index++) { - const augmentedName = (s + index as ts.__String); + const augmentedName = (s + index as __String); if (!hasTypeParameterByName(typeParameters, augmentedName)) { return augmentedName; } } } - function getReturnTypeOfSingleNonGenericCallSignature(funcType: ts.Type) { + function getReturnTypeOfSingleNonGenericCallSignature(funcType: Type) { const signature = getSingleCallSignature(funcType); if (signature && !signature.typeParameters) { return getReturnTypeOfSignature(signature); } } - function getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr: ts.CallChain) { + function getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr: CallChain) { const funcType = checkExpression(expr.expression); const nonOptionalType = getOptionalExpressionType(funcType, expr.expression); const returnType = getReturnTypeOfSingleNonGenericCallSignature(funcType); @@ -35287,14 +35485,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Returns the type of an expression. Unlike checkExpression, this function is simply concerned * with computing the type and may not fully check all contained sub-expressions for errors. */ - function getTypeOfExpression(node: ts.Expression) { + function getTypeOfExpression(node: Expression) { // Don't bother caching types that require no flow analysis and are quick to compute. const quickType = getQuickTypeOfExpression(node); if (quickType) { return quickType; } // If a type has been cached for the node, return it. - if (node.flags & ts.NodeFlags.TypeCached && flowTypeCache) { + if (node.flags & NodeFlags.TypeCached && flowTypeCache) { const cachedType = flowTypeCache[getNodeId(node)]; if (cachedType) { return cachedType; @@ -35306,34 +35504,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (flowInvocationCount !== startInvocationCount) { const cache = flowTypeCache || (flowTypeCache = []); cache[getNodeId(node)] = type; - ts.setNodeFlags(node, node.flags | ts.NodeFlags.TypeCached); + setNodeFlags(node, node.flags | NodeFlags.TypeCached); } return type; } - function getQuickTypeOfExpression(node: ts.Expression) { - let expr = ts.skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); - if (ts.isJSDocTypeAssertion(expr)) { - const type = ts.getJSDocTypeAssertionType(expr); - if (!ts.isConstTypeReference(type)) { + function getQuickTypeOfExpression(node: Expression) { + let expr = skipParentheses(node, /*excludeJSDocTypeAssertions*/ true); + if (isJSDocTypeAssertion(expr)) { + const type = getJSDocTypeAssertionType(expr); + if (!isConstTypeReference(type)) { return getTypeFromTypeNode(type); } } - expr = ts.skipParentheses(node); + expr = skipParentheses(node); // Optimize for the common case of a call to a function with a single non-generic call // signature where we can just fetch the return type without checking the arguments. - if (ts.isCallExpression(expr) && expr.expression.kind !== ts.SyntaxKind.SuperKeyword && !ts.isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) { - const type = ts.isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) : + if (isCallExpression(expr) && expr.expression.kind !== SyntaxKind.SuperKeyword && !isRequireCall(expr, /*checkArgumentIsStringLiteralLike*/ true) && !isSymbolOrSymbolForCall(expr)) { + const type = isCallChain(expr) ? getReturnTypeOfSingleNonGenericSignatureOfCallChain(expr) : getReturnTypeOfSingleNonGenericCallSignature(checkNonNullExpression(expr.expression)); if (type) { return type; } } - else if (ts.isAssertionExpression(expr) && !ts.isConstTypeReference(expr.type)) { - return getTypeFromTypeNode((expr as ts.TypeAssertion).type); + else if (isAssertionExpression(expr) && !isConstTypeReference(expr.type)) { + return getTypeFromTypeNode((expr as TypeAssertion).type); } - else if (node.kind === ts.SyntaxKind.NumericLiteral || node.kind === ts.SyntaxKind.StringLiteral || - node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword) { + else if (node.kind === SyntaxKind.NumericLiteral || node.kind === SyntaxKind.StringLiteral || + node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword) { return checkExpression(node); } return undefined; @@ -35346,7 +35544,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * and requesting the contextual type might cause a circularity or other bad behaviour. * It sets the contextual type of the node to any before calling getTypeOfExpression. */ - function getContextFreeTypeOfExpression(node: ts.Expression) { + function getContextFreeTypeOfExpression(node: Expression) { const links = getNodeLinks(node); if (links.contextFreeType) { return links.contextFreeType; @@ -35365,8 +35563,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkExpression(node: ts.Expression | ts.QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): ts.Type { - ts.tracing?.push(ts.tracing.Phase.Check, "checkExpression", { kind: node.kind, pos: node.pos, end: node.end, path: (node as ts.TracingNode).tracingPath }); + function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type { + tracing?.push(tracing.Phase.Check, "checkExpression", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); const saveCurrentNode = currentNode; currentNode = node; instantiationCount = 0; @@ -35376,170 +35574,170 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkConstEnumAccess(node, type); } currentNode = saveCurrentNode; - ts.tracing?.pop(); + tracing?.pop(); return type; } - function checkConstEnumAccess(node: ts.Expression | ts.QualifiedName, type: ts.Type) { + function checkConstEnumAccess(node: Expression | QualifiedName, type: Type) { // enum object type for const enums are only permitted in: // - 'left' in property access // - 'object' in indexed access // - target in rhs of import statement const ok = - (node.parent.kind === ts.SyntaxKind.PropertyAccessExpression && (node.parent as ts.PropertyAccessExpression).expression === node) || - (node.parent.kind === ts.SyntaxKind.ElementAccessExpression && (node.parent as ts.ElementAccessExpression).expression === node) || - ((node.kind === ts.SyntaxKind.Identifier || node.kind === ts.SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node as ts.Identifier) || - (node.parent.kind === ts.SyntaxKind.TypeQuery && (node.parent as ts.TypeQueryNode).exprName === node)) || - (node.parent.kind === ts.SyntaxKind.ExportSpecifier); // We allow reexporting const enums + (node.parent.kind === SyntaxKind.PropertyAccessExpression && (node.parent as PropertyAccessExpression).expression === node) || + (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent as ElementAccessExpression).expression === node) || + ((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(node as Identifier) || + (node.parent.kind === SyntaxKind.TypeQuery && (node.parent as TypeQueryNode).exprName === node)) || + (node.parent.kind === SyntaxKind.ExportSpecifier); // We allow reexporting const enums if (!ok) { - error(node, ts.Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); + error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment_or_type_query); } if (compilerOptions.isolatedModules) { - ts.Debug.assert(!!(type.symbol.flags & ts.SymbolFlags.ConstEnum)); - const constEnumDeclaration = type.symbol.valueDeclaration as ts.EnumDeclaration; - if (constEnumDeclaration.flags & ts.NodeFlags.Ambient) { - error(node, ts.Diagnostics.Cannot_access_ambient_const_enums_when_the_isolatedModules_flag_is_provided); + Debug.assert(!!(type.symbol.flags & SymbolFlags.ConstEnum)); + const constEnumDeclaration = type.symbol.valueDeclaration as EnumDeclaration; + if (constEnumDeclaration.flags & NodeFlags.Ambient) { + error(node, Diagnostics.Cannot_access_ambient_const_enums_when_the_isolatedModules_flag_is_provided); } } } - function checkParenthesizedExpression(node: ts.ParenthesizedExpression, checkMode?: CheckMode): ts.Type { - if (ts.hasJSDocNodes(node) && ts.isJSDocTypeAssertion(node)) { - const type = ts.getJSDocTypeAssertionType(node); + function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type { + if (hasJSDocNodes(node) && isJSDocTypeAssertion(node)) { + const type = getJSDocTypeAssertionType(node); return checkAssertionWorker(type, type, node.expression, checkMode); } return checkExpression(node.expression, checkMode); } - function checkExpressionWorker(node: ts.Expression | ts.QualifiedName, checkMode: CheckMode | undefined, forceTuple?: boolean): ts.Type { + function checkExpressionWorker(node: Expression | QualifiedName, checkMode: CheckMode | undefined, forceTuple?: boolean): Type { const kind = node.kind; if (cancellationToken) { // Only bother checking on a few construct kinds. We don't want to be excessively // hitting the cancellation token on every node we check. switch (kind) { - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: cancellationToken.throwIfCancellationRequested(); } } switch (kind) { - case ts.SyntaxKind.Identifier: - return checkIdentifier(node as ts.Identifier, checkMode); - case ts.SyntaxKind.PrivateIdentifier: - return checkPrivateIdentifierExpression(node as ts.PrivateIdentifier); - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.Identifier: + return checkIdentifier(node as Identifier, checkMode); + case SyntaxKind.PrivateIdentifier: + return checkPrivateIdentifierExpression(node as PrivateIdentifier); + case SyntaxKind.ThisKeyword: return checkThisExpression(node); - case ts.SyntaxKind.SuperKeyword: + case SyntaxKind.SuperKeyword: return checkSuperExpression(node); - case ts.SyntaxKind.NullKeyword: + case SyntaxKind.NullKeyword: return nullWideningType; - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.StringLiteral: - return getFreshTypeOfLiteralType(getStringLiteralType((node as ts.StringLiteralLike).text)); - case ts.SyntaxKind.NumericLiteral: - checkGrammarNumericLiteral(node as ts.NumericLiteral); - return getFreshTypeOfLiteralType(getNumberLiteralType(+(node as ts.NumericLiteral).text)); - case ts.SyntaxKind.BigIntLiteral: - checkGrammarBigIntLiteral(node as ts.BigIntLiteral); + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: + return getFreshTypeOfLiteralType(getStringLiteralType((node as StringLiteralLike).text)); + case SyntaxKind.NumericLiteral: + checkGrammarNumericLiteral(node as NumericLiteral); + return getFreshTypeOfLiteralType(getNumberLiteralType(+(node as NumericLiteral).text)); + case SyntaxKind.BigIntLiteral: + checkGrammarBigIntLiteral(node as BigIntLiteral); return getFreshTypeOfLiteralType(getBigIntLiteralType({ negative: false, - base10Value: ts.parsePseudoBigInt((node as ts.BigIntLiteral).text) + base10Value: parsePseudoBigInt((node as BigIntLiteral).text) })); - case ts.SyntaxKind.TrueKeyword: + case SyntaxKind.TrueKeyword: return trueType; - case ts.SyntaxKind.FalseKeyword: + case SyntaxKind.FalseKeyword: return falseType; - case ts.SyntaxKind.TemplateExpression: - return checkTemplateExpression(node as ts.TemplateExpression); - case ts.SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.TemplateExpression: + return checkTemplateExpression(node as TemplateExpression); + case SyntaxKind.RegularExpressionLiteral: return globalRegExpType; - case ts.SyntaxKind.ArrayLiteralExpression: - return checkArrayLiteral(node as ts.ArrayLiteralExpression, checkMode, forceTuple); - case ts.SyntaxKind.ObjectLiteralExpression: - return checkObjectLiteral(node as ts.ObjectLiteralExpression, checkMode); - case ts.SyntaxKind.PropertyAccessExpression: - return checkPropertyAccessExpression(node as ts.PropertyAccessExpression, checkMode); - case ts.SyntaxKind.QualifiedName: - return checkQualifiedName(node as ts.QualifiedName, checkMode); - case ts.SyntaxKind.ElementAccessExpression: - return checkIndexedAccess(node as ts.ElementAccessExpression, checkMode); - case ts.SyntaxKind.CallExpression: - if ((node as ts.CallExpression).expression.kind === ts.SyntaxKind.ImportKeyword) { - return checkImportCallExpression(node as ts.ImportCall); + case SyntaxKind.ArrayLiteralExpression: + return checkArrayLiteral(node as ArrayLiteralExpression, checkMode, forceTuple); + case SyntaxKind.ObjectLiteralExpression: + return checkObjectLiteral(node as ObjectLiteralExpression, checkMode); + case SyntaxKind.PropertyAccessExpression: + return checkPropertyAccessExpression(node as PropertyAccessExpression, checkMode); + case SyntaxKind.QualifiedName: + return checkQualifiedName(node as QualifiedName, checkMode); + case SyntaxKind.ElementAccessExpression: + return checkIndexedAccess(node as ElementAccessExpression, checkMode); + case SyntaxKind.CallExpression: + if ((node as CallExpression).expression.kind === SyntaxKind.ImportKeyword) { + return checkImportCallExpression(node as ImportCall); } // falls through - case ts.SyntaxKind.NewExpression: - return checkCallExpression(node as ts.CallExpression, checkMode); - case ts.SyntaxKind.TaggedTemplateExpression: - return checkTaggedTemplateExpression(node as ts.TaggedTemplateExpression); - case ts.SyntaxKind.ParenthesizedExpression: - return checkParenthesizedExpression(node as ts.ParenthesizedExpression, checkMode); - case ts.SyntaxKind.ClassExpression: - return checkClassExpression(node as ts.ClassExpression); - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - return checkFunctionExpressionOrObjectLiteralMethod(node as ts.FunctionExpression | ts.ArrowFunction, checkMode); - case ts.SyntaxKind.TypeOfExpression: - return checkTypeOfExpression(node as ts.TypeOfExpression); - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.AsExpression: - return checkAssertion(node as ts.AssertionExpression); - case ts.SyntaxKind.NonNullExpression: - return checkNonNullAssertion(node as ts.NonNullExpression); - case ts.SyntaxKind.ExpressionWithTypeArguments: - return checkExpressionWithTypeArguments(node as ts.ExpressionWithTypeArguments); - case ts.SyntaxKind.SatisfiesExpression: - return checkSatisfiesExpression(node as ts.SatisfiesExpression); - case ts.SyntaxKind.MetaProperty: - return checkMetaProperty(node as ts.MetaProperty); - case ts.SyntaxKind.DeleteExpression: - return checkDeleteExpression(node as ts.DeleteExpression); - case ts.SyntaxKind.VoidExpression: - return checkVoidExpression(node as ts.VoidExpression); - case ts.SyntaxKind.AwaitExpression: - return checkAwaitExpression(node as ts.AwaitExpression); - case ts.SyntaxKind.PrefixUnaryExpression: - return checkPrefixUnaryExpression(node as ts.PrefixUnaryExpression); - case ts.SyntaxKind.PostfixUnaryExpression: - return checkPostfixUnaryExpression(node as ts.PostfixUnaryExpression); - case ts.SyntaxKind.BinaryExpression: - return checkBinaryExpression(node as ts.BinaryExpression, checkMode); - case ts.SyntaxKind.ConditionalExpression: - return checkConditionalExpression(node as ts.ConditionalExpression, checkMode); - case ts.SyntaxKind.SpreadElement: - return checkSpreadExpression(node as ts.SpreadElement, checkMode); - case ts.SyntaxKind.OmittedExpression: + case SyntaxKind.NewExpression: + return checkCallExpression(node as CallExpression, checkMode); + case SyntaxKind.TaggedTemplateExpression: + return checkTaggedTemplateExpression(node as TaggedTemplateExpression); + case SyntaxKind.ParenthesizedExpression: + return checkParenthesizedExpression(node as ParenthesizedExpression, checkMode); + case SyntaxKind.ClassExpression: + return checkClassExpression(node as ClassExpression); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return checkFunctionExpressionOrObjectLiteralMethod(node as FunctionExpression | ArrowFunction, checkMode); + case SyntaxKind.TypeOfExpression: + return checkTypeOfExpression(node as TypeOfExpression); + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + return checkAssertion(node as AssertionExpression); + case SyntaxKind.NonNullExpression: + return checkNonNullAssertion(node as NonNullExpression); + case SyntaxKind.ExpressionWithTypeArguments: + return checkExpressionWithTypeArguments(node as ExpressionWithTypeArguments); + case SyntaxKind.SatisfiesExpression: + return checkSatisfiesExpression(node as SatisfiesExpression); + case SyntaxKind.MetaProperty: + return checkMetaProperty(node as MetaProperty); + case SyntaxKind.DeleteExpression: + return checkDeleteExpression(node as DeleteExpression); + case SyntaxKind.VoidExpression: + return checkVoidExpression(node as VoidExpression); + case SyntaxKind.AwaitExpression: + return checkAwaitExpression(node as AwaitExpression); + case SyntaxKind.PrefixUnaryExpression: + return checkPrefixUnaryExpression(node as PrefixUnaryExpression); + case SyntaxKind.PostfixUnaryExpression: + return checkPostfixUnaryExpression(node as PostfixUnaryExpression); + case SyntaxKind.BinaryExpression: + return checkBinaryExpression(node as BinaryExpression, checkMode); + case SyntaxKind.ConditionalExpression: + return checkConditionalExpression(node as ConditionalExpression, checkMode); + case SyntaxKind.SpreadElement: + return checkSpreadExpression(node as SpreadElement, checkMode); + case SyntaxKind.OmittedExpression: return undefinedWideningType; - case ts.SyntaxKind.YieldExpression: - return checkYieldExpression(node as ts.YieldExpression); - case ts.SyntaxKind.SyntheticExpression: - return checkSyntheticExpression(node as ts.SyntheticExpression); - case ts.SyntaxKind.JsxExpression: - return checkJsxExpression(node as ts.JsxExpression, checkMode); - case ts.SyntaxKind.JsxElement: - return checkJsxElement(node as ts.JsxElement, checkMode); - case ts.SyntaxKind.JsxSelfClosingElement: - return checkJsxSelfClosingElement(node as ts.JsxSelfClosingElement, checkMode); - case ts.SyntaxKind.JsxFragment: - return checkJsxFragment(node as ts.JsxFragment); - case ts.SyntaxKind.JsxAttributes: - return checkJsxAttributes(node as ts.JsxAttributes, checkMode); - case ts.SyntaxKind.JsxOpeningElement: - ts.Debug.fail("Shouldn't ever directly check a JsxOpeningElement"); + case SyntaxKind.YieldExpression: + return checkYieldExpression(node as YieldExpression); + case SyntaxKind.SyntheticExpression: + return checkSyntheticExpression(node as SyntheticExpression); + case SyntaxKind.JsxExpression: + return checkJsxExpression(node as JsxExpression, checkMode); + case SyntaxKind.JsxElement: + return checkJsxElement(node as JsxElement, checkMode); + case SyntaxKind.JsxSelfClosingElement: + return checkJsxSelfClosingElement(node as JsxSelfClosingElement, checkMode); + case SyntaxKind.JsxFragment: + return checkJsxFragment(node as JsxFragment); + case SyntaxKind.JsxAttributes: + return checkJsxAttributes(node as JsxAttributes, checkMode); + case SyntaxKind.JsxOpeningElement: + Debug.fail("Shouldn't ever directly check a JsxOpeningElement"); } return errorType; } // DECLARATION AND STATEMENT TYPE CHECKING - function checkTypeParameter(node: ts.TypeParameterDeclaration) { + function checkTypeParameter(node: TypeParameterDeclaration) { // Grammar Checking checkGrammarModifiers(node); if (node.expression) { - grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected); + grammarErrorOnFirstToken(node.expression, Diagnostics.Type_expected); } checkSourceElement(node.constraint); @@ -35548,41 +35746,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Resolve base constraint to reveal circularity errors getBaseConstraintOfType(typeParameter); if (!hasNonCircularTypeParameterDefault(typeParameter)) { - error(node.default, ts.Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter)); + error(node.default, Diagnostics.Type_parameter_0_has_a_circular_default, typeToString(typeParameter)); } const constraintType = getConstraintOfTypeParameter(typeParameter); const defaultType = getDefaultFromTypeParameter(typeParameter); if (constraintType && defaultType) { - checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + checkTypeAssignableTo(defaultType, getTypeWithThisArgument(instantiateType(constraintType, makeUnaryTypeMapper(typeParameter, defaultType)), defaultType), node.default, Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } checkNodeDeferred(node); - addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_parameter_name_cannot_be_0)); + addLazyDiagnostic(() => checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0)); } - function checkTypeParameterDeferred(node: ts.TypeParameterDeclaration) { - if (ts.isInterfaceDeclaration(node.parent) || ts.isClassLike(node.parent) || ts.isTypeAliasDeclaration(node.parent)) { + function checkTypeParameterDeferred(node: TypeParameterDeclaration) { + if (isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent)) { const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); const modifiers = getVarianceModifiers(typeParameter); if (modifiers) { const symbol = getSymbolOfNode(node.parent); - if (ts.isTypeAliasDeclaration(node.parent) && !(ts.getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ts.ObjectFlags.Anonymous | ts.ObjectFlags.Mapped))) { - error(node, ts.Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); + if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { + error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); } - else if (modifiers === ts.ModifierFlags.In || modifiers === ts.ModifierFlags.Out) { - ts.tracing?.push(ts.tracing.Phase.CheckTypes, "checkTypeParameterDeferred", { parent: getTypeId(getDeclaredTypeOfSymbol(symbol)), id: getTypeId(typeParameter) }); - const source = createMarkerType(symbol, typeParameter, modifiers === ts.ModifierFlags.Out ? markerSubTypeForCheck : markerSuperTypeForCheck); - const target = createMarkerType(symbol, typeParameter, modifiers === ts.ModifierFlags.Out ? markerSuperTypeForCheck : markerSubTypeForCheck); + else if (modifiers === ModifierFlags.In || modifiers === ModifierFlags.Out) { + tracing?.push(tracing.Phase.CheckTypes, "checkTypeParameterDeferred", { parent: getTypeId(getDeclaredTypeOfSymbol(symbol)), id: getTypeId(typeParameter) }); + const source = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSubTypeForCheck : markerSuperTypeForCheck); + const target = createMarkerType(symbol, typeParameter, modifiers === ModifierFlags.Out ? markerSuperTypeForCheck : markerSubTypeForCheck); const saveVarianceTypeParameter = typeParameter; varianceTypeParameter = typeParameter; - checkTypeAssignableTo(source, target, node, ts.Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation); + checkTypeAssignableTo(source, target, node, Diagnostics.Type_0_is_not_assignable_to_type_1_as_implied_by_variance_annotation); varianceTypeParameter = saveVarianceTypeParameter; - ts.tracing?.pop(); + tracing?.pop(); } } } } - function checkParameter(node: ts.ParameterDeclaration) { + function checkParameter(node: ParameterDeclaration) { // Grammar checking // It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the // Identifier in a PropertySetParameterList of a PropertyAssignment that is contained in strict code @@ -35590,45 +35788,45 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkGrammarDecoratorsAndModifiers(node); checkVariableLikeDeclaration(node); - const func = ts.getContainingFunction(node)!; - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.ParameterPropertyModifier)) { - if (!(func.kind === ts.SyntaxKind.Constructor && ts.nodeIsPresent(func.body))) { - error(node, ts.Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); + const func = getContainingFunction(node)!; + if (hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) { + if (!(func.kind === SyntaxKind.Constructor && nodeIsPresent(func.body))) { + error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } - if (func.kind === ts.SyntaxKind.Constructor && ts.isIdentifier(node.name) && node.name.escapedText === "constructor") { - error(node.name, ts.Diagnostics.constructor_cannot_be_used_as_a_parameter_property_name); + if (func.kind === SyntaxKind.Constructor && isIdentifier(node.name) && node.name.escapedText === "constructor") { + error(node.name, Diagnostics.constructor_cannot_be_used_as_a_parameter_property_name); } } - if ((node.questionToken || isJSDocOptionalParameter(node)) && ts.isBindingPattern(node.name) && (func as ts.FunctionLikeDeclaration).body) { - error(node, ts.Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); + if ((node.questionToken || isJSDocOptionalParameter(node)) && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) { + error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } - if (node.name && ts.isIdentifier(node.name) && (node.name.escapedText === "this" || node.name.escapedText === "new")) { + if (node.name && isIdentifier(node.name) && (node.name.escapedText === "this" || node.name.escapedText === "new")) { if (func.parameters.indexOf(node) !== 0) { - error(node, ts.Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText as string); + error(node, Diagnostics.A_0_parameter_must_be_the_first_parameter, node.name.escapedText as string); } - if (func.kind === ts.SyntaxKind.Constructor || func.kind === ts.SyntaxKind.ConstructSignature || func.kind === ts.SyntaxKind.ConstructorType) { - error(node, ts.Diagnostics.A_constructor_cannot_have_a_this_parameter); + if (func.kind === SyntaxKind.Constructor || func.kind === SyntaxKind.ConstructSignature || func.kind === SyntaxKind.ConstructorType) { + error(node, Diagnostics.A_constructor_cannot_have_a_this_parameter); } - if (func.kind === ts.SyntaxKind.ArrowFunction) { - error(node, ts.Diagnostics.An_arrow_function_cannot_have_a_this_parameter); + if (func.kind === SyntaxKind.ArrowFunction) { + error(node, Diagnostics.An_arrow_function_cannot_have_a_this_parameter); } - if (func.kind === ts.SyntaxKind.GetAccessor || func.kind === ts.SyntaxKind.SetAccessor) { - error(node, ts.Diagnostics.get_and_set_accessors_cannot_declare_this_parameters); + if (func.kind === SyntaxKind.GetAccessor || func.kind === SyntaxKind.SetAccessor) { + error(node, Diagnostics.get_and_set_accessors_cannot_declare_this_parameters); } } // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. - if (node.dotDotDotToken && !ts.isBindingPattern(node.name) && !isTypeAssignableTo(getReducedType(getTypeOfSymbol(node.symbol)), anyReadonlyArrayType)) { - error(node, ts.Diagnostics.A_rest_parameter_must_be_of_an_array_type); + if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getReducedType(getTypeOfSymbol(node.symbol)), anyReadonlyArrayType)) { + error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type); } } - function checkTypePredicate(node: ts.TypePredicateNode): void { + function checkTypePredicate(node: TypePredicateNode): void { const parent = getTypePredicateParent(node); if (!parent) { // The parent must not be valid. - error(node, ts.Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); + error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); return; } @@ -35641,17 +35839,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkSourceElement(node.type); const { parameterName } = node; - if (typePredicate.kind === ts.TypePredicateKind.This || typePredicate.kind === ts.TypePredicateKind.AssertsThis) { - getTypeFromThisTypeNode(parameterName as ts.ThisTypeNode); + if (typePredicate.kind === TypePredicateKind.This || typePredicate.kind === TypePredicateKind.AssertsThis) { + getTypeFromThisTypeNode(parameterName as ThisTypeNode); } else { if (typePredicate.parameterIndex >= 0) { if (signatureHasRestParameter(signature) && typePredicate.parameterIndex === signature.parameters.length - 1) { - error(parameterName, ts.Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); + error(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter); } else { if (typePredicate.type) { - const leadingError = () => ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); + const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type); checkTypeAssignableTo(typePredicate.type, getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]), node.type, @@ -35663,29 +35861,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else if (parameterName) { let hasReportedError = false; for (const { name } of parent.parameters) { - if (ts.isBindingPattern(name) && + if (isBindingPattern(name) && checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, parameterName, typePredicate.parameterName)) { hasReportedError = true; break; } } if (!hasReportedError) { - error(node.parameterName, ts.Diagnostics.Cannot_find_parameter_0, typePredicate.parameterName); + error(node.parameterName, Diagnostics.Cannot_find_parameter_0, typePredicate.parameterName); } } } } - function getTypePredicateParent(node: ts.Node): ts.SignatureDeclaration | undefined { + function getTypePredicateParent(node: Node): SignatureDeclaration | undefined { switch (node.parent.kind) { - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - const parent = node.parent as ts.SignatureDeclaration; + case SyntaxKind.ArrowFunction: + case SyntaxKind.CallSignature: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionType: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + const parent = node.parent as SignatureDeclaration; if (node === parent.type) { return parent; } @@ -35693,22 +35891,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } function checkIfTypePredicateVariableIsDeclaredInBindingPattern( - pattern: ts.BindingPattern, - predicateVariableNode: ts.Node, + pattern: BindingPattern, + predicateVariableNode: Node, predicateVariableName: string) { for (const element of pattern.elements) { - if (ts.isOmittedExpression(element)) { + if (isOmittedExpression(element)) { continue; } const name = element.name; - if (name.kind === ts.SyntaxKind.Identifier && name.escapedText === predicateVariableName) { + if (name.kind === SyntaxKind.Identifier && name.escapedText === predicateVariableName) { error(predicateVariableNode, - ts.Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, + Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName); return true; } - else if (name.kind === ts.SyntaxKind.ArrayBindingPattern || name.kind === ts.SyntaxKind.ObjectBindingPattern) { + else if (name.kind === SyntaxKind.ArrayBindingPattern || name.kind === SyntaxKind.ObjectBindingPattern) { if (checkIfTypePredicateVariableIsDeclaredInBindingPattern( name, predicateVariableNode, @@ -35719,41 +35917,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkSignatureDeclaration(node: ts.SignatureDeclaration) { + function checkSignatureDeclaration(node: SignatureDeclaration) { // Grammar checking - if (node.kind === ts.SyntaxKind.IndexSignature) { + if (node.kind === SyntaxKind.IndexSignature) { checkGrammarIndexSignature(node); } // TODO (yuisu): Remove this check in else-if when SyntaxKind.Construct is moved and ambient context is handled - else if (node.kind === ts.SyntaxKind.FunctionType || node.kind === ts.SyntaxKind.FunctionDeclaration || node.kind === ts.SyntaxKind.ConstructorType || - node.kind === ts.SyntaxKind.CallSignature || node.kind === ts.SyntaxKind.Constructor || - node.kind === ts.SyntaxKind.ConstructSignature) { - checkGrammarFunctionLikeDeclaration(node as ts.FunctionLikeDeclaration); + else if (node.kind === SyntaxKind.FunctionType || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.ConstructorType || + node.kind === SyntaxKind.CallSignature || node.kind === SyntaxKind.Constructor || + node.kind === SyntaxKind.ConstructSignature) { + checkGrammarFunctionLikeDeclaration(node as FunctionLikeDeclaration); } - const functionFlags = ts.getFunctionFlags(node as ts.FunctionLikeDeclaration); - if (!(functionFlags & ts.FunctionFlags.Invalid)) { + const functionFlags = getFunctionFlags(node as FunctionLikeDeclaration); + if (!(functionFlags & FunctionFlags.Invalid)) { // Async generators prior to ESNext require the __await and __asyncGenerator helpers - if ((functionFlags & ts.FunctionFlags.AsyncGenerator) === ts.FunctionFlags.AsyncGenerator && languageVersion < ts.ScriptTarget.ESNext) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.AsyncGeneratorIncludes); + if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.AsyncGenerator && languageVersion < ScriptTarget.ESNext) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.AsyncGeneratorIncludes); } // Async functions prior to ES2017 require the __awaiter helper - if ((functionFlags & ts.FunctionFlags.AsyncGenerator) === ts.FunctionFlags.Async && languageVersion < ts.ScriptTarget.ES2017) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Awaiter); + if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async && languageVersion < ScriptTarget.ES2017) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Awaiter); } // Generator functions, Async functions, and Async Generator functions prior to // ES2015 require the __generator helper - if ((functionFlags & ts.FunctionFlags.AsyncGenerator) !== ts.FunctionFlags.Normal && languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Generator); + if ((functionFlags & FunctionFlags.AsyncGenerator) !== FunctionFlags.Normal && languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Generator); } } - checkTypeParameters(ts.getEffectiveTypeParameterDeclarations(node)); + checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); checkUnmatchedJSDocParameters(node); - ts.forEach(node.parameters, checkParameter); + forEach(node.parameters, checkParameter); // TODO(rbuckton): Should we start checking JSDoc types? if (node.type) { @@ -35764,24 +35962,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function checkSignatureDeclarationDiagnostics() { checkCollisionWithArgumentsInGeneratedCode(node); - const returnTypeNode = ts.getEffectiveReturnTypeNode(node); + const returnTypeNode = getEffectiveReturnTypeNode(node); if (noImplicitAny && !returnTypeNode) { switch (node.kind) { - case ts.SyntaxKind.ConstructSignature: - error(node, ts.Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); + case SyntaxKind.ConstructSignature: + error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; - case ts.SyntaxKind.CallSignature: - error(node, ts.Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); + case SyntaxKind.CallSignature: + error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); break; } } if (returnTypeNode) { - const functionFlags = ts.getFunctionFlags(node as ts.FunctionDeclaration); - if ((functionFlags & (ts.FunctionFlags.Invalid | ts.FunctionFlags.Generator)) === ts.FunctionFlags.Generator) { + const functionFlags = getFunctionFlags(node as FunctionDeclaration); + if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Generator)) === FunctionFlags.Generator) { const returnType = getTypeFromTypeNode(returnTypeNode); if (returnType === voidType) { - error(returnTypeNode, ts.Diagnostics.A_generator_cannot_have_a_void_type_annotation); + error(returnTypeNode, Diagnostics.A_generator_cannot_have_a_void_type_annotation); } else { // Naively, one could check that Generator is assignable to the return type annotation. @@ -35790,65 +35988,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // interface BadGenerator extends Iterable, Iterator { } // function* g(): BadGenerator { } // Iterable and Iterator have different types! // - const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & ts.FunctionFlags.Async) !== 0) || anyType; - const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & ts.FunctionFlags.Async) !== 0) || generatorYieldType; - const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & ts.FunctionFlags.Async) !== 0) || unknownType; - const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & ts.FunctionFlags.Async)); + const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType; + const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & FunctionFlags.Async) !== 0) || generatorYieldType; + const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & FunctionFlags.Async) !== 0) || unknownType; + const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async)); checkTypeAssignableTo(generatorInstantiation, returnType, returnTypeNode); } } - else if ((functionFlags & ts.FunctionFlags.AsyncGenerator) === ts.FunctionFlags.Async) { - checkAsyncFunctionReturnType(node as ts.FunctionLikeDeclaration, returnTypeNode); + else if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { + checkAsyncFunctionReturnType(node as FunctionLikeDeclaration, returnTypeNode); } } - if (node.kind !== ts.SyntaxKind.IndexSignature && node.kind !== ts.SyntaxKind.JSDocFunctionType) { + if (node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.JSDocFunctionType) { registerForUnusedIdentifiersCheck(node); } } } - function checkClassForDuplicateDeclarations(node: ts.ClassLikeDeclaration) { - const instanceNames = new ts.Map(); - const staticNames = new ts.Map(); + function checkClassForDuplicateDeclarations(node: ClassLikeDeclaration) { + const instanceNames = new Map<__String, DeclarationMeaning>(); + const staticNames = new Map<__String, DeclarationMeaning>(); // instance and static private identifiers share the same scope - const privateIdentifiers = new ts.Map(); + const privateIdentifiers = new Map<__String, DeclarationMeaning>(); for (const member of node.members) { - if (member.kind === ts.SyntaxKind.Constructor) { - for (const param of (member as ts.ConstructorDeclaration).parameters) { - if (ts.isParameterPropertyDeclaration(param, member) && !ts.isBindingPattern(param.name)) { + if (member.kind === SyntaxKind.Constructor) { + for (const param of (member as ConstructorDeclaration).parameters) { + if (isParameterPropertyDeclaration(param, member) && !isBindingPattern(param.name)) { addName(instanceNames, param.name, param.name.escapedText, DeclarationMeaning.GetOrSetAccessor); } } } else { - const isStaticMember = ts.isStatic(member); + const isStaticMember = isStatic(member); const name = member.name; if (!name) { continue; } - const isPrivate = ts.isPrivateIdentifier(name); + const isPrivate = isPrivateIdentifier(name); const privateStaticFlags = isPrivate && isStaticMember ? DeclarationMeaning.PrivateStatic : 0; const names = isPrivate ? privateIdentifiers : isStaticMember ? staticNames : instanceNames; - const memberName = name && ts.getPropertyNameForPropertyNameNode(name); + const memberName = name && getPropertyNameForPropertyNameNode(name); if (memberName) { switch (member.kind) { - case ts.SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessor: addName(names, name, memberName, DeclarationMeaning.GetAccessor | privateStaticFlags); break; - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessor: addName(names, name, memberName, DeclarationMeaning.SetAccessor | privateStaticFlags); break; - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyDeclaration: addName(names, name, memberName, DeclarationMeaning.GetOrSetAccessor | privateStaticFlags); break; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: addName(names, name, memberName, DeclarationMeaning.Method | privateStaticFlags); break; } @@ -35856,24 +36054,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function addName(names: ts.UnderscoreEscapedMap, location: ts.Node, name: ts.__String, meaning: DeclarationMeaning) { + function addName(names: UnderscoreEscapedMap, location: Node, name: __String, meaning: DeclarationMeaning) { const prev = names.get(name); if (prev) { // For private identifiers, do not allow mixing of static and instance members with the same name if ((prev & DeclarationMeaning.PrivateStatic) !== (meaning & DeclarationMeaning.PrivateStatic)) { - error(location, ts.Diagnostics.Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, ts.getTextOfNode(location)); + error(location, Diagnostics.Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, getTextOfNode(location)); } else { const prevIsMethod = !!(prev & DeclarationMeaning.Method); const isMethod = !!(meaning & DeclarationMeaning.Method); if (prevIsMethod || isMethod) { if (prevIsMethod !== isMethod) { - error(location, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(location)); + error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location)); } // If this is a method/method duplication is might be an overload, so this will be handled when overloads are considered } else if (prev & meaning & ~DeclarationMeaning.PrivateStatic) { - error(location, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(location)); + error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location)); } else { names.set(name, prev | meaning); @@ -35897,19 +36095,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @see http://www.ecma-international.org/ecma-262/6.0/#sec-properties-of-the-function-constructor * @see http://www.ecma-international.org/ecma-262/6.0/#sec-function-instances */ - function checkClassForStaticPropertyNameConflicts(node: ts.ClassLikeDeclaration) { + function checkClassForStaticPropertyNameConflicts(node: ClassLikeDeclaration) { for (const member of node.members) { const memberNameNode = member.name; - const isStaticMember = ts.isStatic(member); + const isStaticMember = isStatic(member); if (isStaticMember && memberNameNode) { - const memberName = ts.getPropertyNameForPropertyNameNode(memberNameNode); + const memberName = getPropertyNameForPropertyNameNode(memberNameNode); switch (memberName) { case "name": case "length": case "caller": case "arguments": case "prototype": - const message = ts.Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; + const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)); error(memberNameNode, message, memberName, className); break; @@ -35918,27 +36116,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkObjectTypeForDuplicateDeclarations(node: ts.TypeLiteralNode | ts.InterfaceDeclaration) { - const names = new ts.Map(); + function checkObjectTypeForDuplicateDeclarations(node: TypeLiteralNode | InterfaceDeclaration) { + const names = new Map(); for (const member of node.members) { - if (member.kind === ts.SyntaxKind.PropertySignature) { + if (member.kind === SyntaxKind.PropertySignature) { let memberName: string; const name = member.name!; switch (name.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: memberName = name.text; break; - case ts.SyntaxKind.Identifier: - memberName = ts.idText(name); + case SyntaxKind.Identifier: + memberName = idText(name); break; default: continue; } if (names.get(memberName)) { - error(ts.getNameOfDeclaration(member.symbol.valueDeclaration), ts.Diagnostics.Duplicate_identifier_0, memberName); - error(member.name, ts.Diagnostics.Duplicate_identifier_0, memberName); + error(getNameOfDeclaration(member.symbol.valueDeclaration), Diagnostics.Duplicate_identifier_0, memberName); + error(member.name, Diagnostics.Duplicate_identifier_0, memberName); } else { names.set(memberName, true); @@ -35947,9 +36145,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkTypeForDuplicateIndexSignatures(node: ts.Node) { - if (node.kind === ts.SyntaxKind.InterfaceDeclaration) { - const nodeSymbol = getSymbolOfNode(node as ts.InterfaceDeclaration); + function checkTypeForDuplicateIndexSignatures(node: Node) { + if (node.kind === SyntaxKind.InterfaceDeclaration) { + const nodeSymbol = getSymbolOfNode(node as InterfaceDeclaration); // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration // to prevent this run check only for the first declaration of a given kind if (nodeSymbol.declarations && nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { @@ -35962,8 +36160,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration const indexSymbol = getIndexSymbol(getSymbolOfNode(node)!); if (indexSymbol?.declarations) { - const indexSignatureMap = new ts.Map(); - for (const declaration of (indexSymbol.declarations as ts.IndexSignatureDeclaration[])) { + const indexSignatureMap = new Map(); + for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) { if (declaration.parameters.length === 1 && declaration.parameters[0].type) { forEachType(getTypeFromTypeNode(declaration.parameters[0].type), type => { const entry = indexSignatureMap.get(getTypeId(type)); @@ -35979,14 +36177,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { indexSignatureMap.forEach(entry => { if (entry.declarations.length > 1) { for (const declaration of entry.declarations) { - error(declaration, ts.Diagnostics.Duplicate_index_signature_for_type_0, typeToString(entry.type)); + error(declaration, Diagnostics.Duplicate_index_signature_for_type_0, typeToString(entry.type)); } } }); } } - function checkPropertyDeclaration(node: ts.PropertyDeclaration | ts.PropertySignature) { + function checkPropertyDeclaration(node: PropertyDeclaration | PropertySignature) { // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarProperty(node)) checkGrammarComputedPropertyName(node.name); checkVariableLikeDeclaration(node); @@ -35994,68 +36192,68 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { setNodeLinksForPrivateIdentifierScope(node); // property signatures already report "initializer not allowed in ambient context" elsewhere - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.Abstract) && node.kind === ts.SyntaxKind.PropertyDeclaration && node.initializer) { - error(node, ts.Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); + if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.PropertyDeclaration && node.initializer) { + error(node, Diagnostics.Property_0_cannot_have_an_initializer_because_it_is_marked_abstract, declarationNameToString(node.name)); } } - function checkPropertySignature(node: ts.PropertySignature) { - if (ts.isPrivateIdentifier(node.name)) { - error(node, ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + function checkPropertySignature(node: PropertySignature) { + if (isPrivateIdentifier(node.name)) { + error(node, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); } return checkPropertyDeclaration(node); } - function checkMethodDeclaration(node: ts.MethodDeclaration | ts.MethodSignature) { + function checkMethodDeclaration(node: MethodDeclaration | MethodSignature) { // Grammar checking if (!checkGrammarMethod(node)) checkGrammarComputedPropertyName(node.name); - if (ts.isMethodDeclaration(node) && node.asteriskToken && ts.isIdentifier(node.name) && ts.idText(node.name) === "constructor") { - error(node.name, ts.Diagnostics.Class_constructor_may_not_be_a_generator); + if (isMethodDeclaration(node) && node.asteriskToken && isIdentifier(node.name) && idText(node.name) === "constructor") { + error(node.name, Diagnostics.Class_constructor_may_not_be_a_generator); } // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionOrMethodDeclaration(node); // method signatures already report "implementation not allowed in ambient context" elsewhere - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.Abstract) && node.kind === ts.SyntaxKind.MethodDeclaration && node.body) { - error(node, ts.Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, ts.declarationNameToString(node.name)); + if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body) { + error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name)); } // Private named methods are only allowed in class declarations - if (ts.isPrivateIdentifier(node.name) && !ts.getContainingClass(node)) { - error(node, ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + if (isPrivateIdentifier(node.name) && !getContainingClass(node)) { + error(node, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); } setNodeLinksForPrivateIdentifierScope(node); } - function setNodeLinksForPrivateIdentifierScope(node: ts.PropertyDeclaration | ts.PropertySignature | ts.MethodDeclaration | ts.MethodSignature | ts.AccessorDeclaration) { - if (ts.isPrivateIdentifier(node.name) && languageVersion < ts.ScriptTarget.ESNext) { - for (let lexicalScope = ts.getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = ts.getEnclosingBlockScopeContainer(lexicalScope)) { - getNodeLinks(lexicalScope).flags |= ts.NodeCheckFlags.ContainsClassWithPrivateIdentifiers; + function setNodeLinksForPrivateIdentifierScope(node: PropertyDeclaration | PropertySignature | MethodDeclaration | MethodSignature | AccessorDeclaration) { + if (isPrivateIdentifier(node.name) && languageVersion < ScriptTarget.ESNext) { + for (let lexicalScope = getEnclosingBlockScopeContainer(node); !!lexicalScope; lexicalScope = getEnclosingBlockScopeContainer(lexicalScope)) { + getNodeLinks(lexicalScope).flags |= NodeCheckFlags.ContainsClassWithPrivateIdentifiers; } // If this is a private element in a class expression inside the body of a loop, // then we must use a block-scoped binding to store the additional variables required // to transform private elements. - if (ts.isClassExpression(node.parent)) { + if (isClassExpression(node.parent)) { const enclosingIterationStatement = getEnclosingIterationStatement(node.parent); if (enclosingIterationStatement) { - getNodeLinks(node.name).flags |= ts.NodeCheckFlags.BlockScopedBindingInLoop; - getNodeLinks(enclosingIterationStatement).flags |= ts.NodeCheckFlags.LoopWithCapturedBlockScopedBinding; + getNodeLinks(node.name).flags |= NodeCheckFlags.BlockScopedBindingInLoop; + getNodeLinks(enclosingIterationStatement).flags |= NodeCheckFlags.LoopWithCapturedBlockScopedBinding; } } } } - function checkClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function checkClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { checkGrammarDecoratorsAndModifiers(node); - ts.forEachChild(node, checkSourceElement); + forEachChild(node, checkSourceElement); } - function checkConstructorDeclaration(node: ts.ConstructorDeclaration) { + function checkConstructorDeclaration(node: ConstructorDeclaration) { // Grammar check on signature of constructor and modifier of the constructor is done in checkSignatureDeclaration function. checkSignatureDeclaration(node); // Grammar check for checking only related to constructorDeclaration @@ -36064,7 +36262,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkSourceElement(node.body); const symbol = getSymbolOfNode(node); - const firstDeclaration = ts.getDeclarationOfKind(symbol, node.kind); + const firstDeclaration = getDeclarationOfKind(symbol, node.kind); // Only type check the symbol once if (node === firstDeclaration) { @@ -36072,7 +36270,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // exit early in the case of signature - super checks are not relevant to them - if (ts.nodeIsMissing(node.body)) { + if (nodeIsMissing(node.body)) { return; } @@ -36080,27 +36278,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; - function isInstancePropertyWithInitializerOrPrivateIdentifierProperty(n: ts.Node): boolean { - if (ts.isPrivateIdentifierClassElementDeclaration(n)) { + function isInstancePropertyWithInitializerOrPrivateIdentifierProperty(n: Node): boolean { + if (isPrivateIdentifierClassElementDeclaration(n)) { return true; } - return n.kind === ts.SyntaxKind.PropertyDeclaration && - !ts.isStatic(n) && - !!(n as ts.PropertyDeclaration).initializer; + return n.kind === SyntaxKind.PropertyDeclaration && + !isStatic(n) && + !!(n as PropertyDeclaration).initializer; } function checkConstructorDeclarationDiagnostics() { // TS 1.0 spec (April 2014): 8.3.2 // Constructors of classes with no extends clause may not contain super calls, whereas // constructors of derived classes must contain at least one super call somewhere in their function body. - const containingClassDecl = node.parent as ts.ClassDeclaration; - if (ts.getClassExtendsHeritageElement(containingClassDecl)) { + const containingClassDecl = node.parent as ClassDeclaration; + if (getClassExtendsHeritageElement(containingClassDecl)) { captureLexicalThis(node.parent, containingClassDecl); const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); const superCall = findFirstSuperCall(node.body!); if (superCall) { if (classExtendsNull) { - error(superCall, ts.Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); + error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null); } // A super call must be root-level in a constructor if both of the following are true: @@ -36109,22 +36307,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // or the containing class declares instance member variables with initializers. const superCallShouldBeRootLevel = - (ts.getEmitScriptTarget(compilerOptions) !== ts.ScriptTarget.ESNext || !useDefineForClassFields) && - (ts.some((node.parent as ts.ClassDeclaration).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || - ts.some(node.parameters, p => ts.hasSyntacticModifier(p, ts.ModifierFlags.ParameterPropertyModifier))); + (getEmitScriptTarget(compilerOptions) !== ScriptTarget.ESNext || !useDefineForClassFields) && + (some((node.parent as ClassDeclaration).members, isInstancePropertyWithInitializerOrPrivateIdentifierProperty) || + some(node.parameters, p => hasSyntacticModifier(p, ModifierFlags.ParameterPropertyModifier))); if (superCallShouldBeRootLevel) { // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional // See GH #8277 if (!superCallIsRootLevelInConstructor(superCall, node.body!)) { - error(superCall, ts.Diagnostics.A_super_call_must_be_a_root_level_statement_within_a_constructor_of_a_derived_class_that_contains_initialized_properties_parameter_properties_or_private_identifiers); + error(superCall, Diagnostics.A_super_call_must_be_a_root_level_statement_within_a_constructor_of_a_derived_class_that_contains_initialized_properties_parameter_properties_or_private_identifiers); } // Skip past any prologue directives to check statements for referring to 'super' or 'this' before a super call else { - let superCallStatement: ts.ExpressionStatement | undefined; + let superCallStatement: ExpressionStatement | undefined; for (const statement of node.body!.statements) { - if (ts.isExpressionStatement(statement) && ts.isSuperCall(ts.skipOuterExpressions(statement.expression))) { + if (isExpressionStatement(statement) && isSuperCall(skipOuterExpressions(statement.expression))) { superCallStatement = statement; break; } @@ -36136,38 +36334,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Until we have better flow analysis, it is an error to place the super call within any kind of block or conditional // See GH #8277 if (superCallStatement === undefined) { - error(node, ts.Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_parameter_properties_or_private_identifiers); + error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_parameter_properties_or_private_identifiers); } } } } else if (!classExtendsNull) { - error(node, ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call); + error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call); } } } } - function superCallIsRootLevelInConstructor(superCall: ts.Node, body: ts.Block) { - const superCallParent = ts.walkUpParenthesizedExpressions(superCall.parent); - return ts.isExpressionStatement(superCallParent) && superCallParent.parent === body; + function superCallIsRootLevelInConstructor(superCall: Node, body: Block) { + const superCallParent = walkUpParenthesizedExpressions(superCall.parent); + return isExpressionStatement(superCallParent) && superCallParent.parent === body; } - function nodeImmediatelyReferencesSuperOrThis(node: ts.Node): boolean { - if (node.kind === ts.SyntaxKind.SuperKeyword || node.kind === ts.SyntaxKind.ThisKeyword) { + function nodeImmediatelyReferencesSuperOrThis(node: Node): boolean { + if (node.kind === SyntaxKind.SuperKeyword || node.kind === SyntaxKind.ThisKeyword) { return true; } - if (ts.isThisContainerOrFunctionBlock(node)) { + if (isThisContainerOrFunctionBlock(node)) { return false; } - return !!ts.forEachChild(node, nodeImmediatelyReferencesSuperOrThis); + return !!forEachChild(node, nodeImmediatelyReferencesSuperOrThis); } - function checkAccessorDeclaration(node: ts.AccessorDeclaration) { - if (ts.isIdentifier(node.name) && ts.idText(node.name) === "constructor") { - error(node.name, ts.Diagnostics.Class_constructor_may_not_be_an_accessor); + function checkAccessorDeclaration(node: AccessorDeclaration) { + if (isIdentifier(node.name) && idText(node.name) === "constructor") { + error(node.name, Diagnostics.Class_constructor_may_not_be_an_accessor); } addLazyDiagnostic(checkAccessorDeclarationDiagnostics); checkSourceElement(node.body); @@ -36179,17 +36377,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkDecorators(node); checkSignatureDeclaration(node); - if (node.kind === ts.SyntaxKind.GetAccessor) { - if (!(node.flags & ts.NodeFlags.Ambient) && ts.nodeIsPresent(node.body) && (node.flags & ts.NodeFlags.HasImplicitReturn)) { - if (!(node.flags & ts.NodeFlags.HasExplicitReturn)) { - error(node.name, ts.Diagnostics.A_get_accessor_must_return_a_value); + if (node.kind === SyntaxKind.GetAccessor) { + if (!(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) { + if (!(node.flags & NodeFlags.HasExplicitReturn)) { + error(node.name, Diagnostics.A_get_accessor_must_return_a_value); } } } // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. - if (node.name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.name.kind === SyntaxKind.ComputedPropertyName) { checkComputedPropertyName(node.name); } @@ -36197,55 +36395,55 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. const symbol = getSymbolOfNode(node); - const getter = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.GetAccessor); - const setter = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.SetAccessor); - if (getter && setter && !(getNodeCheckFlags(getter) & ts.NodeCheckFlags.TypeChecked)) { - getNodeLinks(getter).flags |= ts.NodeCheckFlags.TypeChecked; - const getterFlags = ts.getEffectiveModifierFlags(getter); - const setterFlags = ts.getEffectiveModifierFlags(setter); - if ((getterFlags & ts.ModifierFlags.Abstract) !== (setterFlags & ts.ModifierFlags.Abstract)) { - error(getter.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); - error(setter.name, ts.Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); - } - if (((getterFlags & ts.ModifierFlags.Protected) && !(setterFlags & (ts.ModifierFlags.Protected | ts.ModifierFlags.Private))) || - ((getterFlags & ts.ModifierFlags.Private) && !(setterFlags & ts.ModifierFlags.Private))) { - error(getter.name, ts.Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); - error(setter.name, ts.Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); + const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); + const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); + if (getter && setter && !(getNodeCheckFlags(getter) & NodeCheckFlags.TypeChecked)) { + getNodeLinks(getter).flags |= NodeCheckFlags.TypeChecked; + const getterFlags = getEffectiveModifierFlags(getter); + const setterFlags = getEffectiveModifierFlags(setter); + if ((getterFlags & ModifierFlags.Abstract) !== (setterFlags & ModifierFlags.Abstract)) { + error(getter.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); + error(setter.name, Diagnostics.Accessors_must_both_be_abstract_or_non_abstract); + } + if (((getterFlags & ModifierFlags.Protected) && !(setterFlags & (ModifierFlags.Protected | ModifierFlags.Private))) || + ((getterFlags & ModifierFlags.Private) && !(setterFlags & ModifierFlags.Private))) { + error(getter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); + error(setter.name, Diagnostics.A_get_accessor_must_be_at_least_as_accessible_as_the_setter); } const getterType = getAnnotatedAccessorType(getter); const setterType = getAnnotatedAccessorType(setter); if (getterType && setterType) { - checkTypeAssignableTo(getterType, setterType, getter, ts.Diagnostics.The_return_type_of_a_get_accessor_must_be_assignable_to_its_set_accessor_type); + checkTypeAssignableTo(getterType, setterType, getter, Diagnostics.The_return_type_of_a_get_accessor_must_be_assignable_to_its_set_accessor_type); } } } const returnType = getTypeOfAccessors(getSymbolOfNode(node)); - if (node.kind === ts.SyntaxKind.GetAccessor) { + if (node.kind === SyntaxKind.GetAccessor) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } } } - function checkMissingDeclaration(node: ts.Node) { + function checkMissingDeclaration(node: Node) { checkDecorators(node); } - function getEffectiveTypeArgumentAtIndex(node: ts.TypeReferenceNode | ts.ExpressionWithTypeArguments, typeParameters: readonly ts.TypeParameter[], index: number): ts.Type { + function getEffectiveTypeArgumentAtIndex(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[], index: number): Type { if (node.typeArguments && index < node.typeArguments.length) { return getTypeFromTypeNode(node.typeArguments[index]); } return getEffectiveTypeArguments(node, typeParameters)[index]; } - function getEffectiveTypeArguments(node: ts.TypeReferenceNode | ts.ExpressionWithTypeArguments, typeParameters: readonly ts.TypeParameter[]): ts.Type[] { - return fillMissingTypeArguments(ts.map(node.typeArguments!, getTypeFromTypeNode), typeParameters, - getMinTypeArgumentCount(typeParameters), ts.isInJSFile(node)); + function getEffectiveTypeArguments(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[]): Type[] { + return fillMissingTypeArguments(map(node.typeArguments!, getTypeFromTypeNode), typeParameters, + getMinTypeArgumentCount(typeParameters), isInJSFile(node)); } - function checkTypeArgumentConstraints(node: ts.TypeReferenceNode | ts.ExpressionWithTypeArguments, typeParameters: readonly ts.TypeParameter[]): boolean { - let typeArguments: ts.Type[] | undefined; - let mapper: ts.TypeMapper | undefined; + function checkTypeArgumentConstraints(node: TypeReferenceNode | ExpressionWithTypeArguments, typeParameters: readonly TypeParameter[]): boolean { + let typeArguments: Type[] | undefined; + let mapper: TypeMapper | undefined; let result = true; for (let i = 0; i < typeParameters.length; i++) { const constraint = getConstraintOfTypeParameter(typeParameters[i]); @@ -36258,30 +36456,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { typeArguments[i], instantiateType(constraint, mapper), node.typeArguments![i], - ts.Diagnostics.Type_0_does_not_satisfy_the_constraint_1); + Diagnostics.Type_0_does_not_satisfy_the_constraint_1); } } return result; } - function getTypeParametersForTypeReference(node: ts.TypeReferenceNode | ts.ExpressionWithTypeArguments) { + function getTypeParametersForTypeReference(node: TypeReferenceNode | ExpressionWithTypeArguments) { const type = getTypeFromTypeReference(node); if (!isErrorType(type)) { const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - return symbol.flags & ts.SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters || - (ts.getObjectFlags(type) & ts.ObjectFlags.Reference ? (type as ts.TypeReference).target.localTypeParameters : undefined); + return symbol.flags & SymbolFlags.TypeAlias && getSymbolLinks(symbol).typeParameters || + (getObjectFlags(type) & ObjectFlags.Reference ? (type as TypeReference).target.localTypeParameters : undefined); } } return undefined; } - function checkTypeReferenceNode(node: ts.TypeReferenceNode | ts.ExpressionWithTypeArguments) { + function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === ts.SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !ts.isInJSFile(node) && !ts.isInJSDoc(node)) { - grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) { + grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } - ts.forEach(node.typeArguments, checkSourceElement); + forEach(node.typeArguments, checkSourceElement); const type = getTypeFromTypeReference(node); if (!isErrorType(type)) { if (node.typeArguments) { @@ -36294,7 +36492,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const symbol = getNodeLinks(node).resolvedSymbol; if (symbol) { - if (ts.some(symbol.declarations, d => ts.isTypeDeclaration(d) && !!(d.flags & ts.NodeFlags.Deprecated))) { + if (some(symbol.declarations, d => isTypeDeclaration(d) && !!(d.flags & NodeFlags.Deprecated))) { addDeprecatedSuggestion( getDeprecatedSuggestionNode(node), symbol.declarations!, @@ -36305,8 +36503,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getTypeArgumentConstraint(node: ts.TypeNode): ts.Type | undefined { - const typeReferenceNode = ts.tryCast(node.parent, ts.isTypeReferenceType); + function getTypeArgumentConstraint(node: TypeNode): Type | undefined { + const typeReferenceNode = tryCast(node.parent, isTypeReferenceType); if (!typeReferenceNode) return undefined; const typeParameters = getTypeParametersForTypeReference(typeReferenceNode); if (!typeParameters) return undefined; @@ -36314,12 +36512,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return constraint && instantiateType(constraint, createTypeMapper(typeParameters, getEffectiveTypeArguments(typeReferenceNode, typeParameters))); } - function checkTypeQuery(node: ts.TypeQueryNode) { + function checkTypeQuery(node: TypeQueryNode) { getTypeFromTypeQueryNode(node); } - function checkTypeLiteral(node: ts.TypeLiteralNode) { - ts.forEach(node.members, checkSourceElement); + function checkTypeLiteral(node: TypeLiteralNode) { + forEach(node.members, checkSourceElement); addLazyDiagnostic(checkTypeLiteralDiagnostics); function checkTypeLiteralDiagnostics() { @@ -36330,100 +36528,100 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkArrayType(node: ts.ArrayTypeNode) { + function checkArrayType(node: ArrayTypeNode) { checkSourceElement(node.elementType); } - function checkTupleType(node: ts.TupleTypeNode) { + function checkTupleType(node: TupleTypeNode) { const elementTypes = node.elements; let seenOptionalElement = false; let seenRestElement = false; - const hasNamedElement = ts.some(elementTypes, ts.isNamedTupleMember); + const hasNamedElement = some(elementTypes, isNamedTupleMember); for (const e of elementTypes) { - if (e.kind !== ts.SyntaxKind.NamedTupleMember && hasNamedElement) { - grammarErrorOnNode(e, ts.Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); + if (e.kind !== SyntaxKind.NamedTupleMember && hasNamedElement) { + grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names); break; } const flags = getTupleElementFlags(e); - if (flags & ts.ElementFlags.Variadic) { - const type = getTypeFromTypeNode((e as ts.RestTypeNode | ts.NamedTupleMember).type); + if (flags & ElementFlags.Variadic) { + const type = getTypeFromTypeNode((e as RestTypeNode | NamedTupleMember).type); if (!isArrayLikeType(type)) { - error(e, ts.Diagnostics.A_rest_element_type_must_be_an_array_type); + error(e, Diagnostics.A_rest_element_type_must_be_an_array_type); break; } - if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ts.ElementFlags.Rest) { + if (isArrayType(type) || isTupleType(type) && type.target.combinedFlags & ElementFlags.Rest) { seenRestElement = true; } } - else if (flags & ts.ElementFlags.Rest) { + else if (flags & ElementFlags.Rest) { if (seenRestElement) { - grammarErrorOnNode(e, ts.Diagnostics.A_rest_element_cannot_follow_another_rest_element); + grammarErrorOnNode(e, Diagnostics.A_rest_element_cannot_follow_another_rest_element); break; } seenRestElement = true; } - else if (flags & ts.ElementFlags.Optional) { + else if (flags & ElementFlags.Optional) { if (seenRestElement) { - grammarErrorOnNode(e, ts.Diagnostics.An_optional_element_cannot_follow_a_rest_element); + grammarErrorOnNode(e, Diagnostics.An_optional_element_cannot_follow_a_rest_element); break; } seenOptionalElement = true; } else if (seenOptionalElement) { - grammarErrorOnNode(e, ts.Diagnostics.A_required_element_cannot_follow_an_optional_element); + grammarErrorOnNode(e, Diagnostics.A_required_element_cannot_follow_an_optional_element); break; } } - ts.forEach(node.elements, checkSourceElement); + forEach(node.elements, checkSourceElement); getTypeFromTypeNode(node); } - function checkUnionOrIntersectionType(node: ts.UnionOrIntersectionTypeNode) { - ts.forEach(node.types, checkSourceElement); + function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) { + forEach(node.types, checkSourceElement); getTypeFromTypeNode(node); } - function checkIndexedAccessIndexType(type: ts.Type, accessNode: ts.IndexedAccessTypeNode | ts.ElementAccessExpression) { - if (!(type.flags & ts.TypeFlags.IndexedAccess)) { + function checkIndexedAccessIndexType(type: Type, accessNode: IndexedAccessTypeNode | ElementAccessExpression) { + if (!(type.flags & TypeFlags.IndexedAccess)) { return type; } // Check if the index type is assignable to 'keyof T' for the object type. - const objectType = (type as ts.IndexedAccessType).objectType; - const indexType = (type as ts.IndexedAccessType).indexType; + const objectType = (type as IndexedAccessType).objectType; + const indexType = (type as IndexedAccessType).indexType; if (isTypeAssignableTo(indexType, getIndexType(objectType, /*stringsOnly*/ false))) { - if (accessNode.kind === ts.SyntaxKind.ElementAccessExpression && ts.isAssignmentTarget(accessNode) && - ts.getObjectFlags(objectType) & ts.ObjectFlags.Mapped && getMappedTypeModifiers(objectType as ts.MappedType) & MappedTypeModifiers.IncludeReadonly) { - error(accessNode, ts.Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); + if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) && + getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(objectType as MappedType) & MappedTypeModifiers.IncludeReadonly) { + error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType)); } return type; } // Check if we're indexing with a numeric type and if either object or index types // is a generic type with a constraint that has a numeric index signature. const apparentObjectType = getApparentType(objectType); - if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, ts.TypeFlags.NumberLike)) { + if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { return type; } if (isGenericObjectType(objectType)) { const propertyName = getPropertyNameFromIndex(indexType, accessNode); if (propertyName) { const propertySymbol = forEachType(apparentObjectType, t => getPropertyOfType(t, propertyName)); - if (propertySymbol && ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & ts.ModifierFlags.NonPublicAccessibilityModifier) { - error(accessNode, ts.Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, ts.unescapeLeadingUnderscores(propertyName)); + if (propertySymbol && getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.NonPublicAccessibilityModifier) { + error(accessNode, Diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, unescapeLeadingUnderscores(propertyName)); return errorType; } } } - error(accessNode, ts.Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); + error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType)); return errorType; } - function checkIndexedAccessType(node: ts.IndexedAccessTypeNode) { + function checkIndexedAccessType(node: IndexedAccessTypeNode) { checkSourceElement(node.objectType); checkSourceElement(node.indexType); checkIndexedAccessIndexType(getTypeFromIndexedAccessTypeNode(node), node); } - function checkMappedType(node: ts.MappedTypeNode) { + function checkMappedType(node: MappedTypeNode) { checkGrammarMappedType(node); checkSourceElement(node.typeParameter); checkSourceElement(node.nameType); @@ -36433,39 +36631,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { reportImplicitAny(node, anyType); } - const type = getTypeFromMappedTypeNode(node) as ts.MappedType; + const type = getTypeFromMappedTypeNode(node) as MappedType; const nameType = getNameTypeFromMappedType(type); if (nameType) { checkTypeAssignableTo(nameType, keyofConstraintType, node.nameType); } else { const constraintType = getConstraintTypeFromMappedType(type); - checkTypeAssignableTo(constraintType, keyofConstraintType, ts.getEffectiveConstraintOfTypeParameter(node.typeParameter)); + checkTypeAssignableTo(constraintType, keyofConstraintType, getEffectiveConstraintOfTypeParameter(node.typeParameter)); } } - function checkGrammarMappedType(node: ts.MappedTypeNode) { + function checkGrammarMappedType(node: MappedTypeNode) { if (node.members?.length) { - return grammarErrorOnNode(node.members[0], ts.Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); + return grammarErrorOnNode(node.members[0], Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); } } - function checkThisType(node: ts.ThisTypeNode) { + function checkThisType(node: ThisTypeNode) { getTypeFromThisTypeNode(node); } - function checkTypeOperator(node: ts.TypeOperatorNode) { + function checkTypeOperator(node: TypeOperatorNode) { checkGrammarTypeOperatorNode(node); checkSourceElement(node.type); } - function checkConditionalType(node: ts.ConditionalTypeNode) { - ts.forEachChild(node, checkSourceElement); + function checkConditionalType(node: ConditionalTypeNode) { + forEachChild(node, checkSourceElement); } - function checkInferType(node: ts.InferTypeNode) { - if (!ts.findAncestor(node, n => n.parent && n.parent.kind === ts.SyntaxKind.ConditionalType && (n.parent as ts.ConditionalTypeNode).extendsType === n)) { - grammarErrorOnNode(node, ts.Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); + function checkInferType(node: InferTypeNode) { + if (!findAncestor(node, n => n.parent && n.parent.kind === SyntaxKind.ConditionalType && (n.parent as ConditionalTypeNode).extendsType === n)) { + grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); } checkSourceElement(node.typeParameter); const symbol = getSymbolOfNode(node.typeParameter); @@ -36474,12 +36672,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!links.typeParametersChecked) { links.typeParametersChecked = true; const typeParameter = getDeclaredTypeOfTypeParameter(symbol); - const declarations: ts.TypeParameterDeclaration[] = ts.getDeclarationsOfKind(symbol, ts.SyntaxKind.TypeParameter); + const declarations: TypeParameterDeclaration[] = getDeclarationsOfKind(symbol, SyntaxKind.TypeParameter); if (!areTypeParametersIdentical(declarations, [typeParameter], decl => [decl])) { // Report an error on every conflicting declaration. const name = symbolToString(symbol); for (const declaration of declarations) { - error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_constraints, name); + error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_constraints, name); } } } @@ -36487,7 +36685,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { registerForUnusedIdentifiersCheck(node); } - function checkTemplateLiteralType(node: ts.TemplateLiteralTypeNode) { + function checkTemplateLiteralType(node: TemplateLiteralTypeNode) { for (const span of node.templateSpans) { checkSourceElement(span.type); const type = getTypeFromTypeNode(span.type); @@ -36496,17 +36694,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getTypeFromTypeNode(node); } - function checkImportType(node: ts.ImportTypeNode) { + function checkImportType(node: ImportTypeNode) { checkSourceElement(node.argument); if (node.assertions) { - const override = ts.getResolutionModeOverrideForClause(node.assertions.assertClause, grammarErrorOnNode); + const override = getResolutionModeOverrideForClause(node.assertions.assertClause, grammarErrorOnNode); if (override) { - if (!ts.isNightly()) { - grammarErrorOnNode(node.assertions.assertClause, ts.Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); + if (!isNightly()) { + grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); } - if (ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Node16 && ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeNext) { - grammarErrorOnNode(node.assertions.assertClause, ts.Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { + grammarErrorOnNode(node.assertions.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); } } } @@ -36514,49 +36712,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getTypeFromTypeNode(node); } - function checkNamedTupleMember(node: ts.NamedTupleMember) { + function checkNamedTupleMember(node: NamedTupleMember) { if (node.dotDotDotToken && node.questionToken) { - grammarErrorOnNode(node, ts.Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest); + grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest); } - if (node.type.kind === ts.SyntaxKind.OptionalType) { - grammarErrorOnNode(node.type, ts.Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type); + if (node.type.kind === SyntaxKind.OptionalType) { + grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type); } - if (node.type.kind === ts.SyntaxKind.RestType) { - grammarErrorOnNode(node.type, ts.Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type); + if (node.type.kind === SyntaxKind.RestType) { + grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type); } checkSourceElement(node.type); getTypeFromTypeNode(node); } - function isPrivateWithinAmbient(node: ts.Node): boolean { - return (ts.hasEffectiveModifier(node, ts.ModifierFlags.Private) || ts.isPrivateIdentifierClassElementDeclaration(node)) && !!(node.flags & ts.NodeFlags.Ambient); + function isPrivateWithinAmbient(node: Node): boolean { + return (hasEffectiveModifier(node, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(node)) && !!(node.flags & NodeFlags.Ambient); } - function getEffectiveDeclarationFlags(n: ts.Declaration, flagsToCheck: ts.ModifierFlags): ts.ModifierFlags { - let flags = ts.getCombinedModifierFlags(n); + function getEffectiveDeclarationFlags(n: Declaration, flagsToCheck: ModifierFlags): ModifierFlags { + let flags = getCombinedModifierFlags(n); // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. - if (n.parent.kind !== ts.SyntaxKind.InterfaceDeclaration && - n.parent.kind !== ts.SyntaxKind.ClassDeclaration && - n.parent.kind !== ts.SyntaxKind.ClassExpression && - n.flags & ts.NodeFlags.Ambient) { - if (!(flags & ts.ModifierFlags.Ambient) && !(ts.isModuleBlock(n.parent) && ts.isModuleDeclaration(n.parent.parent) && ts.isGlobalScopeAugmentation(n.parent.parent))) { + if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && + n.parent.kind !== SyntaxKind.ClassDeclaration && + n.parent.kind !== SyntaxKind.ClassExpression && + n.flags & NodeFlags.Ambient) { + if (!(flags & ModifierFlags.Ambient) && !(isModuleBlock(n.parent) && isModuleDeclaration(n.parent.parent) && isGlobalScopeAugmentation(n.parent.parent))) { // It is nested in an ambient context, which means it is automatically exported - flags |= ts.ModifierFlags.Export; + flags |= ModifierFlags.Export; } - flags |= ts.ModifierFlags.Ambient; + flags |= ModifierFlags.Ambient; } return flags & flagsToCheck; } - function checkFunctionOrConstructorSymbol(symbol: ts.Symbol): void { + function checkFunctionOrConstructorSymbol(symbol: Symbol): void { addLazyDiagnostic(() => checkFunctionOrConstructorSymbolWorker(symbol)); } - function checkFunctionOrConstructorSymbolWorker(symbol: ts.Symbol): void { - function getCanonicalOverload(overloads: ts.Declaration[], implementation: ts.FunctionLikeDeclaration | undefined): ts.Declaration { + function checkFunctionOrConstructorSymbolWorker(symbol: Symbol): void { + function getCanonicalOverload(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined): Declaration { // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration // Error on all deviations from this canonical set of flags // The caveat is that if some overloads are defined in lib.d.ts, we don't want to @@ -36566,62 +36764,62 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } - function checkFlagAgreementBetweenOverloads(overloads: ts.Declaration[], implementation: ts.FunctionLikeDeclaration | undefined, flagsToCheck: ts.ModifierFlags, someOverloadFlags: ts.ModifierFlags, allOverloadFlags: ts.ModifierFlags): void { + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; if (someButNotAllOverloadFlags !== 0) { const canonicalFlags = getEffectiveDeclarationFlags(getCanonicalOverload(overloads, implementation), flagsToCheck); - ts.forEach(overloads, o => { + forEach(overloads, o => { const deviation = getEffectiveDeclarationFlags(o, flagsToCheck) ^ canonicalFlags; - if (deviation & ts.ModifierFlags.Export) { - error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); + if (deviation & ModifierFlags.Export) { + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_exported_or_non_exported); } - else if (deviation & ts.ModifierFlags.Ambient) { - error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); + else if (deviation & ModifierFlags.Ambient) { + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); } - else if (deviation & (ts.ModifierFlags.Private | ts.ModifierFlags.Protected)) { - error(ts.getNameOfDeclaration(o) || o, ts.Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); + else if (deviation & (ModifierFlags.Private | ModifierFlags.Protected)) { + error(getNameOfDeclaration(o) || o, Diagnostics.Overload_signatures_must_all_be_public_private_or_protected); } - else if (deviation & ts.ModifierFlags.Abstract) { - error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); + else if (deviation & ModifierFlags.Abstract) { + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_abstract_or_non_abstract); } }); } } - function checkQuestionTokenAgreementBetweenOverloads(overloads: ts.Declaration[], implementation: ts.FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { if (someHaveQuestionToken !== allHaveQuestionToken) { - const canonicalHasQuestionToken = ts.hasQuestionToken(getCanonicalOverload(overloads, implementation)); - ts.forEach(overloads, o => { - const deviation = ts.hasQuestionToken(o) !== canonicalHasQuestionToken; + const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); + forEach(overloads, o => { + const deviation = hasQuestionToken(o) !== canonicalHasQuestionToken; if (deviation) { - error(ts.getNameOfDeclaration(o), ts.Diagnostics.Overload_signatures_must_all_be_optional_or_required); + error(getNameOfDeclaration(o), Diagnostics.Overload_signatures_must_all_be_optional_or_required); } }); } } - const flagsToCheck: ts.ModifierFlags = ts.ModifierFlags.Export | ts.ModifierFlags.Ambient | ts.ModifierFlags.Private | ts.ModifierFlags.Protected | ts.ModifierFlags.Abstract; - let someNodeFlags: ts.ModifierFlags = ts.ModifierFlags.None; + const flagsToCheck: ModifierFlags = ModifierFlags.Export | ModifierFlags.Ambient | ModifierFlags.Private | ModifierFlags.Protected | ModifierFlags.Abstract; + let someNodeFlags: ModifierFlags = ModifierFlags.None; let allNodeFlags = flagsToCheck; let someHaveQuestionToken = false; let allHaveQuestionToken = true; let hasOverloads = false; - let bodyDeclaration: ts.FunctionLikeDeclaration | undefined; - let lastSeenNonAmbientDeclaration: ts.FunctionLikeDeclaration | undefined; - let previousDeclaration: ts.SignatureDeclaration | undefined; + let bodyDeclaration: FunctionLikeDeclaration | undefined; + let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration | undefined; + let previousDeclaration: SignatureDeclaration | undefined; const declarations = symbol.declarations; - const isConstructor = (symbol.flags & ts.SymbolFlags.Constructor) !== 0; + const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; - function reportImplementationExpectedError(node: ts.SignatureDeclaration): void { - if (node.name && ts.nodeIsMissing(node.name)) { + function reportImplementationExpectedError(node: SignatureDeclaration): void { + if (node.name && nodeIsMissing(node.name)) { return; } let seen = false; - const subsequentNode = ts.forEachChild(node.parent, c => { + const subsequentNode = forEachChild(node.parent, c => { if (seen) { return c; } @@ -36633,49 +36831,49 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // In this case the subsequent node is not really consecutive (.pos !== node.end), and we must ignore it here. if (subsequentNode && subsequentNode.pos === node.end) { if (subsequentNode.kind === node.kind) { - const errorNode: ts.Node = (subsequentNode as ts.FunctionLikeDeclaration).name || subsequentNode; - const subsequentName = (subsequentNode as ts.FunctionLikeDeclaration).name; + const errorNode: Node = (subsequentNode as FunctionLikeDeclaration).name || subsequentNode; + const subsequentName = (subsequentNode as FunctionLikeDeclaration).name; if (node.name && subsequentName && ( // both are private identifiers - ts.isPrivateIdentifier(node.name) && ts.isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText || + isPrivateIdentifier(node.name) && isPrivateIdentifier(subsequentName) && node.name.escapedText === subsequentName.escapedText || // Both are computed property names // TODO: GH#17345: These are methods, so handle computed name case. (`Always allowing computed property names is *not* the correct behavior!) - ts.isComputedPropertyName(node.name) && ts.isComputedPropertyName(subsequentName) || + isComputedPropertyName(node.name) && isComputedPropertyName(subsequentName) || // Both are literal property names that are the same. - ts.isPropertyNameLiteral(node.name) && ts.isPropertyNameLiteral(subsequentName) && - ts.getEscapedTextOfIdentifierOrLiteral(node.name) === ts.getEscapedTextOfIdentifierOrLiteral(subsequentName) + isPropertyNameLiteral(node.name) && isPropertyNameLiteral(subsequentName) && + getEscapedTextOfIdentifierOrLiteral(node.name) === getEscapedTextOfIdentifierOrLiteral(subsequentName) )) { const reportError = - (node.kind === ts.SyntaxKind.MethodDeclaration || node.kind === ts.SyntaxKind.MethodSignature) && - ts.isStatic(node) !== ts.isStatic(subsequentNode); + (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && + isStatic(node) !== isStatic(subsequentNode); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder if (reportError) { - const diagnostic = ts.isStatic(node) ? ts.Diagnostics.Function_overload_must_be_static : ts.Diagnostics.Function_overload_must_not_be_static; + const diagnostic = isStatic(node) ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; error(errorNode, diagnostic); } return; } - if (ts.nodeIsPresent((subsequentNode as ts.FunctionLikeDeclaration).body)) { - error(errorNode, ts.Diagnostics.Function_implementation_name_must_be_0, ts.declarationNameToString(node.name)); + if (nodeIsPresent((subsequentNode as FunctionLikeDeclaration).body)) { + error(errorNode, Diagnostics.Function_implementation_name_must_be_0, declarationNameToString(node.name)); return; } } } - const errorNode: ts.Node = node.name || node; + const errorNode: Node = node.name || node; if (isConstructor) { - error(errorNode, ts.Diagnostics.Constructor_implementation_is_missing); + error(errorNode, Diagnostics.Constructor_implementation_is_missing); } else { // Report different errors regarding non-consecutive blocks of declarations depending on whether // the node in question is abstract. - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.Abstract)) { - error(errorNode, ts.Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); + if (hasSyntacticModifier(node, ModifierFlags.Abstract)) { + error(errorNode, Diagnostics.All_declarations_of_an_abstract_method_must_be_consecutive); } else { - error(errorNode, ts.Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration); + error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration); } } } @@ -36683,12 +36881,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let duplicateFunctionDeclaration = false; let multipleConstructorImplementation = false; let hasNonAmbientClass = false; - const functionDeclarations = [] as ts.Declaration[]; + const functionDeclarations = [] as Declaration[]; if (declarations) { for (const current of declarations) { - const node = current as ts.SignatureDeclaration | ts.ClassDeclaration | ts.ClassExpression; - const inAmbientContext = node.flags & ts.NodeFlags.Ambient; - const inAmbientContextOrInterface = node.parent && (node.parent.kind === ts.SyntaxKind.InterfaceDeclaration || node.parent.kind === ts.SyntaxKind.TypeLiteral) || inAmbientContext; + const node = current as SignatureDeclaration | ClassDeclaration | ClassExpression; + const inAmbientContext = node.flags & NodeFlags.Ambient; + const inAmbientContextOrInterface = node.parent && (node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral) || inAmbientContext; if (inAmbientContextOrInterface) { // check if declarations are consecutive only if they are non-ambient // 1. ambient declarations can be interleaved @@ -36700,18 +36898,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { previousDeclaration = undefined; } - if ((node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ClassExpression) && !inAmbientContext) { + if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && !inAmbientContext) { hasNonAmbientClass = true; } - if (node.kind === ts.SyntaxKind.FunctionDeclaration || node.kind === ts.SyntaxKind.MethodDeclaration || node.kind === ts.SyntaxKind.MethodSignature || node.kind === ts.SyntaxKind.Constructor) { + if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) { functionDeclarations.push(node); const currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck); someNodeFlags |= currentNodeFlags; allNodeFlags &= currentNodeFlags; - someHaveQuestionToken = someHaveQuestionToken || ts.hasQuestionToken(node); - allHaveQuestionToken = allHaveQuestionToken && ts.hasQuestionToken(node); - const bodyIsPresent = ts.nodeIsPresent((node as ts.FunctionLikeDeclaration).body); + someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node); + allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node); + const bodyIsPresent = nodeIsPresent((node as FunctionLikeDeclaration).body); if (bodyIsPresent && bodyDeclaration) { if (isConstructor) { @@ -36727,7 +36925,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (bodyIsPresent) { if (!bodyDeclaration) { - bodyDeclaration = node as ts.FunctionLikeDeclaration; + bodyDeclaration = node as FunctionLikeDeclaration; } } else { @@ -36737,37 +36935,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { previousDeclaration = node; if (!inAmbientContextOrInterface) { - lastSeenNonAmbientDeclaration = node as ts.FunctionLikeDeclaration; + lastSeenNonAmbientDeclaration = node as FunctionLikeDeclaration; } } } } if (multipleConstructorImplementation) { - ts.forEach(functionDeclarations, declaration => { - error(declaration, ts.Diagnostics.Multiple_constructor_implementations_are_not_allowed); + forEach(functionDeclarations, declaration => { + error(declaration, Diagnostics.Multiple_constructor_implementations_are_not_allowed); }); } if (duplicateFunctionDeclaration) { - ts.forEach(functionDeclarations, declaration => { - error(ts.getNameOfDeclaration(declaration) || declaration, ts.Diagnostics.Duplicate_function_implementation); + forEach(functionDeclarations, declaration => { + error(getNameOfDeclaration(declaration) || declaration, Diagnostics.Duplicate_function_implementation); }); } - if (hasNonAmbientClass && !isConstructor && symbol.flags & ts.SymbolFlags.Function && declarations) { - const relatedDiagnostics = ts.filter(declarations, d => d.kind === ts.SyntaxKind.ClassDeclaration) - .map(d => ts.createDiagnosticForNode(d, ts.Diagnostics.Consider_adding_a_declare_modifier_to_this_class)); + if (hasNonAmbientClass && !isConstructor && symbol.flags & SymbolFlags.Function && declarations) { + const relatedDiagnostics = filter(declarations, d => d.kind === SyntaxKind.ClassDeclaration) + .map(d => createDiagnosticForNode(d, Diagnostics.Consider_adding_a_declare_modifier_to_this_class)); - ts.forEach(declarations, declaration => { - const diagnostic = declaration.kind === ts.SyntaxKind.ClassDeclaration - ? ts.Diagnostics.Class_declaration_cannot_implement_overload_list_for_0 - : declaration.kind === ts.SyntaxKind.FunctionDeclaration - ? ts.Diagnostics.Function_with_bodies_can_only_merge_with_classes_that_are_ambient + forEach(declarations, declaration => { + const diagnostic = declaration.kind === SyntaxKind.ClassDeclaration + ? Diagnostics.Class_declaration_cannot_implement_overload_list_for_0 + : declaration.kind === SyntaxKind.FunctionDeclaration + ? Diagnostics.Function_with_bodies_can_only_merge_with_classes_that_are_ambient : undefined; if (diagnostic) { - ts.addRelatedInfo( - error(ts.getNameOfDeclaration(declaration) || declaration, diagnostic, ts.symbolName(symbol)), + addRelatedInfo( + error(getNameOfDeclaration(declaration) || declaration, diagnostic, symbolName(symbol)), ...relatedDiagnostics ); } @@ -36776,7 +36974,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Abstract methods can't have an implementation -- in particular, they don't need one. if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && - !ts.hasSyntacticModifier(lastSeenNonAmbientDeclaration, ts.ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { + !hasSyntacticModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } @@ -36791,9 +36989,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const bodySignature = getSignatureFromDeclaration(bodyDeclaration); for (const signature of signatures) { if (!isImplementationCompatibleWithOverload(bodySignature, signature)) { - ts.addRelatedInfo( - error(signature.declaration, ts.Diagnostics.This_overload_signature_is_not_compatible_with_its_implementation_signature), - ts.createDiagnosticForNode(bodyDeclaration, ts.Diagnostics.The_implementation_signature_is_declared_here) + addRelatedInfo( + error(signature.declaration, Diagnostics.This_overload_signature_is_not_compatible_with_its_implementation_signature), + createDiagnosticForNode(bodyDeclaration, Diagnostics.The_implementation_signature_is_declared_here) ); break; } @@ -36802,11 +37000,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkExportsOnMergedDeclarations(node: ts.Declaration): void { + function checkExportsOnMergedDeclarations(node: Declaration): void { addLazyDiagnostic(() => checkExportsOnMergedDeclarationsWorker(node)); } - function checkExportsOnMergedDeclarationsWorker(node: ts.Declaration): void { + function checkExportsOnMergedDeclarationsWorker(node: Declaration): void { // if localSymbol is defined on node then node itself is exported - check is required let symbol = node.localSymbol; if (!symbol) { @@ -36820,7 +37018,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // run the check only for the first declaration in the list - if (ts.getDeclarationOfKind(symbol, node.kind) !== node) { + if (getDeclarationOfKind(symbol, node.kind) !== node) { return; } @@ -36829,10 +37027,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { let defaultExportedDeclarationSpaces = DeclarationSpaces.None; for (const d of symbol.declarations!) { const declarationSpaces = getDeclarationSpaces(d); - const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ts.ModifierFlags.Export | ts.ModifierFlags.Default); + const effectiveDeclarationFlags = getEffectiveDeclarationFlags(d, ModifierFlags.Export | ModifierFlags.Default); - if (effectiveDeclarationFlags & ts.ModifierFlags.Export) { - if (effectiveDeclarationFlags & ts.ModifierFlags.Default) { + if (effectiveDeclarationFlags & ModifierFlags.Export) { + if (effectiveDeclarationFlags & ModifierFlags.Default) { defaultExportedDeclarationSpaces |= declarationSpaces; } else { @@ -36855,65 +37053,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { for (const d of symbol.declarations!) { const declarationSpaces = getDeclarationSpaces(d); - const name = ts.getNameOfDeclaration(d); + const name = getNameOfDeclaration(d); // Only error on the declarations that contributed to the intersecting spaces. if (declarationSpaces & commonDeclarationSpacesForDefaultAndNonDefault) { - error(name, ts.Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, ts.declarationNameToString(name)); + error(name, Diagnostics.Merged_declaration_0_cannot_include_a_default_export_declaration_Consider_adding_a_separate_export_default_0_declaration_instead, declarationNameToString(name)); } else if (declarationSpaces & commonDeclarationSpacesForExportsAndLocals) { - error(name, ts.Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, ts.declarationNameToString(name)); + error(name, Diagnostics.Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local, declarationNameToString(name)); } } } - function getDeclarationSpaces(decl: ts.Declaration): DeclarationSpaces { - let d = decl as ts.Node; + function getDeclarationSpaces(decl: Declaration): DeclarationSpaces { + let d = decl as Node; switch (d.kind) { - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: // A jsdoc typedef and callback are, by definition, type aliases. // falls through - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: return DeclarationSpaces.ExportType; - case ts.SyntaxKind.ModuleDeclaration: - return ts.isAmbientModule(d as ts.ModuleDeclaration) || ts.getModuleInstanceState(d as ts.ModuleDeclaration) !== ts.ModuleInstanceState.NonInstantiated + case SyntaxKind.ModuleDeclaration: + return isAmbientModule(d as ModuleDeclaration) || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated ? DeclarationSpaces.ExportNamespace | DeclarationSpaces.ExportValue : DeclarationSpaces.ExportNamespace; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.EnumMember: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue; - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: return DeclarationSpaces.ExportType | DeclarationSpaces.ExportValue | DeclarationSpaces.ExportNamespace; - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.BinaryExpression: - const node = d as ts.ExportAssignment | ts.BinaryExpression; - const expression = ts.isExportAssignment(node) ? node.expression : node.right; + case SyntaxKind.ExportAssignment: + case SyntaxKind.BinaryExpression: + const node = d as ExportAssignment | BinaryExpression; + const expression = isExportAssignment(node) ? node.expression : node.right; // Export assigned entity name expressions act as aliases and should fall through, otherwise they export values - if (!ts.isEntityNameExpression(expression)) { + if (!isEntityNameExpression(expression)) { return DeclarationSpaces.ExportValue; } d = expression; // The below options all declare an Alias, which is allowed to merge with other values within the importing module. // falls through - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.ImportClause: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportClause: let result = DeclarationSpaces.None; const target = resolveAlias(getSymbolOfNode(d)!); - ts.forEach(target.declarations, d => { + forEach(target.declarations, d => { result |= getDeclarationSpaces(d); }); return result; - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ImportSpecifier: // https://github.com/Microsoft/TypeScript/pull/7591 - case ts.SyntaxKind.Identifier: // https://github.com/microsoft/TypeScript/issues/36098 + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ImportSpecifier: // https://github.com/Microsoft/TypeScript/pull/7591 + case SyntaxKind.Identifier: // https://github.com/microsoft/TypeScript/issues/36098 // Identifiers are used as declarations of assignment declarations whose parents may be // SyntaxKind.CallExpression - `Object.defineProperty(thing, "aField", {value: 42});` // SyntaxKind.ElementAccessExpression - `thing["aField"] = 42;` or `thing["aField"];` (with a doc comment on it) @@ -36922,12 +37120,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // It may be apprpriate to treat these as aliases in the future. return DeclarationSpaces.ExportValue; default: - return ts.Debug.failBadSyntaxKind(d); + return Debug.failBadSyntaxKind(d); } } } - function getAwaitedTypeOfPromise(type: ts.Type, errorNode?: ts.Node, diagnosticMessage?: ts.DiagnosticMessage, arg0?: string | number): ts.Type | undefined { + function getAwaitedTypeOfPromise(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined { const promisedType = getPromisedTypeOfPromise(type, errorNode); return promisedType && getAwaitedType(promisedType, errorNode, diagnosticMessage, arg0); } @@ -36937,7 +37135,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param type The type of the promise. * @remarks The "promised type" of a type is the type of the "value" parameter of the "onfulfilled" callback. */ - function getPromisedTypeOfPromise(type: ts.Type, errorNode?: ts.Node, thisTypeForErrorOut?: { value?: ts.Type }): ts.Type | undefined { + function getPromisedTypeOfPromise(type: Type, errorNode?: Node, thisTypeForErrorOut?: { value?: Type }): Type | undefined { // // { // type // then( // thenFunction @@ -36952,70 +37150,70 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - const typeAsPromise = type as ts.PromiseOrAwaitableType; + const typeAsPromise = type as PromiseOrAwaitableType; if (typeAsPromise.promisedTypeOfPromise) { return typeAsPromise.promisedTypeOfPromise; } if (isReferenceToType(type, getGlobalPromiseType(/*reportErrors*/ false))) { - return typeAsPromise.promisedTypeOfPromise = getTypeArguments(type as ts.GenericType)[0]; + return typeAsPromise.promisedTypeOfPromise = getTypeArguments(type as GenericType)[0]; } // primitives with a `{ then() }` won't be unwrapped/adopted. - if (allTypesAssignableToKind(getBaseConstraintOrType(type), ts.TypeFlags.Primitive | ts.TypeFlags.Never)) { + if (allTypesAssignableToKind(getBaseConstraintOrType(type), TypeFlags.Primitive | TypeFlags.Never)) { return undefined; } - const thenFunction = getTypeOfPropertyOfType(type, "then" as ts.__String)!; // TODO: GH#18217 + const thenFunction = getTypeOfPropertyOfType(type, "then" as __String)!; // TODO: GH#18217 if (isTypeAny(thenFunction)) { return undefined; } - const thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, ts.SignatureKind.Call) : ts.emptyArray; + const thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray; if (thenSignatures.length === 0) { if (errorNode) { - error(errorNode, ts.Diagnostics.A_promise_must_have_a_then_method); + error(errorNode, Diagnostics.A_promise_must_have_a_then_method); } return undefined; } - let thisTypeForError: ts.Type | undefined; - let candidates: ts.Signature[] | undefined; + let thisTypeForError: Type | undefined; + let candidates: Signature[] | undefined; for (const thenSignature of thenSignatures) { const thisType = getThisTypeOfSignature(thenSignature); if (thisType && thisType !== voidType && !isTypeRelatedTo(type, thisType, subtypeRelation)) { thisTypeForError = thisType; } else { - candidates = ts.append(candidates, thenSignature); + candidates = append(candidates, thenSignature); } } if (!candidates) { - ts.Debug.assertIsDefined(thisTypeForError); + Debug.assertIsDefined(thisTypeForError); if (thisTypeForErrorOut) { thisTypeForErrorOut.value = thisTypeForError; } if (errorNode) { - error(errorNode, ts.Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForError)); + error(errorNode, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForError)); } return undefined; } - const onfulfilledParameterType = getTypeWithFacts(getUnionType(ts.map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull); + const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull); if (isTypeAny(onfulfilledParameterType)) { return undefined; } - const onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, ts.SignatureKind.Call); + const onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call); if (onfulfilledParameterSignatures.length === 0) { if (errorNode) { - error(errorNode, ts.Diagnostics.The_first_parameter_of_the_then_method_of_a_promise_must_be_a_callback); + error(errorNode, Diagnostics.The_first_parameter_of_the_then_method_of_a_promise_must_be_a_callback); } return undefined; } - return typeAsPromise.promisedTypeOfPromise = getUnionType(ts.map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), ts.UnionReduction.Subtype); + return typeAsPromise.promisedTypeOfPromise = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature), UnionReduction.Subtype); } /** @@ -37026,7 +37224,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Promise-like type; otherwise, it is the type of the expression. This is used to reflect * The runtime behavior of the `await` keyword. */ - function checkAwaitedType(type: ts.Type, withAlias: boolean, errorNode: ts.Node, diagnosticMessage: ts.DiagnosticMessage, arg0?: string | number): ts.Type { + function checkAwaitedType(type: Type, withAlias: boolean, errorNode: Node, diagnosticMessage: DiagnosticMessage, arg0?: string | number): Type { const awaitedType = withAlias ? getAwaitedType(type, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, arg0); @@ -37036,24 +37234,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Determines whether a type is an object with a callable `then` member. */ - function isThenableType(type: ts.Type): boolean { - if (allTypesAssignableToKind(getBaseConstraintOrType(type), ts.TypeFlags.Primitive | ts.TypeFlags.Never)) { + function isThenableType(type: Type): boolean { + if (allTypesAssignableToKind(getBaseConstraintOrType(type), TypeFlags.Primitive | TypeFlags.Never)) { // primitive types cannot be considered "thenable" since they are not objects. return false; } - const thenFunction = getTypeOfPropertyOfType(type, "then" as ts.__String); - return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), ts.SignatureKind.Call).length > 0; + const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); + return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0; } - interface AwaitedTypeInstantiation extends ts.Type { + interface AwaitedTypeInstantiation extends Type { _awaitedTypeBrand: never; - aliasSymbol: ts.Symbol; - aliasTypeArguments: readonly ts.Type[]; + aliasSymbol: Symbol; + aliasTypeArguments: readonly Type[]; } - function isAwaitedTypeInstantiation(type: ts.Type): type is AwaitedTypeInstantiation { - if (type.flags & ts.TypeFlags.Conditional) { + function isAwaitedTypeInstantiation(type: Type): type is AwaitedTypeInstantiation { + if (type.flags & TypeFlags.Conditional) { const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ false); return !!awaitedSymbol && type.aliasSymbol === awaitedSymbol && type.aliasTypeArguments?.length === 1; } @@ -37063,13 +37261,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * For a generic `Awaited`, gets `T`. */ - function unwrapAwaitedType(type: ts.Type) { - return type.flags & ts.TypeFlags.Union ? mapType(type, unwrapAwaitedType) : + function unwrapAwaitedType(type: Type) { + return type.flags & TypeFlags.Union ? mapType(type, unwrapAwaitedType) : isAwaitedTypeInstantiation(type) ? type.aliasTypeArguments[0] : type; } - function isAwaitedTypeNeeded(type: ts.Type) { + function isAwaitedTypeNeeded(type: Type) { // If this is already an `Awaited`, we shouldn't wrap it. This helps to avoid `Awaited>` in higher-order. if (isTypeAny(type) || isAwaitedTypeInstantiation(type)) { return false; @@ -37081,8 +37279,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // We only need `Awaited` if `T` is a type variable that has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`, // or is promise-like. if (baseConstraint ? - baseConstraint.flags & ts.TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) || someType(baseConstraint, isThenableType) : - maybeTypeOfKind(type, ts.TypeFlags.TypeVariable)) { + baseConstraint.flags & TypeFlags.AnyOrUnknown || isEmptyObjectType(baseConstraint) || someType(baseConstraint, isThenableType) : + maybeTypeOfKind(type, TypeFlags.TypeVariable)) { return true; } } @@ -37090,7 +37288,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function tryCreateAwaitedType(type: ts.Type): ts.Type | undefined { + function tryCreateAwaitedType(type: Type): Type | undefined { // Nothing to do if `Awaited` doesn't exist const awaitedSymbol = getGlobalAwaitedSymbol(/*reportErrors*/ true); if (awaitedSymbol) { @@ -37102,7 +37300,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function createAwaitedTypeIfNeeded(type: ts.Type): ts.Type { + function createAwaitedTypeIfNeeded(type: Type): Type { // We wrap type `T` in `Awaited` based on the following conditions: // - `T` is not already an `Awaited`, and // - `T` is generic, and @@ -37118,7 +37316,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - ts.Debug.assert(getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like."); + Debug.assert(getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like."); return type; } @@ -37132,7 +37330,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * This is used to reflect the runtime behavior of the `await` keyword. */ - function getAwaitedType(type: ts.Type, errorNode?: ts.Node, diagnosticMessage?: ts.DiagnosticMessage, arg0?: string | number): ts.Type | undefined { + function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined { const awaitedType = getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, arg0); return awaitedType && createAwaitedTypeIfNeeded(awaitedType); } @@ -37142,7 +37340,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * @see {@link getAwaitedType} */ - function getAwaitedTypeNoAlias(type: ts.Type, errorNode?: ts.Node, diagnosticMessage?: ts.DiagnosticMessage, arg0?: string | number): ts.Type | undefined { + function getAwaitedTypeNoAlias(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined { if (isTypeAny(type)) { return type; } @@ -37153,21 +37351,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // If we've already cached an awaited type, return a possible `Awaited` for it. - const typeAsAwaitable = type as ts.PromiseOrAwaitableType; + const typeAsAwaitable = type as PromiseOrAwaitableType; if (typeAsAwaitable.awaitedTypeOfType) { return typeAsAwaitable.awaitedTypeOfType; } // For a union, get a union of the awaited types of each constituent. - if (type.flags & ts.TypeFlags.Union) { + if (type.flags & TypeFlags.Union) { if (awaitedTypeStack.lastIndexOf(type.id) >= 0) { if (errorNode) { - error(errorNode, ts.Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); + error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); } return undefined; } - const mapper = errorNode ? (constituentType: ts.Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias; + const mapper = errorNode ? (constituentType: Type) => getAwaitedTypeNoAlias(constituentType, errorNode, diagnosticMessage, arg0) : getAwaitedTypeNoAlias; awaitedTypeStack.push(type.id); const mapped = mapType(type, mapper); @@ -37181,7 +37379,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeAsAwaitable.awaitedTypeOfType = type; } - const thisTypeForErrorOut: { value: ts.Type | undefined } = { value: undefined }; + const thisTypeForErrorOut: { value: Type | undefined } = { value: undefined }; const promisedType = getPromisedTypeOfPromise(type, /*errorNode*/ undefined, thisTypeForErrorOut); if (promisedType) { if (type.id === promisedType.id || awaitedTypeStack.lastIndexOf(promisedType.id) >= 0) { @@ -37219,7 +37417,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // } // if (errorNode) { - error(errorNode, ts.Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); + error(errorNode, Diagnostics.Type_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method); } return undefined; } @@ -37254,13 +37452,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // be treated as a promise, they can cast to . if (isThenableType(type)) { if (errorNode) { - ts.Debug.assertIsDefined(diagnosticMessage); - let chain: ts.DiagnosticMessageChain | undefined; + Debug.assertIsDefined(diagnosticMessage); + let chain: DiagnosticMessageChain | undefined; if (thisTypeForErrorOut.value) { - chain = ts.chainDiagnosticMessages(chain, ts.Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForErrorOut.value)); + chain = chainDiagnosticMessages(chain, Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1, typeToString(type), typeToString(thisTypeForErrorOut.value)); } - chain = ts.chainDiagnosticMessages(chain, diagnosticMessage, arg0); - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(errorNode, chain)); + chain = chainDiagnosticMessages(chain, diagnosticMessage, arg0); + diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, chain)); } return undefined; } @@ -37280,7 +37478,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * @param node The signature to check */ - function checkAsyncFunctionReturnType(node: ts.FunctionLikeDeclaration | ts.MethodSignature, returnTypeNode: ts.TypeNode) { + function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration | MethodSignature, returnTypeNode: TypeNode) { // As part of our emit for an async function, we will need to emit the entity name of // the return type annotation as an expression. To meet the necessary runtime semantics // for __awaiter, we must also check that the type of the declaration (e.g. the static @@ -37307,7 +37505,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // const returnType = getTypeFromTypeNode(returnTypeNode); - if (languageVersion >= ts.ScriptTarget.ES2015) { + if (languageVersion >= ScriptTarget.ES2015) { if (isErrorType(returnType)) { return; } @@ -37315,7 +37513,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (globalPromiseType !== emptyGenericType && !isReferenceToType(returnType, globalPromiseType)) { // The promise type was not a valid type reference to the global promise type, so we // report an error and return the unknown type. - error(returnTypeNode, ts.Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, typeToString(getAwaitedTypeNoAlias(returnType) || voidType)); + error(returnTypeNode, Diagnostics.The_return_type_of_an_async_function_or_method_must_be_the_global_Promise_T_type_Did_you_mean_to_write_Promise_0, typeToString(getAwaitedTypeNoAlias(returnType) || voidType)); return; } } @@ -37327,20 +37525,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } - const promiseConstructorName = ts.getEntityNameFromTypeNode(returnTypeNode); + const promiseConstructorName = getEntityNameFromTypeNode(returnTypeNode); if (promiseConstructorName === undefined) { - error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, typeToString(returnType)); return; } - const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, ts.SymbolFlags.Value, /*ignoreErrors*/ true); + const promiseConstructorSymbol = resolveEntityName(promiseConstructorName, SymbolFlags.Value, /*ignoreErrors*/ true); const promiseConstructorType = promiseConstructorSymbol ? getTypeOfSymbol(promiseConstructorSymbol) : errorType; if (isErrorType(promiseConstructorType)) { - if (promiseConstructorName.kind === ts.SyntaxKind.Identifier && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { - error(returnTypeNode, ts.Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); + if (promiseConstructorName.kind === SyntaxKind.Identifier && promiseConstructorName.escapedText === "Promise" && getTargetType(returnType) === getGlobalPromiseType(/*reportErrors*/ false)) { + error(returnTypeNode, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option); } else { - error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, ts.entityNameToString(promiseConstructorName)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); } return; } @@ -37349,64 +37547,64 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (globalPromiseConstructorLikeType === emptyObjectType) { // If we couldn't resolve the global PromiseConstructorLike type we cannot verify // compatibility with __awaiter. - error(returnTypeNode, ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, ts.entityNameToString(promiseConstructorName)); + error(returnTypeNode, Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value, entityNameToString(promiseConstructorName)); return; } if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, returnTypeNode, - ts.Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { + Diagnostics.Type_0_is_not_a_valid_async_function_return_type_in_ES5_SlashES3_because_it_does_not_refer_to_a_Promise_compatible_constructor_value)) { return; } // Verify there is no local declaration that could collide with the promise constructor. - const rootName = promiseConstructorName && ts.getFirstIdentifier(promiseConstructorName); - const collidingSymbol = getSymbol(node.locals!, rootName.escapedText, ts.SymbolFlags.Value); + const rootName = promiseConstructorName && getFirstIdentifier(promiseConstructorName); + const collidingSymbol = getSymbol(node.locals!, rootName.escapedText, SymbolFlags.Value); if (collidingSymbol) { - error(collidingSymbol.valueDeclaration, ts.Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, - ts.idText(rootName), - ts.entityNameToString(promiseConstructorName)); + error(collidingSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, + idText(rootName), + entityNameToString(promiseConstructorName)); return; } } - checkAwaitedType(returnType, /*withAlias*/ false, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + checkAwaitedType(returnType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); } /** Check a decorator */ - function checkDecorator(node: ts.Decorator): void { + function checkDecorator(node: Decorator): void { const signature = getResolvedSignature(node); checkDeprecatedSignature(signature, node); const returnType = getReturnTypeOfSignature(signature); - if (returnType.flags & ts.TypeFlags.Any) { + if (returnType.flags & TypeFlags.Any) { return; } - let headMessage: ts.DiagnosticMessage; - let expectedReturnType: ts.Type; + let headMessage: DiagnosticMessage; + let expectedReturnType: Type; switch (node.parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - headMessage = ts.Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1; + case SyntaxKind.ClassDeclaration: + headMessage = Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1; const classSymbol = getSymbolOfNode(node.parent); const classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.Parameter: - headMessage = ts.Diagnostics.Decorator_function_return_type_is_0_but_is_expected_to_be_void_or_any; + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.Parameter: + headMessage = Diagnostics.Decorator_function_return_type_is_0_but_is_expected_to_be_void_or_any; expectedReturnType = voidType; break; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - headMessage = ts.Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + headMessage = Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1; const methodType = getTypeOfNode(node.parent); const descriptorType = createTypedPropertyDescriptorType(methodType); expectedReturnType = getUnionType([descriptorType, voidType]); break; default: - return ts.Debug.fail(); + return Debug.fail(); } checkTypeAssignableTo( @@ -37420,17 +37618,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * If a TypeNode can be resolved to a value symbol imported from an external module, it is * marked as referenced to prevent import elision. */ - function markTypeNodeAsReferenced(node: ts.TypeNode) { - markEntityNameOrEntityExpressionAsReference(node && ts.getEntityNameFromTypeNode(node), /*forDecoratorMetadata*/ false); + function markTypeNodeAsReferenced(node: TypeNode) { + markEntityNameOrEntityExpressionAsReference(node && getEntityNameFromTypeNode(node), /*forDecoratorMetadata*/ false); } - function markEntityNameOrEntityExpressionAsReference(typeName: ts.EntityNameOrEntityNameExpression | undefined, forDecoratorMetadata: boolean) { + function markEntityNameOrEntityExpressionAsReference(typeName: EntityNameOrEntityNameExpression | undefined, forDecoratorMetadata: boolean) { if (!typeName) return; - const rootName = ts.getFirstIdentifier(typeName); - const meaning = (typeName.kind === ts.SyntaxKind.Identifier ? ts.SymbolFlags.Type : ts.SymbolFlags.Namespace) | ts.SymbolFlags.Alias; + const rootName = getFirstIdentifier(typeName); + const meaning = (typeName.kind === SyntaxKind.Identifier ? SymbolFlags.Type : SymbolFlags.Namespace) | SymbolFlags.Alias; const rootSymbol = resolveName(rootName, rootName.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isReference*/ true); - if (rootSymbol && rootSymbol.flags & ts.SymbolFlags.Alias) { + if (rootSymbol && rootSymbol.flags & SymbolFlags.Alias) { if (symbolIsValue(rootSymbol) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(rootSymbol)) && !getTypeOnlyAliasDeclaration(rootSymbol)) { @@ -37438,13 +37636,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else if (forDecoratorMetadata && compilerOptions.isolatedModules - && ts.getEmitModuleKind(compilerOptions) >= ts.ModuleKind.ES2015 + && getEmitModuleKind(compilerOptions) >= ModuleKind.ES2015 && !symbolIsValue(rootSymbol) - && !ts.some(rootSymbol.declarations, ts.isTypeOnlyImportOrExportDeclaration)) { - const diag = error(typeName, ts.Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled); - const aliasDeclaration = ts.find(rootSymbol.declarations || ts.emptyArray, isAliasSymbolDeclaration); + && !some(rootSymbol.declarations, isTypeOnlyImportOrExportDeclaration)) { + const diag = error(typeName, Diagnostics.A_type_referenced_in_a_decorated_signature_must_be_imported_with_import_type_or_a_namespace_import_when_isolatedModules_and_emitDecoratorMetadata_are_enabled); + const aliasDeclaration = find(rootSymbol.declarations || emptyArray, isAliasSymbolDeclaration); if (aliasDeclaration) { - ts.addRelatedInfo(diag, ts.createDiagnosticForNode(aliasDeclaration, ts.Diagnostics._0_was_imported_here, ts.idText(rootName))); + addRelatedInfo(diag, createDiagnosticForNode(aliasDeclaration, Diagnostics._0_was_imported_here, idText(rootName))); } } } @@ -37457,43 +37655,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * union and intersection type * @param node */ - function markDecoratorMedataDataTypeNodeAsReferenced(node: ts.TypeNode | undefined): void { + function markDecoratorMedataDataTypeNodeAsReferenced(node: TypeNode | undefined): void { const entityName = getEntityNameForDecoratorMetadata(node); - if (entityName && ts.isEntityName(entityName)) { + if (entityName && isEntityName(entityName)) { markEntityNameOrEntityExpressionAsReference(entityName, /*forDecoratorMetadata*/ true); } } - function getEntityNameForDecoratorMetadata(node: ts.TypeNode | undefined): ts.EntityName | undefined { + function getEntityNameForDecoratorMetadata(node: TypeNode | undefined): EntityName | undefined { if (node) { switch (node.kind) { - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.UnionType: - return getEntityNameForDecoratorMetadataFromTypeList((node as ts.UnionOrIntersectionTypeNode).types); + case SyntaxKind.IntersectionType: + case SyntaxKind.UnionType: + return getEntityNameForDecoratorMetadataFromTypeList((node as UnionOrIntersectionTypeNode).types); - case ts.SyntaxKind.ConditionalType: - return getEntityNameForDecoratorMetadataFromTypeList([(node as ts.ConditionalTypeNode).trueType, (node as ts.ConditionalTypeNode).falseType]); + case SyntaxKind.ConditionalType: + return getEntityNameForDecoratorMetadataFromTypeList([(node as ConditionalTypeNode).trueType, (node as ConditionalTypeNode).falseType]); - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.NamedTupleMember: - return getEntityNameForDecoratorMetadata((node as ts.ParenthesizedTypeNode).type); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.NamedTupleMember: + return getEntityNameForDecoratorMetadata((node as ParenthesizedTypeNode).type); - case ts.SyntaxKind.TypeReference: - return (node as ts.TypeReferenceNode).typeName; + case SyntaxKind.TypeReference: + return (node as TypeReferenceNode).typeName; } } } - function getEntityNameForDecoratorMetadataFromTypeList(types: readonly ts.TypeNode[]): ts.EntityName | undefined { - let commonEntityName: ts.EntityName | undefined; + function getEntityNameForDecoratorMetadataFromTypeList(types: readonly TypeNode[]): EntityName | undefined { + let commonEntityName: EntityName | undefined; for (let typeNode of types) { - while (typeNode.kind === ts.SyntaxKind.ParenthesizedType || typeNode.kind === ts.SyntaxKind.NamedTupleMember) { - typeNode = (typeNode as ts.ParenthesizedTypeNode | ts.NamedTupleMember).type; // Skip parens if need be + while (typeNode.kind === SyntaxKind.ParenthesizedType || typeNode.kind === SyntaxKind.NamedTupleMember) { + typeNode = (typeNode as ParenthesizedTypeNode | NamedTupleMember).type; // Skip parens if need be } - if (typeNode.kind === ts.SyntaxKind.NeverKeyword) { + if (typeNode.kind === SyntaxKind.NeverKeyword) { continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === ts.SyntaxKind.LiteralType && (typeNode as ts.LiteralTypeNode).literal.kind === ts.SyntaxKind.NullKeyword || typeNode.kind === ts.SyntaxKind.UndefinedKeyword)) { + if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } const individualEntityName = getEntityNameForDecoratorMetadata(typeNode); @@ -37509,8 +37707,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Keep this in sync with serializeUnionOrIntersectionType // Verify if they refer to same entity and is identifier // return undefined if they dont match because we would emit object - if (!ts.isIdentifier(commonEntityName) || - !ts.isIdentifier(individualEntityName) || + if (!isIdentifier(commonEntityName) || + !isIdentifier(individualEntityName) || commonEntityName.escapedText !== individualEntityName.escapedText) { return undefined; } @@ -37522,40 +37720,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return commonEntityName; } - function getParameterTypeNodeForDecoratorCheck(node: ts.ParameterDeclaration): ts.TypeNode | undefined { - const typeNode = ts.getEffectiveTypeAnnotationNode(node); - return ts.isRestParameter(node) ? ts.getRestParameterElementType(typeNode) : typeNode; + function getParameterTypeNodeForDecoratorCheck(node: ParameterDeclaration): TypeNode | undefined { + const typeNode = getEffectiveTypeAnnotationNode(node); + return isRestParameter(node) ? getRestParameterElementType(typeNode) : typeNode; } /** Check the decorators of a node */ - function checkDecorators(node: ts.Node): void { + function checkDecorators(node: Node): void { // skip this check for nodes that cannot have decorators. These should have already had an error reported by // checkGrammarDecorators. - if (!ts.canHaveDecorators(node) || !ts.hasDecorators(node) || !node.modifiers || !ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { + if (!canHaveDecorators(node) || !hasDecorators(node) || !node.modifiers || !nodeCanBeDecorated(node, node.parent, node.parent.parent)) { return; } if (!compilerOptions.experimentalDecorators) { - error(node, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning); + error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning); } - const firstDecorator = ts.find(node.modifiers, ts.isDecorator); + const firstDecorator = find(node.modifiers, isDecorator); if (!firstDecorator) { return; } - checkExternalEmitHelpers(firstDecorator, ts.ExternalEmitHelpers.Decorate); - if (node.kind === ts.SyntaxKind.Parameter) { - checkExternalEmitHelpers(firstDecorator, ts.ExternalEmitHelpers.Param); + checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Decorate); + if (node.kind === SyntaxKind.Parameter) { + checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Param); } if (compilerOptions.emitDecoratorMetadata) { - checkExternalEmitHelpers(firstDecorator, ts.ExternalEmitHelpers.Metadata); + checkExternalEmitHelpers(firstDecorator, ExternalEmitHelpers.Metadata); // we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator. switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - const constructor = ts.getFirstConstructorWithBody(node); + case SyntaxKind.ClassDeclaration: + const constructor = getFirstConstructorWithBody(node); if (constructor) { for (const parameter of constructor.parameters) { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); @@ -37563,25 +37761,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } break; - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - const otherKind = node.kind === ts.SyntaxKind.GetAccessor ? ts.SyntaxKind.SetAccessor : ts.SyntaxKind.GetAccessor; - const otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(node), otherKind); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor)); break; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: for (const parameter of node.parameters) { markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(parameter)); } - markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveReturnTypeNode(node)); + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveReturnTypeNode(node)); break; - case ts.SyntaxKind.PropertyDeclaration: - markDecoratorMedataDataTypeNodeAsReferenced(ts.getEffectiveTypeAnnotationNode(node)); + case SyntaxKind.PropertyDeclaration: + markDecoratorMedataDataTypeNodeAsReferenced(getEffectiveTypeAnnotationNode(node)); break; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: markDecoratorMedataDataTypeNodeAsReferenced(getParameterTypeNodeForDecoratorCheck(node)); const containingSignature = node.parent; for (const parameter of containingSignature.parameters) { @@ -37592,13 +37790,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } for (const modifier of node.modifiers) { - if (ts.isDecorator(modifier)) { + if (isDecorator(modifier)) { checkDecorator(modifier); } } } - function checkFunctionDeclaration(node: ts.FunctionDeclaration): void { + function checkFunctionDeclaration(node: FunctionDeclaration): void { addLazyDiagnostic(checkFunctionDeclarationDiagnostics); function checkFunctionDeclarationDiagnostics() { @@ -37608,113 +37806,113 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkJSDocTypeAliasTag(node: ts.JSDocTypedefTag | ts.JSDocCallbackTag) { + function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag) { if (!node.typeExpression) { // If the node had `@property` tags, `typeExpression` would have been set to the first property tag. - error(node.name, ts.Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); + error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags); } if (node.name) { - checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0); + checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); } checkSourceElement(node.typeExpression); - checkTypeParameters(ts.getEffectiveTypeParameterDeclarations(node)); + checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); } - function checkJSDocTemplateTag(node: ts.JSDocTemplateTag): void { + function checkJSDocTemplateTag(node: JSDocTemplateTag): void { checkSourceElement(node.constraint); for (const tp of node.typeParameters) { checkSourceElement(tp); } } - function checkJSDocTypeTag(node: ts.JSDocTypeTag) { + function checkJSDocTypeTag(node: JSDocTypeTag) { checkSourceElement(node.typeExpression); } - function checkJSDocLinkLikeTag(node: ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain) { + function checkJSDocLinkLikeTag(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain) { if (node.name) { resolveJSDocMemberName(node.name, /*ignoreErrors*/ true); } } - function checkJSDocParameterTag(node: ts.JSDocParameterTag) { + function checkJSDocParameterTag(node: JSDocParameterTag) { checkSourceElement(node.typeExpression); } - function checkJSDocPropertyTag(node: ts.JSDocPropertyTag) { + function checkJSDocPropertyTag(node: JSDocPropertyTag) { checkSourceElement(node.typeExpression); } - function checkJSDocFunctionType(node: ts.JSDocFunctionType): void { + function checkJSDocFunctionType(node: JSDocFunctionType): void { addLazyDiagnostic(checkJSDocFunctionTypeImplicitAny); checkSignatureDeclaration(node); function checkJSDocFunctionTypeImplicitAny() { - if (!node.type && !ts.isJSDocConstructSignature(node)) { + if (!node.type && !isJSDocConstructSignature(node)) { reportImplicitAny(node, anyType); } } } - function checkJSDocImplementsTag(node: ts.JSDocImplementsTag): void { - const classLike = ts.getEffectiveJSDocHost(node); - if (!classLike || !ts.isClassDeclaration(classLike) && !ts.isClassExpression(classLike)) { - error(classLike, ts.Diagnostics.JSDoc_0_is_not_attached_to_a_class, ts.idText(node.tagName)); + function checkJSDocImplementsTag(node: JSDocImplementsTag): void { + const classLike = getEffectiveJSDocHost(node); + if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) { + error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName)); } } - function checkJSDocAugmentsTag(node: ts.JSDocAugmentsTag): void { - const classLike = ts.getEffectiveJSDocHost(node); - if (!classLike || !ts.isClassDeclaration(classLike) && !ts.isClassExpression(classLike)) { - error(classLike, ts.Diagnostics.JSDoc_0_is_not_attached_to_a_class, ts.idText(node.tagName)); + function checkJSDocAugmentsTag(node: JSDocAugmentsTag): void { + const classLike = getEffectiveJSDocHost(node); + if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) { + error(classLike, Diagnostics.JSDoc_0_is_not_attached_to_a_class, idText(node.tagName)); return; } - const augmentsTags = ts.getJSDocTags(classLike).filter(ts.isJSDocAugmentsTag); - ts.Debug.assert(augmentsTags.length > 0); + const augmentsTags = getJSDocTags(classLike).filter(isJSDocAugmentsTag); + Debug.assert(augmentsTags.length > 0); if (augmentsTags.length > 1) { - error(augmentsTags[1], ts.Diagnostics.Class_declarations_cannot_have_more_than_one_augments_or_extends_tag); + error(augmentsTags[1], Diagnostics.Class_declarations_cannot_have_more_than_one_augments_or_extends_tag); } const name = getIdentifierFromEntityNameExpression(node.class.expression); - const extend = ts.getClassExtendsHeritageElement(classLike); + const extend = getClassExtendsHeritageElement(classLike); if (extend) { const className = getIdentifierFromEntityNameExpression(extend.expression); if (className && name.escapedText !== className.escapedText) { - error(name, ts.Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, ts.idText(node.tagName), ts.idText(name), ts.idText(className)); + error(name, Diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, idText(node.tagName), idText(name), idText(className)); } } } - function checkJSDocAccessibilityModifiers(node: ts.JSDocPublicTag | ts.JSDocProtectedTag | ts.JSDocPrivateTag): void { - const host = ts.getJSDocHost(node); - if (host && ts.isPrivateIdentifierClassElementDeclaration(host)) { - error(node, ts.Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier); + function checkJSDocAccessibilityModifiers(node: JSDocPublicTag | JSDocProtectedTag | JSDocPrivateTag): void { + const host = getJSDocHost(node); + if (host && isPrivateIdentifierClassElementDeclaration(host)) { + error(node, Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier); } } - function getIdentifierFromEntityNameExpression(node: ts.Identifier | ts.PropertyAccessExpression): ts.Identifier | ts.PrivateIdentifier; - function getIdentifierFromEntityNameExpression(node: ts.Expression): ts.Identifier | ts.PrivateIdentifier | undefined; - function getIdentifierFromEntityNameExpression(node: ts.Expression): ts.Identifier | ts.PrivateIdentifier | undefined { + function getIdentifierFromEntityNameExpression(node: Identifier | PropertyAccessExpression): Identifier | PrivateIdentifier; + function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined; + function getIdentifierFromEntityNameExpression(node: Expression): Identifier | PrivateIdentifier | undefined { switch (node.kind) { - case ts.SyntaxKind.Identifier: - return node as ts.Identifier; - case ts.SyntaxKind.PropertyAccessExpression: - return (node as ts.PropertyAccessExpression).name; + case SyntaxKind.Identifier: + return node as Identifier; + case SyntaxKind.PropertyAccessExpression: + return (node as PropertyAccessExpression).name; default: return undefined; } } - function checkFunctionOrMethodDeclaration(node: ts.FunctionDeclaration | ts.MethodDeclaration | ts.MethodSignature): void { + function checkFunctionOrMethodDeclaration(node: FunctionDeclaration | MethodDeclaration | MethodSignature): void { checkDecorators(node); checkSignatureDeclaration(node); - const functionFlags = ts.getFunctionFlags(node); + const functionFlags = getFunctionFlags(node); // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. - if (node.name && node.name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.name && node.name.kind === SyntaxKind.ComputedPropertyName) { // This check will account for methods in class/interface declarations, // as well as accessors in classes/object literals checkComputedPropertyName(node.name); @@ -37732,7 +37930,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function. const firstDeclaration = localSymbol.declarations?.find( // Get first non javascript function declaration - declaration => declaration.kind === node.kind && !(declaration.flags & ts.NodeFlags.JavaScriptFile)); + declaration => declaration.kind === node.kind && !(declaration.flags & NodeFlags.JavaScriptFile)); // Only type check the symbol once if (node === firstDeclaration) { @@ -37745,29 +37943,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - const body = node.kind === ts.SyntaxKind.MethodSignature ? undefined : node.body; + const body = node.kind === SyntaxKind.MethodSignature ? undefined : node.body; checkSourceElement(body); checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, getReturnTypeFromAnnotation(node)); addLazyDiagnostic(checkFunctionOrMethodDeclarationDiagnostics); // A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature - if (ts.isInJSFile(node)) { - const typeTag = ts.getJSDocTypeTag(node); + if (isInJSFile(node)) { + const typeTag = getJSDocTypeTag(node); if (typeTag && typeTag.typeExpression && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node)) { - error(typeTag.typeExpression.type, ts.Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature); + error(typeTag.typeExpression.type, Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature); } } function checkFunctionOrMethodDeclarationDiagnostics() { - if (!ts.getEffectiveReturnTypeNode(node)) { + if (!getEffectiveReturnTypeNode(node)) { // Report an implicit any error if there is no body, no explicit return type, and node is not a private method // in an ambient context - if (ts.nodeIsMissing(body) && !isPrivateWithinAmbient(node)) { + if (nodeIsMissing(body) && !isPrivateWithinAmbient(node)) { reportImplicitAny(node, anyType); } - if (functionFlags & ts.FunctionFlags.Generator && ts.nodeIsPresent(body)) { + if (functionFlags & FunctionFlags.Generator && nodeIsPresent(body)) { // A generator with a body and no type annotation can still cause errors. It can error if the // yielded values have no common supertype, or it can give an implicit any error if it has no // yielded values. The only way to trigger these errors is to try checking its return type. @@ -37782,7 +37980,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function registerForUnusedIdentifiersCheckDiagnostics() { // May be in a call such as getTypeOfNode that happened to call this. But potentiallyUnusedIdentifiers is only defined in the scope of `checkSourceFile`. - const sourceFile = ts.getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(node); let potentiallyUnusedIdentifiers = allPotentiallyUnusedIdentifiers.get(sourceFile.path); if (!potentiallyUnusedIdentifiers) { potentiallyUnusedIdentifiers = []; @@ -37795,151 +37993,151 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } type PotentiallyUnusedIdentifier = - | ts.SourceFile | ts.ModuleDeclaration | ts.ClassLikeDeclaration | ts.InterfaceDeclaration - | ts.Block | ts.CaseBlock | ts.ForStatement | ts.ForInStatement | ts.ForOfStatement - | Exclude | ts.TypeAliasDeclaration - | ts.InferTypeNode; + | SourceFile | ModuleDeclaration | ClassLikeDeclaration | InterfaceDeclaration + | Block | CaseBlock | ForStatement | ForInStatement | ForOfStatement + | Exclude | TypeAliasDeclaration + | InferTypeNode; function checkUnusedIdentifiers(potentiallyUnusedIdentifiers: readonly PotentiallyUnusedIdentifier[], addDiagnostic: AddUnusedDiagnostic) { for (const node of potentiallyUnusedIdentifiers) { switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: checkUnusedClassMembers(node, addDiagnostic); checkUnusedTypeParameters(node, addDiagnostic); break; - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.CaseBlock: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.Block: + case SyntaxKind.CaseBlock: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: checkUnusedLocalsAndParameters(node, addDiagnostic); break; - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.Constructor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: if (node.body) { // Don't report unused parameters in overloads checkUnusedLocalsAndParameters(node, addDiagnostic); } checkUnusedTypeParameters(node, addDiagnostic); break; - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: checkUnusedTypeParameters(node, addDiagnostic); break; - case ts.SyntaxKind.InferType: + case SyntaxKind.InferType: checkUnusedInferTypeParameter(node, addDiagnostic); break; default: - ts.Debug.assertNever(node, "Node should not have been registered for unused identifiers check"); + Debug.assertNever(node, "Node should not have been registered for unused identifiers check"); } } } - function errorUnusedLocal(declaration: ts.Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) { - const node = ts.getNameOfDeclaration(declaration) || declaration; - const message = ts.isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; - addDiagnostic(declaration, UnusedKind.Local, ts.createDiagnosticForNode(node, message, name)); + function errorUnusedLocal(declaration: Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) { + const node = getNameOfDeclaration(declaration) || declaration; + const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read; + addDiagnostic(declaration, UnusedKind.Local, createDiagnosticForNode(node, message, name)); } - function isIdentifierThatStartsWithUnderscore(node: ts.Node) { - return ts.isIdentifier(node) && ts.idText(node).charCodeAt(0) === ts.CharacterCodes._; + function isIdentifierThatStartsWithUnderscore(node: Node) { + return isIdentifier(node) && idText(node).charCodeAt(0) === CharacterCodes._; } - function checkUnusedClassMembers(node: ts.ClassDeclaration | ts.ClassExpression, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedClassMembers(node: ClassDeclaration | ClassExpression, addDiagnostic: AddUnusedDiagnostic): void { for (const member of node.members) { switch (member.kind) { - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - if (member.kind === ts.SyntaxKind.SetAccessor && member.symbol.flags & ts.SymbolFlags.GetAccessor) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + if (member.kind === SyntaxKind.SetAccessor && member.symbol.flags & SymbolFlags.GetAccessor) { // Already would have reported an error on the getter. break; } const symbol = getSymbolOfNode(member); if (!symbol.isReferenced - && (ts.hasEffectiveModifier(member, ts.ModifierFlags.Private) || ts.isNamedDeclaration(member) && ts.isPrivateIdentifier(member.name)) - && !(member.flags & ts.NodeFlags.Ambient)) { - addDiagnostic(member, UnusedKind.Local, ts.createDiagnosticForNode(member.name!, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); + && (hasEffectiveModifier(member, ModifierFlags.Private) || isNamedDeclaration(member) && isPrivateIdentifier(member.name)) + && !(member.flags & NodeFlags.Ambient)) { + addDiagnostic(member, UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol))); } break; - case ts.SyntaxKind.Constructor: - for (const parameter of (member as ts.ConstructorDeclaration).parameters) { - if (!parameter.symbol.isReferenced && ts.hasSyntacticModifier(parameter, ts.ModifierFlags.Private)) { - addDiagnostic(parameter, UnusedKind.Local, ts.createDiagnosticForNode(parameter.name, ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read, ts.symbolName(parameter.symbol))); + case SyntaxKind.Constructor: + for (const parameter of (member as ConstructorDeclaration).parameters) { + if (!parameter.symbol.isReferenced && hasSyntacticModifier(parameter, ModifierFlags.Private)) { + addDiagnostic(parameter, UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol))); } } break; - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.SemicolonClassElement: - case ts.SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.IndexSignature: + case SyntaxKind.SemicolonClassElement: + case SyntaxKind.ClassStaticBlockDeclaration: // Can't be private break; default: - ts.Debug.fail("Unexpected class member"); + Debug.fail("Unexpected class member"); } } } - function checkUnusedInferTypeParameter(node: ts.InferTypeNode, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedInferTypeParameter(node: InferTypeNode, addDiagnostic: AddUnusedDiagnostic): void { const { typeParameter } = node; if (isTypeParameterUnused(typeParameter)) { - addDiagnostic(node, UnusedKind.Parameter, ts.createDiagnosticForNode(node, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(typeParameter.name))); + addDiagnostic(node, UnusedKind.Parameter, createDiagnosticForNode(node, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(typeParameter.name))); } } - function checkUnusedTypeParameters(node: ts.ClassLikeDeclaration | ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedTypeParameters(node: ClassLikeDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration, addDiagnostic: AddUnusedDiagnostic): void { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. const declarations = getSymbolOfNode(node).declarations; - if (!declarations || ts.last(declarations) !== node) return; + if (!declarations || last(declarations) !== node) return; - const typeParameters = ts.getEffectiveTypeParameterDeclarations(node); - const seenParentsWithEveryUnused = new ts.Set(); + const typeParameters = getEffectiveTypeParameterDeclarations(node); + const seenParentsWithEveryUnused = new Set(); for (const typeParameter of typeParameters) { if (!isTypeParameterUnused(typeParameter)) continue; - const name = ts.idText(typeParameter.name); + const name = idText(typeParameter.name); const { parent } = typeParameter; - if (parent.kind !== ts.SyntaxKind.InferType && parent.typeParameters!.every(isTypeParameterUnused)) { - if (ts.tryAddToSet(seenParentsWithEveryUnused, parent)) { - const sourceFile = ts.getSourceFileOfNode(parent); - const range = ts.isJSDocTemplateTag(parent) + if (parent.kind !== SyntaxKind.InferType && parent.typeParameters!.every(isTypeParameterUnused)) { + if (tryAddToSet(seenParentsWithEveryUnused, parent)) { + const sourceFile = getSourceFileOfNode(parent); + const range = isJSDocTemplateTag(parent) // Whole @template tag - ? ts.rangeOfNode(parent) + ? rangeOfNode(parent) // Include the `<>` in the error message - : ts.rangeOfTypeParameters(sourceFile, parent.typeParameters!); + : rangeOfTypeParameters(sourceFile, parent.typeParameters!); const only = parent.typeParameters!.length === 1; //TODO: following line is possible reason for bug #41974, unusedTypeParameters_TemplateTag - const message = only ? ts.Diagnostics._0_is_declared_but_its_value_is_never_read : ts.Diagnostics.All_type_parameters_are_unused; + const message = only ? Diagnostics._0_is_declared_but_its_value_is_never_read : Diagnostics.All_type_parameters_are_unused; const arg0 = only ? name : undefined; - addDiagnostic(typeParameter, UnusedKind.Parameter, ts.createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, message, arg0)); + addDiagnostic(typeParameter, UnusedKind.Parameter, createFileDiagnostic(sourceFile, range.pos, range.end - range.pos, message, arg0)); } } else { //TODO: following line is possible reason for bug #41974, unusedTypeParameters_TemplateTag - addDiagnostic(typeParameter, UnusedKind.Parameter, ts.createDiagnosticForNode(typeParameter, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, name)); + addDiagnostic(typeParameter, UnusedKind.Parameter, createDiagnosticForNode(typeParameter, Diagnostics._0_is_declared_but_its_value_is_never_read, name)); } } } - function isTypeParameterUnused(typeParameter: ts.TypeParameterDeclaration): boolean { - return !(getMergedSymbol(typeParameter.symbol).isReferenced! & ts.SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderscore(typeParameter.name); + function isTypeParameterUnused(typeParameter: TypeParameterDeclaration): boolean { + return !(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderscore(typeParameter.name); } - function addToGroup(map: ts.ESMap, key: K, value: V, getKey: (key: K) => number | string): void { + function addToGroup(map: ESMap, key: K, value: V, getKey: (key: K) => number | string): void { const keyString = String(getKey(key)); const group = map.get(keyString); if (group) { @@ -37950,13 +38148,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function tryGetRootParameterDeclaration(node: ts.Node): ts.ParameterDeclaration | undefined { - return ts.tryCast(ts.getRootDeclaration(node), ts.isParameter); + function tryGetRootParameterDeclaration(node: Node): ParameterDeclaration | undefined { + return tryCast(getRootDeclaration(node), isParameter); } - function isValidUnusedLocalDeclaration(declaration: ts.Declaration): boolean { - if (ts.isBindingElement(declaration)) { - if (ts.isObjectBindingPattern(declaration.parent)) { + function isValidUnusedLocalDeclaration(declaration: Declaration): boolean { + if (isBindingElement(declaration)) { + if (isObjectBindingPattern(declaration.parent)) { /** * ignore starts with underscore names _ * const { a: _a } = { a: 1 } @@ -37965,19 +38163,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } return isIdentifierThatStartsWithUnderscore(declaration.name); } - return ts.isAmbientModule(declaration) || - (ts.isVariableDeclaration(declaration) && ts.isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!); + return isAmbientModule(declaration) || + (isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!); } - function checkUnusedLocalsAndParameters(nodeWithLocals: ts.Node, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedLocalsAndParameters(nodeWithLocals: Node, addDiagnostic: AddUnusedDiagnostic): void { // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. - const unusedImports = new ts.Map(); - const unusedDestructures = new ts.Map(); - const unusedVariables = new ts.Map(); + const unusedImports = new Map(); + const unusedDestructures = new Map(); + const unusedVariables = new Map(); nodeWithLocals.locals!.forEach(local => { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. - if (local.flags & ts.SymbolFlags.TypeParameter ? !(local.flags & ts.SymbolFlags.Variable && !(local.isReferenced! & ts.SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { + if (local.flags & SymbolFlags.TypeParameter ? !(local.flags & SymbolFlags.Variable && !(local.isReferenced! & SymbolFlags.Variable)) : local.isReferenced || local.exportSymbol) { return; } @@ -37990,31 +38188,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isImportedDeclaration(declaration)) { addToGroup(unusedImports, importClauseFromImported(declaration), declaration, getNodeId); } - else if (ts.isBindingElement(declaration) && ts.isObjectBindingPattern(declaration.parent)) { + else if (isBindingElement(declaration) && isObjectBindingPattern(declaration.parent)) { // In `{ a, ...b }, `a` is considered used since it removes a property from `b`. `b` may still be unused though. - const lastElement = ts.last(declaration.parent.elements); - if (declaration === lastElement || !ts.last(declaration.parent.elements).dotDotDotToken) { + const lastElement = last(declaration.parent.elements); + if (declaration === lastElement || !last(declaration.parent.elements).dotDotDotToken) { addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } - else if (ts.isVariableDeclaration(declaration)) { + else if (isVariableDeclaration(declaration)) { addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); } else { const parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); - const name = local.valueDeclaration && ts.getNameOfDeclaration(local.valueDeclaration); + const name = local.valueDeclaration && getNameOfDeclaration(local.valueDeclaration); if (parameter && name) { - if (!ts.isParameterPropertyDeclaration(parameter, parameter.parent) && !ts.parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) { - if (ts.isBindingElement(declaration) && ts.isArrayBindingPattern(declaration.parent)) { + if (!isParameterPropertyDeclaration(parameter, parameter.parent) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) { + if (isBindingElement(declaration) && isArrayBindingPattern(declaration.parent)) { addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } else { - addDiagnostic(parameter, UnusedKind.Parameter, ts.createDiagnosticForNode(name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.symbolName(local))); + addDiagnostic(parameter, UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local))); } } } else { - errorUnusedLocal(declaration, ts.symbolName(local), addDiagnostic); + errorUnusedLocal(declaration, symbolName(local), addDiagnostic); } } } @@ -38024,44 +38222,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const importDecl = importClause.parent; const nDeclarations = (importClause.name ? 1 : 0) + (importClause.namedBindings ? - (importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport ? 1 : importClause.namedBindings.elements.length) + (importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? 1 : importClause.namedBindings.elements.length) : 0); if (nDeclarations === unuseds.length) { addDiagnostic(importDecl, UnusedKind.Local, unuseds.length === 1 - ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name!)) - : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + ? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name!)) + : createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused)); } else { - for (const unused of unuseds) errorUnusedLocal(unused, ts.idText(unused.name!), addDiagnostic); + for (const unused of unuseds) errorUnusedLocal(unused, idText(unused.name!), addDiagnostic); } }); unusedDestructures.forEach(([bindingPattern, bindingElements]) => { const kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? UnusedKind.Parameter : UnusedKind.Local; if (bindingPattern.elements.length === bindingElements.length) { - if (bindingElements.length === 1 && bindingPattern.parent.kind === ts.SyntaxKind.VariableDeclaration && bindingPattern.parent.parent.kind === ts.SyntaxKind.VariableDeclarationList) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === SyntaxKind.VariableDeclaration && bindingPattern.parent.parent.kind === SyntaxKind.VariableDeclarationList) { addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); } else { addDiagnostic(bindingPattern, kind, bindingElements.length === 1 - ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(bindingElements).name)) - : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + ? createDiagnosticForNode(bindingPattern, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(bindingElements).name)) + : createDiagnosticForNode(bindingPattern, Diagnostics.All_destructured_elements_are_unused)); } } else { for (const e of bindingElements) { - addDiagnostic(e, kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(e.name))); + addDiagnostic(e, kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(e.name))); } } }); unusedVariables.forEach(([declarationList, declarations]) => { if (declarationList.declarations.length === declarations.length) { addDiagnostic(declarationList, UnusedKind.Local, declarations.length === 1 - ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) - : ts.createDiagnosticForNode(declarationList.parent.kind === ts.SyntaxKind.VariableStatement ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); + ? createDiagnosticForNode(first(declarations).name, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(declarations).name)) + : createDiagnosticForNode(declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent : declarationList, Diagnostics.All_variables_are_unused)); } else { for (const decl of declarations) { - addDiagnostic(decl, UnusedKind.Local, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(decl.name))); + addDiagnostic(decl, UnusedKind.Local, createDiagnosticForNode(decl, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(decl.name))); } } }); @@ -38070,14 +38268,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function checkPotentialUncheckedRenamedBindingElementsInTypes() { for (const node of potentialUnusedRenamedBindingElementsInTypes) { if (!getSymbolOfNode(node)?.isReferenced) { - const wrappingDeclaration = ts.walkUpBindingElementsAndPatterns(node); - ts.Debug.assert(ts.isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here"); - const diagnostic = ts.createDiagnosticForNode(node.name, ts.Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, ts.declarationNameToString(node.name), ts.declarationNameToString(node.propertyName)); + const wrappingDeclaration = walkUpBindingElementsAndPatterns(node); + Debug.assert(isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here"); + const diagnostic = createDiagnosticForNode(node.name, Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, declarationNameToString(node.name), declarationNameToString(node.propertyName)); if (!wrappingDeclaration.type) { // entire parameter does not have type annotation, suggest adding an annotation - ts.addRelatedInfo( + addRelatedInfo( diagnostic, - ts.createFileDiagnostic(ts.getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, ts.Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, ts.declarationNameToString(node.propertyName)) + createFileDiagnostic(getSourceFileOfNode(wrappingDeclaration), wrappingDeclaration.end, 1, Diagnostics.We_can_only_write_a_type_for_0_by_adding_a_type_for_the_entire_parameter_here, declarationNameToString(node.propertyName)) ); } diagnostics.add(diagnostic); @@ -38085,53 +38283,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function bindingNameText(name: ts.BindingName): string { + function bindingNameText(name: BindingName): string { switch (name.kind) { - case ts.SyntaxKind.Identifier: - return ts.idText(name); - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ObjectBindingPattern: - return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + case SyntaxKind.Identifier: + return idText(name); + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ObjectBindingPattern: + return bindingNameText(cast(first(name.elements), isBindingElement).name); default: - return ts.Debug.assertNever(name); + return Debug.assertNever(name); } } - type ImportedDeclaration = ts.ImportClause | ts.ImportSpecifier | ts.NamespaceImport; - function isImportedDeclaration(node: ts.Node): node is ImportedDeclaration { - return node.kind === ts.SyntaxKind.ImportClause || node.kind === ts.SyntaxKind.ImportSpecifier || node.kind === ts.SyntaxKind.NamespaceImport; + type ImportedDeclaration = ImportClause | ImportSpecifier | NamespaceImport; + function isImportedDeclaration(node: Node): node is ImportedDeclaration { + return node.kind === SyntaxKind.ImportClause || node.kind === SyntaxKind.ImportSpecifier || node.kind === SyntaxKind.NamespaceImport; } - function importClauseFromImported(decl: ImportedDeclaration): ts.ImportClause { - return decl.kind === ts.SyntaxKind.ImportClause ? decl : decl.kind === ts.SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent; + function importClauseFromImported(decl: ImportedDeclaration): ImportClause { + return decl.kind === SyntaxKind.ImportClause ? decl : decl.kind === SyntaxKind.NamespaceImport ? decl.parent : decl.parent.parent; } - function checkBlock(node: ts.Block) { + function checkBlock(node: Block) { // Grammar checking for SyntaxKind.Block - if (node.kind === ts.SyntaxKind.Block) { + if (node.kind === SyntaxKind.Block) { checkGrammarStatementInAmbientContext(node); } - if (ts.isFunctionOrModuleBlock(node)) { + if (isFunctionOrModuleBlock(node)) { const saveFlowAnalysisDisabled = flowAnalysisDisabled; - ts.forEach(node.statements, checkSourceElement); + forEach(node.statements, checkSourceElement); flowAnalysisDisabled = saveFlowAnalysisDisabled; } else { - ts.forEach(node.statements, checkSourceElement); + forEach(node.statements, checkSourceElement); } if (node.locals) { registerForUnusedIdentifiersCheck(node); } } - function checkCollisionWithArgumentsInGeneratedCode(node: ts.SignatureDeclaration) { + function checkCollisionWithArgumentsInGeneratedCode(node: SignatureDeclaration) { // no rest parameters \ declaration context \ overload - no codegen impact - if (languageVersion >= ts.ScriptTarget.ES2015 || !ts.hasRestParameter(node) || node.flags & ts.NodeFlags.Ambient || ts.nodeIsMissing((node as ts.FunctionLikeDeclaration).body)) { + if (languageVersion >= ScriptTarget.ES2015 || !hasRestParameter(node) || node.flags & NodeFlags.Ambient || nodeIsMissing((node as FunctionLikeDeclaration).body)) { return; } - ts.forEach(node.parameters, p => { - if (p.name && !ts.isBindingPattern(p.name) && p.name.escapedText === argumentsSymbol.escapedName) { - errorSkippedOn("noEmit", p, ts.Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters); + forEach(node.parameters, p => { + if (p.name && !isBindingPattern(p.name) && p.name.escapedText === argumentsSymbol.escapedName) { + errorSkippedOn("noEmit", p, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_arguments_to_initialize_rest_parameters); } }); } @@ -38141,36 +38339,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * of {@link name} in an outer scope. This is used to check for collisions for downlevel transformations that * require names like `Object`, `Promise`, `Reflect`, `require`, `exports`, etc. */ - function needCollisionCheckForIdentifier(node: ts.Node, identifier: ts.Identifier | undefined, name: string): boolean { + function needCollisionCheckForIdentifier(node: Node, identifier: Identifier | undefined, name: string): boolean { if (identifier?.escapedText !== name) { return false; } - if (node.kind === ts.SyntaxKind.PropertyDeclaration || - node.kind === ts.SyntaxKind.PropertySignature || - node.kind === ts.SyntaxKind.MethodDeclaration || - node.kind === ts.SyntaxKind.MethodSignature || - node.kind === ts.SyntaxKind.GetAccessor || - node.kind === ts.SyntaxKind.SetAccessor || - node.kind === ts.SyntaxKind.PropertyAssignment) { + if (node.kind === SyntaxKind.PropertyDeclaration || + node.kind === SyntaxKind.PropertySignature || + node.kind === SyntaxKind.MethodDeclaration || + node.kind === SyntaxKind.MethodSignature || + node.kind === SyntaxKind.GetAccessor || + node.kind === SyntaxKind.SetAccessor || + node.kind === SyntaxKind.PropertyAssignment) { // it is ok to have member named '_super', '_this', `Promise`, etc. - member access is always qualified return false; } - if (node.flags & ts.NodeFlags.Ambient) { + if (node.flags & NodeFlags.Ambient) { // ambient context - no codegen impact return false; } - if (ts.isImportClause(node) || ts.isImportEqualsDeclaration(node) || ts.isImportSpecifier(node)) { + if (isImportClause(node) || isImportEqualsDeclaration(node) || isImportSpecifier(node)) { // type-only imports do not require collision checks against runtime values. - if (ts.isTypeOnlyImportOrExportDeclaration(node)) { + if (isTypeOnlyImportOrExportDeclaration(node)) { return false; } } - const root = ts.getRootDeclaration(node); - if (ts.isParameter(root) && ts.nodeIsMissing((root.parent as ts.FunctionLikeDeclaration).body)) { + const root = getRootDeclaration(node); + if (isParameter(root) && nodeIsMissing((root.parent as FunctionLikeDeclaration).body)) { // just an overload - no codegen impact return false; } @@ -38179,15 +38377,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // this function will run after checking the source file so 'CaptureThis' is correct for all nodes - function checkIfThisIsCapturedInEnclosingScope(node: ts.Node): void { - ts.findAncestor(node, current => { - if (getNodeCheckFlags(current) & ts.NodeCheckFlags.CaptureThis) { - const isDeclaration = node.kind !== ts.SyntaxKind.Identifier; + function checkIfThisIsCapturedInEnclosingScope(node: Node): void { + findAncestor(node, current => { + if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureThis) { + const isDeclaration = node.kind !== SyntaxKind.Identifier; if (isDeclaration) { - error(ts.getNameOfDeclaration(node as ts.Declaration), ts.Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); + error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_this_Compiler_uses_variable_declaration_this_to_capture_this_reference); } else { - error(node, ts.Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference); + error(node, Diagnostics.Expression_resolves_to_variable_declaration_this_that_compiler_uses_to_capture_this_reference); } return true; } @@ -38195,15 +38393,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function checkIfNewTargetIsCapturedInEnclosingScope(node: ts.Node): void { - ts.findAncestor(node, current => { - if (getNodeCheckFlags(current) & ts.NodeCheckFlags.CaptureNewTarget) { - const isDeclaration = node.kind !== ts.SyntaxKind.Identifier; + function checkIfNewTargetIsCapturedInEnclosingScope(node: Node): void { + findAncestor(node, current => { + if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureNewTarget) { + const isDeclaration = node.kind !== SyntaxKind.Identifier; if (isDeclaration) { - error(ts.getNameOfDeclaration(node as ts.Declaration), ts.Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); + error(getNameOfDeclaration(node as Declaration), Diagnostics.Duplicate_identifier_newTarget_Compiler_uses_variable_declaration_newTarget_to_capture_new_target_meta_property_reference); } else { - error(node, ts.Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference); + error(node, Diagnostics.Expression_resolves_to_variable_declaration_newTarget_that_compiler_uses_to_capture_new_target_meta_property_reference); } return true; } @@ -38211,9 +38409,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function checkCollisionWithRequireExportsInGeneratedCode(node: ts.Node, name: ts.Identifier | undefined) { + function checkCollisionWithRequireExportsInGeneratedCode(node: Node, name: Identifier | undefined) { // No need to check for require or exports for ES6 modules and later - if (moduleKind >= ts.ModuleKind.ES2015 && !(moduleKind >= ts.ModuleKind.Node16 && ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS)) { + if (moduleKind >= ModuleKind.ES2015 && !(moduleKind >= ModuleKind.Node16 && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { return; } @@ -38222,109 +38420,109 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Uninstantiated modules shouldnt do this check - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== ts.ModuleInstanceState.Instantiated) { + if (isModuleDeclaration(node) && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) { return; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent const parent = getDeclarationContainer(node); - if (parent.kind === ts.SyntaxKind.SourceFile && ts.isExternalOrCommonJsModule(parent as ts.SourceFile)) { + if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile)) { // If the declaration happens to be in external module, report error that require and exports are reserved keywords - errorSkippedOn("noEmit", name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, - ts.declarationNameToString(name), ts.declarationNameToString(name)); + errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module, + declarationNameToString(name), declarationNameToString(name)); } } - function checkCollisionWithGlobalPromiseInGeneratedCode(node: ts.Node, name: ts.Identifier | undefined): void { - if (!name || languageVersion >= ts.ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) { + function checkCollisionWithGlobalPromiseInGeneratedCode(node: Node, name: Identifier | undefined): void { + if (!name || languageVersion >= ScriptTarget.ES2017 || !needCollisionCheckForIdentifier(node, name, "Promise")) { return; } // Uninstantiated modules shouldnt do this check - if (ts.isModuleDeclaration(node) && ts.getModuleInstanceState(node) !== ts.ModuleInstanceState.Instantiated) { + if (isModuleDeclaration(node) && getModuleInstanceState(node) !== ModuleInstanceState.Instantiated) { return; } // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent const parent = getDeclarationContainer(node); - if (parent.kind === ts.SyntaxKind.SourceFile && ts.isExternalOrCommonJsModule(parent as ts.SourceFile) && parent.flags & ts.NodeFlags.HasAsyncFunctions) { + if (parent.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(parent as SourceFile) && parent.flags & NodeFlags.HasAsyncFunctions) { // If the declaration happens to be in external module, report error that Promise is a reserved identifier. - errorSkippedOn("noEmit", name, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, - ts.declarationNameToString(name), ts.declarationNameToString(name)); + errorSkippedOn("noEmit", name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_a_module_containing_async_functions, + declarationNameToString(name), declarationNameToString(name)); } } - function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: ts.Node, name: ts.Identifier): void { - if (languageVersion <= ts.ScriptTarget.ES2021 + function recordPotentialCollisionWithWeakMapSetInGeneratedCode(node: Node, name: Identifier): void { + if (languageVersion <= ScriptTarget.ES2021 && (needCollisionCheckForIdentifier(node, name, "WeakMap") || needCollisionCheckForIdentifier(node, name, "WeakSet"))) { potentialWeakMapSetCollisions.push(node); } } - function checkWeakMapSetCollision(node: ts.Node) { - const enclosingBlockScope = ts.getEnclosingBlockScopeContainer(node); - if (getNodeCheckFlags(enclosingBlockScope) & ts.NodeCheckFlags.ContainsClassWithPrivateIdentifiers) { - ts.Debug.assert(ts.isNamedDeclaration(node) && ts.isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier"); - errorSkippedOn("noEmit", node, ts.Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText); + function checkWeakMapSetCollision(node: Node) { + const enclosingBlockScope = getEnclosingBlockScopeContainer(node); + if (getNodeCheckFlags(enclosingBlockScope) & NodeCheckFlags.ContainsClassWithPrivateIdentifiers) { + Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name) && typeof node.name.escapedText === "string", "The target of a WeakMap/WeakSet collision check should be an identifier"); + errorSkippedOn("noEmit", node, Diagnostics.Compiler_reserves_name_0_when_emitting_private_identifier_downlevel, node.name.escapedText); } } - function recordPotentialCollisionWithReflectInGeneratedCode(node: ts.Node, name: ts.Identifier | undefined): void { - if (name && languageVersion >= ts.ScriptTarget.ES2015 && languageVersion <= ts.ScriptTarget.ES2021 + function recordPotentialCollisionWithReflectInGeneratedCode(node: Node, name: Identifier | undefined): void { + if (name && languageVersion >= ScriptTarget.ES2015 && languageVersion <= ScriptTarget.ES2021 && needCollisionCheckForIdentifier(node, name, "Reflect")) { potentialReflectCollisions.push(node); } } - function checkReflectCollision(node: ts.Node) { + function checkReflectCollision(node: Node) { let hasCollision = false; - if (ts.isClassExpression(node)) { + if (isClassExpression(node)) { // ClassExpression names don't contribute to their containers, but do matter for any of their block-scoped members. for (const member of node.members) { - if (getNodeCheckFlags(member) & ts.NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { + if (getNodeCheckFlags(member) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { hasCollision = true; break; } } } - else if (ts.isFunctionExpression(node)) { + else if (isFunctionExpression(node)) { // FunctionExpression names don't contribute to their containers, but do matter for their contents - if (getNodeCheckFlags(node) & ts.NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { + if (getNodeCheckFlags(node) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { hasCollision = true; } } else { - const container = ts.getEnclosingBlockScopeContainer(node); - if (container && getNodeCheckFlags(container) & ts.NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { + const container = getEnclosingBlockScopeContainer(node); + if (container && getNodeCheckFlags(container) & NodeCheckFlags.ContainsSuperPropertyInStaticInitializer) { hasCollision = true; } } if (hasCollision) { - ts.Debug.assert(ts.isNamedDeclaration(node) && ts.isIdentifier(node.name), "The target of a Reflect collision check should be an identifier"); - errorSkippedOn("noEmit", node, ts.Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers, - ts.declarationNameToString(node.name), + Debug.assert(isNamedDeclaration(node) && isIdentifier(node.name), "The target of a Reflect collision check should be an identifier"); + errorSkippedOn("noEmit", node, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_when_emitting_super_references_in_static_initializers, + declarationNameToString(node.name), "Reflect"); } } - function checkCollisionsForDeclarationName(node: ts.Node, name: ts.Identifier | undefined) { + function checkCollisionsForDeclarationName(node: Node, name: Identifier | undefined) { if (!name) return; checkCollisionWithRequireExportsInGeneratedCode(node, name); checkCollisionWithGlobalPromiseInGeneratedCode(node, name); recordPotentialCollisionWithWeakMapSetInGeneratedCode(node, name); recordPotentialCollisionWithReflectInGeneratedCode(node, name); - if (ts.isClassLike(node)) { - checkTypeNameIsReserved(name, ts.Diagnostics.Class_name_cannot_be_0); - if (!(node.flags & ts.NodeFlags.Ambient)) { + if (isClassLike(node)) { + checkTypeNameIsReserved(name, Diagnostics.Class_name_cannot_be_0); + if (!(node.flags & NodeFlags.Ambient)) { checkClassNameCollisionWithObject(name); } } - else if (ts.isEnumDeclaration(node)) { - checkTypeNameIsReserved(name, ts.Diagnostics.Enum_name_cannot_be_0); + else if (isEnumDeclaration(node)) { + checkTypeNameIsReserved(name, Diagnostics.Enum_name_cannot_be_0); } } - function checkVarDeclaredNamesNotShadowed(node: ts.VariableDeclaration | ts.BindingElement) { + function checkVarDeclaredNamesNotShadowed(node: VariableDeclaration | BindingElement) { // - ScriptBody : StatementList // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList // also occurs in the VarDeclaredNames of StatementList. @@ -38351,28 +38549,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // } // skip block-scoped variables and parameters - if ((ts.getCombinedNodeFlags(node) & ts.NodeFlags.BlockScoped) !== 0 || ts.isParameterDeclaration(node)) { + if ((getCombinedNodeFlags(node) & NodeFlags.BlockScoped) !== 0 || isParameterDeclaration(node)) { return; } // skip variable declarations that don't have initializers // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern // so we'll always treat binding elements as initialized - if (node.kind === ts.SyntaxKind.VariableDeclaration && !node.initializer) { + if (node.kind === SyntaxKind.VariableDeclaration && !node.initializer) { return; } const symbol = getSymbolOfNode(node); - if (symbol.flags & ts.SymbolFlags.FunctionScopedVariable) { - if (!ts.isIdentifier(node.name)) return ts.Debug.fail(); - const localDeclarationSymbol = resolveName(node, node.name.escapedText, ts.SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); + if (symbol.flags & SymbolFlags.FunctionScopedVariable) { + if (!isIdentifier(node.name)) return Debug.fail(); + const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); if (localDeclarationSymbol && localDeclarationSymbol !== symbol && - localDeclarationSymbol.flags & ts.SymbolFlags.BlockScopedVariable) { - if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & ts.NodeFlags.BlockScoped) { - const varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, ts.SyntaxKind.VariableDeclarationList)!; + localDeclarationSymbol.flags & SymbolFlags.BlockScopedVariable) { + if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & NodeFlags.BlockScoped) { + const varDeclList = getAncestor(localDeclarationSymbol.valueDeclaration, SyntaxKind.VariableDeclarationList)!; const container = - varDeclList.parent.kind === ts.SyntaxKind.VariableStatement && varDeclList.parent.parent + varDeclList.parent.kind === SyntaxKind.VariableStatement && varDeclList.parent.parent ? varDeclList.parent.parent : undefined; @@ -38380,10 +38578,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting) const namesShareScope = container && - (container.kind === ts.SyntaxKind.Block && ts.isFunctionLike(container.parent) || - container.kind === ts.SyntaxKind.ModuleBlock || - container.kind === ts.SyntaxKind.ModuleDeclaration || - container.kind === ts.SyntaxKind.SourceFile); + (container.kind === SyntaxKind.Block && isFunctionLike(container.parent) || + container.kind === SyntaxKind.ModuleBlock || + container.kind === SyntaxKind.ModuleDeclaration || + container.kind === SyntaxKind.SourceFile); // here we know that function scoped variable is shadowed by block scoped one // if they are defined in the same scope - binder has already reported redeclaration error @@ -38391,21 +38589,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // since LHS will be block scoped name instead of function scoped if (!namesShareScope) { const name = symbolToString(localDeclarationSymbol); - error(node, ts.Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); + error(node, Diagnostics.Cannot_initialize_outer_scoped_variable_0_in_the_same_scope_as_block_scoped_declaration_1, name, name); } } } } } - function convertAutoToAny(type: ts.Type) { + function convertAutoToAny(type: Type) { return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type; } // Check variable, parameter, or property declaration - function checkVariableLikeDeclaration(node: ts.ParameterDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.VariableDeclaration | ts.BindingElement) { + function checkVariableLikeDeclaration(node: ParameterDeclaration | PropertyDeclaration | PropertySignature | VariableDeclaration | BindingElement) { checkDecorators(node); - if (!ts.isBindingElement(node)) { + if (!isBindingElement(node)) { checkSourceElement(node.type); } @@ -38418,19 +38616,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including // well known symbols. - if (node.name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.name.kind === SyntaxKind.ComputedPropertyName) { checkComputedPropertyName(node.name); - if (ts.hasOnlyExpressionInitializer(node) && node.initializer) { + if (hasOnlyExpressionInitializer(node) && node.initializer) { checkExpressionCached(node.initializer); } } - if (ts.isBindingElement(node)) { + if (isBindingElement(node)) { if ( node.propertyName && - ts.isIdentifier(node.name) && - ts.isParameterDeclaration(node) && - ts.nodeIsMissing((ts.getContainingFunction(node) as ts.FunctionLikeDeclaration).body)) { + isIdentifier(node.name) && + isParameterDeclaration(node) && + nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) { // type F = ({a: string}) => void; // ^^^^^^ // variable renaming in function type notation is confusing, @@ -38439,11 +38637,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } - if (ts.isObjectBindingPattern(node.parent) && node.dotDotDotToken && languageVersion < ts.ScriptTarget.ES2018) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Rest); + if (isObjectBindingPattern(node.parent) && node.dotDotDotToken && languageVersion < ScriptTarget.ES2018) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Rest); } // check computed properties inside property names of binding elements - if (node.propertyName && node.propertyName.kind === ts.SyntaxKind.ComputedPropertyName) { + if (node.propertyName && node.propertyName.kind === SyntaxKind.ComputedPropertyName) { checkComputedPropertyName(node.propertyName); } @@ -38452,36 +38650,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const parentCheckMode = node.dotDotDotToken ? CheckMode.RestBindingElement : CheckMode.Normal; const parentType = getTypeForBindingElementParent(parent, parentCheckMode); const name = node.propertyName || node.name; - if (parentType && !ts.isBindingPattern(name)) { + if (parentType && !isBindingPattern(name)) { const exprType = getLiteralTypeFromPropertyName(name); if (isTypeUsableAsPropertyName(exprType)) { const nameText = getPropertyNameFromType(exprType); const property = getPropertyOfType(parentType, nameText); if (property) { markPropertyAsReferenced(property, /*nodeForCheckWriteOnly*/ undefined, /*isSelfTypeAccess*/ false); // A destructuring is never a write-only reference. - checkPropertyAccessibility(node, !!parent.initializer && parent.initializer.kind === ts.SyntaxKind.SuperKeyword, /*writing*/ false, parentType, property); + checkPropertyAccessibility(node, !!parent.initializer && parent.initializer.kind === SyntaxKind.SuperKeyword, /*writing*/ false, parentType, property); } } } } // For a binding pattern, check contained binding elements - if (ts.isBindingPattern(node.name)) { - if (node.name.kind === ts.SyntaxKind.ArrayBindingPattern && languageVersion < ts.ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.Read); + if (isBindingPattern(node.name)) { + if (node.name.kind === SyntaxKind.ArrayBindingPattern && languageVersion < ScriptTarget.ES2015 && compilerOptions.downlevelIteration) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.Read); } - ts.forEach(node.name.elements, checkSourceElement); + forEach(node.name.elements, checkSourceElement); } // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body - if (ts.isParameter(node) && node.initializer && ts.nodeIsMissing((ts.getContainingFunction(node) as ts.FunctionLikeDeclaration).body)) { - error(node, ts.Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); + if (isParameter(node) && node.initializer && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) { + error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); return; } // For a binding pattern, validate the initializer and exit - if (ts.isBindingPattern(node.name)) { - const needCheckInitializer = ts.hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== ts.SyntaxKind.ForInStatement; - const needCheckWidenedType = !ts.some(node.name.elements, ts.not(ts.isOmittedExpression)); + if (isBindingPattern(node.name)) { + const needCheckInitializer = hasOnlyExpressionInitializer(node) && node.initializer && node.parent.parent.kind !== SyntaxKind.ForInStatement; + const needCheckWidenedType = !some(node.name.elements, not(isOmittedExpression)); if (needCheckInitializer || needCheckWidenedType) { // Don't validate for-in initializer as it is already an error const widenedType = getWidenedTypeForVariableLikeDeclaration(node); @@ -38496,7 +38694,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // check the binding pattern with empty elements if (needCheckWidenedType) { - if (ts.isArrayBindingPattern(node.name)) { + if (isArrayBindingPattern(node.name)) { checkIteratedTypeOrElementType(IterationUse.Destructuring, widenedType, undefinedType, node); } else if (strictNullChecks) { @@ -38508,8 +38706,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // For a commonjs `const x = require`, validate the alias and exit const symbol = getSymbolOfNode(node); - if (symbol.flags & ts.SymbolFlags.Alias && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(node.kind === ts.SyntaxKind.BindingElement ? node.parent.parent : node)) { - checkAliasSymbol(node as ts.BindingElement | ts.VariableDeclaration); + if (symbol.flags & SymbolFlags.Alias && isVariableDeclarationInitializedToBareOrAccessedRequire(node.kind === SyntaxKind.BindingElement ? node.parent.parent : node)) { + checkAliasSymbol(node as BindingElement | VariableDeclaration); return; } @@ -38517,19 +38715,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (node === symbol.valueDeclaration) { // Node is the primary declaration of the symbol, just validate the initializer // Don't validate for-in initializer as it is already an error - const initializer = ts.hasOnlyExpressionInitializer(node) && ts.getEffectiveInitializer(node); + const initializer = hasOnlyExpressionInitializer(node) && getEffectiveInitializer(node); if (initializer) { - const isJSObjectLiteralInitializer = ts.isInJSFile(node) && - ts.isObjectLiteralExpression(initializer) && - (initializer.properties.length === 0 || ts.isPrototypeAccess(node.name)) && + const isJSObjectLiteralInitializer = isInJSFile(node) && + isObjectLiteralExpression(initializer) && + (initializer.properties.length === 0 || isPrototypeAccess(node.name)) && !!symbol.exports?.size; - if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== ts.SyntaxKind.ForInStatement) { + if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) { checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(initializer), type, node, initializer, /*headMessage*/ undefined); } } if (symbol.declarations && symbol.declarations.length > 1) { - if (ts.some(symbol.declarations, d => d !== node && ts.isVariableLike(d) && !areDeclarationFlagsIdentical(d, node))) { - error(node.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); + if (some(symbol.declarations, d => d !== node && isVariableLike(d) && !areDeclarationFlagsIdentical(d, node))) { + error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); } } } @@ -38540,32 +38738,32 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isErrorType(type) && !isErrorType(declarationType) && !isTypeIdenticalTo(type, declarationType) && - !(symbol.flags & ts.SymbolFlags.Assignment)) { + !(symbol.flags & SymbolFlags.Assignment)) { errorNextVariableOrPropertyDeclarationMustHaveSameType(symbol.valueDeclaration, type, node, declarationType); } - if (ts.hasOnlyExpressionInitializer(node) && node.initializer) { + if (hasOnlyExpressionInitializer(node) && node.initializer) { checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(node.initializer), declarationType, node, node.initializer, /*headMessage*/ undefined); } if (symbol.valueDeclaration && !areDeclarationFlagsIdentical(node, symbol.valueDeclaration)) { - error(node.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_modifiers, ts.declarationNameToString(node.name)); + error(node.name, Diagnostics.All_declarations_of_0_must_have_identical_modifiers, declarationNameToString(node.name)); } } - if (node.kind !== ts.SyntaxKind.PropertyDeclaration && node.kind !== ts.SyntaxKind.PropertySignature) { + if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature) { // We know we don't have a binding pattern or computed name here checkExportsOnMergedDeclarations(node); - if (node.kind === ts.SyntaxKind.VariableDeclaration || node.kind === ts.SyntaxKind.BindingElement) { + if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) { checkVarDeclaredNamesNotShadowed(node); } checkCollisionsForDeclarationName(node, node.name); } } - function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstDeclaration: ts.Declaration | undefined, firstType: ts.Type, nextDeclaration: ts.Declaration, nextType: ts.Type): void { - const nextDeclarationName = ts.getNameOfDeclaration(nextDeclaration); - const message = nextDeclaration.kind === ts.SyntaxKind.PropertyDeclaration || nextDeclaration.kind === ts.SyntaxKind.PropertySignature - ? ts.Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 - : ts.Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; - const declName = ts.declarationNameToString(nextDeclarationName); + function errorNextVariableOrPropertyDeclarationMustHaveSameType(firstDeclaration: Declaration | undefined, firstType: Type, nextDeclaration: Declaration, nextType: Type): void { + const nextDeclarationName = getNameOfDeclaration(nextDeclaration); + const message = nextDeclaration.kind === SyntaxKind.PropertyDeclaration || nextDeclaration.kind === SyntaxKind.PropertySignature + ? Diagnostics.Subsequent_property_declarations_must_have_the_same_type_Property_0_must_be_of_type_1_but_here_has_type_2 + : Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2; + const declName = declarationNameToString(nextDeclarationName); const err = error( nextDeclarationName, message, @@ -38574,89 +38772,89 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { typeToString(nextType) ); if (firstDeclaration) { - ts.addRelatedInfo(err, - ts.createDiagnosticForNode(firstDeclaration, ts.Diagnostics._0_was_also_declared_here, declName) + addRelatedInfo(err, + createDiagnosticForNode(firstDeclaration, Diagnostics._0_was_also_declared_here, declName) ); } } - function areDeclarationFlagsIdentical(left: ts.Declaration, right: ts.Declaration) { - if ((left.kind === ts.SyntaxKind.Parameter && right.kind === ts.SyntaxKind.VariableDeclaration) || - (left.kind === ts.SyntaxKind.VariableDeclaration && right.kind === ts.SyntaxKind.Parameter)) { + function areDeclarationFlagsIdentical(left: Declaration, right: Declaration) { + if ((left.kind === SyntaxKind.Parameter && right.kind === SyntaxKind.VariableDeclaration) || + (left.kind === SyntaxKind.VariableDeclaration && right.kind === SyntaxKind.Parameter)) { // Differences in optionality between parameters and variables are allowed. return true; } - if (ts.hasQuestionToken(left) !== ts.hasQuestionToken(right)) { + if (hasQuestionToken(left) !== hasQuestionToken(right)) { return false; } - const interestingFlags = ts.ModifierFlags.Private | - ts.ModifierFlags.Protected | - ts.ModifierFlags.Async | - ts.ModifierFlags.Abstract | - ts.ModifierFlags.Readonly | - ts.ModifierFlags.Static; + const interestingFlags = ModifierFlags.Private | + ModifierFlags.Protected | + ModifierFlags.Async | + ModifierFlags.Abstract | + ModifierFlags.Readonly | + ModifierFlags.Static; - return ts.getSelectedEffectiveModifierFlags(left, interestingFlags) === ts.getSelectedEffectiveModifierFlags(right, interestingFlags); + return getSelectedEffectiveModifierFlags(left, interestingFlags) === getSelectedEffectiveModifierFlags(right, interestingFlags); } - function checkVariableDeclaration(node: ts.VariableDeclaration) { - ts.tracing?.push(ts.tracing.Phase.Check, "checkVariableDeclaration", { kind: node.kind, pos: node.pos, end: node.end, path: (node as ts.TracingNode).tracingPath }); + function checkVariableDeclaration(node: VariableDeclaration) { + tracing?.push(tracing.Phase.Check, "checkVariableDeclaration", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); checkGrammarVariableDeclaration(node); checkVariableLikeDeclaration(node); - ts.tracing?.pop(); + tracing?.pop(); } - function checkBindingElement(node: ts.BindingElement) { + function checkBindingElement(node: BindingElement) { checkGrammarBindingElement(node); return checkVariableLikeDeclaration(node); } - function checkVariableStatement(node: ts.VariableStatement) { + function checkVariableStatement(node: VariableStatement) { // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node) && !checkGrammarVariableDeclarationList(node.declarationList)) checkGrammarForDisallowedLetOrConstStatement(node); - ts.forEach(node.declarationList.declarations, checkSourceElement); + forEach(node.declarationList.declarations, checkSourceElement); } - function checkExpressionStatement(node: ts.ExpressionStatement) { + function checkExpressionStatement(node: ExpressionStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); checkExpression(node.expression); } - function checkIfStatement(node: ts.IfStatement) { + function checkIfStatement(node: IfStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); const type = checkTruthinessExpression(node.expression); checkTestingKnownTruthyCallableOrAwaitableType(node.expression, type, node.thenStatement); checkSourceElement(node.thenStatement); - if (node.thenStatement.kind === ts.SyntaxKind.EmptyStatement) { - error(node.thenStatement, ts.Diagnostics.The_body_of_an_if_statement_cannot_be_the_empty_statement); + if (node.thenStatement.kind === SyntaxKind.EmptyStatement) { + error(node.thenStatement, Diagnostics.The_body_of_an_if_statement_cannot_be_the_empty_statement); } checkSourceElement(node.elseStatement); } - function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: ts.Expression, condType: ts.Type, body?: ts.Statement | ts.Expression) { + function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, condType: Type, body?: Statement | Expression) { if (!strictNullChecks) return; helper(condExpr, body); - while (ts.isBinaryExpression(condExpr) && condExpr.operatorToken.kind === ts.SyntaxKind.BarBarToken) { + while (isBinaryExpression(condExpr) && condExpr.operatorToken.kind === SyntaxKind.BarBarToken) { condExpr = condExpr.left; helper(condExpr, body); } - function helper(condExpr: ts.Expression, body: ts.Expression | ts.Statement | undefined) { - const location = ts.isBinaryExpression(condExpr) && - (condExpr.operatorToken.kind === ts.SyntaxKind.BarBarToken || condExpr.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) + function helper(condExpr: Expression, body: Expression | Statement | undefined) { + const location = isBinaryExpression(condExpr) && + (condExpr.operatorToken.kind === SyntaxKind.BarBarToken || condExpr.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) ? condExpr.right : condExpr; - if (ts.isModuleExportsAccessExpression(location)) return; + if (isModuleExportsAccessExpression(location)) return; const type = location === condExpr ? condType : checkTruthinessExpression(location); - const isPropertyExpressionCast = ts.isPropertyAccessExpression(location) && isTypeAssertion(location.expression); + const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression); if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return; // While it technically should be invalid for any known-truthy value @@ -38664,63 +38862,63 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // the block as a heuristic to identify the most common bugs. There // are too many false positives for values sourced from type // definitions without strictNullChecks otherwise. - const callSignatures = getSignaturesOfType(type, ts.SignatureKind.Call); + const callSignatures = getSignaturesOfType(type, SignatureKind.Call); const isPromise = !!getAwaitedTypeOfPromise(type); if (callSignatures.length === 0 && !isPromise) { return; } - const testedNode = ts.isIdentifier(location) ? location - : ts.isPropertyAccessExpression(location) ? location.name - : ts.isBinaryExpression(location) && ts.isIdentifier(location.right) ? location.right + const testedNode = isIdentifier(location) ? location + : isPropertyAccessExpression(location) ? location.name + : isBinaryExpression(location) && isIdentifier(location.right) ? location.right : undefined; const testedSymbol = testedNode && getSymbolAtLocation(testedNode); if (!testedSymbol && !isPromise) { return; } - const isUsed = testedSymbol && ts.isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) + const isUsed = testedSymbol && isBinaryExpression(condExpr.parent) && isSymbolUsedInBinaryExpressionChain(condExpr.parent, testedSymbol) || testedSymbol && body && isSymbolUsedInConditionBody(condExpr, body, testedNode, testedSymbol); if (!isUsed) { if (isPromise) { errorAndMaybeSuggestAwait( location, /*maybeMissingAwait*/ true, - ts.Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined, + Diagnostics.This_condition_will_always_return_true_since_this_0_is_always_defined, getTypeNameForErrorDisplay(type)); } else { - error(location, ts.Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead); + error(location, Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead); } } } } - function isSymbolUsedInConditionBody(expr: ts.Expression, body: ts.Statement | ts.Expression, testedNode: ts.Node, testedSymbol: ts.Symbol): boolean { - return !!ts.forEachChild(body, function check(childNode): boolean | undefined { - if (ts.isIdentifier(childNode)) { + function isSymbolUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean { + return !!forEachChild(body, function check(childNode): boolean | undefined { + if (isIdentifier(childNode)) { const childSymbol = getSymbolAtLocation(childNode); if (childSymbol && childSymbol === testedSymbol) { // If the test was a simple identifier, the above check is sufficient - if (ts.isIdentifier(expr) || ts.isIdentifier(testedNode) && ts.isBinaryExpression(testedNode.parent)) { + if (isIdentifier(expr) || isIdentifier(testedNode) && isBinaryExpression(testedNode.parent)) { return true; } // Otherwise we need to ensure the symbol is called on the same target let testedExpression = testedNode.parent; let childExpression = childNode.parent; while (testedExpression && childExpression) { - if (ts.isIdentifier(testedExpression) && ts.isIdentifier(childExpression) || - testedExpression.kind === ts.SyntaxKind.ThisKeyword && childExpression.kind === ts.SyntaxKind.ThisKeyword) { + if (isIdentifier(testedExpression) && isIdentifier(childExpression) || + testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword) { return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression); } - else if (ts.isPropertyAccessExpression(testedExpression) && ts.isPropertyAccessExpression(childExpression)) { + else if (isPropertyAccessExpression(testedExpression) && isPropertyAccessExpression(childExpression)) { if (getSymbolAtLocation(testedExpression.name) !== getSymbolAtLocation(childExpression.name)) { return false; } childExpression = childExpression.expression; testedExpression = testedExpression.expression; } - else if (ts.isCallExpression(testedExpression) && ts.isCallExpression(childExpression)) { + else if (isCallExpression(testedExpression) && isCallExpression(childExpression)) { childExpression = childExpression.expression; testedExpression = testedExpression.expression; } @@ -38730,20 +38928,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - return ts.forEachChild(childNode, check); + return forEachChild(childNode, check); }); } - function isSymbolUsedInBinaryExpressionChain(node: ts.Node, testedSymbol: ts.Symbol): boolean { - while (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) { - const isUsed = ts.forEachChild(node.right, function visit(child): boolean | undefined { - if (ts.isIdentifier(child)) { + function isSymbolUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean { + while (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + const isUsed = forEachChild(node.right, function visit(child): boolean | undefined { + if (isIdentifier(child)) { const symbol = getSymbolAtLocation(child); if (symbol && symbol === testedSymbol) { return true; } } - return ts.forEachChild(child, visit); + return forEachChild(child, visit); }); if (isUsed) { return true; @@ -38753,7 +38951,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkDoStatement(node: ts.DoStatement) { + function checkDoStatement(node: DoStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); @@ -38761,7 +38959,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkTruthinessExpression(node.expression); } - function checkWhileStatement(node: ts.WhileStatement) { + function checkWhileStatement(node: WhileStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); @@ -38769,28 +38967,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkSourceElement(node.statement); } - function checkTruthinessOfType(type: ts.Type, node: ts.Node) { - if (type.flags & ts.TypeFlags.Void) { - error(node, ts.Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness); + function checkTruthinessOfType(type: Type, node: Node) { + if (type.flags & TypeFlags.Void) { + error(node, Diagnostics.An_expression_of_type_void_cannot_be_tested_for_truthiness); } return type; } - function checkTruthinessExpression(node: ts.Expression, checkMode?: CheckMode) { + function checkTruthinessExpression(node: Expression, checkMode?: CheckMode) { return checkTruthinessOfType(checkExpression(node, checkMode), node); } - function checkForStatement(node: ts.ForStatement) { + function checkForStatement(node: ForStatement) { // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { - if (node.initializer && node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { - checkGrammarVariableDeclarationList(node.initializer as ts.VariableDeclarationList); + if (node.initializer && node.initializer.kind === SyntaxKind.VariableDeclarationList) { + checkGrammarVariableDeclarationList(node.initializer as VariableDeclarationList); } } if (node.initializer) { - if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { - ts.forEach((node.initializer as ts.VariableDeclarationList).declarations, checkVariableDeclaration); + if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { + forEach((node.initializer as VariableDeclarationList).declarations, checkVariableDeclaration); } else { checkExpression(node.initializer); @@ -38805,25 +39003,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkForOfStatement(node: ts.ForOfStatement): void { + function checkForOfStatement(node: ForOfStatement): void { checkGrammarForInOrForOfStatement(node); - const container = ts.getContainingFunctionOrClassStaticBlock(node); + const container = getContainingFunctionOrClassStaticBlock(node); if (node.awaitModifier) { - if (container && ts.isClassStaticBlockDeclaration(container)) { - grammarErrorOnNode(node.awaitModifier, ts.Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block); + if (container && isClassStaticBlockDeclaration(container)) { + grammarErrorOnNode(node.awaitModifier, Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block); } else { - const functionFlags = ts.getFunctionFlags(container); - if ((functionFlags & (ts.FunctionFlags.Invalid | ts.FunctionFlags.Async)) === ts.FunctionFlags.Async && languageVersion < ts.ScriptTarget.ESNext) { + const functionFlags = getFunctionFlags(container); + if ((functionFlags & (FunctionFlags.Invalid | FunctionFlags.Async)) === FunctionFlags.Async && languageVersion < ScriptTarget.ESNext) { // for..await..of in an async function or async generator function prior to ESNext requires the __asyncValues helper - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ForAwaitOfIncludes); + checkExternalEmitHelpers(node, ExternalEmitHelpers.ForAwaitOfIncludes); } } } - else if (compilerOptions.downlevelIteration && languageVersion < ts.ScriptTarget.ES2015) { + else if (compilerOptions.downlevelIteration && languageVersion < ScriptTarget.ES2015) { // for..of prior to ES2015 requires the __values helper when downlevelIteration is enabled - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ForOfIncludes); + checkExternalEmitHelpers(node, ExternalEmitHelpers.ForOfIncludes); } // Check the LHS and RHS @@ -38831,7 +39029,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // via checkRightHandSideOfForOf. // If the LHS is an expression, check the LHS, as a destructuring assignment or as a reference. // Then check that the RHS is assignable to it. - if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { + if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { checkForInOrForOfVariableDeclaration(node); } else { @@ -38839,7 +39037,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const iteratedType = checkRightHandSideOfForOf(node); // There may be a destructuring assignment on the left side - if (varExpr.kind === ts.SyntaxKind.ArrayLiteralExpression || varExpr.kind === ts.SyntaxKind.ObjectLiteralExpression) { + if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { // iteratedType may be undefined. In this case, we still want to check the structure of // varExpr, in particular making sure it's a valid LeftHandSideExpression. But we'd like // to short circuit the type relation checking as much as possible, so we pass the unknownType. @@ -38849,8 +39047,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const leftType = checkExpression(varExpr); checkReferenceExpression( varExpr, - ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access, - ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_an_optional_property_access); + Diagnostics.The_left_hand_side_of_a_for_of_statement_must_be_a_variable_or_a_property_access, + Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_an_optional_property_access); // iteratedType will be undefined if the rightType was missing properties/signatures // required to get its iteratedType (like [Symbol.iterator] or next). This may be @@ -38868,7 +39066,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkForInStatement(node: ts.ForInStatement) { + function checkForInStatement(node: ForInStatement) { // Grammar checking checkGrammarForInOrForOfStatement(node); @@ -38878,10 +39076,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // for (let VarDecl in Expr) Statement // VarDecl must be a variable declaration without a type annotation that declares a variable of type Any, // and Expr must be an expression of type Any, an object type, or a type parameter type. - if (node.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { - const variable = (node.initializer as ts.VariableDeclarationList).declarations[0]; - if (variable && ts.isBindingPattern(variable.name)) { - error(variable.name, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + if (node.initializer.kind === SyntaxKind.VariableDeclarationList) { + const variable = (node.initializer as VariableDeclarationList).declarations[0]; + if (variable && isBindingPattern(variable.name)) { + error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); } checkForInOrForOfVariableDeclaration(node); } @@ -38892,25 +39090,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // and Expr must be an expression of type Any, an object type, or a type parameter type. const varExpr = node.initializer; const leftType = checkExpression(varExpr); - if (varExpr.kind === ts.SyntaxKind.ArrayLiteralExpression || varExpr.kind === ts.SyntaxKind.ObjectLiteralExpression) { - error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); + if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) { + error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern); } else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) { - error(varExpr, ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); + error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any); } else { // run check only former check succeeded to avoid cascading errors checkReferenceExpression( varExpr, - ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_a_variable_or_a_property_access, - ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_may_not_be_an_optional_property_access); + Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_a_variable_or_a_property_access, + Diagnostics.The_left_hand_side_of_a_for_in_statement_may_not_be_an_optional_property_access); } } // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (rightType === neverType || !isTypeAssignableToKind(rightType, ts.TypeFlags.NonPrimitive | ts.TypeFlags.InstantiableNonPrimitive)) { - error(node.expression, ts.Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType)); + if (rightType === neverType || !isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) { + error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType)); } checkSourceElement(node.statement); @@ -38919,8 +39117,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkForInOrForOfVariableDeclaration(iterationStatement: ts.ForInOrOfStatement): void { - const variableDeclarationList = iterationStatement.initializer as ts.VariableDeclarationList; + function checkForInOrForOfVariableDeclaration(iterationStatement: ForInOrOfStatement): void { + const variableDeclarationList = iterationStatement.initializer as VariableDeclarationList; // checkGrammarForInOrForOfStatement will check that there is exactly one declaration. if (variableDeclarationList.declarations.length >= 1) { const decl = variableDeclarationList.declarations[0]; @@ -38928,12 +39126,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkRightHandSideOfForOf(statement: ts.ForOfStatement): ts.Type { + function checkRightHandSideOfForOf(statement: ForOfStatement): Type { const use = statement.awaitModifier ? IterationUse.ForAwaitOf : IterationUse.ForOf; return checkIteratedTypeOrElementType(use, checkNonNullExpression(statement.expression), undefinedType, statement.expression); } - function checkIteratedTypeOrElementType(use: IterationUse, inputType: ts.Type, sentType: ts.Type, errorNode: ts.Node | undefined): ts.Type { + function checkIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined): Type { if (isTypeAny(inputType)) { return inputType; } @@ -38945,14 +39143,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * we want to get the iterated type of an iterable for ES2015 or later, or the iterated type * of a iterable (if defined globally) or element type of an array like for ES2015 or earlier. */ - function getIteratedTypeOrElementType(use: IterationUse, inputType: ts.Type, sentType: ts.Type, errorNode: ts.Node | undefined, checkAssignability: boolean): ts.Type | undefined { + function getIteratedTypeOrElementType(use: IterationUse, inputType: Type, sentType: Type, errorNode: Node | undefined, checkAssignability: boolean): Type | undefined { const allowAsyncIterables = (use & IterationUse.AllowsAsyncIterablesFlag) !== 0; if (inputType === neverType) { reportTypeNotIterableError(errorNode!, inputType, allowAsyncIterables); // TODO: GH#18217 return undefined; } - const uplevelIteration = languageVersion >= ts.ScriptTarget.ES2015; + const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; const possibleOutOfBounds = compilerOptions.noUncheckedIndexedAccess && !!(use & IterationUse.PossiblyOutOfBounds); @@ -38965,10 +39163,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (checkAssignability) { if (iterationTypes) { const diagnostic = - use & IterationUse.ForOfFlag ? ts.Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_for_of_will_always_send_0 : - use & IterationUse.SpreadFlag ? ts.Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_spread_will_always_send_0 : - use & IterationUse.DestructuringFlag ? ts.Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_destructuring_will_always_send_0 : - use & IterationUse.YieldStarFlag ? ts.Diagnostics.Cannot_delegate_iteration_to_value_because_the_next_method_of_its_iterator_expects_type_1_but_the_containing_generator_will_always_send_0 : + use & IterationUse.ForOfFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_for_of_will_always_send_0 : + use & IterationUse.SpreadFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_spread_will_always_send_0 : + use & IterationUse.DestructuringFlag ? Diagnostics.Cannot_iterate_value_because_the_next_method_of_its_iterator_expects_type_1_but_array_destructuring_will_always_send_0 : + use & IterationUse.YieldStarFlag ? Diagnostics.Cannot_delegate_iteration_to_value_because_the_next_method_of_its_iterator_expects_type_1_but_the_containing_generator_will_always_send_0 : undefined; if (diagnostic) { checkTypeAssignableTo(sentType, iterationTypes.nextType, errorNode, diagnostic); @@ -38988,31 +39186,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // This allows us to find other non-string element types from an array unioned with // a string. if (use & IterationUse.AllowsStringInputFlag) { - if (arrayType.flags & ts.TypeFlags.Union) { + if (arrayType.flags & TypeFlags.Union) { // After we remove all types that are StringLike, we will know if there was a string constituent // based on whether the result of filter is a new array. - const arrayTypes = (inputType as ts.UnionType).types; - const filteredTypes = ts.filter(arrayTypes, t => !(t.flags & ts.TypeFlags.StringLike)); + const arrayTypes = (inputType as UnionType).types; + const filteredTypes = filter(arrayTypes, t => !(t.flags & TypeFlags.StringLike)); if (filteredTypes !== arrayTypes) { - arrayType = getUnionType(filteredTypes, ts.UnionReduction.Subtype); + arrayType = getUnionType(filteredTypes, UnionReduction.Subtype); } } - else if (arrayType.flags & ts.TypeFlags.StringLike) { + else if (arrayType.flags & TypeFlags.StringLike) { arrayType = neverType; } hasStringConstituent = arrayType !== inputType; if (hasStringConstituent) { - if (languageVersion < ts.ScriptTarget.ES5) { + if (languageVersion < ScriptTarget.ES5) { if (errorNode) { - error(errorNode, ts.Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); + error(errorNode, Diagnostics.Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher); reportedError = true; } } // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. - if (arrayType.flags & ts.TypeFlags.Never) { + if (arrayType.flags & TypeFlags.Never) { return possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType; } } @@ -39039,39 +39237,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const arrayElementType = getIndexTypeOfType(arrayType, numberType); if (hasStringConstituent && arrayElementType) { // This is just an optimization for the case where arrayOrStringType is string | string[] - if (arrayElementType.flags & ts.TypeFlags.StringLike && !compilerOptions.noUncheckedIndexedAccess) { + if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.noUncheckedIndexedAccess) { return stringType; } - return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], ts.UnionReduction.Subtype); + return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype); } return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType; - function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [error: ts.DiagnosticMessage, maybeMissingAwait: boolean] { + function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [error: DiagnosticMessage, maybeMissingAwait: boolean] { if (downlevelIteration) { return allowsStrings - ? [ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true] - : [ts.Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]; + ? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true] + : [Diagnostics.Type_0_is_not_an_array_type_or_does_not_have_a_Symbol_iterator_method_that_returns_an_iterator, true]; } const yieldType = getIterationTypeOfIterable(use, IterationTypeKind.Yield, inputType, /*errorNode*/ undefined); if (yieldType) { - return [ts.Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false]; + return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false]; } if (isES2015OrLaterIterable(inputType.symbol?.escapedName)) { - return [ts.Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true]; + return [Diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true]; } return allowsStrings - ? [ts.Diagnostics.Type_0_is_not_an_array_type_or_a_string_type, true] - : [ts.Diagnostics.Type_0_is_not_an_array_type, true]; + ? [Diagnostics.Type_0_is_not_an_array_type_or_a_string_type, true] + : [Diagnostics.Type_0_is_not_an_array_type, true]; } } - function isES2015OrLaterIterable(n: ts.__String) { + function isES2015OrLaterIterable(n: __String) { switch (n) { case "Float32Array": case "Float64Array": @@ -39091,7 +39289,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Gets the requested "iteration type" from an `Iterable`-like or `AsyncIterable`-like type. */ - function getIterationTypeOfIterable(use: IterationUse, typeKind: IterationTypeKind, inputType: ts.Type, errorNode: ts.Node | undefined): ts.Type | undefined { + function getIterationTypeOfIterable(use: IterationUse, typeKind: IterationTypeKind, inputType: Type, errorNode: Node | undefined): Type | undefined { if (isTypeAny(inputType)) { return undefined; } @@ -39100,7 +39298,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return iterationTypes && iterationTypes[getIterationTypesKeyFromIterationTypeKind(typeKind)]; } - function createIterationTypes(yieldType: ts.Type = neverType, returnType: ts.Type = neverType, nextType: ts.Type = unknownType): ts.IterationTypes { + function createIterationTypes(yieldType: Type = neverType, returnType: Type = neverType, nextType: Type = unknownType): IterationTypes { // `yieldType` and `returnType` are defaulted to `neverType` they each will be combined // via `getUnionType` when merging iteration types. `nextType` is defined as `unknownType` // as it is combined via `getIntersectionType` when merging iteration types. @@ -39109,9 +39307,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // more frequently created (i.e. `Iterator`). Iteration types // are also cached on the type they are requested for, so we shouldn't need to maintain // the cache for less-frequently used types. - if (yieldType.flags & ts.TypeFlags.Intrinsic && - returnType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never | ts.TypeFlags.Unknown | ts.TypeFlags.Void | ts.TypeFlags.Undefined) && - nextType.flags & (ts.TypeFlags.Any | ts.TypeFlags.Never | ts.TypeFlags.Unknown | ts.TypeFlags.Void | ts.TypeFlags.Undefined)) { + if (yieldType.flags & TypeFlags.Intrinsic && + returnType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined) && + nextType.flags & (TypeFlags.Any | TypeFlags.Never | TypeFlags.Unknown | TypeFlags.Void | TypeFlags.Undefined)) { const id = getTypeListId([yieldType, returnType, nextType]); let iterationTypes = iterationTypesCache.get(id); if (!iterationTypes) { @@ -39130,10 +39328,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * then `noIterationTypes` is returned. Otherwise, an `IterationTypes` record is returned * for the combined iteration types. */ - function combineIterationTypes(array: (ts.IterationTypes | undefined)[]) { - let yieldTypes: ts.Type[] | undefined; - let returnTypes: ts.Type[] | undefined; - let nextTypes: ts.Type[] | undefined; + function combineIterationTypes(array: (IterationTypes | undefined)[]) { + let yieldTypes: Type[] | undefined; + let returnTypes: Type[] | undefined; + let nextTypes: Type[] | undefined; for (const iterationTypes of array) { if (iterationTypes === undefined || iterationTypes === noIterationTypes) { continue; @@ -39141,9 +39339,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (iterationTypes === anyIterationTypes) { return anyIterationTypes; } - yieldTypes = ts.append(yieldTypes, iterationTypes.yieldType); - returnTypes = ts.append(returnTypes, iterationTypes.returnType); - nextTypes = ts.append(nextTypes, iterationTypes.nextType); + yieldTypes = append(yieldTypes, iterationTypes.yieldType); + returnTypes = append(returnTypes, iterationTypes.returnType); + nextTypes = append(nextTypes, iterationTypes.nextType); } if (yieldTypes || returnTypes || nextTypes) { return createIterationTypes( @@ -39154,12 +39352,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return noIterationTypes; } - function getCachedIterationTypes(type: ts.Type, cacheKey: ts.MatchingKeys) { - return (type as ts.IterableOrIteratorType)[cacheKey]; + function getCachedIterationTypes(type: Type, cacheKey: MatchingKeys) { + return (type as IterableOrIteratorType)[cacheKey]; } - function setCachedIterationTypes(type: ts.Type, cacheKey: ts.MatchingKeys, cachedTypes: ts.IterationTypes) { - return (type as ts.IterableOrIteratorType)[cacheKey] = cachedTypes; + function setCachedIterationTypes(type: Type, cacheKey: MatchingKeys, cachedTypes: IterationTypes) { + return (type as IterableOrIteratorType)[cacheKey] = cachedTypes; } /** @@ -39183,19 +39381,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * For a **for-await-of** statement or a `yield*` in an async generator we will look for * the `[Symbol.asyncIterator]()` method first, and then the `[Symbol.iterator]()` method. */ - function getIterationTypesOfIterable(type: ts.Type, use: IterationUse, errorNode: ts.Node | undefined) { + function getIterationTypesOfIterable(type: Type, use: IterationUse, errorNode: Node | undefined) { if (isTypeAny(type)) { return anyIterationTypes; } - if (!(type.flags & ts.TypeFlags.Union)) { - const errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined; + if (!(type.flags & TypeFlags.Union)) { + const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined; const iterationTypes = getIterationTypesOfIterableWorker(type, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); if (errorOutputContainer?.errors) { - ts.addRelatedInfo(rootDiag, ...errorOutputContainer.errors); + addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } } return undefined; @@ -39212,15 +39410,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const cachedTypes = getCachedIterationTypes(type, cacheKey); if (cachedTypes) return cachedTypes === noIterationTypes ? undefined : cachedTypes; - let allIterationTypes: ts.IterationTypes[] | undefined; - for (const constituent of (type as ts.UnionType).types) { - const errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined; + let allIterationTypes: IterationTypes[] | undefined; + for (const constituent of (type as UnionType).types) { + const errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined = errorNode ? { errors: undefined } : undefined; const iterationTypes = getIterationTypesOfIterableWorker(constituent, use, errorNode, errorOutputContainer); if (iterationTypes === noIterationTypes) { if (errorNode) { const rootDiag = reportTypeNotIterableError(errorNode, type, !!(use & IterationUse.AllowsAsyncIterablesFlag)); if (errorOutputContainer?.errors) { - ts.addRelatedInfo(rootDiag, ...errorOutputContainer.errors); + addRelatedInfo(rootDiag, ...errorOutputContainer.errors); } } setCachedIterationTypes(type, cacheKey, noIterationTypes); @@ -39232,7 +39430,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - allIterationTypes = ts.append(allIterationTypes, iterationTypes); + allIterationTypes = append(allIterationTypes, iterationTypes); } const iterationTypes = allIterationTypes ? combineIterationTypes(allIterationTypes) : noIterationTypes; @@ -39240,7 +39438,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return iterationTypes === noIterationTypes ? undefined : iterationTypes; } - function getAsyncFromSyncIterationTypes(iterationTypes: ts.IterationTypes, errorNode: ts.Node | undefined) { + function getAsyncFromSyncIterationTypes(iterationTypes: IterationTypes, errorNode: Node | undefined) { if (iterationTypes === noIterationTypes) return noIterationTypes; if (iterationTypes === anyIterationTypes) return anyIterationTypes; const { yieldType, returnType, nextType } = iterationTypes; @@ -39264,7 +39462,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableWorker(type: ts.Type, use: IterationUse, errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined) { + function getIterationTypesOfIterableWorker(type: Type, use: IterationUse, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -39344,11 +39542,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableCached(type: ts.Type, resolver: IterationTypesResolver) { + function getIterationTypesOfIterableCached(type: Type, resolver: IterationTypesResolver) { return getCachedIterationTypes(type, resolver.iterableCacheKey); } - function getIterationTypesOfGlobalIterableType(globalType: ts.Type, resolver: IterationTypesResolver) { + function getIterationTypesOfGlobalIterableType(globalType: Type, resolver: IterationTypesResolver) { const globalIterationTypes = getIterationTypesOfIterableCached(globalType, resolver) || getIterationTypesOfIterableSlow(globalType, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined, /*noCache*/ false); @@ -39367,15 +39565,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableFast(type: ts.Type, resolver: IterationTypesResolver) { + function getIterationTypesOfIterableFast(type: Type, resolver: IterationTypesResolver) { // As an optimization, if the type is an instantiation of one of the following global types, then // just grab its related type argument: // - `Iterable` or `AsyncIterable` // - `IterableIterator` or `AsyncIterableIterator` - let globalType: ts.Type; + let globalType: Type; if (isReferenceToType(type, globalType = resolver.getGlobalIterableType(/*reportErrors*/ false)) || isReferenceToType(type, globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false))) { - const [yieldType] = getTypeArguments(type as ts.GenericType); + const [yieldType] = getTypeArguments(type as GenericType); // The "return" and "next" types of `Iterable` and `IterableIterator` are defined by the // iteration types of their `[Symbol.iterator]()` method. The same is true for their async cousins. // While we define these as `any` and `undefined` in our libs by default, a custom lib *could* use @@ -39388,15 +39586,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // just grab its related type arguments: // - `Generator` or `AsyncGenerator` if (isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) { - const [yieldType, returnType, nextType] = getTypeArguments(type as ts.GenericType); + const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType); return setCachedIterationTypes(type, resolver.iterableCacheKey, createIterationTypes(resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || yieldType, resolver.resolveIterationType(returnType, /*errorNode*/ undefined) || returnType, nextType)); } } - function getPropertyNameForKnownSymbolName(symbolName: string): ts.__String { + function getPropertyNameForKnownSymbolName(symbolName: string): __String { const ctorType = getGlobalESSymbolConstructorSymbol(/*reportErrors*/ false); - const uniqueType = ctorType && getTypeOfPropertyOfType(getTypeOfSymbol(ctorType), ts.escapeLeadingUnderscores(symbolName)); - return uniqueType && isTypeUsableAsPropertyName(uniqueType) ? getPropertyNameFromType(uniqueType) : `__@${symbolName}` as ts.__String; + const uniqueType = ctorType && getTypeOfPropertyOfType(getTypeOfSymbol(ctorType), escapeLeadingUnderscores(symbolName)); + return uniqueType && isTypeUsableAsPropertyName(uniqueType) ? getPropertyNameFromType(uniqueType) : `__@${symbolName}` as __String; } /** @@ -39409,34 +39607,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterable` instead. */ - function getIterationTypesOfIterableSlow(type: ts.Type, resolver: IterationTypesResolver, errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined, noCache: boolean) { + function getIterationTypesOfIterableSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) { const method = getPropertyOfType(type, getPropertyNameForKnownSymbolName(resolver.iteratorSymbolName)); - const methodType = method && !(method.flags & ts.SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined; + const methodType = method && !(method.flags & SymbolFlags.Optional) ? getTypeOfSymbol(method) : undefined; if (isTypeAny(methodType)) { return noCache ? anyIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, anyIterationTypes); } - const signatures = methodType ? getSignaturesOfType(methodType, ts.SignatureKind.Call) : undefined; - if (!ts.some(signatures)) { + const signatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : undefined; + if (!some(signatures)) { return noCache ? noIterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, noIterationTypes); } - const iteratorType = getIntersectionType(ts.map(signatures, getReturnTypeOfSignature)); + const iteratorType = getIntersectionType(map(signatures, getReturnTypeOfSignature)); const iterationTypes = getIterationTypesOfIteratorWorker(iteratorType, resolver, errorNode, errorOutputContainer, noCache) ?? noIterationTypes; return noCache ? iterationTypes : setCachedIterationTypes(type, resolver.iterableCacheKey, iterationTypes); } - function reportTypeNotIterableError(errorNode: ts.Node, type: ts.Type, allowAsyncIterables: boolean): ts.Diagnostic { + function reportTypeNotIterableError(errorNode: Node, type: Type, allowAsyncIterables: boolean): Diagnostic { const message = allowAsyncIterables - ? ts.Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator - : ts.Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator; + ? Diagnostics.Type_0_must_have_a_Symbol_asyncIterator_method_that_returns_an_async_iterator + : Diagnostics.Type_0_must_have_a_Symbol_iterator_method_that_returns_an_iterator; const suggestAwait = // for (const x of Promise<...>) or [...Promise<...>] !!getAwaitedTypeOfPromise(type) // for (const x of AsyncIterable<...>) || ( !allowAsyncIterables && - ts.isForOfStatement(errorNode.parent) && + isForOfStatement(errorNode.parent) && errorNode.parent.expression === errorNode && getGlobalAsyncIterableType(/** reportErrors */ false) !== emptyGenericType && isTypeAssignableTo(type, getGlobalAsyncIterableType(/** reportErrors */ false) @@ -39450,7 +39648,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes` * record is returned. Otherwise, `undefined` is returned. */ - function getIterationTypesOfIterator(type: ts.Type, resolver: IterationTypesResolver, errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined) { + function getIterationTypesOfIterator(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined) { return getIterationTypesOfIteratorWorker(type, resolver, errorNode, errorOutputContainer, /*noCache*/ false); } @@ -39463,7 +39661,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorWorker(type: ts.Type, resolver: IterationTypesResolver, errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined, noCache: boolean) { + function getIterationTypesOfIteratorWorker(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -39488,7 +39686,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorCached(type: ts.Type, resolver: IterationTypesResolver) { + function getIterationTypesOfIteratorCached(type: Type, resolver: IterationTypesResolver) { return getCachedIterationTypes(type, resolver.iteratorCacheKey); } @@ -39504,7 +39702,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorFast(type: ts.Type, resolver: IterationTypesResolver) { + function getIterationTypesOfIteratorFast(type: Type, resolver: IterationTypesResolver) { // As an optimization, if the type is an instantiation of one of the following global types, // then just grab its related type argument: // - `IterableIterator` or `AsyncIterableIterator` @@ -39512,7 +39710,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // - `Generator` or `AsyncGenerator` const globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false); if (isReferenceToType(type, globalType)) { - const [yieldType] = getTypeArguments(type as ts.GenericType); + const [yieldType] = getTypeArguments(type as GenericType); // The "return" and "next" types of `IterableIterator` and `AsyncIterableIterator` are defined by the // iteration types of their `next`, `return`, and `throw` methods. While we define these as `any` // and `undefined` in our libs by default, a custom lib *could* use different definitions. @@ -39524,25 +39722,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (isReferenceToType(type, resolver.getGlobalIteratorType(/*reportErrors*/ false)) || isReferenceToType(type, resolver.getGlobalGeneratorType(/*reportErrors*/ false))) { - const [yieldType, returnType, nextType] = getTypeArguments(type as ts.GenericType); + const [yieldType, returnType, nextType] = getTypeArguments(type as GenericType); return setCachedIterationTypes(type, resolver.iteratorCacheKey, createIterationTypes(yieldType, returnType, nextType)); } } - function isIteratorResult(type: ts.Type, kind: IterationTypeKind.Yield | IterationTypeKind.Return) { + function isIteratorResult(type: Type, kind: IterationTypeKind.Yield | IterationTypeKind.Return) { // From https://tc39.github.io/ecma262/#sec-iteratorresult-interface: // > [done] is the result status of an iterator `next` method call. If the end of the iterator was reached `done` is `true`. // > If the end was not reached `done` is `false` and a value is available. // > If a `done` property (either own or inherited) does not exist, it is consider to have the value `false`. - const doneType = getTypeOfPropertyOfType(type, "done" as ts.__String) || falseType; + const doneType = getTypeOfPropertyOfType(type, "done" as __String) || falseType; return isTypeAssignableTo(kind === IterationTypeKind.Yield ? falseType : trueType, doneType); } - function isYieldIteratorResult(type: ts.Type) { + function isYieldIteratorResult(type: Type) { return isIteratorResult(type, IterationTypeKind.Yield); } - function isReturnIteratorResult(type: ts.Type) { + function isReturnIteratorResult(type: Type) { return isIteratorResult(type, IterationTypeKind.Return); } @@ -39553,7 +39751,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * returned to indicate to the caller that it should handle the error. Otherwise, an * `IterationTypes` record is returned. */ - function getIterationTypesOfIteratorResult(type: ts.Type) { + function getIterationTypesOfIteratorResult(type: Type) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -39566,20 +39764,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // As an optimization, if the type is an instantiation of one of the global `IteratorYieldResult` // or `IteratorReturnResult` types, then just grab its type argument. if (isReferenceToType(type, getGlobalIteratorYieldResultType(/*reportErrors*/ false))) { - const yieldType = getTypeArguments(type as ts.GenericType)[0]; + const yieldType = getTypeArguments(type as GenericType)[0]; return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(yieldType, /*returnType*/ undefined, /*nextType*/ undefined)); } if (isReferenceToType(type, getGlobalIteratorReturnResultType(/*reportErrors*/ false))) { - const returnType = getTypeArguments(type as ts.GenericType)[0]; + const returnType = getTypeArguments(type as GenericType)[0]; return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", createIterationTypes(/*yieldType*/ undefined, returnType, /*nextType*/ undefined)); } // Choose any constituents that can produce the requested iteration type. const yieldIteratorResult = filterType(type, isYieldIteratorResult); - const yieldType = yieldIteratorResult !== neverType ? getTypeOfPropertyOfType(yieldIteratorResult, "value" as ts.__String) : undefined; + const yieldType = yieldIteratorResult !== neverType ? getTypeOfPropertyOfType(yieldIteratorResult, "value" as __String) : undefined; const returnIteratorResult = filterType(type, isReturnIteratorResult); - const returnType = returnIteratorResult !== neverType ? getTypeOfPropertyOfType(returnIteratorResult, "value" as ts.__String) : undefined; + const returnType = returnIteratorResult !== neverType ? getTypeOfPropertyOfType(returnIteratorResult, "value" as __String) : undefined; if (!yieldType && !returnType) { return setCachedIterationTypes(type, "iterationTypesOfIteratorResult", noIterationTypes); @@ -39599,15 +39797,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * If we successfully found the *yield*, *return*, and *next* types, an `IterationTypes` * record is returned. Otherwise, we return `undefined`. */ - function getIterationTypesOfMethod(type: ts.Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined): ts.IterationTypes | undefined { - const method = getPropertyOfType(type, methodName as ts.__String); + function getIterationTypesOfMethod(type: Type, resolver: IterationTypesResolver, methodName: "next" | "return" | "throw", errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined): IterationTypes | undefined { + const method = getPropertyOfType(type, methodName as __String); // Ignore 'return' or 'throw' if they are missing. if (!method && methodName !== "next") { return undefined; } - const methodType = method && !(methodName === "next" && (method.flags & ts.SymbolFlags.Optional)) + const methodType = method && !(methodName === "next" && (method.flags & SymbolFlags.Optional)) ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull) : undefined; @@ -39617,7 +39815,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Both async and non-async iterators *must* have a `next` method. - const methodSignatures = methodType ? getSignaturesOfType(methodType, ts.SignatureKind.Call) : ts.emptyArray; + const methodSignatures = methodType ? getSignaturesOfType(methodType, SignatureKind.Call) : emptyArray; if (methodSignatures.length === 0) { if (errorNode) { const diagnostic = methodName === "next" @@ -39625,7 +39823,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { : resolver.mustBeAMethodDiagnostic; if (errorOutputContainer) { errorOutputContainer.errors ??= []; - errorOutputContainer.errors.push(ts.createDiagnosticForNode(errorNode, diagnostic, methodName)); + errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, diagnostic, methodName)); } else { error(errorNode, diagnostic, methodName); @@ -39644,11 +39842,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (methodType?.symbol && methodSignatures.length === 1) { const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false); const globalIteratorType = resolver.getGlobalIteratorType(/*reportErrors*/ false); - const isGeneratorMethod = globalGeneratorType.symbol?.members?.get(methodName as ts.__String) === methodType.symbol; - const isIteratorMethod = !isGeneratorMethod && globalIteratorType.symbol?.members?.get(methodName as ts.__String) === methodType.symbol; + const isGeneratorMethod = globalGeneratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; + const isIteratorMethod = !isGeneratorMethod && globalIteratorType.symbol?.members?.get(methodName as __String) === methodType.symbol; if (isGeneratorMethod || isIteratorMethod) { const globalType = isGeneratorMethod ? globalGeneratorType : globalIteratorType; - const { mapper } = methodType as ts.AnonymousType; + const { mapper } = methodType as AnonymousType; return createIterationTypes( getMappedType(globalType.typeParameters![0], mapper!), getMappedType(globalType.typeParameters![1], mapper!), @@ -39657,19 +39855,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Extract the first parameter and return type of each signature. - let methodParameterTypes: ts.Type[] | undefined; - let methodReturnTypes: ts.Type[] | undefined; + let methodParameterTypes: Type[] | undefined; + let methodReturnTypes: Type[] | undefined; for (const signature of methodSignatures) { - if (methodName !== "throw" && ts.some(signature.parameters)) { - methodParameterTypes = ts.append(methodParameterTypes, getTypeAtPosition(signature, 0)); + if (methodName !== "throw" && some(signature.parameters)) { + methodParameterTypes = append(methodParameterTypes, getTypeAtPosition(signature, 0)); } - methodReturnTypes = ts.append(methodReturnTypes, getReturnTypeOfSignature(signature)); + methodReturnTypes = append(methodReturnTypes, getReturnTypeOfSignature(signature)); } // Resolve the *next* or *return* type from the first parameter of a `next()` or // `return()` method, respectively. - let returnTypes: ts.Type[] | undefined; - let nextType: ts.Type | undefined; + let returnTypes: Type[] | undefined; + let nextType: Type | undefined; if (methodName !== "throw") { const methodParameterType = methodParameterTypes ? getUnionType(methodParameterTypes) : unknownType; if (methodName === "next") { @@ -39679,12 +39877,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else if (methodName === "return") { // The value of `return(value)` *is* awaited by async generators const resolvedMethodParameterType = resolver.resolveIterationType(methodParameterType, errorNode) || anyType; - returnTypes = ts.append(returnTypes, resolvedMethodParameterType); + returnTypes = append(returnTypes, resolvedMethodParameterType); } } // Resolve the *yield* and *return* types from the return type of the method (i.e. `IteratorResult`) - let yieldType: ts.Type; + let yieldType: Type; const methodReturnType = methodReturnTypes ? getIntersectionType(methodReturnTypes) : neverType; const resolvedMethodReturnType = resolver.resolveIterationType(methodReturnType, errorNode) || anyType; const iterationTypes = getIterationTypesOfIteratorResult(resolvedMethodReturnType); @@ -39692,18 +39890,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (errorNode) { if (errorOutputContainer) { errorOutputContainer.errors ??= []; - errorOutputContainer.errors.push(ts.createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName)); + errorOutputContainer.errors.push(createDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName)); } else { error(errorNode, resolver.mustHaveAValueDiagnostic, methodName); } } yieldType = anyType; - returnTypes = ts.append(returnTypes, anyType); + returnTypes = append(returnTypes, anyType); } else { yieldType = iterationTypes.yieldType; - returnTypes = ts.append(returnTypes, iterationTypes.returnType); + returnTypes = append(returnTypes, iterationTypes.returnType); } return createIterationTypes(yieldType, getUnionType(returnTypes), nextType); @@ -39719,7 +39917,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * NOTE: You probably don't want to call this directly and should be calling * `getIterationTypesOfIterator` instead. */ - function getIterationTypesOfIteratorSlow(type: ts.Type, resolver: IterationTypesResolver, errorNode: ts.Node | undefined, errorOutputContainer: { errors: ts.Diagnostic[] | undefined } | undefined, noCache: boolean) { + function getIterationTypesOfIteratorSlow(type: Type, resolver: IterationTypesResolver, errorNode: Node | undefined, errorOutputContainer: { errors: Diagnostic[] | undefined } | undefined, noCache: boolean) { const iterationTypes = combineIterationTypes([ getIterationTypesOfMethod(type, resolver, "next", errorNode, errorOutputContainer), getIterationTypesOfMethod(type, resolver, "return", errorNode, errorOutputContainer), @@ -39733,7 +39931,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * `IterableIterator`-like, or `Generator`-like (for a non-async generator); or `AsyncIterable`-like, * `AsyncIterator`-like, `AsyncIterableIterator`-like, or `AsyncGenerator`-like (for an async generator). */ - function getIterationTypeOfGeneratorFunctionReturnType(kind: IterationTypeKind, returnType: ts.Type, isAsyncGenerator: boolean): ts.Type | undefined { + function getIterationTypeOfGeneratorFunctionReturnType(kind: IterationTypeKind, returnType: Type, isAsyncGenerator: boolean): Type | undefined { if (isTypeAny(returnType)) { return undefined; } @@ -39742,7 +39940,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return iterationTypes && iterationTypes[getIterationTypesKeyFromIterationTypeKind(kind)]; } - function getIterationTypesOfGeneratorFunctionReturnType(type: ts.Type, isAsyncGenerator: boolean) { + function getIterationTypesOfGeneratorFunctionReturnType(type: Type, isAsyncGenerator: boolean) { if (isTypeAny(type)) { return anyIterationTypes; } @@ -39753,16 +39951,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getIterationTypesOfIterator(type, resolver, /*errorNode*/ undefined, /*errorOutputContainer*/ undefined); } - function checkBreakOrContinueStatement(node: ts.BreakOrContinueStatement) { + function checkBreakOrContinueStatement(node: BreakOrContinueStatement) { // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) checkGrammarBreakOrContinueStatement(node); // TODO: Check that target label is valid } - function unwrapReturnType(returnType: ts.Type, functionFlags: ts.FunctionFlags) { - const isGenerator = !!(functionFlags & ts.FunctionFlags.Generator); - const isAsync = !!(functionFlags & ts.FunctionFlags.Async); + function unwrapReturnType(returnType: Type, functionFlags: FunctionFlags) { + const isGenerator = !!(functionFlags & FunctionFlags.Generator); + const isAsync = !!(functionFlags & FunctionFlags.Async); if (isGenerator) { const returnIterationType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, isAsync); if (!returnIterationType) { @@ -39773,47 +39971,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return isAsync ? getAwaitedTypeNoAlias(returnType) || errorType : returnType; } - function isUnwrappedReturnTypeVoidOrAny(func: ts.SignatureDeclaration, returnType: ts.Type): boolean { - const unwrappedReturnType = unwrapReturnType(returnType, ts.getFunctionFlags(func)); - return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, ts.TypeFlags.Void | ts.TypeFlags.AnyOrUnknown); + function isUnwrappedReturnTypeVoidOrAny(func: SignatureDeclaration, returnType: Type): boolean { + const unwrappedReturnType = unwrapReturnType(returnType, getFunctionFlags(func)); + return !!unwrappedReturnType && maybeTypeOfKind(unwrappedReturnType, TypeFlags.Void | TypeFlags.AnyOrUnknown); } - function checkReturnStatement(node: ts.ReturnStatement) { + function checkReturnStatement(node: ReturnStatement) { // Grammar checking if (checkGrammarStatementInAmbientContext(node)) { return; } - const container = ts.getContainingFunctionOrClassStaticBlock(node); - if(container && ts.isClassStaticBlockDeclaration(container)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block); + const container = getContainingFunctionOrClassStaticBlock(node); + if(container && isClassStaticBlockDeclaration(container)) { + grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block); return; } if (!container) { - grammarErrorOnFirstToken(node, ts.Diagnostics.A_return_statement_can_only_be_used_within_a_function_body); + grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body); return; } const signature = getSignatureFromDeclaration(container); const returnType = getReturnTypeOfSignature(signature); - const functionFlags = ts.getFunctionFlags(container); - if (strictNullChecks || node.expression || returnType.flags & ts.TypeFlags.Never) { + const functionFlags = getFunctionFlags(container); + if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) { const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; - if (container.kind === ts.SyntaxKind.SetAccessor) { + if (container.kind === SyntaxKind.SetAccessor) { if (node.expression) { - error(node, ts.Diagnostics.Setters_cannot_return_a_value); + error(node, Diagnostics.Setters_cannot_return_a_value); } } - else if (container.kind === ts.SyntaxKind.Constructor) { + else if (container.kind === SyntaxKind.Constructor) { if (node.expression && !checkTypeAssignableToAndOptionallyElaborate(exprType, returnType, node, node.expression)) { - error(node, ts.Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); + error(node, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class); } } else if (getReturnTypeFromAnnotation(container)) { const unwrappedReturnType = unwrapReturnType(returnType, functionFlags) ?? returnType; - const unwrappedExprType = functionFlags & ts.FunctionFlags.Async - ? checkAwaitedType(exprType, /*withAlias*/ false, node, ts.Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member) + const unwrappedExprType = functionFlags & FunctionFlags.Async + ? checkAwaitedType(exprType, /*withAlias*/ false, node, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member) : exprType; if (unwrappedReturnType) { // If the function has a return type, but promisedType is @@ -39823,60 +40021,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } } - else if (container.kind !== ts.SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) { + else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) { // The function has a return type, but the return statement doesn't have an expression. - error(node, ts.Diagnostics.Not_all_code_paths_return_a_value); + error(node, Diagnostics.Not_all_code_paths_return_a_value); } } - function checkWithStatement(node: ts.WithStatement) { + function checkWithStatement(node: WithStatement) { // Grammar checking for withStatement if (!checkGrammarStatementInAmbientContext(node)) { - if (node.flags & ts.NodeFlags.AwaitContext) { - grammarErrorOnFirstToken(node, ts.Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); + if (node.flags & NodeFlags.AwaitContext) { + grammarErrorOnFirstToken(node, Diagnostics.with_statements_are_not_allowed_in_an_async_function_block); } } checkExpression(node.expression); - const sourceFile = ts.getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - const start = ts.getSpanOfTokenAtPosition(sourceFile, node.pos).start; + const start = getSpanOfTokenAtPosition(sourceFile, node.pos).start; const end = node.statement.pos; - grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); + grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.The_with_statement_is_not_supported_All_symbols_in_a_with_block_will_have_type_any); } } - function checkSwitchStatement(node: ts.SwitchStatement) { + function checkSwitchStatement(node: SwitchStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); - let firstDefaultClause: ts.CaseOrDefaultClause; + let firstDefaultClause: CaseOrDefaultClause; let hasDuplicateDefaultClause = false; const expressionType = checkExpression(node.expression); const expressionIsLiteral = isLiteralType(expressionType); - ts.forEach(node.caseBlock.clauses, clause => { + forEach(node.caseBlock.clauses, clause => { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause - if (clause.kind === ts.SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) { + if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) { if (firstDefaultClause === undefined) { firstDefaultClause = clause; } else { - grammarErrorOnNode(clause, ts.Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement); + grammarErrorOnNode(clause, Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement); hasDuplicateDefaultClause = true; } } - if (clause.kind === ts.SyntaxKind.CaseClause) { + if (clause.kind === SyntaxKind.CaseClause) { addLazyDiagnostic(createLazyCaseClauseDiagnostics(clause)); } - ts.forEach(clause.statements, checkSourceElement); + forEach(clause.statements, checkSourceElement); if (compilerOptions.noFallthroughCasesInSwitch && clause.fallthroughFlowNode && isReachableFlowNode(clause.fallthroughFlowNode)) { - error(clause, ts.Diagnostics.Fallthrough_case_in_switch); + error(clause, Diagnostics.Fallthrough_case_in_switch); } - function createLazyCaseClauseDiagnostics(clause: ts.CaseClause) { + function createLazyCaseClauseDiagnostics(clause: CaseClause) { return () => { // TypeScript 1.0 spec (April 2014): 5.9 // In a 'switch' statement, each 'case' expression must be of a type that is comparable @@ -39900,15 +40098,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkLabeledStatement(node: ts.LabeledStatement) { + function checkLabeledStatement(node: LabeledStatement) { // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { - ts.findAncestor(node.parent, current => { - if (ts.isFunctionLike(current)) { + findAncestor(node.parent, current => { + if (isFunctionLike(current)) { return "quit"; } - if (current.kind === ts.SyntaxKind.LabeledStatement && (current as ts.LabeledStatement).label.escapedText === node.label.escapedText) { - grammarErrorOnNode(node.label, ts.Diagnostics.Duplicate_label_0, ts.getTextOfNode(node.label)); + if (current.kind === SyntaxKind.LabeledStatement && (current as LabeledStatement).label.escapedText === node.label.escapedText) { + grammarErrorOnNode(node.label, Diagnostics.Duplicate_label_0, getTextOfNode(node.label)); return true; } return false; @@ -39919,11 +40117,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkSourceElement(node.statement); } - function checkThrowStatement(node: ts.ThrowStatement) { + function checkThrowStatement(node: ThrowStatement) { // Grammar checking if (!checkGrammarStatementInAmbientContext(node)) { - if (ts.isIdentifier(node.expression) && !node.expression.escapedText) { - grammarErrorAfterFirstToken(node, ts.Diagnostics.Line_break_not_permitted_here); + if (isIdentifier(node.expression) && !node.expression.escapedText) { + grammarErrorAfterFirstToken(node, Diagnostics.Line_break_not_permitted_here); } } @@ -39932,7 +40130,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkTryStatement(node: ts.TryStatement) { + function checkTryStatement(node: TryStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); @@ -39942,23 +40140,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Grammar checking if (catchClause.variableDeclaration) { const declaration = catchClause.variableDeclaration; - const typeNode = ts.getEffectiveTypeAnnotationNode(ts.getRootDeclaration(declaration)); + const typeNode = getEffectiveTypeAnnotationNode(getRootDeclaration(declaration)); if (typeNode) { const type = getTypeForVariableLikeDeclaration(declaration, /*includeOptionality*/ false, CheckMode.Normal); - if (type && !(type.flags & ts.TypeFlags.AnyOrUnknown)) { - grammarErrorOnFirstToken(typeNode, ts.Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified); + if (type && !(type.flags & TypeFlags.AnyOrUnknown)) { + grammarErrorOnFirstToken(typeNode, Diagnostics.Catch_clause_variable_type_annotation_must_be_any_or_unknown_if_specified); } } else if (declaration.initializer) { - grammarErrorOnFirstToken(declaration.initializer, ts.Diagnostics.Catch_clause_variable_cannot_have_an_initializer); + grammarErrorOnFirstToken(declaration.initializer, Diagnostics.Catch_clause_variable_cannot_have_an_initializer); } else { const blockLocals = catchClause.block.locals; if (blockLocals) { - ts.forEachKey(catchClause.locals!, caughtName => { + forEachKey(catchClause.locals!, caughtName => { const blockLocal = blockLocals.get(caughtName); - if (blockLocal?.valueDeclaration && (blockLocal.flags & ts.SymbolFlags.BlockScopedVariable) !== 0) { - grammarErrorOnNode(blockLocal.valueDeclaration, ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); + if (blockLocal?.valueDeclaration && (blockLocal.flags & SymbolFlags.BlockScopedVariable) !== 0) { + grammarErrorOnNode(blockLocal.valueDeclaration, Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName); } }); } @@ -39973,24 +40171,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkIndexConstraints(type: ts.Type, symbol: ts.Symbol, isStaticIndex?: boolean) { + function checkIndexConstraints(type: Type, symbol: Symbol, isStaticIndex?: boolean) { const indexInfos = getIndexInfosOfType(type); if (indexInfos.length === 0) { return; } for (const prop of getPropertiesOfObjectType(type)) { - if (!(isStaticIndex && prop.flags & ts.SymbolFlags.Prototype)) { - checkIndexConstraintForProperty(type, prop, getLiteralTypeFromProperty(prop, ts.TypeFlags.StringOrNumberLiteralOrUnique, /*includeNonPublic*/ true), getNonMissingTypeOfSymbol(prop)); + if (!(isStaticIndex && prop.flags & SymbolFlags.Prototype)) { + checkIndexConstraintForProperty(type, prop, getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique, /*includeNonPublic*/ true), getNonMissingTypeOfSymbol(prop)); } } const typeDeclaration = symbol.valueDeclaration; - if (typeDeclaration && ts.isClassLike(typeDeclaration)) { + if (typeDeclaration && isClassLike(typeDeclaration)) { for (const member of typeDeclaration.members) { // Only process instance properties with computed names here. Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. - if (!ts.isStatic(member) && !hasBindableName(member)) { + if (!isStatic(member) && !hasBindableName(member)) { const symbol = getSymbolOfNode(member); - checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as ts.DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); + checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); } } } @@ -40001,16 +40199,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkIndexConstraintForProperty(type: ts.Type, prop: ts.Symbol, propNameType: ts.Type, propType: ts.Type) { + function checkIndexConstraintForProperty(type: Type, prop: Symbol, propNameType: Type, propType: Type) { const declaration = prop.valueDeclaration; - const name = ts.getNameOfDeclaration(declaration); - if (name && ts.isPrivateIdentifier(name)) { + const name = getNameOfDeclaration(declaration); + if (name && isPrivateIdentifier(name)) { return; } const indexInfos = getApplicableIndexInfos(type, propNameType); - const interfaceDeclaration = ts.getObjectFlags(type) & ts.ObjectFlags.Interface ? ts.getDeclarationOfKind(type.symbol, ts.SyntaxKind.InterfaceDeclaration) : undefined; - const propDeclaration = declaration && declaration.kind === ts.SyntaxKind.BinaryExpression || - name && name.kind === ts.SyntaxKind.ComputedPropertyName ? declaration : undefined; + const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; + const propDeclaration = declaration && declaration.kind === SyntaxKind.BinaryExpression || + name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined; const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined; for (const info of indexInfos) { const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined; @@ -40018,22 +40216,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // in the containing type, or (c) the containing type is an interface and no base interface contains both the property and // the index signature (i.e. property and index signature are declared in separate inherited interfaces). const errorNode = localPropDeclaration || localIndexDeclaration || - (interfaceDeclaration && !ts.some(getBaseTypes(type as ts.InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); + (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getPropertyOfObjectType(base, prop.escapedName) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); if (errorNode && !isTypeAssignableTo(propType, info.type)) { - const diagnostic = createError(errorNode, ts.Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3, + const diagnostic = createError(errorNode, Diagnostics.Property_0_of_type_1_is_not_assignable_to_2_index_type_3, symbolToString(prop), typeToString(propType), typeToString(info.keyType), typeToString(info.type)); if (propDeclaration && errorNode !== propDeclaration) { - ts.addRelatedInfo(diagnostic, ts.createDiagnosticForNode(propDeclaration, ts.Diagnostics._0_is_declared_here, symbolToString(prop))); + addRelatedInfo(diagnostic, createDiagnosticForNode(propDeclaration, Diagnostics._0_is_declared_here, symbolToString(prop))); } diagnostics.add(diagnostic); } } } - function checkIndexConstraintForIndexSignature(type: ts.Type, checkInfo: ts.IndexInfo) { + function checkIndexConstraintForIndexSignature(type: Type, checkInfo: IndexInfo) { const declaration = checkInfo.declaration; const indexInfos = getApplicableIndexInfos(type, checkInfo.keyType); - const interfaceDeclaration = ts.getObjectFlags(type) & ts.ObjectFlags.Interface ? ts.getDeclarationOfKind(type.symbol, ts.SyntaxKind.InterfaceDeclaration) : undefined; + const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; const localCheckDeclaration = declaration && getParentOfSymbol(getSymbolOfNode(declaration)) === type.symbol ? declaration : undefined; for (const info of indexInfos) { if (info === checkInfo) continue; @@ -40042,15 +40240,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // signature is declared in the containing type, or (c) the containing type is an interface and no base interface contains // both index signatures (i.e. the index signatures are declared in separate inherited interfaces). const errorNode = localCheckDeclaration || localIndexDeclaration || - (interfaceDeclaration && !ts.some(getBaseTypes(type as ts.InterfaceType), base => !!getIndexInfoOfType(base, checkInfo.keyType) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); + (interfaceDeclaration && !some(getBaseTypes(type as InterfaceType), base => !!getIndexInfoOfType(base, checkInfo.keyType) && !!getIndexTypeOfType(base, info.keyType)) ? interfaceDeclaration : undefined); if (errorNode && !isTypeAssignableTo(checkInfo.type, info.type)) { - error(errorNode, ts.Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3, + error(errorNode, Diagnostics._0_index_type_1_is_not_assignable_to_2_index_type_3, typeToString(checkInfo.keyType), typeToString(checkInfo.type), typeToString(info.keyType), typeToString(info.type)); } } } - function checkTypeNameIsReserved(name: ts.Identifier, message: ts.DiagnosticMessage): void { + function checkTypeNameIsReserved(name: Identifier, message: DiagnosticMessage): void { // TS 1.0 spec (April 2014): 3.6.1 // The predefined type keywords are reserved and cannot be used as names of user defined types. switch (name.escapedText) { @@ -40071,50 +40269,50 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * The name cannot be used as 'Object' of user defined types with special target. */ - function checkClassNameCollisionWithObject(name: ts.Identifier): void { - if (languageVersion >= ts.ScriptTarget.ES5 && name.escapedText === "Object" - && (moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(name).impliedNodeFormat === ts.ModuleKind.CommonJS)) { - error(name, ts.Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ts.ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 + function checkClassNameCollisionWithObject(name: Identifier): void { + if (languageVersion >= ScriptTarget.ES5 && name.escapedText === "Object" + && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(name).impliedNodeFormat === ModuleKind.CommonJS)) { + error(name, Diagnostics.Class_name_cannot_be_Object_when_targeting_ES5_with_module_0, ModuleKind[moduleKind]); // https://github.com/Microsoft/TypeScript/issues/17494 } } - function checkUnmatchedJSDocParameters(node: ts.SignatureDeclaration) { - const jsdocParameters = ts.filter(ts.getJSDocTags(node), ts.isJSDocParameterTag); - if (!ts.length(jsdocParameters)) return; + function checkUnmatchedJSDocParameters(node: SignatureDeclaration) { + const jsdocParameters = filter(getJSDocTags(node), isJSDocParameterTag); + if (!length(jsdocParameters)) return; - const isJs = ts.isInJSFile(node); - const parameters = new ts.Set(); - const excludedParameters = new ts.Set(); - ts.forEach(node.parameters, ({ name }, index) => { - if (ts.isIdentifier(name)) { + const isJs = isInJSFile(node); + const parameters = new Set<__String>(); + const excludedParameters = new Set(); + forEach(node.parameters, ({ name }, index) => { + if (isIdentifier(name)) { parameters.add(name.escapedText); } - if (ts.isBindingPattern(name)) { + if (isBindingPattern(name)) { excludedParameters.add(index); } }); const containsArguments = containsArgumentsReference(node); if (containsArguments) { - const lastJSDocParam = ts.lastOrUndefined(jsdocParameters); - if (isJs && lastJSDocParam && ts.isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression && + const lastJSDocParam = lastOrUndefined(jsdocParameters); + if (isJs && lastJSDocParam && isIdentifier(lastJSDocParam.name) && lastJSDocParam.typeExpression && lastJSDocParam.typeExpression.type && !parameters.has(lastJSDocParam.name.escapedText) && !isArrayType(getTypeFromTypeNode(lastJSDocParam.typeExpression.type))) { - error(lastJSDocParam.name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, ts.idText(lastJSDocParam.name)); + error(lastJSDocParam.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name_It_would_match_arguments_if_it_had_an_array_type, idText(lastJSDocParam.name)); } } else { - ts.forEach(jsdocParameters, ({ name, isNameFirst }, index) => { - if (excludedParameters.has(index) || ts.isIdentifier(name) && parameters.has(name.escapedText)) { + forEach(jsdocParameters, ({ name, isNameFirst }, index) => { + if (excludedParameters.has(index) || isIdentifier(name) && parameters.has(name.escapedText)) { return; } - if (ts.isQualifiedName(name)) { + if (isQualifiedName(name)) { if (isJs) { - error(name, ts.Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, ts.entityNameToString(name), ts.entityNameToString(name.left)); + error(name, Diagnostics.Qualified_name_0_is_not_allowed_without_a_leading_param_object_1, entityNameToString(name), entityNameToString(name.left)); } } else { if (!isNameFirst) { - errorOrSuggestion(isJs, name, ts.Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, ts.idText(name)); + errorOrSuggestion(isJs, name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(name)); } } }); @@ -40124,7 +40322,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /** * Check each type parameter and check that type parameters have no duplicate type parameter declarations */ - function checkTypeParameters(typeParameterDeclarations: readonly ts.TypeParameterDeclaration[] | undefined) { + function checkTypeParameters(typeParameterDeclarations: readonly TypeParameterDeclaration[] | undefined) { let seenDefault = false; if (typeParameterDeclarations) { for (let i = 0; i < typeParameterDeclarations.length; i++) { @@ -40135,18 +40333,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function createCheckTypeParameterDiagnostic(node: ts.TypeParameterDeclaration, i: number) { + function createCheckTypeParameterDiagnostic(node: TypeParameterDeclaration, i: number) { return () => { if (node.default) { seenDefault = true; checkTypeParametersNotReferenced(node.default, typeParameterDeclarations!, i); } else if (seenDefault) { - error(node, ts.Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters); + error(node, Diagnostics.Required_type_parameters_may_not_follow_optional_type_parameters); } for (let j = 0; j < i; j++) { if (typeParameterDeclarations![j].symbol === node.symbol) { - error(node.name, ts.Diagnostics.Duplicate_identifier_0, ts.declarationNameToString(node.name)); + error(node.name, Diagnostics.Duplicate_identifier_0, declarationNameToString(node.name)); } } }; @@ -40154,25 +40352,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } /** Check that type parameter defaults only reference previously declared type parameters */ - function checkTypeParametersNotReferenced(root: ts.TypeNode, typeParameters: readonly ts.TypeParameterDeclaration[], index: number) { + function checkTypeParametersNotReferenced(root: TypeNode, typeParameters: readonly TypeParameterDeclaration[], index: number) { visit(root); - function visit(node: ts.Node) { - if (node.kind === ts.SyntaxKind.TypeReference) { - const type = getTypeFromTypeReference(node as ts.TypeReferenceNode); - if (type.flags & ts.TypeFlags.TypeParameter) { + function visit(node: Node) { + if (node.kind === SyntaxKind.TypeReference) { + const type = getTypeFromTypeReference(node as TypeReferenceNode); + if (type.flags & TypeFlags.TypeParameter) { for (let i = index; i < typeParameters.length; i++) { if (type.symbol === getSymbolOfNode(typeParameters[i])) { - error(node, ts.Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters); + error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters); } } } } - ts.forEachChild(node, visit); + forEachChild(node, visit); } } /** Check that type parameter lists are identical across multiple declarations */ - function checkTypeParameterListsIdentical(symbol: ts.Symbol) { + function checkTypeParameterListsIdentical(symbol: Symbol) { if (symbol.declarations && symbol.declarations.length === 1) { return; } @@ -40185,19 +40383,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } - const type = getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType; - if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, ts.getEffectiveTypeParameterDeclarations)) { + const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; + if (!areTypeParametersIdentical(declarations, type.localTypeParameters!, getEffectiveTypeParameterDeclarations)) { // Report an error on every conflicting declaration. const name = symbolToString(symbol); for (const declaration of declarations) { - error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); + error(declaration.name, Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } } } - function areTypeParametersIdentical(declarations: readonly T[], targetParameters: ts.TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly ts.TypeParameterDeclaration[]) { - const maxTypeArgumentCount = ts.length(targetParameters); + function areTypeParametersIdentical(declarations: readonly T[], targetParameters: TypeParameter[], getTypeParameterDeclarations: (node: T) => readonly TypeParameterDeclaration[]) { + const maxTypeArgumentCount = length(targetParameters); const minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); for (const declaration of declarations) { @@ -40220,7 +40418,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If the type parameter node does not have an identical constraint as the resolved // type parameter at this position, we report an error. - const constraint = ts.getEffectiveConstraintOfTypeParameter(source); + const constraint = getEffectiveConstraintOfTypeParameter(source); const sourceConstraint = constraint && getTypeFromTypeNode(constraint); const targetConstraint = getConstraintOfTypeParameter(target); // relax check if later interface augmentation has no constraint, it's more broad and is OK to merge with @@ -40242,59 +40440,59 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function checkClassExpression(node: ts.ClassExpression): ts.Type { + function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); checkNodeDeferred(node); return getTypeOfSymbol(getSymbolOfNode(node)); } - function checkClassExpressionDeferred(node: ts.ClassExpression) { - ts.forEach(node.members, checkSourceElement); + function checkClassExpressionDeferred(node: ClassExpression) { + forEach(node.members, checkSourceElement); registerForUnusedIdentifiersCheck(node); } - function checkClassDeclaration(node: ts.ClassDeclaration) { - const firstDecorator = ts.find(node.modifiers, ts.isDecorator); - if (firstDecorator && ts.some(node.members, p => ts.hasStaticModifier(p) && ts.isPrivateIdentifierClassElementDeclaration(p))) { - grammarErrorOnNode(firstDecorator, ts.Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator); + function checkClassDeclaration(node: ClassDeclaration) { + const firstDecorator = find(node.modifiers, isDecorator); + if (firstDecorator && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p))) { + grammarErrorOnNode(firstDecorator, Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator); } - if (!node.name && !ts.hasSyntacticModifier(node, ts.ModifierFlags.Default)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); + if (!node.name && !hasSyntacticModifier(node, ModifierFlags.Default)) { + grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name); } checkClassLikeDeclaration(node); - ts.forEach(node.members, checkSourceElement); + forEach(node.members, checkSourceElement); registerForUnusedIdentifiersCheck(node); } - function checkClassLikeDeclaration(node: ts.ClassLikeDeclaration) { + function checkClassLikeDeclaration(node: ClassLikeDeclaration) { checkGrammarClassLikeDeclaration(node); checkDecorators(node); checkCollisionsForDeclarationName(node, node.name); - checkTypeParameters(ts.getEffectiveTypeParameterDeclarations(node)); + checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); checkExportsOnMergedDeclarations(node); const symbol = getSymbolOfNode(node); - const type = getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType; + const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); - const staticType = getTypeOfSymbol(symbol) as ts.ObjectType; + const staticType = getTypeOfSymbol(symbol) as ObjectType; checkTypeParameterListsIdentical(symbol); checkFunctionOrConstructorSymbol(symbol); checkClassForDuplicateDeclarations(node); // Only check for reserved static identifiers on non-ambient context. - const nodeInAmbientContext = !!(node.flags & ts.NodeFlags.Ambient); + const nodeInAmbientContext = !!(node.flags & NodeFlags.Ambient); if (!nodeInAmbientContext) { checkClassForStaticPropertyNameConflicts(node); } - const baseTypeNode = ts.getEffectiveBaseTypeNode(node); + const baseTypeNode = getEffectiveBaseTypeNode(node); if (baseTypeNode) { - ts.forEach(baseTypeNode.typeArguments, checkSourceElement); - if (languageVersion < ts.ScriptTarget.ES2015) { - checkExternalEmitHelpers(baseTypeNode.parent, ts.ExternalEmitHelpers.Extends); + forEach(baseTypeNode.typeArguments, checkSourceElement); + if (languageVersion < ScriptTarget.ES2015) { + checkExternalEmitHelpers(baseTypeNode.parent, ExternalEmitHelpers.Extends); } // check both @extends and extends if both are specified. - const extendsNode = ts.getClassExtendsHeritageElement(node); + const extendsNode = getClassExtendsHeritageElement(node); if (extendsNode && extendsNode !== baseTypeNode) { checkExpression(extendsNode.expression); } @@ -40307,8 +40505,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const staticBaseType = getApparentType(baseConstructorType); checkBaseTypeAccessibility(staticBaseType, baseTypeNode); checkSourceElement(baseTypeNode.expression); - if (ts.some(baseTypeNode.typeArguments)) { - ts.forEach(baseTypeNode.typeArguments, checkSourceElement); + if (some(baseTypeNode.typeArguments)) { + forEach(baseTypeNode.typeArguments, checkSourceElement); for (const constructor of getConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode)) { if (!checkTypeArgumentConstraints(baseTypeNode, constructor.typeParameters!)) { break; @@ -40317,31 +40515,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } const baseWithThis = getTypeWithThisArgument(baseType, type.thisType); if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { - issueMemberSpecificError(node, typeWithThis, baseWithThis, ts.Diagnostics.Class_0_incorrectly_extends_base_class_1); + issueMemberSpecificError(node, typeWithThis, baseWithThis, Diagnostics.Class_0_incorrectly_extends_base_class_1); } else { // Report static side error only when instance type is assignable checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node, - ts.Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1); + Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1); } - if (baseConstructorType.flags & ts.TypeFlags.TypeVariable) { + if (baseConstructorType.flags & TypeFlags.TypeVariable) { if (!isMixinConstructorType(staticType)) { - error(node.name || node, ts.Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any); + error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any); } else { - const constructSignatures = getSignaturesOfType(baseConstructorType, ts.SignatureKind.Construct); - if (constructSignatures.some(signature => signature.flags & ts.SignatureFlags.Abstract) && !ts.hasSyntacticModifier(node, ts.ModifierFlags.Abstract)) { - error(node.name || node, ts.Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract); + const constructSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct); + if (constructSignatures.some(signature => signature.flags & SignatureFlags.Abstract) && !hasSyntacticModifier(node, ModifierFlags.Abstract)) { + error(node.name || node, Diagnostics.A_mixin_class_that_extends_from_a_type_variable_containing_an_abstract_construct_signature_must_also_be_declared_abstract); } } } - if (!(staticBaseType.symbol && staticBaseType.symbol.flags & ts.SymbolFlags.Class) && !(baseConstructorType.flags & ts.TypeFlags.TypeVariable)) { + if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) { // When the static base type is a "class-like" constructor function (but not actually a class), we verify // that all instantiated base constructor signatures return the same type. const constructors = getInstantiatedConstructorsForTypeArguments(staticBaseType, baseTypeNode.typeArguments, baseTypeNode); - if (ts.forEach(constructors, sig => !isJSConstructor(sig.declaration) && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType))) { - error(baseTypeNode.expression, ts.Diagnostics.Base_constructors_must_all_have_the_same_return_type); + if (forEach(constructors, sig => !isJSConstructor(sig.declaration) && !isTypeIdenticalTo(getReturnTypeOfSignature(sig), baseType))) { + error(baseTypeNode.expression, Diagnostics.Base_constructors_must_all_have_the_same_return_type); } } checkKindsOfPropertyMemberOverrides(type, baseType); @@ -40351,11 +40549,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkMembersForOverrideModifier(node, type, typeWithThis, staticType); - const implementedTypeNodes = ts.getEffectiveImplementsTypeNodes(node); + const implementedTypeNodes = getEffectiveImplementsTypeNodes(node); if (implementedTypeNodes) { for (const typeRefNode of implementedTypeNodes) { - if (!ts.isEntityNameExpression(typeRefNode.expression) || ts.isOptionalChain(typeRefNode.expression)) { - error(typeRefNode.expression, ts.Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments); + if (!isEntityNameExpression(typeRefNode.expression) || isOptionalChain(typeRefNode.expression)) { + error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(typeRefNode); addLazyDiagnostic(createImplementsDiagnostics(typeRefNode)); @@ -40369,41 +40567,41 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkPropertyInitialization(node); }); - function createImplementsDiagnostics(typeRefNode: ts.ExpressionWithTypeArguments) { + function createImplementsDiagnostics(typeRefNode: ExpressionWithTypeArguments) { return () => { const t = getReducedType(getTypeFromTypeNode(typeRefNode)); if (!isErrorType(t)) { if (isValidBaseType(t)) { - const genericDiag = t.symbol && t.symbol.flags & ts.SymbolFlags.Class ? - ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass : - ts.Diagnostics.Class_0_incorrectly_implements_interface_1; + const genericDiag = t.symbol && t.symbol.flags & SymbolFlags.Class ? + Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass : + Diagnostics.Class_0_incorrectly_implements_interface_1; const baseWithThis = getTypeWithThisArgument(t, type.thisType); if (!checkTypeAssignableTo(typeWithThis, baseWithThis, /*errorNode*/ undefined)) { issueMemberSpecificError(node, typeWithThis, baseWithThis, genericDiag); } } else { - error(typeRefNode, ts.Diagnostics.A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_members); + error(typeRefNode, Diagnostics.A_class_can_only_implement_an_object_type_or_intersection_of_object_types_with_statically_known_members); } } }; } } - function checkMembersForOverrideModifier(node: ts.ClassLikeDeclaration, type: ts.InterfaceType, typeWithThis: ts.Type, staticType: ts.ObjectType) { - const baseTypeNode = ts.getEffectiveBaseTypeNode(node); + function checkMembersForOverrideModifier(node: ClassLikeDeclaration, type: InterfaceType, typeWithThis: Type, staticType: ObjectType) { + const baseTypeNode = getEffectiveBaseTypeNode(node); const baseTypes = baseTypeNode && getBaseTypes(type); - const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(ts.first(baseTypes), type.thisType) : undefined; + const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(first(baseTypes), type.thisType) : undefined; const baseStaticType = getBaseConstructorTypeOfClass(type); for (const member of node.members) { - if (ts.hasAmbientModifier(member)) { + if (hasAmbientModifier(member)) { continue; } - if (ts.isConstructorDeclaration(member)) { - ts.forEach(member.parameters, param => { - if (ts.isParameterPropertyDeclaration(param, member)) { + if (isConstructorDeclaration(member)) { + forEach(member.parameters, param => { + if (isParameterPropertyDeclaration(param, member)) { checkExistingMemberForOverrideModifier( node, staticType, @@ -40435,21 +40633,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Note: `member` cannot be a synthetic node. */ function checkExistingMemberForOverrideModifier( - node: ts.ClassLikeDeclaration, - staticType: ts.ObjectType, - baseStaticType: ts.Type, - baseWithThis: ts.Type | undefined, - type: ts.InterfaceType, - typeWithThis: ts.Type, - member: ts.ClassElement | ts.ParameterPropertyDeclaration, + node: ClassLikeDeclaration, + staticType: ObjectType, + baseStaticType: Type, + baseWithThis: Type | undefined, + type: InterfaceType, + typeWithThis: Type, + member: ClassElement | ParameterPropertyDeclaration, memberIsParameterProperty: boolean, reportErrors = true, - ): ts.MemberOverrideStatus { + ): MemberOverrideStatus { const declaredProp = member.name && getSymbolAtLocation(member.name) || getSymbolAtLocation(member); if (!declaredProp) { - return ts.MemberOverrideStatus.Ok; + return MemberOverrideStatus.Ok; } return checkMemberForOverrideModifier( @@ -40459,11 +40657,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { baseWithThis, type, typeWithThis, - ts.hasOverrideModifier(member), - ts.hasAbstractModifier(member), - ts.isStatic(member), + hasOverrideModifier(member), + hasAbstractModifier(member), + isStatic(member), memberIsParameterProperty, - ts.symbolName(declaredProp), + symbolName(declaredProp), reportErrors ? member : undefined, ); } @@ -40477,23 +40675,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param errorNode The node where we should report an error, or undefined if we should not report errors. */ function checkMemberForOverrideModifier( - node: ts.ClassLikeDeclaration, - staticType: ts.ObjectType, - baseStaticType: ts.Type, - baseWithThis: ts.Type | undefined, - type: ts.InterfaceType, - typeWithThis: ts.Type, + node: ClassLikeDeclaration, + staticType: ObjectType, + baseStaticType: Type, + baseWithThis: Type | undefined, + type: InterfaceType, + typeWithThis: Type, memberHasOverrideModifier: boolean, memberHasAbstractModifier: boolean, memberIsStatic: boolean, memberIsParameterProperty: boolean, memberName: string, - errorNode?: ts.Node, - ): ts.MemberOverrideStatus { - const isJs = ts.isInJSFile(node); - const nodeInAmbientContext = !!(node.flags & ts.NodeFlags.Ambient); + errorNode?: Node, + ): MemberOverrideStatus { + const isJs = isInJSFile(node); + const nodeInAmbientContext = !!(node.flags & NodeFlags.Ambient); if (baseWithThis && (memberHasOverrideModifier || compilerOptions.noImplicitOverride)) { - const memberEscapedName = ts.escapeLeadingUnderscores(memberName); + const memberEscapedName = escapeLeadingUnderscores(memberName); const thisType = memberIsStatic ? staticType : typeWithThis; const baseType = memberIsStatic ? baseStaticType : baseWithThis; const prop = getPropertyOfType(thisType, memberEscapedName); @@ -40507,43 +40705,43 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { error( errorNode, isJs ? - ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 : - ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, + Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1 : + Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, baseClassName, symbolToString(suggestion)) : error( errorNode, isJs ? - ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 : - ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, + Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0 : + Diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0, baseClassName); } - return ts.MemberOverrideStatus.HasInvalidOverride; + return MemberOverrideStatus.HasInvalidOverride; } else if (prop && baseProp?.declarations && compilerOptions.noImplicitOverride && !nodeInAmbientContext) { - const baseHasAbstract = ts.some(baseProp.declarations, ts.hasAbstractModifier); + const baseHasAbstract = some(baseProp.declarations, hasAbstractModifier); if (memberHasOverrideModifier) { - return ts.MemberOverrideStatus.Ok; + return MemberOverrideStatus.Ok; } if (!baseHasAbstract) { if (errorNode) { const diag = memberIsParameterProperty ? isJs ? - ts.Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : - ts.Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 : + Diagnostics.This_parameter_property_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : + Diagnostics.This_parameter_property_must_have_an_override_modifier_because_it_overrides_a_member_in_base_class_0 : isJs ? - ts.Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : - ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0; + Diagnostics.This_member_must_have_a_JSDoc_comment_with_an_override_tag_because_it_overrides_a_member_in_the_base_class_0 : + Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_a_member_in_the_base_class_0; error(errorNode, diag, baseClassName); } - return ts.MemberOverrideStatus.NeedsOverride; + return MemberOverrideStatus.NeedsOverride; } else if (memberHasAbstractModifier && baseHasAbstract) { if (errorNode) { - error(errorNode, ts.Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0, baseClassName); + error(errorNode, Diagnostics.This_member_must_have_an_override_modifier_because_it_overrides_an_abstract_method_that_is_declared_in_the_base_class_0, baseClassName); } - return ts.MemberOverrideStatus.NeedsOverride; + return MemberOverrideStatus.NeedsOverride; } } } @@ -40553,21 +40751,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { error( errorNode, isJs ? - ts.Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class : - ts.Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class, + Diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_its_containing_class_0_does_not_extend_another_class : + Diagnostics.This_member_cannot_have_an_override_modifier_because_its_containing_class_0_does_not_extend_another_class, className); } - return ts.MemberOverrideStatus.HasInvalidOverride; + return MemberOverrideStatus.HasInvalidOverride; } - return ts.MemberOverrideStatus.Ok; + return MemberOverrideStatus.Ok; } - function issueMemberSpecificError(node: ts.ClassLikeDeclaration, typeWithThis: ts.Type, baseWithThis: ts.Type, broadDiag: ts.DiagnosticMessage) { + function issueMemberSpecificError(node: ClassLikeDeclaration, typeWithThis: Type, baseWithThis: Type, broadDiag: DiagnosticMessage) { // iterate over all implemented properties and issue errors on each one which isn't compatible, rather than the class as a whole, if possible let issuedMemberError = false; for (const member of node.members) { - if (ts.isStatic(member)) { + if (isStatic(member)) { continue; } const declaredProp = member.name && getSymbolAtLocation(member.name) || getSymbolAtLocation(member); @@ -40575,9 +40773,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const prop = getPropertyOfType(typeWithThis, declaredProp.escapedName); const baseProp = getPropertyOfType(baseWithThis, declaredProp.escapedName); if (prop && baseProp) { - const rootChain = () => ts.chainDiagnosticMessages( + const rootChain = () => chainDiagnosticMessages( /*details*/ undefined, - ts.Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, + Diagnostics.Property_0_in_type_1_is_not_assignable_to_the_same_property_in_base_type_2, symbolToString(declaredProp), typeToString(typeWithThis), typeToString(baseWithThis) @@ -40594,14 +40792,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkBaseTypeAccessibility(type: ts.Type, node: ts.ExpressionWithTypeArguments) { - const signatures = getSignaturesOfType(type, ts.SignatureKind.Construct); + function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) { + const signatures = getSignaturesOfType(type, SignatureKind.Construct); if (signatures.length) { const declaration = signatures[0].declaration; - if (declaration && ts.hasEffectiveModifier(declaration, ts.ModifierFlags.Private)) { - const typeClassDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol)!; + if (declaration && hasEffectiveModifier(declaration, ModifierFlags.Private)) { + const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol)!; if (!isNodeWithinClass(node, typeClassDeclaration)) { - error(node, ts.Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); + error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol)); } } } @@ -40613,26 +40811,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param member Member declaration node. * Note: `member` can be a synthetic node without a parent. */ - function getMemberOverrideModifierStatus(node: ts.ClassLikeDeclaration, member: ts.ClassElement): ts.MemberOverrideStatus { + function getMemberOverrideModifierStatus(node: ClassLikeDeclaration, member: ClassElement): MemberOverrideStatus { if (!member.name) { - return ts.MemberOverrideStatus.Ok; + return MemberOverrideStatus.Ok; } const symbol = getSymbolOfNode(node); - const type = getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType; + const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); - const staticType = getTypeOfSymbol(symbol) as ts.ObjectType; + const staticType = getTypeOfSymbol(symbol) as ObjectType; - const baseTypeNode = ts.getEffectiveBaseTypeNode(node); + const baseTypeNode = getEffectiveBaseTypeNode(node); const baseTypes = baseTypeNode && getBaseTypes(type); - const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(ts.first(baseTypes), type.thisType) : undefined; + const baseWithThis = baseTypes?.length ? getTypeWithThisArgument(first(baseTypes), type.thisType) : undefined; const baseStaticType = getBaseConstructorTypeOfClass(type); const memberHasOverrideModifier = member.parent - ? ts.hasOverrideModifier(member) - : ts.hasSyntacticModifier(member, ts.ModifierFlags.Override); + ? hasOverrideModifier(member) + : hasSyntacticModifier(member, ModifierFlags.Override); - const memberName = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(member.name)); + const memberName = unescapeLeadingUnderscores(getTextOfPropertyName(member.name)); return checkMemberForOverrideModifier( node, @@ -40642,25 +40840,25 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { type, typeWithThis, memberHasOverrideModifier, - ts.hasAbstractModifier(member), - ts.isStatic(member), + hasAbstractModifier(member), + isStatic(member), /* memberIsParameterProperty */ false, memberName, ); } - function getTargetSymbol(s: ts.Symbol) { + function getTargetSymbol(s: Symbol) { // if symbol is instantiated its flags are not copied from the 'target' // so we'll need to get back original 'target' symbol to work with correct set of flags - return ts.getCheckFlags(s) & ts.CheckFlags.Instantiated ? (s as ts.TransientSymbol).target! : s; + return getCheckFlags(s) & CheckFlags.Instantiated ? (s as TransientSymbol).target! : s; } - function getClassOrInterfaceDeclarationsOfSymbol(symbol: ts.Symbol) { - return ts.filter(symbol.declarations, (d: ts.Declaration): d is ts.ClassDeclaration | ts.InterfaceDeclaration => - d.kind === ts.SyntaxKind.ClassDeclaration || d.kind === ts.SyntaxKind.InterfaceDeclaration); + function getClassOrInterfaceDeclarationsOfSymbol(symbol: Symbol) { + return filter(symbol.declarations, (d: Declaration): d is ClassDeclaration | InterfaceDeclaration => + d.kind === SyntaxKind.ClassDeclaration || d.kind === SyntaxKind.InterfaceDeclaration); } - function checkKindsOfPropertyMemberOverrides(type: ts.InterfaceType, baseType: ts.BaseType): void { + function checkKindsOfPropertyMemberOverrides(type: InterfaceType, baseType: BaseType): void { // TypeScript 1.0 spec (April 2014): 8.2.3 // A derived class inherits all members from its base class it doesn't override. // Inheritance means that a derived class implicitly contains all non - overridden members of the base class. @@ -40680,7 +40878,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { basePropertyCheck: for (const baseProperty of baseProperties) { const base = getTargetSymbol(baseProperty); - if (base.flags & ts.SymbolFlags.Prototype) { + if (base.flags & SymbolFlags.Prototype) { continue; } const baseSymbol = getPropertyOfObjectType(type, base.escapedName); @@ -40688,21 +40886,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { continue; } const derived = getTargetSymbol(baseSymbol); - const baseDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(base); + const baseDeclarationFlags = getDeclarationModifierFlagsFromSymbol(base); - ts.Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); + Debug.assert(!!derived, "derived should point to something, even if it is the base class' declaration."); // In order to resolve whether the inherited method was overridden in the base class or not, // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* // type declaration, derived and base resolve to the same symbol even in the case of generic classes. if (derived === base) { // derived class inherits base without override/redeclaration - const derivedClassDecl = ts.getClassLikeDeclarationOfSymbol(type.symbol)!; + const derivedClassDecl = getClassLikeDeclarationOfSymbol(type.symbol)!; // It is an error to inherit an abstract member without implementing it or being declared abstract. // If there is no declaration for the derived class (as in the case of class expressions), // then the class cannot be declared abstract. - if (baseDeclarationFlags & ts.ModifierFlags.Abstract && (!derivedClassDecl || !ts.hasSyntacticModifier(derivedClassDecl, ts.ModifierFlags.Abstract))) { + if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasSyntacticModifier(derivedClassDecl, ModifierFlags.Abstract))) { // Searches other base types for a declaration that would satisfy the inherited abstract member. // (The class may have more than one base type via declaration merging with an interface with the // same name.) @@ -40715,64 +40913,64 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (derivedClassDecl.kind === ts.SyntaxKind.ClassExpression) { - error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, + if (derivedClassDecl.kind === SyntaxKind.ClassExpression) { + error(derivedClassDecl, Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1, symbolToString(baseProperty), typeToString(baseType)); } else { - error(derivedClassDecl, ts.Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, + error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, typeToString(type), symbolToString(baseProperty), typeToString(baseType)); } } } else { // derived overrides base. - const derivedDeclarationFlags = ts.getDeclarationModifierFlagsFromSymbol(derived); - if (baseDeclarationFlags & ts.ModifierFlags.Private || derivedDeclarationFlags & ts.ModifierFlags.Private) { + const derivedDeclarationFlags = getDeclarationModifierFlagsFromSymbol(derived); + if (baseDeclarationFlags & ModifierFlags.Private || derivedDeclarationFlags & ModifierFlags.Private) { // either base or derived property is private - not override, skip it continue; } - let errorMessage: ts.DiagnosticMessage; - const basePropertyFlags = base.flags & ts.SymbolFlags.PropertyOrAccessor; - const derivedPropertyFlags = derived.flags & ts.SymbolFlags.PropertyOrAccessor; + let errorMessage: DiagnosticMessage; + const basePropertyFlags = base.flags & SymbolFlags.PropertyOrAccessor; + const derivedPropertyFlags = derived.flags & SymbolFlags.PropertyOrAccessor; if (basePropertyFlags && derivedPropertyFlags) { // property/accessor is overridden with property/accessor - if ((ts.getCheckFlags(base) & ts.CheckFlags.Synthetic + if ((getCheckFlags(base) & CheckFlags.Synthetic ? base.declarations?.some(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags)) : base.declarations?.every(d => isPropertyAbstractOrInterface(d, baseDeclarationFlags))) - || ts.getCheckFlags(base) & ts.CheckFlags.Mapped - || derived.valueDeclaration && ts.isBinaryExpression(derived.valueDeclaration)) { + || getCheckFlags(base) & CheckFlags.Mapped + || derived.valueDeclaration && isBinaryExpression(derived.valueDeclaration)) { // when the base property is abstract or from an interface, base/derived flags don't need to match // for intersection properties, this must be true of *any* of the declarations, for others it must be true of *all* // same when the derived property is from an assignment continue; } - const overriddenInstanceProperty = basePropertyFlags !== ts.SymbolFlags.Property && derivedPropertyFlags === ts.SymbolFlags.Property; - const overriddenInstanceAccessor = basePropertyFlags === ts.SymbolFlags.Property && derivedPropertyFlags !== ts.SymbolFlags.Property; + const overriddenInstanceProperty = basePropertyFlags !== SymbolFlags.Property && derivedPropertyFlags === SymbolFlags.Property; + const overriddenInstanceAccessor = basePropertyFlags === SymbolFlags.Property && derivedPropertyFlags !== SymbolFlags.Property; if (overriddenInstanceProperty || overriddenInstanceAccessor) { const errorMessage = overriddenInstanceProperty ? - ts.Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property : - ts.Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor; - error(ts.getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type)); + Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property : + Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor; + error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type)); } else if (useDefineForClassFields) { - const uninitialized = derived.declarations?.find(d => d.kind === ts.SyntaxKind.PropertyDeclaration && !(d as ts.PropertyDeclaration).initializer); + const uninitialized = derived.declarations?.find(d => d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer); if (uninitialized - && !(derived.flags & ts.SymbolFlags.Transient) - && !(baseDeclarationFlags & ts.ModifierFlags.Abstract) - && !(derivedDeclarationFlags & ts.ModifierFlags.Abstract) - && !derived.declarations?.some(d => !!(d.flags & ts.NodeFlags.Ambient))) { - const constructor = findConstructorDeclaration(ts.getClassLikeDeclarationOfSymbol(type.symbol)!); - const propName = (uninitialized as ts.PropertyDeclaration).name; - if ((uninitialized as ts.PropertyDeclaration).exclamationToken + && !(derived.flags & SymbolFlags.Transient) + && !(baseDeclarationFlags & ModifierFlags.Abstract) + && !(derivedDeclarationFlags & ModifierFlags.Abstract) + && !derived.declarations?.some(d => !!(d.flags & NodeFlags.Ambient))) { + const constructor = findConstructorDeclaration(getClassLikeDeclarationOfSymbol(type.symbol)!); + const propName = (uninitialized as PropertyDeclaration).name; + if ((uninitialized as PropertyDeclaration).exclamationToken || !constructor - || !ts.isIdentifier(propName) + || !isIdentifier(propName) || !strictNullChecks || !isPropertyInitializedInConstructor(propName, type, constructor)) { - const errorMessage = ts.Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration; - error(ts.getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType)); + const errorMessage = Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration; + error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType)); } } } @@ -40781,38 +40979,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { continue; } else if (isPrototypeProperty(base)) { - if (isPrototypeProperty(derived) || derived.flags & ts.SymbolFlags.Property) { + if (isPrototypeProperty(derived) || derived.flags & SymbolFlags.Property) { // method is overridden with method or property -- correct case continue; } else { - ts.Debug.assert(!!(derived.flags & ts.SymbolFlags.Accessor)); - errorMessage = ts.Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; + Debug.assert(!!(derived.flags & SymbolFlags.Accessor)); + errorMessage = Diagnostics.Class_0_defines_instance_member_function_1_but_extended_class_2_defines_it_as_instance_member_accessor; } } - else if (base.flags & ts.SymbolFlags.Accessor) { - errorMessage = ts.Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; + else if (base.flags & SymbolFlags.Accessor) { + errorMessage = Diagnostics.Class_0_defines_instance_member_accessor_1_but_extended_class_2_defines_it_as_instance_member_function; } else { - errorMessage = ts.Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function; + errorMessage = Diagnostics.Class_0_defines_instance_member_property_1_but_extended_class_2_defines_it_as_instance_member_function; } - error(ts.getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); + error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, typeToString(baseType), symbolToString(base), typeToString(type)); } } } - function isPropertyAbstractOrInterface(declaration: ts.Declaration, baseDeclarationFlags: ts.ModifierFlags) { - return baseDeclarationFlags & ts.ModifierFlags.Abstract && (!ts.isPropertyDeclaration(declaration) || !declaration.initializer) - || ts.isInterfaceDeclaration(declaration.parent); + function isPropertyAbstractOrInterface(declaration: Declaration, baseDeclarationFlags: ModifierFlags) { + return baseDeclarationFlags & ModifierFlags.Abstract && (!isPropertyDeclaration(declaration) || !declaration.initializer) + || isInterfaceDeclaration(declaration.parent); } - function getNonInheritedProperties(type: ts.InterfaceType, baseTypes: ts.BaseType[], properties: ts.Symbol[]) { - if (!ts.length(baseTypes)) { + function getNonInheritedProperties(type: InterfaceType, baseTypes: BaseType[], properties: Symbol[]) { + if (!length(baseTypes)) { return properties; } - const seen = new ts.Map(); - ts.forEach(properties, p => { + const seen = new Map<__String, Symbol>(); + forEach(properties, p => { seen.set(p.escapedName, p); }); @@ -40826,18 +41024,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - return ts.arrayFrom(seen.values()); + return arrayFrom(seen.values()); } - function checkInheritedPropertiesAreIdentical(type: ts.InterfaceType, typeNode: ts.Node): boolean { + function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean { const baseTypes = getBaseTypes(type); if (baseTypes.length < 2) { return true; } - interface InheritanceInfoMap { prop: ts.Symbol; containingType: ts.Type; } - const seen = new ts.Map(); - ts.forEach(resolveDeclaredMembers(type).declaredProperties, p => { + interface InheritanceInfoMap { prop: Symbol; containingType: Type; } + const seen = new Map<__String, InheritanceInfoMap>(); + forEach(resolveDeclaredMembers(type).declaredProperties, p => { seen.set(p.escapedName, { prop: p, containingType: type }); }); let ok = true; @@ -40857,9 +41055,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const typeName1 = typeToString(existing.containingType); const typeName2 = typeToString(base); - let errorInfo = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); - errorInfo = ts.chainDiagnosticMessages(errorInfo, ts.Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2); - diagnostics.add(ts.createDiagnosticForNodeFromMessageChain(typeNode, errorInfo)); + let errorInfo = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Named_property_0_of_types_1_and_2_are_not_identical, symbolToString(prop), typeName1, typeName2); + errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Interface_0_cannot_simultaneously_extend_types_1_and_2, typeToString(type), typeName1, typeName2); + diagnostics.add(createDiagnosticForNodeFromMessageChain(typeNode, errorInfo)); } } } @@ -40868,22 +41066,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return ok; } - function checkPropertyInitialization(node: ts.ClassLikeDeclaration) { - if (!strictNullChecks || !strictPropertyInitialization || node.flags & ts.NodeFlags.Ambient) { + function checkPropertyInitialization(node: ClassLikeDeclaration) { + if (!strictNullChecks || !strictPropertyInitialization || node.flags & NodeFlags.Ambient) { return; } const constructor = findConstructorDeclaration(node); for (const member of node.members) { - if (ts.getEffectiveModifierFlags(member) & ts.ModifierFlags.Ambient) { + if (getEffectiveModifierFlags(member) & ModifierFlags.Ambient) { continue; } - if (!ts.isStatic(member) && isPropertyWithoutInitializer(member)) { - const propName = (member as ts.PropertyDeclaration).name; - if (ts.isIdentifier(propName) || ts.isPrivateIdentifier(propName) || ts.isComputedPropertyName(propName)) { + if (!isStatic(member) && isPropertyWithoutInitializer(member)) { + const propName = (member as PropertyDeclaration).name; + if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) { const type = getTypeOfSymbol(getSymbolOfNode(member)); - if (!(type.flags & ts.TypeFlags.AnyOrUnknown || containsUndefinedType(type))) { + if (!(type.flags & TypeFlags.AnyOrUnknown || containsUndefinedType(type))) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { - error(member.name, ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, ts.declarationNameToString(propName)); + error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); } } } @@ -40891,20 +41089,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isPropertyWithoutInitializer(node: ts.Node) { - return node.kind === ts.SyntaxKind.PropertyDeclaration && - !ts.hasAbstractModifier(node) && - !(node as ts.PropertyDeclaration).exclamationToken && - !(node as ts.PropertyDeclaration).initializer; + function isPropertyWithoutInitializer(node: Node) { + return node.kind === SyntaxKind.PropertyDeclaration && + !hasAbstractModifier(node) && + !(node as PropertyDeclaration).exclamationToken && + !(node as PropertyDeclaration).initializer; } - function isPropertyInitializedInStaticBlocks(propName: ts.Identifier | ts.PrivateIdentifier, propType: ts.Type, staticBlocks: readonly ts.ClassStaticBlockDeclaration[], startPos: number, endPos: number) { + function isPropertyInitializedInStaticBlocks(propName: Identifier | PrivateIdentifier, propType: Type, staticBlocks: readonly ClassStaticBlockDeclaration[], startPos: number, endPos: number) { for (const staticBlock of staticBlocks) { // static block must be within the provided range as they are evaluated in document order (unlike constructors) if (staticBlock.pos >= startPos && staticBlock.pos <= endPos) { - const reference = ts.factory.createPropertyAccessExpression(ts.factory.createThis(), propName); - ts.setParent(reference.expression, reference); - ts.setParent(reference, staticBlock); + const reference = factory.createPropertyAccessExpression(factory.createThis(), propName); + setParent(reference.expression, reference); + setParent(reference, staticBlock); reference.flowNode = staticBlock.returnFlowNode; const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); if (!containsUndefinedType(flowType)) { @@ -40915,53 +41113,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isPropertyInitializedInConstructor(propName: ts.Identifier | ts.PrivateIdentifier | ts.ComputedPropertyName, propType: ts.Type, constructor: ts.ConstructorDeclaration) { - const reference = ts.isComputedPropertyName(propName) - ? ts.factory.createElementAccessExpression(ts.factory.createThis(), propName.expression) - : ts.factory.createPropertyAccessExpression(ts.factory.createThis(), propName); - ts.setParent(reference.expression, reference); - ts.setParent(reference, constructor); + function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier | ComputedPropertyName, propType: Type, constructor: ConstructorDeclaration) { + const reference = isComputedPropertyName(propName) + ? factory.createElementAccessExpression(factory.createThis(), propName.expression) + : factory.createPropertyAccessExpression(factory.createThis(), propName); + setParent(reference.expression, reference); + setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); return !containsUndefinedType(flowType); } - function checkInterfaceDeclaration(node: ts.InterfaceDeclaration) { + function checkInterfaceDeclaration(node: InterfaceDeclaration) { // Grammar checking if (!checkGrammarDecoratorsAndModifiers(node)) checkGrammarInterfaceDeclaration(node); checkTypeParameters(node.typeParameters); addLazyDiagnostic(() => { - checkTypeNameIsReserved(node.name, ts.Diagnostics.Interface_name_cannot_be_0); + checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0); checkExportsOnMergedDeclarations(node); const symbol = getSymbolOfNode(node); checkTypeParameterListsIdentical(symbol); // Only check this symbol once - const firstInterfaceDecl = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.InterfaceDeclaration); + const firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); if (node === firstInterfaceDecl) { - const type = getDeclaredTypeOfSymbol(symbol) as ts.InterfaceType; + const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); // run subsequent checks only if first set succeeded if (checkInheritedPropertiesAreIdentical(type, node.name)) { for (const baseType of getBaseTypes(type)) { - checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name, ts.Diagnostics.Interface_0_incorrectly_extends_interface_1); + checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(baseType, type.thisType), node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1); } checkIndexConstraints(type, symbol); } } checkObjectTypeForDuplicateDeclarations(node); }); - ts.forEach(ts.getInterfaceBaseTypeNodes(node), heritageElement => { - if (!ts.isEntityNameExpression(heritageElement.expression) || ts.isOptionalChain(heritageElement.expression)) { - error(heritageElement.expression, ts.Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments); + forEach(getInterfaceBaseTypeNodes(node), heritageElement => { + if (!isEntityNameExpression(heritageElement.expression) || isOptionalChain(heritageElement.expression)) { + error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments); } checkTypeReferenceNode(heritageElement); }); - ts.forEach(node.members, checkSourceElement); + forEach(node.members, checkSourceElement); addLazyDiagnostic(() => { checkTypeForDuplicateIndexSignatures(node); @@ -40969,15 +41167,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function checkTypeAliasDeclaration(node: ts.TypeAliasDeclaration) { + function checkTypeAliasDeclaration(node: TypeAliasDeclaration) { // Grammar checking checkGrammarDecoratorsAndModifiers(node); - checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_alias_name_cannot_be_0); + checkTypeNameIsReserved(node.name, Diagnostics.Type_alias_name_cannot_be_0); checkExportsOnMergedDeclarations(node); checkTypeParameters(node.typeParameters); - if (node.type.kind === ts.SyntaxKind.IntrinsicKeyword) { - if (!intrinsicTypeKinds.has(node.name.escapedText as string) || ts.length(node.typeParameters) !== 1) { - error(node.type, ts.Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); + if (node.type.kind === SyntaxKind.IntrinsicKeyword) { + if (!intrinsicTypeKinds.has(node.name.escapedText as string) || length(node.typeParameters) !== 1) { + error(node.type, Diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types); } } else { @@ -40986,10 +41184,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function computeEnumMemberValues(node: ts.EnumDeclaration) { + function computeEnumMemberValues(node: EnumDeclaration) { const nodeLinks = getNodeLinks(node); - if (!(nodeLinks.flags & ts.NodeCheckFlags.EnumValuesComputed)) { - nodeLinks.flags |= ts.NodeCheckFlags.EnumValuesComputed; + if (!(nodeLinks.flags & NodeCheckFlags.EnumValuesComputed)) { + nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed; let autoValue: number | undefined = 0; for (const member of node.members) { const value = computeMemberValue(member, autoValue); @@ -40999,14 +41197,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function computeMemberValue(member: ts.EnumMember, autoValue: number | undefined) { - if (ts.isComputedNonLiteralName(member.name)) { - error(member.name, ts.Diagnostics.Computed_property_names_are_not_allowed_in_enums); + function computeMemberValue(member: EnumMember, autoValue: number | undefined) { + if (isComputedNonLiteralName(member.name)) { + error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); } else { - const text = ts.getTextOfPropertyName(member.name); - if (ts.isNumericLiteralName(text) && !ts.isInfinityOrNaNString(text)) { - error(member.name, ts.Diagnostics.An_enum_member_cannot_have_a_numeric_name); + const text = getTextOfPropertyName(member.name); + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { + error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } if (member.initializer) { @@ -41014,7 +41212,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // In ambient non-const numeric enum declarations, enum members without initializers are // considered computed members (as opposed to having auto-incremented values). - if (member.parent.flags & ts.NodeFlags.Ambient && !ts.isEnumConst(member.parent)) { + if (member.parent.flags & NodeFlags.Ambient && !isEnumConst(member.parent)) { return undefined; } // If the member declaration specifies no value, the member is considered a constant enum member. @@ -41024,94 +41222,94 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (autoValue !== undefined) { return autoValue; } - error(member.name, ts.Diagnostics.Enum_member_must_have_initializer); + error(member.name, Diagnostics.Enum_member_must_have_initializer); return undefined; } - function computeConstantValue(member: ts.EnumMember): string | number | undefined { - const isConstEnum = ts.isEnumConst(member.parent); + function computeConstantValue(member: EnumMember): string | number | undefined { + const isConstEnum = isEnumConst(member.parent); const initializer = member.initializer!; const value = evaluate(initializer, member); if (value !== undefined) { if (isConstEnum && typeof value === "number" && !isFinite(value)) { error(initializer, isNaN(value) ? - ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : - ts.Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); + Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : + Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); } } else if (isConstEnum) { - error(initializer, ts.Diagnostics.const_enum_member_initializers_must_be_constant_expressions); + error(initializer, Diagnostics.const_enum_member_initializers_must_be_constant_expressions); } - else if (member.parent.flags & ts.NodeFlags.Ambient) { - error(initializer, ts.Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); + else if (member.parent.flags & NodeFlags.Ambient) { + error(initializer, Diagnostics.In_ambient_enum_declarations_member_initializer_must_be_constant_expression); } else { - checkTypeAssignableTo(checkExpression(initializer), numberType, initializer, ts.Diagnostics.Type_0_is_not_assignable_to_type_1_as_required_for_computed_enum_member_values); + checkTypeAssignableTo(checkExpression(initializer), numberType, initializer, Diagnostics.Type_0_is_not_assignable_to_type_1_as_required_for_computed_enum_member_values); } return value; } - function evaluate(expr: ts.Expression, location: ts.Declaration): string | number | undefined { + function evaluate(expr: Expression, location: Declaration): string | number | undefined { switch (expr.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: - const value = evaluate((expr as ts.PrefixUnaryExpression).operand, location); + case SyntaxKind.PrefixUnaryExpression: + const value = evaluate((expr as PrefixUnaryExpression).operand, location); if (typeof value === "number") { - switch ((expr as ts.PrefixUnaryExpression).operator) { - case ts.SyntaxKind.PlusToken: return value; - case ts.SyntaxKind.MinusToken: return -value; - case ts.SyntaxKind.TildeToken: return ~value; + switch ((expr as PrefixUnaryExpression).operator) { + case SyntaxKind.PlusToken: return value; + case SyntaxKind.MinusToken: return -value; + case SyntaxKind.TildeToken: return ~value; } } break; - case ts.SyntaxKind.BinaryExpression: - const left = evaluate((expr as ts.BinaryExpression).left, location); - const right = evaluate((expr as ts.BinaryExpression).right, location); + case SyntaxKind.BinaryExpression: + const left = evaluate((expr as BinaryExpression).left, location); + const right = evaluate((expr as BinaryExpression).right, location); if (typeof left === "number" && typeof right === "number") { - switch ((expr as ts.BinaryExpression).operatorToken.kind) { - case ts.SyntaxKind.BarToken: return left | right; - case ts.SyntaxKind.AmpersandToken: return left & right; - case ts.SyntaxKind.GreaterThanGreaterThanToken: return left >> right; - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right; - case ts.SyntaxKind.LessThanLessThanToken: return left << right; - case ts.SyntaxKind.CaretToken: return left ^ right; - case ts.SyntaxKind.AsteriskToken: return left * right; - case ts.SyntaxKind.SlashToken: return left / right; - case ts.SyntaxKind.PlusToken: return left + right; - case ts.SyntaxKind.MinusToken: return left - right; - case ts.SyntaxKind.PercentToken: return left % right; - case ts.SyntaxKind.AsteriskAsteriskToken: return left ** right; + switch ((expr as BinaryExpression).operatorToken.kind) { + case SyntaxKind.BarToken: return left | right; + case SyntaxKind.AmpersandToken: return left & right; + case SyntaxKind.GreaterThanGreaterThanToken: return left >> right; + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: return left >>> right; + case SyntaxKind.LessThanLessThanToken: return left << right; + case SyntaxKind.CaretToken: return left ^ right; + case SyntaxKind.AsteriskToken: return left * right; + case SyntaxKind.SlashToken: return left / right; + case SyntaxKind.PlusToken: return left + right; + case SyntaxKind.MinusToken: return left - right; + case SyntaxKind.PercentToken: return left % right; + case SyntaxKind.AsteriskAsteriskToken: return left ** right; } } else if ((typeof left === "string" || typeof left === "number") && (typeof right === "string" || typeof right === "number") && - (expr as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.PlusToken) { + (expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken) { return "" + left + right; } break; - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - return (expr as ts.StringLiteralLike).text; - case ts.SyntaxKind.TemplateExpression: - return evaluateTemplateExpression(expr as ts.TemplateExpression, location); - case ts.SyntaxKind.NumericLiteral: - checkGrammarNumericLiteral(expr as ts.NumericLiteral); - return +(expr as ts.NumericLiteral).text; - case ts.SyntaxKind.ParenthesizedExpression: - return evaluate((expr as ts.ParenthesizedExpression).expression, location); - case ts.SyntaxKind.Identifier: - if (ts.isInfinityOrNaNString((expr as ts.Identifier).escapedText)) { - return +((expr as ts.Identifier).escapedText); + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return (expr as StringLiteralLike).text; + case SyntaxKind.TemplateExpression: + return evaluateTemplateExpression(expr as TemplateExpression, location); + case SyntaxKind.NumericLiteral: + checkGrammarNumericLiteral(expr as NumericLiteral); + return +(expr as NumericLiteral).text; + case SyntaxKind.ParenthesizedExpression: + return evaluate((expr as ParenthesizedExpression).expression, location); + case SyntaxKind.Identifier: + if (isInfinityOrNaNString((expr as Identifier).escapedText)) { + return +((expr as Identifier).escapedText); } // falls through - case ts.SyntaxKind.PropertyAccessExpression: - if (ts.isEntityNameExpression(expr)) { - const symbol = resolveEntityName(expr, ts.SymbolFlags.Value, /*ignoreErrors*/ true); + case SyntaxKind.PropertyAccessExpression: + if (isEntityNameExpression(expr)) { + const symbol = resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true); if (symbol) { - if (symbol.flags & ts.SymbolFlags.EnumMember) { + if (symbol.flags & SymbolFlags.EnumMember) { return evaluateEnumMember(expr, symbol, location); } if (isConstVariable(symbol)) { - const declaration = symbol.valueDeclaration as ts.VariableDeclaration | undefined; + const declaration = symbol.valueDeclaration as VariableDeclaration | undefined; if (declaration && !declaration.type && declaration.initializer && declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location)) { return evaluate(declaration.initializer, declaration); } @@ -41119,12 +41317,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } break; - case ts.SyntaxKind.ElementAccessExpression: - const root = (expr as ts.ElementAccessExpression).expression; - if (ts.isEntityNameExpression(root) && ts.isStringLiteralLike((expr as ts.ElementAccessExpression).argumentExpression)) { - const rootSymbol = resolveEntityName(root, ts.SymbolFlags.Value, /*ignoreErrors*/ true); - if (rootSymbol && rootSymbol.flags & ts.SymbolFlags.Enum) { - const name = ts.escapeLeadingUnderscores(((expr as ts.ElementAccessExpression).argumentExpression as ts.StringLiteralLike).text); + case SyntaxKind.ElementAccessExpression: + const root = (expr as ElementAccessExpression).expression; + if (isEntityNameExpression(root) && isStringLiteralLike((expr as ElementAccessExpression).argumentExpression)) { + const rootSymbol = resolveEntityName(root, SymbolFlags.Value, /*ignoreErrors*/ true); + if (rootSymbol && rootSymbol.flags & SymbolFlags.Enum) { + const name = escapeLeadingUnderscores(((expr as ElementAccessExpression).argumentExpression as StringLiteralLike).text); const member = rootSymbol.exports!.get(name); if (member) { return evaluateEnumMember(expr, member, location); @@ -41136,20 +41334,20 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function evaluateEnumMember(expr: ts.Expression, symbol: ts.Symbol, location: ts.Declaration) { + function evaluateEnumMember(expr: Expression, symbol: Symbol, location: Declaration) { const declaration = symbol.valueDeclaration; if (!declaration || declaration === location) { - error(expr, ts.Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(symbol)); + error(expr, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(symbol)); return undefined; } if (!isBlockScopedNameDeclaredBeforeUse(declaration, location)) { - error(expr, ts.Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); + error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums); return 0; } - return getEnumMemberValue(declaration as ts.EnumMember); + return getEnumMemberValue(declaration as EnumMember); } - function evaluateTemplateExpression(expr: ts.TemplateExpression, location: ts.Declaration) { + function evaluateTemplateExpression(expr: TemplateExpression, location: Declaration) { let result = expr.head.text; for (const span of expr.templateSpans) { const value = evaluate(span.expression, location); @@ -41162,11 +41360,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function checkEnumDeclaration(node: ts.EnumDeclaration) { + function checkEnumDeclaration(node: EnumDeclaration) { addLazyDiagnostic(() => checkEnumDeclarationWorker(node)); } - function checkEnumDeclarationWorker(node: ts.EnumDeclaration) { + function checkEnumDeclarationWorker(node: EnumDeclaration) { // Grammar checking checkGrammarDecoratorsAndModifiers(node); @@ -41183,26 +41381,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // // Only perform this check once per symbol const enumSymbol = getSymbolOfNode(node); - const firstDeclaration = ts.getDeclarationOfKind(enumSymbol, node.kind); + const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations && enumSymbol.declarations.length > 1) { - const enumIsConst = ts.isEnumConst(node); + const enumIsConst = isEnumConst(node); // check that const is placed\omitted on all enum declarations - ts.forEach(enumSymbol.declarations, decl => { - if (ts.isEnumDeclaration(decl) && ts.isEnumConst(decl) !== enumIsConst) { - error(ts.getNameOfDeclaration(decl), ts.Diagnostics.Enum_declarations_must_all_be_const_or_non_const); + forEach(enumSymbol.declarations, decl => { + if (isEnumDeclaration(decl) && isEnumConst(decl) !== enumIsConst) { + error(getNameOfDeclaration(decl), Diagnostics.Enum_declarations_must_all_be_const_or_non_const); } }); } let seenEnumMissingInitialInitializer = false; - ts.forEach(enumSymbol.declarations, declaration => { + forEach(enumSymbol.declarations, declaration => { // return true if we hit a violation of the rule, false otherwise - if (declaration.kind !== ts.SyntaxKind.EnumDeclaration) { + if (declaration.kind !== SyntaxKind.EnumDeclaration) { return false; } - const enumDeclaration = declaration as ts.EnumDeclaration; + const enumDeclaration = declaration as EnumDeclaration; if (!enumDeclaration.members.length) { return false; } @@ -41210,7 +41408,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const firstEnumMember = enumDeclaration.members[0]; if (!firstEnumMember.initializer) { if (seenEnumMissingInitialInitializer) { - error(firstEnumMember.name, ts.Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element); + error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element); } else { seenEnumMissingInitialInitializer = true; @@ -41220,22 +41418,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkEnumMember(node: ts.EnumMember) { - if (ts.isPrivateIdentifier(node.name)) { - error(node, ts.Diagnostics.An_enum_member_cannot_be_named_with_a_private_identifier); + function checkEnumMember(node: EnumMember) { + if (isPrivateIdentifier(node.name)) { + error(node, Diagnostics.An_enum_member_cannot_be_named_with_a_private_identifier); } if (node.initializer) { checkExpression(node.initializer); } } - function getFirstNonAmbientClassOrFunctionDeclaration(symbol: ts.Symbol): ts.Declaration | undefined { + function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration | undefined { const declarations = symbol.declarations; if (declarations) { for (const declaration of declarations) { - if ((declaration.kind === ts.SyntaxKind.ClassDeclaration || - (declaration.kind === ts.SyntaxKind.FunctionDeclaration && ts.nodeIsPresent((declaration as ts.FunctionLikeDeclaration).body))) && - !(declaration.flags & ts.NodeFlags.Ambient)) { + if ((declaration.kind === SyntaxKind.ClassDeclaration || + (declaration.kind === SyntaxKind.FunctionDeclaration && nodeIsPresent((declaration as FunctionLikeDeclaration).body))) && + !(declaration.flags & NodeFlags.Ambient)) { return declaration; } } @@ -41243,9 +41441,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function inSameLexicalScope(node1: ts.Node, node2: ts.Node) { - const container1 = ts.getEnclosingBlockScopeContainer(node1); - const container2 = ts.getEnclosingBlockScopeContainer(node2); + function inSameLexicalScope(node1: Node, node2: Node) { + const container1 = getEnclosingBlockScopeContainer(node1); + const container2 = getEnclosingBlockScopeContainer(node2); if (isGlobalSourceFile(container1)) { return isGlobalSourceFile(container2); } @@ -41257,10 +41455,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkModuleDeclaration(node: ts.ModuleDeclaration) { + function checkModuleDeclaration(node: ModuleDeclaration) { if (node.body) { checkSourceElement(node.body); - if (!ts.isGlobalScopeAugmentation(node)) { + if (!isGlobalScopeAugmentation(node)) { registerForUnusedIdentifiersCheck(node); } } @@ -41269,28 +41467,28 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { function checkModuleDeclarationDiagnostics() { // Grammar checking - const isGlobalAugmentation = ts.isGlobalScopeAugmentation(node); - const inAmbientContext = node.flags & ts.NodeFlags.Ambient; + const isGlobalAugmentation = isGlobalScopeAugmentation(node); + const inAmbientContext = node.flags & NodeFlags.Ambient; if (isGlobalAugmentation && !inAmbientContext) { - error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); + error(node.name, Diagnostics.Augmentations_for_the_global_scope_should_have_declare_modifier_unless_they_appear_in_already_ambient_context); } - const isAmbientExternalModule: boolean = ts.isAmbientModule(node); + const isAmbientExternalModule: boolean = isAmbientModule(node); const contextErrorMessage = isAmbientExternalModule - ? ts.Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file - : ts.Diagnostics.A_namespace_declaration_is_only_allowed_at_the_top_level_of_a_namespace_or_module; + ? Diagnostics.An_ambient_module_declaration_is_only_allowed_at_the_top_level_in_a_file + : Diagnostics.A_namespace_declaration_is_only_allowed_at_the_top_level_of_a_namespace_or_module; if (checkGrammarModuleElementContext(node, contextErrorMessage)) { // If we hit a module declaration in an illegal context, just bail out to avoid cascading errors. return; } if (!checkGrammarDecoratorsAndModifiers(node)) { - if (!inAmbientContext && node.name.kind === ts.SyntaxKind.StringLiteral) { - grammarErrorOnNode(node.name, ts.Diagnostics.Only_ambient_modules_can_use_quoted_names); + if (!inAmbientContext && node.name.kind === SyntaxKind.StringLiteral) { + grammarErrorOnNode(node.name, Diagnostics.Only_ambient_modules_can_use_quoted_names); } } - if (ts.isIdentifier(node.name)) { + if (isIdentifier(node.name)) { checkCollisionsForDeclarationName(node, node.name); } @@ -41298,38 +41496,38 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const symbol = getSymbolOfNode(node); // The following checks only apply on a non-ambient instantiated module declaration. - if (symbol.flags & ts.SymbolFlags.ValueModule + if (symbol.flags & SymbolFlags.ValueModule && !inAmbientContext && symbol.declarations && symbol.declarations.length > 1 - && isInstantiatedModule(node, ts.shouldPreserveConstEnums(compilerOptions))) { + && isInstantiatedModule(node, shouldPreserveConstEnums(compilerOptions))) { const firstNonAmbientClassOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); if (firstNonAmbientClassOrFunc) { - if (ts.getSourceFileOfNode(node) !== ts.getSourceFileOfNode(firstNonAmbientClassOrFunc)) { - error(node.name, ts.Diagnostics.A_namespace_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged); + if (getSourceFileOfNode(node) !== getSourceFileOfNode(firstNonAmbientClassOrFunc)) { + error(node.name, Diagnostics.A_namespace_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged); } else if (node.pos < firstNonAmbientClassOrFunc.pos) { - error(node.name, ts.Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged); + error(node.name, Diagnostics.A_namespace_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged); } } // if the module merges with a class declaration in the same lexical scope, // we need to track this to ensure the correct emit. - const mergedClass = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ClassDeclaration); + const mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); if (mergedClass && inSameLexicalScope(node, mergedClass)) { - getNodeLinks(node).flags |= ts.NodeCheckFlags.LexicalModuleMergesWithClass; + getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass; } } if (isAmbientExternalModule) { - if (ts.isExternalModuleAugmentation(node)) { + if (isExternalModuleAugmentation(node)) { // body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module) // otherwise we'll be swamped in cascading errors. // We can detect if augmentation was applied using following rules: // - augmentation for a global scope is always applied // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). - const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & ts.SymbolFlags.Transient); + const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Transient); if (checkBody && node.body) { for (const statement of node.body.statements) { checkModuleAugmentationElement(statement, isGlobalAugmentation); @@ -41338,46 +41536,46 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else if (isGlobalSourceFile(node.parent)) { if (isGlobalAugmentation) { - error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); + error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } - else if (ts.isExternalModuleNameRelative(ts.getTextOfIdentifierOrLiteral(node.name))) { - error(node.name, ts.Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); + else if (isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(node.name))) { + error(node.name, Diagnostics.Ambient_module_declaration_cannot_specify_relative_module_name); } } else { if (isGlobalAugmentation) { - error(node.name, ts.Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); + error(node.name, Diagnostics.Augmentations_for_the_global_scope_can_only_be_directly_nested_in_external_modules_or_ambient_module_declarations); } else { // Node is not an augmentation and is not located on the script level. // This means that this is declaration of ambient module that is located in other module or namespace which is prohibited. - error(node.name, ts.Diagnostics.Ambient_modules_cannot_be_nested_in_other_modules_or_namespaces); + error(node.name, Diagnostics.Ambient_modules_cannot_be_nested_in_other_modules_or_namespaces); } } } } } - function checkModuleAugmentationElement(node: ts.Node, isGlobalAugmentation: boolean): void { + function checkModuleAugmentationElement(node: Node, isGlobalAugmentation: boolean): void { switch (node.kind) { - case ts.SyntaxKind.VariableStatement: + case SyntaxKind.VariableStatement: // error each individual name in variable statement instead of marking the entire variable statement - for (const decl of (node as ts.VariableStatement).declarationList.declarations) { + for (const decl of (node as VariableStatement).declarationList.declarations) { checkModuleAugmentationElement(decl, isGlobalAugmentation); } break; - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.ExportDeclaration: - grammarErrorOnFirstToken(node, ts.Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: + grammarErrorOnFirstToken(node, Diagnostics.Exports_and_export_assignments_are_not_permitted_in_module_augmentations); break; - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportDeclaration: - grammarErrorOnFirstToken(node, ts.Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + grammarErrorOnFirstToken(node, Diagnostics.Imports_are_not_permitted_in_module_augmentations_Consider_moving_them_to_the_enclosing_external_module); break; - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.VariableDeclaration: - const name = (node as ts.VariableDeclaration | ts.BindingElement).name; - if (ts.isBindingPattern(name)) { + case SyntaxKind.BindingElement: + case SyntaxKind.VariableDeclaration: + const name = (node as VariableDeclaration | BindingElement).name; + if (isBindingPattern(name)) { for (const el of name.elements) { // mark individual names in binding pattern checkModuleAugmentationElement(el, isGlobalAugmentation); @@ -41385,12 +41583,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { break; } // falls through - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.TypeAliasDeclaration: if (isGlobalAugmentation) { return; } @@ -41398,44 +41596,44 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getFirstNonModuleExportsIdentifier(node: ts.EntityNameOrEntityNameExpression): ts.Identifier { + function getFirstNonModuleExportsIdentifier(node: EntityNameOrEntityNameExpression): Identifier { switch (node.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: return node; - case ts.SyntaxKind.QualifiedName: + case SyntaxKind.QualifiedName: do { node = node.left; - } while (node.kind !== ts.SyntaxKind.Identifier); + } while (node.kind !== SyntaxKind.Identifier); return node; - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAccessExpression: do { - if (ts.isModuleExportsAccessExpression(node.expression) && !ts.isPrivateIdentifier(node.name)) { + if (isModuleExportsAccessExpression(node.expression) && !isPrivateIdentifier(node.name)) { return node.name; } node = node.expression; - } while (node.kind !== ts.SyntaxKind.Identifier); + } while (node.kind !== SyntaxKind.Identifier); return node; } } - function checkExternalImportOrExportDeclaration(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration | ts.ExportDeclaration): boolean { - const moduleName = ts.getExternalModuleName(node); - if (!moduleName || ts.nodeIsMissing(moduleName)) { + function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { + const moduleName = getExternalModuleName(node); + if (!moduleName || nodeIsMissing(moduleName)) { // Should be a parse error. return false; } - if (!ts.isStringLiteral(moduleName)) { - error(moduleName, ts.Diagnostics.String_literal_expected); + if (!isStringLiteral(moduleName)) { + error(moduleName, Diagnostics.String_literal_expected); return false; } - const inAmbientExternalModule = node.parent.kind === ts.SyntaxKind.ModuleBlock && ts.isAmbientModule(node.parent.parent); - if (node.parent.kind !== ts.SyntaxKind.SourceFile && !inAmbientExternalModule) { - error(moduleName, node.kind === ts.SyntaxKind.ExportDeclaration ? - ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace : - ts.Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module); + const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent); + if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) { + error(moduleName, node.kind === SyntaxKind.ExportDeclaration ? + Diagnostics.Export_declarations_are_not_permitted_in_a_namespace : + Diagnostics.Import_declarations_in_a_namespace_cannot_reference_a_module); return false; } - if (inAmbientExternalModule && ts.isExternalModuleNameRelative(moduleName.text)) { + if (inAmbientExternalModule && isExternalModuleNameRelative(moduleName.text)) { // we have already reported errors on top level imports/exports in external module augmentations in checkModuleDeclaration // no need to do this again. if (!isTopLevelInExternalModuleAugmentation(node)) { @@ -41443,16 +41641,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference // other external modules only through top - level external module names. // Relative external module names are not permitted. - error(node, ts.Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name); + error(node, Diagnostics.Import_or_export_declaration_in_an_ambient_module_declaration_cannot_reference_module_through_relative_module_name); return false; } } - if (!ts.isImportEqualsDeclaration(node) && node.assertClause) { + if (!isImportEqualsDeclaration(node) && node.assertClause) { let hasError = false; for (const clause of node.assertClause.elements) { - if (!ts.isStringLiteral(clause.value)) { + if (!isStringLiteral(clause.value)) { hasError = true; - error(clause.value, ts.Diagnostics.Import_assertion_values_must_be_string_literal_expressions); + error(clause.value, Diagnostics.Import_assertion_values_must_be_string_literal_expressions); } } return !hasError; @@ -41460,7 +41658,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } - function checkAliasSymbol(node: ts.ImportEqualsDeclaration | ts.VariableDeclaration | ts.ImportClause | ts.NamespaceImport | ts.ImportSpecifier | ts.ExportSpecifier | ts.NamespaceExport | ts.BindingElement) { + function checkAliasSymbol(node: ImportEqualsDeclaration | VariableDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier | NamespaceExport | BindingElement) { let symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); @@ -41474,34 +41672,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { symbol = getMergedSymbol(symbol.exportSymbol || symbol); // A type-only import/export will already have a grammar error in a JS file, so no need to issue more errors within - if (ts.isInJSFile(node) && !(target.flags & ts.SymbolFlags.Value) && !ts.isTypeOnlyImportOrExportDeclaration(node)) { + if (isInJSFile(node) && !(target.flags & SymbolFlags.Value) && !isTypeOnlyImportOrExportDeclaration(node)) { const errorNode = - ts.isImportOrExportSpecifier(node) ? node.propertyName || node.name : - ts.isNamedDeclaration(node) ? node.name : + isImportOrExportSpecifier(node) ? node.propertyName || node.name : + isNamedDeclaration(node) ? node.name : node; - ts.Debug.assert(node.kind !== ts.SyntaxKind.NamespaceExport); - if (node.kind === ts.SyntaxKind.ExportSpecifier) { - const diag = error(errorNode, ts.Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files); - const alreadyExportedSymbol = ts.getSourceFileOfNode(node).symbol?.exports?.get((node.propertyName || node.name).escapedText); + Debug.assert(node.kind !== SyntaxKind.NamespaceExport); + if (node.kind === SyntaxKind.ExportSpecifier) { + const diag = error(errorNode, Diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files); + const alreadyExportedSymbol = getSourceFileOfNode(node).symbol?.exports?.get((node.propertyName || node.name).escapedText); if (alreadyExportedSymbol === target) { - const exportingDeclaration = alreadyExportedSymbol.declarations?.find(ts.isJSDocNode); + const exportingDeclaration = alreadyExportedSymbol.declarations?.find(isJSDocNode); if (exportingDeclaration) { - ts.addRelatedInfo(diag, ts.createDiagnosticForNode( + addRelatedInfo(diag, createDiagnosticForNode( exportingDeclaration, - ts.Diagnostics._0_is_automatically_exported_here, - ts.unescapeLeadingUnderscores(alreadyExportedSymbol.escapedName))); + Diagnostics._0_is_automatically_exported_here, + unescapeLeadingUnderscores(alreadyExportedSymbol.escapedName))); } } } else { - ts.Debug.assert(node.kind !== ts.SyntaxKind.VariableDeclaration); - const importDeclaration = ts.findAncestor(node, ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration)); - const moduleSpecifier = (importDeclaration && ts.tryGetModuleSpecifierFromDeclaration(importDeclaration)?.text) ?? "..."; - const importedIdentifier = ts.unescapeLeadingUnderscores(ts.isIdentifier(errorNode) ? errorNode.escapedText : symbol.escapedName); + Debug.assert(node.kind !== SyntaxKind.VariableDeclaration); + const importDeclaration = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration)); + const moduleSpecifier = (importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration)?.text) ?? "..."; + const importedIdentifier = unescapeLeadingUnderscores(isIdentifier(errorNode) ? errorNode.escapedText : symbol.escapedName); error( errorNode, - ts.Diagnostics._0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, + Diagnostics._0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, importedIdentifier, `import("${moduleSpecifier}").${importedIdentifier}`); } @@ -41510,52 +41708,52 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const targetFlags = getAllSymbolFlags(target); const excludedMeanings = - (symbol.flags & (ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue) ? ts.SymbolFlags.Value : 0) | - (symbol.flags & ts.SymbolFlags.Type ? ts.SymbolFlags.Type : 0) | - (symbol.flags & ts.SymbolFlags.Namespace ? ts.SymbolFlags.Namespace : 0); + (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | + (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | + (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); if (targetFlags & excludedMeanings) { - const message = node.kind === ts.SyntaxKind.ExportSpecifier ? - ts.Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : - ts.Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; + const message = node.kind === SyntaxKind.ExportSpecifier ? + Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : + Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; error(node, message, symbolToString(symbol)); } if (compilerOptions.isolatedModules - && !ts.isTypeOnlyImportOrExportDeclaration(node) - && !(node.flags & ts.NodeFlags.Ambient)) { + && !isTypeOnlyImportOrExportDeclaration(node) + && !(node.flags & NodeFlags.Ambient)) { const typeOnlyAlias = getTypeOnlyAliasDeclaration(symbol); - const isType = !(targetFlags & ts.SymbolFlags.Value); + const isType = !(targetFlags & SymbolFlags.Value); if (isType || typeOnlyAlias) { switch (node.kind) { - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ImportEqualsDeclaration: { + case SyntaxKind.ImportClause: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: { if (compilerOptions.preserveValueImports) { - ts.Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name"); + Debug.assertIsDefined(node.name, "An ImportClause with a symbol should have a name"); const message = isType - ? ts.Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled - : ts.Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled; - const name = ts.idText(node.kind === ts.SyntaxKind.ImportSpecifier ? node.propertyName || node.name : node.name); + ? Diagnostics._0_is_a_type_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled + : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_imported_using_a_type_only_import_when_preserveValueImports_and_isolatedModules_are_both_enabled; + const name = idText(node.kind === SyntaxKind.ImportSpecifier ? node.propertyName || node.name : node.name); addTypeOnlyDeclarationRelatedInfo( error(node, message, name), isType ? undefined : typeOnlyAlias, name ); } - if (isType && node.kind === ts.SyntaxKind.ImportEqualsDeclaration && ts.hasEffectiveModifier(node, ts.ModifierFlags.Export)) { - error(node, ts.Diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_the_isolatedModules_flag_is_provided); + if (isType && node.kind === SyntaxKind.ImportEqualsDeclaration && hasEffectiveModifier(node, ModifierFlags.Export)) { + error(node, Diagnostics.Cannot_use_export_import_on_a_type_or_type_only_namespace_when_the_isolatedModules_flag_is_provided); } break; } - case ts.SyntaxKind.ExportSpecifier: { + case SyntaxKind.ExportSpecifier: { // Don't allow re-exporting an export that will be elided when `--isolatedModules` is set. // The exception is that `import type { A } from './a'; export { A }` is allowed // because single-file analysis can determine that the export should be dropped. - if (ts.getSourceFileOfNode(typeOnlyAlias) !== ts.getSourceFileOfNode(node)) { + if (getSourceFileOfNode(typeOnlyAlias) !== getSourceFileOfNode(node)) { const message = isType - ? ts.Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type - : ts.Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_isolatedModules_is_enabled; - const name = ts.idText(node.propertyName || node.name); + ? Diagnostics.Re_exporting_a_type_when_the_isolatedModules_flag_is_provided_requires_using_export_type + : Diagnostics._0_resolves_to_a_type_only_declaration_and_must_be_re_exported_using_a_type_only_re_export_when_isolatedModules_is_enabled; + const name = idText(node.propertyName || node.name); addTypeOnlyDeclarationRelatedInfo( error(node, message, name), isType ? undefined : typeOnlyAlias, @@ -41568,7 +41766,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isImportSpecifier(node)) { + if (isImportSpecifier(node)) { const targetSymbol = checkDeprecatedAliasedSymbol(symbol, node); if (isDeprecatedAliasedSymbol(targetSymbol) && targetSymbol.declarations) { addDeprecatedSuggestion(node, targetSymbol.declarations, targetSymbol.escapedName as string); @@ -41577,21 +41775,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isDeprecatedAliasedSymbol(symbol: ts.Symbol) { - return !!symbol.declarations && ts.every(symbol.declarations, d => !!(ts.getCombinedNodeFlags(d) & ts.NodeFlags.Deprecated)); + function isDeprecatedAliasedSymbol(symbol: Symbol) { + return !!symbol.declarations && every(symbol.declarations, d => !!(getCombinedNodeFlags(d) & NodeFlags.Deprecated)); } - function checkDeprecatedAliasedSymbol(symbol: ts.Symbol, location: ts.Node) { - if (!(symbol.flags & ts.SymbolFlags.Alias)) return symbol; + function checkDeprecatedAliasedSymbol(symbol: Symbol, location: Node) { + if (!(symbol.flags & SymbolFlags.Alias)) return symbol; const targetSymbol = resolveAlias(symbol); if (targetSymbol === unknownSymbol) return targetSymbol; - while (symbol.flags & ts.SymbolFlags.Alias) { + while (symbol.flags & SymbolFlags.Alias) { const target = getImmediateAliasedSymbol(symbol); if (target) { if (target === targetSymbol) break; - if (target.declarations && ts.length(target.declarations)) { + if (target.declarations && length(target.declarations)) { if (isDeprecatedAliasedSymbol(target)) { addDeprecatedSuggestion(location, target.declarations, target.escapedName as string); break; @@ -41609,57 +41807,57 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return targetSymbol; } - function checkImportBinding(node: ts.ImportEqualsDeclaration | ts.ImportClause | ts.NamespaceImport | ts.ImportSpecifier) { + function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) { checkCollisionsForDeclarationName(node, node.name); checkAliasSymbol(node); - if (node.kind === ts.SyntaxKind.ImportSpecifier && - ts.idText(node.propertyName || node.name) === "default" && - ts.getESModuleInterop(compilerOptions) && - moduleKind !== ts.ModuleKind.System && (moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS)) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ImportDefault); + if (node.kind === SyntaxKind.ImportSpecifier && + idText(node.propertyName || node.name) === "default" && + getESModuleInterop(compilerOptions) && + moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); } } - function checkAssertClause(declaration: ts.ImportDeclaration | ts.ExportDeclaration) { + function checkAssertClause(declaration: ImportDeclaration | ExportDeclaration) { if (declaration.assertClause) { - const validForTypeAssertions = ts.isExclusivelyTypeOnlyImportOrExport(declaration); - const override = ts.getResolutionModeOverrideForClause(declaration.assertClause, validForTypeAssertions ? grammarErrorOnNode : undefined); + const validForTypeAssertions = isExclusivelyTypeOnlyImportOrExport(declaration); + const override = getResolutionModeOverrideForClause(declaration.assertClause, validForTypeAssertions ? grammarErrorOnNode : undefined); if (validForTypeAssertions && override) { - if (!ts.isNightly()) { - grammarErrorOnNode(declaration.assertClause, ts.Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); + if (!isNightly()) { + grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); } - if (ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Node16 && ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeNext) { - return grammarErrorOnNode(declaration.assertClause, ts.Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { + return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext); } return; // Other grammar checks do not apply to type-only imports with resolution mode assertions } - const mode = (moduleKind === ts.ModuleKind.NodeNext) && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier); - if (mode !== ts.ModuleKind.ESNext && moduleKind !== ts.ModuleKind.ESNext) { + const mode = (moduleKind === ModuleKind.NodeNext) && declaration.moduleSpecifier && getUsageModeForExpression(declaration.moduleSpecifier); + if (mode !== ModuleKind.ESNext && moduleKind !== ModuleKind.ESNext) { return grammarErrorOnNode(declaration.assertClause, - moduleKind === ts.ModuleKind.NodeNext - ? ts.Diagnostics.Import_assertions_are_not_allowed_on_statements_that_transpile_to_commonjs_require_calls - : ts.Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_or_nodenext); + moduleKind === ModuleKind.NodeNext + ? Diagnostics.Import_assertions_are_not_allowed_on_statements_that_transpile_to_commonjs_require_calls + : Diagnostics.Import_assertions_are_only_supported_when_the_module_option_is_set_to_esnext_or_nodenext); } - if (ts.isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) { - return grammarErrorOnNode(declaration.assertClause, ts.Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports); + if (isImportDeclaration(declaration) ? declaration.importClause?.isTypeOnly : declaration.isTypeOnly) { + return grammarErrorOnNode(declaration.assertClause, Diagnostics.Import_assertions_cannot_be_used_with_type_only_imports_or_exports); } if (override) { - return grammarErrorOnNode(declaration.assertClause, ts.Diagnostics.resolution_mode_can_only_be_set_for_type_only_imports); + return grammarErrorOnNode(declaration.assertClause, Diagnostics.resolution_mode_can_only_be_set_for_type_only_imports); } } } - function checkImportDeclaration(node: ts.ImportDeclaration) { - if (checkGrammarModuleElementContext(node, ts.isInJSFile(node) ? ts.Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : ts.Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + function checkImportDeclaration(node: ImportDeclaration) { + if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasEffectiveModifiers(node)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.An_import_declaration_cannot_have_modifiers); + if (!checkGrammarDecoratorsAndModifiers(node) && hasEffectiveModifiers(node)) { + grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers); } if (checkExternalImportOrExportDeclaration(node)) { const importClause = node.importClause; @@ -41668,17 +41866,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkImportBinding(importClause); } if (importClause.namedBindings) { - if (importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { checkImportBinding(importClause.namedBindings); - if (moduleKind !== ts.ModuleKind.System && (moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS) && ts.getESModuleInterop(compilerOptions)) { + if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && getESModuleInterop(compilerOptions)) { // import * as ns from "foo"; - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ImportStar); + checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar); } } else { const moduleExisted = resolveExternalModuleName(node, node.moduleSpecifier); if (moduleExisted) { - ts.forEach(importClause.namedBindings.elements, checkImportBinding); + forEach(importClause.namedBindings.elements, checkImportBinding); } } } @@ -41687,71 +41885,71 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkAssertClause(node); } - function checkImportEqualsDeclaration(node: ts.ImportEqualsDeclaration) { - if (checkGrammarModuleElementContext(node, ts.isInJSFile(node) ? ts.Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : ts.Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + function checkImportEqualsDeclaration(node: ImportEqualsDeclaration) { + if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { // If we hit an import declaration in an illegal context, just bail out to avoid cascading errors. return; } checkGrammarDecoratorsAndModifiers(node); - if (ts.isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { + if (isInternalModuleImportEqualsDeclaration(node) || checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); - if (ts.hasSyntacticModifier(node, ts.ModifierFlags.Export)) { + if (hasSyntacticModifier(node, ModifierFlags.Export)) { markExportAsReferenced(node); } - if (node.moduleReference.kind !== ts.SyntaxKind.ExternalModuleReference) { + if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { const target = resolveAlias(getSymbolOfNode(node)); if (target !== unknownSymbol) { const targetFlags = getAllSymbolFlags(target); - if (targetFlags & ts.SymbolFlags.Value) { + if (targetFlags & SymbolFlags.Value) { // Target is a value symbol, check that it is not hidden by a local declaration with the same name - const moduleName = ts.getFirstIdentifier(node.moduleReference); - if (!(resolveEntityName(moduleName, ts.SymbolFlags.Value | ts.SymbolFlags.Namespace)!.flags & ts.SymbolFlags.Namespace)) { - error(moduleName, ts.Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, ts.declarationNameToString(moduleName)); + const moduleName = getFirstIdentifier(node.moduleReference); + if (!(resolveEntityName(moduleName, SymbolFlags.Value | SymbolFlags.Namespace)!.flags & SymbolFlags.Namespace)) { + error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, declarationNameToString(moduleName)); } } - if (targetFlags & ts.SymbolFlags.Type) { - checkTypeNameIsReserved(node.name, ts.Diagnostics.Import_name_cannot_be_0); + if (targetFlags & SymbolFlags.Type) { + checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); } } if (node.isTypeOnly) { - grammarErrorOnNode(node, ts.Diagnostics.An_import_alias_cannot_use_import_type); + grammarErrorOnNode(node, Diagnostics.An_import_alias_cannot_use_import_type); } } else { - if (moduleKind >= ts.ModuleKind.ES2015 && ts.getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & ts.NodeFlags.Ambient)) { + if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) { // Import equals declaration is deprecated in es6 or above - grammarErrorOnNode(node, ts.Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); + grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead); } } } } - function checkExportDeclaration(node: ts.ExportDeclaration) { - if (checkGrammarModuleElementContext(node, ts.isInJSFile(node) ? ts.Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module : ts.Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { + function checkExportDeclaration(node: ExportDeclaration) { + if (checkGrammarModuleElementContext(node, isInJSFile(node) ? Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module : Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_namespace_or_module)) { // If we hit an export in an illegal context, just bail out to avoid cascading errors. return; } - if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasSyntacticModifiers(node)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_declaration_cannot_have_modifiers); + if (!checkGrammarDecoratorsAndModifiers(node) && hasSyntacticModifiers(node)) { + grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); } - if (node.moduleSpecifier && node.exportClause && ts.isNamedExports(node.exportClause) && ts.length(node.exportClause.elements) && languageVersion === ts.ScriptTarget.ES3) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.CreateBinding); + if (node.moduleSpecifier && node.exportClause && isNamedExports(node.exportClause) && length(node.exportClause.elements) && languageVersion === ScriptTarget.ES3) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.CreateBinding); } checkGrammarExportDeclaration(node); if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { - if (node.exportClause && !ts.isNamespaceExport(node.exportClause)) { + if (node.exportClause && !isNamespaceExport(node.exportClause)) { // export { x, y } // export { x, y } from "foo" - ts.forEach(node.exportClause.elements, checkExportSpecifier); - const inAmbientExternalModule = node.parent.kind === ts.SyntaxKind.ModuleBlock && ts.isAmbientModule(node.parent.parent); - const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === ts.SyntaxKind.ModuleBlock && - !node.moduleSpecifier && node.flags & ts.NodeFlags.Ambient; - if (node.parent.kind !== ts.SyntaxKind.SourceFile && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { - error(node, ts.Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); + forEach(node.exportClause.elements, checkExportSpecifier); + const inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && isAmbientModule(node.parent.parent); + const inAmbientNamespaceDeclaration = !inAmbientExternalModule && node.parent.kind === SyntaxKind.ModuleBlock && + !node.moduleSpecifier && node.flags & NodeFlags.Ambient; + if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule && !inAmbientNamespaceDeclaration) { + error(node, Diagnostics.Export_declarations_are_not_permitted_in_a_namespace); } } else { @@ -41759,23 +41957,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // export * as ns from "foo"; const moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier!); if (moduleSymbol && hasExportAssignmentSymbol(moduleSymbol)) { - error(node.moduleSpecifier, ts.Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); + error(node.moduleSpecifier, Diagnostics.Module_0_uses_export_and_cannot_be_used_with_export_Asterisk, symbolToString(moduleSymbol)); } else if (node.exportClause) { checkAliasSymbol(node.exportClause); } - if (moduleKind !== ts.ModuleKind.System && (moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS)) { + if (moduleKind !== ModuleKind.System && (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS)) { if (node.exportClause) { // export * as ns from "foo"; // For ES2015 modules, we emit it as a pair of `import * as a_1 ...; export { a_1 as ns }` and don't need the helper. // We only use the helper here when in esModuleInterop - if (ts.getESModuleInterop(compilerOptions)) { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ImportStar); + if (getESModuleInterop(compilerOptions)) { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportStar); } } else { // export * from "foo" - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ExportStar); + checkExternalEmitHelpers(node, ExternalEmitHelpers.ExportStar); } } } @@ -41783,40 +41981,40 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkAssertClause(node); } - function checkGrammarExportDeclaration(node: ts.ExportDeclaration): boolean { + function checkGrammarExportDeclaration(node: ExportDeclaration): boolean { if (node.isTypeOnly) { - if (node.exportClause?.kind === ts.SyntaxKind.NamedExports) { + if (node.exportClause?.kind === SyntaxKind.NamedExports) { return checkGrammarNamedImportsOrExports(node.exportClause); } else { - return grammarErrorOnNode(node, ts.Diagnostics.Only_named_exports_may_use_export_type); + return grammarErrorOnNode(node, Diagnostics.Only_named_exports_may_use_export_type); } } return false; } - function checkGrammarModuleElementContext(node: ts.Statement, errorMessage: ts.DiagnosticMessage): boolean { - const isInAppropriateContext = node.parent.kind === ts.SyntaxKind.SourceFile || node.parent.kind === ts.SyntaxKind.ModuleBlock || node.parent.kind === ts.SyntaxKind.ModuleDeclaration; + function checkGrammarModuleElementContext(node: Statement, errorMessage: DiagnosticMessage): boolean { + const isInAppropriateContext = node.parent.kind === SyntaxKind.SourceFile || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.ModuleDeclaration; if (!isInAppropriateContext) { grammarErrorOnFirstToken(node, errorMessage); } return !isInAppropriateContext; } - function importClauseContainsReferencedImport(importClause: ts.ImportClause) { - return ts.forEachImportClauseDeclaration(importClause, declaration => { + function importClauseContainsReferencedImport(importClause: ImportClause) { + return forEachImportClauseDeclaration(importClause, declaration => { return !!getSymbolOfNode(declaration).isReferenced; }); } - function importClauseContainsConstEnumUsedAsValue(importClause: ts.ImportClause) { - return ts.forEachImportClauseDeclaration(importClause, declaration => { + function importClauseContainsConstEnumUsedAsValue(importClause: ImportClause) { + return forEachImportClauseDeclaration(importClause, declaration => { return !!getSymbolLinks(getSymbolOfNode(declaration)).constEnumReferenced; }); } - function canConvertImportDeclarationToTypeOnly(statement: ts.Statement) { - return ts.isImportDeclaration(statement) && + function canConvertImportDeclarationToTypeOnly(statement: Statement) { + return isImportDeclaration(statement) && statement.importClause && !statement.importClause.isTypeOnly && importClauseContainsReferencedImport(statement.importClause) && @@ -41824,96 +42022,96 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { !importClauseContainsConstEnumUsedAsValue(statement.importClause); } - function canConvertImportEqualsDeclarationToTypeOnly(statement: ts.Statement) { - return ts.isImportEqualsDeclaration(statement) && - ts.isExternalModuleReference(statement.moduleReference) && + function canConvertImportEqualsDeclarationToTypeOnly(statement: Statement) { + return isImportEqualsDeclaration(statement) && + isExternalModuleReference(statement.moduleReference) && !statement.isTypeOnly && getSymbolOfNode(statement).isReferenced && !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) && !getSymbolLinks(getSymbolOfNode(statement)).constEnumReferenced; } - function checkImportsForTypeOnlyConversion(sourceFile: ts.SourceFile) { + function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) { for (const statement of sourceFile.statements) { if (canConvertImportDeclarationToTypeOnly(statement) || canConvertImportEqualsDeclarationToTypeOnly(statement)) { error( statement, - ts.Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error); + Diagnostics.This_import_is_never_used_as_a_value_and_must_use_import_type_because_importsNotUsedAsValues_is_set_to_error); } } } - function checkExportSpecifier(node: ts.ExportSpecifier) { + function checkExportSpecifier(node: ExportSpecifier) { checkAliasSymbol(node); - if (ts.getEmitDeclarations(compilerOptions)) { + if (getEmitDeclarations(compilerOptions)) { collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true); } if (!node.parent.parent.moduleSpecifier) { const exportedName = node.propertyName || node.name; // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) - const symbol = resolveName(exportedName, exportedName.escapedText, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias, + const symbol = resolveName(exportedName, exportedName.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); if (symbol && (symbol === undefinedSymbol || symbol === globalThisSymbol || symbol.declarations && isGlobalSourceFile(getDeclarationContainer(symbol.declarations[0])))) { - error(exportedName, ts.Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, ts.idText(exportedName)); + error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName)); } else { if (!node.isTypeOnly && !node.parent.parent.isTypeOnly) { markExportAsReferenced(node); } - const target = symbol && (symbol.flags & ts.SymbolFlags.Alias ? resolveAlias(symbol) : symbol); - if (!target || getAllSymbolFlags(target) & ts.SymbolFlags.Value) { + const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); + if (!target || getAllSymbolFlags(target) & SymbolFlags.Value) { checkExpressionCached(node.propertyName || node.name); } } } else { - if (ts.getESModuleInterop(compilerOptions) && - moduleKind !== ts.ModuleKind.System && - (moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS) && - ts.idText(node.propertyName || node.name) === "default") { - checkExternalEmitHelpers(node, ts.ExternalEmitHelpers.ImportDefault); + if (getESModuleInterop(compilerOptions) && + moduleKind !== ModuleKind.System && + (moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && + idText(node.propertyName || node.name) === "default") { + checkExternalEmitHelpers(node, ExternalEmitHelpers.ImportDefault); } } } - function checkExportAssignment(node: ts.ExportAssignment) { + function checkExportAssignment(node: ExportAssignment) { const illegalContextMessage = node.isExportEquals - ? ts.Diagnostics.An_export_assignment_must_be_at_the_top_level_of_a_file_or_module_declaration - : ts.Diagnostics.A_default_export_must_be_at_the_top_level_of_a_file_or_module_declaration; + ? Diagnostics.An_export_assignment_must_be_at_the_top_level_of_a_file_or_module_declaration + : Diagnostics.A_default_export_must_be_at_the_top_level_of_a_file_or_module_declaration; if (checkGrammarModuleElementContext(node, illegalContextMessage)) { // If we hit an export assignment in an illegal context, just bail out to avoid cascading errors. return; } - const container = node.parent.kind === ts.SyntaxKind.SourceFile ? node.parent : node.parent.parent as ts.ModuleDeclaration; - if (container.kind === ts.SyntaxKind.ModuleDeclaration && !ts.isAmbientModule(container)) { + const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent as ModuleDeclaration; + if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { if (node.isExportEquals) { - error(node, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); + error(node, Diagnostics.An_export_assignment_cannot_be_used_in_a_namespace); } else { - error(node, ts.Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); + error(node, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); } return; } // Grammar checking - if (!checkGrammarDecoratorsAndModifiers(node) && ts.hasEffectiveModifiers(node)) { - grammarErrorOnFirstToken(node, ts.Diagnostics.An_export_assignment_cannot_have_modifiers); + if (!checkGrammarDecoratorsAndModifiers(node) && hasEffectiveModifiers(node)) { + grammarErrorOnFirstToken(node, Diagnostics.An_export_assignment_cannot_have_modifiers); } - const typeAnnotationNode = ts.getEffectiveTypeAnnotationNode(node); + const typeAnnotationNode = getEffectiveTypeAnnotationNode(node); if (typeAnnotationNode) { checkTypeAssignableTo(checkExpressionCached(node.expression), getTypeFromTypeNode(typeAnnotationNode), node.expression); } - if (node.expression.kind === ts.SyntaxKind.Identifier) { - const id = node.expression as ts.Identifier; - const sym = resolveEntityName(id, ts.SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node); + if (node.expression.kind === SyntaxKind.Identifier) { + const id = node.expression as Identifier; + const sym = resolveEntityName(id, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, node); if (sym) { markAliasReferenced(sym, id); // If not a value, we're interpreting the identifier as a type export, along the lines of (`export { Id as default }`) - const target = sym.flags & ts.SymbolFlags.Alias ? resolveAlias(sym) : sym; - if (getAllSymbolFlags(target) & ts.SymbolFlags.Value) { + const target = sym.flags & SymbolFlags.Alias ? resolveAlias(sym) : sym; + if (getAllSymbolFlags(target) & SymbolFlags.Value) { // However if it is a value, we need to check it's being used correctly checkExpressionCached(node.expression); } @@ -41922,8 +42120,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkExpressionCached(node.expression); // doesn't resolve, check as expression to mark as error } - if (ts.getEmitDeclarations(compilerOptions)) { - collectLinkedAliases(node.expression as ts.Identifier, /*setVisibility*/ true); + if (getEmitDeclarations(compilerOptions)) { + collectLinkedAliases(node.expression as Identifier, /*setVisibility*/ true); } } else { @@ -41932,35 +42130,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { checkExternalModuleExports(container); - if ((node.flags & ts.NodeFlags.Ambient) && !ts.isEntityNameExpression(node.expression)) { - grammarErrorOnNode(node.expression, ts.Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); + if ((node.flags & NodeFlags.Ambient) && !isEntityNameExpression(node.expression)) { + grammarErrorOnNode(node.expression, Diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context); } - if (node.isExportEquals && !(node.flags & ts.NodeFlags.Ambient)) { - if (moduleKind >= ts.ModuleKind.ES2015 && ts.getSourceFileOfNode(node).impliedNodeFormat !== ts.ModuleKind.CommonJS) { + if (node.isExportEquals && !(node.flags & NodeFlags.Ambient)) { + if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS) { // export assignment is not supported in es6 modules - grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); + grammarErrorOnNode(node, Diagnostics.Export_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_export_default_or_another_module_format_instead); } - else if (moduleKind === ts.ModuleKind.System) { + else if (moduleKind === ModuleKind.System) { // system modules does not support export assignment - grammarErrorOnNode(node, ts.Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); + grammarErrorOnNode(node, Diagnostics.Export_assignment_is_not_supported_when_module_flag_is_system); } } } - function hasExportedMembers(moduleSymbol: ts.Symbol) { - return ts.forEachEntry(moduleSymbol.exports!, (_, id) => id !== "export="); + function hasExportedMembers(moduleSymbol: Symbol) { + return forEachEntry(moduleSymbol.exports!, (_, id) => id !== "export="); } - function checkExternalModuleExports(node: ts.SourceFile | ts.ModuleDeclaration) { + function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) { const moduleSymbol = getSymbolOfNode(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { - const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as ts.__String); + const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; - if (declaration && !isTopLevelInExternalModuleAugmentation(declaration) && !ts.isInJSFile(declaration)) { - error(declaration, ts.Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); + if (declaration && !isTopLevelInExternalModuleAugmentation(declaration) && !isInJSFile(declaration)) { + error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } // Checks for export * conflicts @@ -41972,11 +42170,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // ECMA262: 15.2.1.1 It is a Syntax Error if the ExportedNames of ModuleItemList contains any duplicate entries. // (TS Exceptions: namespaces, function overloads, enums, and interfaces) - if (flags & (ts.SymbolFlags.Namespace | ts.SymbolFlags.Enum)) { + if (flags & (SymbolFlags.Namespace | SymbolFlags.Enum)) { return; } - const exportedDeclarationsCount = ts.countWhere(declarations, ts.and(isNotOverloadAndNotAccessor, ts.not(ts.isInterfaceDeclaration))); - if (flags & ts.SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { + const exportedDeclarationsCount = countWhere(declarations, and(isNotOverloadAndNotAccessor, not(isInterfaceDeclaration))); + if (flags & SymbolFlags.TypeAlias && exportedDeclarationsCount <= 2) { // it is legal to merge type alias with other values // so count should be either 1 (just type alias) or 2 (type alias + merged value) return; @@ -41985,7 +42183,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (!isDuplicatedCommonJSExport(declarations)) { for (const declaration of declarations!) { if (isNotOverload(declaration)) { - diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Cannot_redeclare_exported_variable_0, unescapeLeadingUnderscores(id))); } } } @@ -41996,13 +42194,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isDuplicatedCommonJSExport(declarations: ts.Declaration[] | undefined) { + function isDuplicatedCommonJSExport(declarations: Declaration[] | undefined) { return declarations && declarations.length > 1 - && declarations.every(d => ts.isInJSFile(d) && ts.isAccessExpression(d) && (ts.isExportsIdentifier(d.expression) || ts.isModuleExportsAccessExpression(d.expression))); + && declarations.every(d => isInJSFile(d) && isAccessExpression(d) && (isExportsIdentifier(d.expression) || isModuleExportsAccessExpression(d.expression))); } - function checkSourceElement(node: ts.Node | undefined): void { + function checkSourceElement(node: Node | undefined): void { if (node) { const saveCurrentNode = currentNode; currentNode = node; @@ -42012,12 +42210,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkSourceElementWorker(node: ts.Node): void { - ts.forEach((node as ts.JSDocContainer).jsDoc, ({ comment, tags }) => { + function checkSourceElementWorker(node: Node): void { + forEach((node as JSDocContainer).jsDoc, ({ comment, tags }) => { checkJSDocCommentWorker(comment); - ts.forEach(tags, tag => { + forEach(tags, tag => { checkJSDocCommentWorker(tag.comment); - if (ts.isInJSFile(node)) { + if (isInJSFile(node)) { checkSourceElement(tag); } }); @@ -42028,245 +42226,245 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Only bother checking on a few construct kinds. We don't want to be excessively // hitting the cancellation token on every node we check. switch (kind) { - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.FunctionDeclaration: cancellationToken.throwIfCancellationRequested(); } } - if (kind >= ts.SyntaxKind.FirstStatement && kind <= ts.SyntaxKind.LastStatement && node.flowNode && !isReachableFlowNode(node.flowNode)) { - errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, ts.Diagnostics.Unreachable_code_detected); + if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && node.flowNode && !isReachableFlowNode(node.flowNode)) { + errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected); } switch (kind) { - case ts.SyntaxKind.TypeParameter: - return checkTypeParameter(node as ts.TypeParameterDeclaration); - case ts.SyntaxKind.Parameter: - return checkParameter(node as ts.ParameterDeclaration); - case ts.SyntaxKind.PropertyDeclaration: - return checkPropertyDeclaration(node as ts.PropertyDeclaration); - case ts.SyntaxKind.PropertySignature: - return checkPropertySignature(node as ts.PropertySignature); - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.IndexSignature: - return checkSignatureDeclaration(node as ts.SignatureDeclaration); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - return checkMethodDeclaration(node as ts.MethodDeclaration | ts.MethodSignature); - case ts.SyntaxKind.ClassStaticBlockDeclaration: - return checkClassStaticBlockDeclaration(node as ts.ClassStaticBlockDeclaration); - case ts.SyntaxKind.Constructor: - return checkConstructorDeclaration(node as ts.ConstructorDeclaration); - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return checkAccessorDeclaration(node as ts.AccessorDeclaration); - case ts.SyntaxKind.TypeReference: - return checkTypeReferenceNode(node as ts.TypeReferenceNode); - case ts.SyntaxKind.TypePredicate: - return checkTypePredicate(node as ts.TypePredicateNode); - case ts.SyntaxKind.TypeQuery: - return checkTypeQuery(node as ts.TypeQueryNode); - case ts.SyntaxKind.TypeLiteral: - return checkTypeLiteral(node as ts.TypeLiteralNode); - case ts.SyntaxKind.ArrayType: - return checkArrayType(node as ts.ArrayTypeNode); - case ts.SyntaxKind.TupleType: - return checkTupleType(node as ts.TupleTypeNode); - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - return checkUnionOrIntersectionType(node as ts.UnionOrIntersectionTypeNode); - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.OptionalType: - case ts.SyntaxKind.RestType: - return checkSourceElement((node as ts.ParenthesizedTypeNode | ts.OptionalTypeNode | ts.RestTypeNode).type); - case ts.SyntaxKind.ThisType: - return checkThisType(node as ts.ThisTypeNode); - case ts.SyntaxKind.TypeOperator: - return checkTypeOperator(node as ts.TypeOperatorNode); - case ts.SyntaxKind.ConditionalType: - return checkConditionalType(node as ts.ConditionalTypeNode); - case ts.SyntaxKind.InferType: - return checkInferType(node as ts.InferTypeNode); - case ts.SyntaxKind.TemplateLiteralType: - return checkTemplateLiteralType(node as ts.TemplateLiteralTypeNode); - case ts.SyntaxKind.ImportType: - return checkImportType(node as ts.ImportTypeNode); - case ts.SyntaxKind.NamedTupleMember: - return checkNamedTupleMember(node as ts.NamedTupleMember); - case ts.SyntaxKind.JSDocAugmentsTag: - return checkJSDocAugmentsTag(node as ts.JSDocAugmentsTag); - case ts.SyntaxKind.JSDocImplementsTag: - return checkJSDocImplementsTag(node as ts.JSDocImplementsTag); - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocEnumTag: - return checkJSDocTypeAliasTag(node as ts.JSDocTypedefTag); - case ts.SyntaxKind.JSDocTemplateTag: - return checkJSDocTemplateTag(node as ts.JSDocTemplateTag); - case ts.SyntaxKind.JSDocTypeTag: - return checkJSDocTypeTag(node as ts.JSDocTypeTag); - case ts.SyntaxKind.JSDocLink: - case ts.SyntaxKind.JSDocLinkCode: - case ts.SyntaxKind.JSDocLinkPlain: - return checkJSDocLinkLikeTag(node as ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain); - case ts.SyntaxKind.JSDocParameterTag: - return checkJSDocParameterTag(node as ts.JSDocParameterTag); - case ts.SyntaxKind.JSDocPropertyTag: - return checkJSDocPropertyTag(node as ts.JSDocPropertyTag); - case ts.SyntaxKind.JSDocFunctionType: - checkJSDocFunctionType(node as ts.JSDocFunctionType); + case SyntaxKind.TypeParameter: + return checkTypeParameter(node as TypeParameterDeclaration); + case SyntaxKind.Parameter: + return checkParameter(node as ParameterDeclaration); + case SyntaxKind.PropertyDeclaration: + return checkPropertyDeclaration(node as PropertyDeclaration); + case SyntaxKind.PropertySignature: + return checkPropertySignature(node as PropertySignature); + case SyntaxKind.ConstructorType: + case SyntaxKind.FunctionType: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + return checkSignatureDeclaration(node as SignatureDeclaration); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return checkMethodDeclaration(node as MethodDeclaration | MethodSignature); + case SyntaxKind.ClassStaticBlockDeclaration: + return checkClassStaticBlockDeclaration(node as ClassStaticBlockDeclaration); + case SyntaxKind.Constructor: + return checkConstructorDeclaration(node as ConstructorDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return checkAccessorDeclaration(node as AccessorDeclaration); + case SyntaxKind.TypeReference: + return checkTypeReferenceNode(node as TypeReferenceNode); + case SyntaxKind.TypePredicate: + return checkTypePredicate(node as TypePredicateNode); + case SyntaxKind.TypeQuery: + return checkTypeQuery(node as TypeQueryNode); + case SyntaxKind.TypeLiteral: + return checkTypeLiteral(node as TypeLiteralNode); + case SyntaxKind.ArrayType: + return checkArrayType(node as ArrayTypeNode); + case SyntaxKind.TupleType: + return checkTupleType(node as TupleTypeNode); + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + return checkUnionOrIntersectionType(node as UnionOrIntersectionTypeNode); + case SyntaxKind.ParenthesizedType: + case SyntaxKind.OptionalType: + case SyntaxKind.RestType: + return checkSourceElement((node as ParenthesizedTypeNode | OptionalTypeNode | RestTypeNode).type); + case SyntaxKind.ThisType: + return checkThisType(node as ThisTypeNode); + case SyntaxKind.TypeOperator: + return checkTypeOperator(node as TypeOperatorNode); + case SyntaxKind.ConditionalType: + return checkConditionalType(node as ConditionalTypeNode); + case SyntaxKind.InferType: + return checkInferType(node as InferTypeNode); + case SyntaxKind.TemplateLiteralType: + return checkTemplateLiteralType(node as TemplateLiteralTypeNode); + case SyntaxKind.ImportType: + return checkImportType(node as ImportTypeNode); + case SyntaxKind.NamedTupleMember: + return checkNamedTupleMember(node as NamedTupleMember); + case SyntaxKind.JSDocAugmentsTag: + return checkJSDocAugmentsTag(node as JSDocAugmentsTag); + case SyntaxKind.JSDocImplementsTag: + return checkJSDocImplementsTag(node as JSDocImplementsTag); + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + return checkJSDocTypeAliasTag(node as JSDocTypedefTag); + case SyntaxKind.JSDocTemplateTag: + return checkJSDocTemplateTag(node as JSDocTemplateTag); + case SyntaxKind.JSDocTypeTag: + return checkJSDocTypeTag(node as JSDocTypeTag); + case SyntaxKind.JSDocLink: + case SyntaxKind.JSDocLinkCode: + case SyntaxKind.JSDocLinkPlain: + return checkJSDocLinkLikeTag(node as JSDocLink | JSDocLinkCode | JSDocLinkPlain); + case SyntaxKind.JSDocParameterTag: + return checkJSDocParameterTag(node as JSDocParameterTag); + case SyntaxKind.JSDocPropertyTag: + return checkJSDocPropertyTag(node as JSDocPropertyTag); + case SyntaxKind.JSDocFunctionType: + checkJSDocFunctionType(node as JSDocFunctionType); // falls through - case ts.SyntaxKind.JSDocNonNullableType: - case ts.SyntaxKind.JSDocNullableType: - case ts.SyntaxKind.JSDocAllType: - case ts.SyntaxKind.JSDocUnknownType: - case ts.SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JSDocNonNullableType: + case SyntaxKind.JSDocNullableType: + case SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocUnknownType: + case SyntaxKind.JSDocTypeLiteral: checkJSDocTypeIsInJsFile(node); - ts.forEachChild(node, checkSourceElement); + forEachChild(node, checkSourceElement); return; - case ts.SyntaxKind.JSDocVariadicType: - checkJSDocVariadicType(node as ts.JSDocVariadicType); + case SyntaxKind.JSDocVariadicType: + checkJSDocVariadicType(node as JSDocVariadicType); return; - case ts.SyntaxKind.JSDocTypeExpression: - return checkSourceElement((node as ts.JSDocTypeExpression).type); - case ts.SyntaxKind.JSDocPublicTag: - case ts.SyntaxKind.JSDocProtectedTag: - case ts.SyntaxKind.JSDocPrivateTag: - return checkJSDocAccessibilityModifiers(node as ts.JSDocPublicTag | ts.JSDocProtectedTag | ts.JSDocPrivateTag); - case ts.SyntaxKind.IndexedAccessType: - return checkIndexedAccessType(node as ts.IndexedAccessTypeNode); - case ts.SyntaxKind.MappedType: - return checkMappedType(node as ts.MappedTypeNode); - case ts.SyntaxKind.FunctionDeclaration: - return checkFunctionDeclaration(node as ts.FunctionDeclaration); - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - return checkBlock(node as ts.Block); - case ts.SyntaxKind.VariableStatement: - return checkVariableStatement(node as ts.VariableStatement); - case ts.SyntaxKind.ExpressionStatement: - return checkExpressionStatement(node as ts.ExpressionStatement); - case ts.SyntaxKind.IfStatement: - return checkIfStatement(node as ts.IfStatement); - case ts.SyntaxKind.DoStatement: - return checkDoStatement(node as ts.DoStatement); - case ts.SyntaxKind.WhileStatement: - return checkWhileStatement(node as ts.WhileStatement); - case ts.SyntaxKind.ForStatement: - return checkForStatement(node as ts.ForStatement); - case ts.SyntaxKind.ForInStatement: - return checkForInStatement(node as ts.ForInStatement); - case ts.SyntaxKind.ForOfStatement: - return checkForOfStatement(node as ts.ForOfStatement); - case ts.SyntaxKind.ContinueStatement: - case ts.SyntaxKind.BreakStatement: - return checkBreakOrContinueStatement(node as ts.BreakOrContinueStatement); - case ts.SyntaxKind.ReturnStatement: - return checkReturnStatement(node as ts.ReturnStatement); - case ts.SyntaxKind.WithStatement: - return checkWithStatement(node as ts.WithStatement); - case ts.SyntaxKind.SwitchStatement: - return checkSwitchStatement(node as ts.SwitchStatement); - case ts.SyntaxKind.LabeledStatement: - return checkLabeledStatement(node as ts.LabeledStatement); - case ts.SyntaxKind.ThrowStatement: - return checkThrowStatement(node as ts.ThrowStatement); - case ts.SyntaxKind.TryStatement: - return checkTryStatement(node as ts.TryStatement); - case ts.SyntaxKind.VariableDeclaration: - return checkVariableDeclaration(node as ts.VariableDeclaration); - case ts.SyntaxKind.BindingElement: - return checkBindingElement(node as ts.BindingElement); - case ts.SyntaxKind.ClassDeclaration: - return checkClassDeclaration(node as ts.ClassDeclaration); - case ts.SyntaxKind.InterfaceDeclaration: - return checkInterfaceDeclaration(node as ts.InterfaceDeclaration); - case ts.SyntaxKind.TypeAliasDeclaration: - return checkTypeAliasDeclaration(node as ts.TypeAliasDeclaration); - case ts.SyntaxKind.EnumDeclaration: - return checkEnumDeclaration(node as ts.EnumDeclaration); - case ts.SyntaxKind.ModuleDeclaration: - return checkModuleDeclaration(node as ts.ModuleDeclaration); - case ts.SyntaxKind.ImportDeclaration: - return checkImportDeclaration(node as ts.ImportDeclaration); - case ts.SyntaxKind.ImportEqualsDeclaration: - return checkImportEqualsDeclaration(node as ts.ImportEqualsDeclaration); - case ts.SyntaxKind.ExportDeclaration: - return checkExportDeclaration(node as ts.ExportDeclaration); - case ts.SyntaxKind.ExportAssignment: - return checkExportAssignment(node as ts.ExportAssignment); - case ts.SyntaxKind.EmptyStatement: - case ts.SyntaxKind.DebuggerStatement: + case SyntaxKind.JSDocTypeExpression: + return checkSourceElement((node as JSDocTypeExpression).type); + case SyntaxKind.JSDocPublicTag: + case SyntaxKind.JSDocProtectedTag: + case SyntaxKind.JSDocPrivateTag: + return checkJSDocAccessibilityModifiers(node as JSDocPublicTag | JSDocProtectedTag | JSDocPrivateTag); + case SyntaxKind.IndexedAccessType: + return checkIndexedAccessType(node as IndexedAccessTypeNode); + case SyntaxKind.MappedType: + return checkMappedType(node as MappedTypeNode); + case SyntaxKind.FunctionDeclaration: + return checkFunctionDeclaration(node as FunctionDeclaration); + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + return checkBlock(node as Block); + case SyntaxKind.VariableStatement: + return checkVariableStatement(node as VariableStatement); + case SyntaxKind.ExpressionStatement: + return checkExpressionStatement(node as ExpressionStatement); + case SyntaxKind.IfStatement: + return checkIfStatement(node as IfStatement); + case SyntaxKind.DoStatement: + return checkDoStatement(node as DoStatement); + case SyntaxKind.WhileStatement: + return checkWhileStatement(node as WhileStatement); + case SyntaxKind.ForStatement: + return checkForStatement(node as ForStatement); + case SyntaxKind.ForInStatement: + return checkForInStatement(node as ForInStatement); + case SyntaxKind.ForOfStatement: + return checkForOfStatement(node as ForOfStatement); + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + return checkBreakOrContinueStatement(node as BreakOrContinueStatement); + case SyntaxKind.ReturnStatement: + return checkReturnStatement(node as ReturnStatement); + case SyntaxKind.WithStatement: + return checkWithStatement(node as WithStatement); + case SyntaxKind.SwitchStatement: + return checkSwitchStatement(node as SwitchStatement); + case SyntaxKind.LabeledStatement: + return checkLabeledStatement(node as LabeledStatement); + case SyntaxKind.ThrowStatement: + return checkThrowStatement(node as ThrowStatement); + case SyntaxKind.TryStatement: + return checkTryStatement(node as TryStatement); + case SyntaxKind.VariableDeclaration: + return checkVariableDeclaration(node as VariableDeclaration); + case SyntaxKind.BindingElement: + return checkBindingElement(node as BindingElement); + case SyntaxKind.ClassDeclaration: + return checkClassDeclaration(node as ClassDeclaration); + case SyntaxKind.InterfaceDeclaration: + return checkInterfaceDeclaration(node as InterfaceDeclaration); + case SyntaxKind.TypeAliasDeclaration: + return checkTypeAliasDeclaration(node as TypeAliasDeclaration); + case SyntaxKind.EnumDeclaration: + return checkEnumDeclaration(node as EnumDeclaration); + case SyntaxKind.ModuleDeclaration: + return checkModuleDeclaration(node as ModuleDeclaration); + case SyntaxKind.ImportDeclaration: + return checkImportDeclaration(node as ImportDeclaration); + case SyntaxKind.ImportEqualsDeclaration: + return checkImportEqualsDeclaration(node as ImportEqualsDeclaration); + case SyntaxKind.ExportDeclaration: + return checkExportDeclaration(node as ExportDeclaration); + case SyntaxKind.ExportAssignment: + return checkExportAssignment(node as ExportAssignment); + case SyntaxKind.EmptyStatement: + case SyntaxKind.DebuggerStatement: checkGrammarStatementInAmbientContext(node); return; - case ts.SyntaxKind.MissingDeclaration: + case SyntaxKind.MissingDeclaration: return checkMissingDeclaration(node); } } - function checkJSDocCommentWorker(node: string | readonly ts.JSDocComment[] | undefined) { - if (ts.isArray(node)) { - ts.forEach(node, tag => { - if (ts.isJSDocLinkLike(tag)) { + function checkJSDocCommentWorker(node: string | readonly JSDocComment[] | undefined) { + if (isArray(node)) { + forEach(node, tag => { + if (isJSDocLinkLike(tag)) { checkSourceElement(tag); } }); } } - function checkJSDocTypeIsInJsFile(node: ts.Node): void { - if (!ts.isInJSFile(node)) { - grammarErrorOnNode(node, ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + function checkJSDocTypeIsInJsFile(node: Node): void { + if (!isInJSFile(node)) { + grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); } } - function checkJSDocVariadicType(node: ts.JSDocVariadicType): void { + function checkJSDocVariadicType(node: JSDocVariadicType): void { checkJSDocTypeIsInJsFile(node); checkSourceElement(node.type); // Only legal location is in the *last* parameter tag or last parameter of a JSDoc function. const { parent } = node; - if (ts.isParameter(parent) && ts.isJSDocFunctionType(parent.parent)) { - if (ts.last(parent.parent.parameters) !== parent) { - error(node, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + if (isParameter(parent) && isJSDocFunctionType(parent.parent)) { + if (last(parent.parent.parameters) !== parent) { + error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } return; } - if (!ts.isJSDocTypeExpression(parent)) { - error(node, ts.Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); + if (!isJSDocTypeExpression(parent)) { + error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); } const paramTag = node.parent.parent; - if (!ts.isJSDocParameterTag(paramTag)) { - error(node, ts.Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); + if (!isJSDocParameterTag(paramTag)) { + error(node, Diagnostics.JSDoc_may_only_appear_in_the_last_parameter_of_a_signature); return; } - const param = ts.getParameterSymbolFromJSDoc(paramTag); + const param = getParameterSymbolFromJSDoc(paramTag); if (!param) { // We will error in `checkJSDocParameterTag`. return; } - const host = ts.getHostSignatureFromJSDoc(paramTag); - if (!host || ts.last(host.parameters).symbol !== param) { - error(node, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + const host = getHostSignatureFromJSDoc(paramTag); + if (!host || last(host.parameters).symbol !== param) { + error(node, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } } - function getTypeFromJSDocVariadicType(node: ts.JSDocVariadicType): ts.Type { + function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { const type = getTypeFromTypeNode(node.type); const { parent } = node; const paramTag = node.parent.parent; - if (ts.isJSDocTypeExpression(node.parent) && ts.isJSDocParameterTag(paramTag)) { + if (isJSDocTypeExpression(node.parent) && isJSDocParameterTag(paramTag)) { // Else we will add a diagnostic, see `checkJSDocVariadicType`. - const host = ts.getHostSignatureFromJSDoc(paramTag); - const isCallbackTag = ts.isJSDocCallbackTag(paramTag.parent.parent); + const host = getHostSignatureFromJSDoc(paramTag); + const isCallbackTag = isJSDocCallbackTag(paramTag.parent.parent); if (host || isCallbackTag) { /* Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters. @@ -42276,16 +42474,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. */ const lastParamDeclaration = isCallbackTag - ? ts.lastOrUndefined((paramTag.parent.parent as unknown as ts.JSDocCallbackTag).typeExpression.parameters) - : ts.lastOrUndefined(host!.parameters); - const symbol = ts.getParameterSymbolFromJSDoc(paramTag); + ? lastOrUndefined((paramTag.parent.parent as unknown as JSDocCallbackTag).typeExpression.parameters) + : lastOrUndefined(host!.parameters); + const symbol = getParameterSymbolFromJSDoc(paramTag); if (!lastParamDeclaration || - symbol && lastParamDeclaration.symbol === symbol && ts.isRestParameter(lastParamDeclaration)) { + symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration)) { return createArrayType(type); } } } - if (ts.isParameter(parent) && ts.isJSDocFunctionType(parent.parent)) { + if (isParameter(parent) && isJSDocFunctionType(parent.parent)) { return createArrayType(type); } return addOptionality(type); @@ -42300,72 +42498,72 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Here, performing a full type check of the body of the function expression whilst in the process of // determining the type of foo would cause foo to be given type any because of the recursive reference. // Delaying the type check of the body ensures foo has been assigned a type. - function checkNodeDeferred(node: ts.Node) { - const enclosingFile = ts.getSourceFileOfNode(node); + function checkNodeDeferred(node: Node) { + const enclosingFile = getSourceFileOfNode(node); const links = getNodeLinks(enclosingFile); - if (!(links.flags & ts.NodeCheckFlags.TypeChecked)) { - links.deferredNodes ||= new ts.Set(); + if (!(links.flags & NodeCheckFlags.TypeChecked)) { + links.deferredNodes ||= new Set(); links.deferredNodes.add(node); } } - function checkDeferredNodes(context: ts.SourceFile) { + function checkDeferredNodes(context: SourceFile) { const links = getNodeLinks(context); if (links.deferredNodes) { links.deferredNodes.forEach(checkDeferredNode); } } - function checkDeferredNode(node: ts.Node) { - ts.tracing?.push(ts.tracing.Phase.Check, "checkDeferredNode", { kind: node.kind, pos: node.pos, end: node.end, path: (node as ts.TracingNode).tracingPath }); + function checkDeferredNode(node: Node) { + tracing?.push(tracing.Phase.Check, "checkDeferredNode", { kind: node.kind, pos: node.pos, end: node.end, path: (node as TracingNode).tracingPath }); const saveCurrentNode = currentNode; currentNode = node; instantiationCount = 0; switch (node.kind) { - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.TaggedTemplateExpression: - case ts.SyntaxKind.Decorator: - case ts.SyntaxKind.JsxOpeningElement: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.Decorator: + case SyntaxKind.JsxOpeningElement: // These node kinds are deferred checked when overload resolution fails // To save on work, we ensure the arguments are checked just once, in // a deferred way - resolveUntypedCall(node as ts.CallLikeExpression); + resolveUntypedCall(node as CallLikeExpression); break; - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - checkFunctionExpressionOrObjectLiteralMethodDeferred(node as ts.FunctionExpression); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + checkFunctionExpressionOrObjectLiteralMethodDeferred(node as FunctionExpression); break; - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - checkAccessorDeclaration(node as ts.AccessorDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + checkAccessorDeclaration(node as AccessorDeclaration); break; - case ts.SyntaxKind.ClassExpression: - checkClassExpressionDeferred(node as ts.ClassExpression); + case SyntaxKind.ClassExpression: + checkClassExpressionDeferred(node as ClassExpression); break; - case ts.SyntaxKind.TypeParameter: - checkTypeParameterDeferred(node as ts.TypeParameterDeclaration); + case SyntaxKind.TypeParameter: + checkTypeParameterDeferred(node as TypeParameterDeclaration); break; - case ts.SyntaxKind.JsxSelfClosingElement: - checkJsxSelfClosingElementDeferred(node as ts.JsxSelfClosingElement); + case SyntaxKind.JsxSelfClosingElement: + checkJsxSelfClosingElementDeferred(node as JsxSelfClosingElement); break; - case ts.SyntaxKind.JsxElement: - checkJsxElementDeferred(node as ts.JsxElement); + case SyntaxKind.JsxElement: + checkJsxElementDeferred(node as JsxElement); break; } currentNode = saveCurrentNode; - ts.tracing?.pop(); + tracing?.pop(); } - function checkSourceFile(node: ts.SourceFile) { - ts.tracing?.push(ts.tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true); + function checkSourceFile(node: SourceFile) { + tracing?.push(tracing.Phase.Check, "checkSourceFile", { path: node.path }, /*separateBeginAndEnd*/ true); ts.performance.mark("beforeCheck"); checkSourceFileWorker(node); ts.performance.mark("afterCheck"); ts.performance.measure("Check", "beforeCheck", "afterCheck"); - ts.tracing?.pop(); + tracing?.pop(); } function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean { @@ -42378,37 +42576,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { case UnusedKind.Parameter: return !!compilerOptions.noUnusedParameters; default: - return ts.Debug.assertNever(kind); + return Debug.assertNever(kind); } } - function getPotentiallyUnusedIdentifiers(sourceFile: ts.SourceFile): readonly PotentiallyUnusedIdentifier[] { - return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || ts.emptyArray; + function getPotentiallyUnusedIdentifiers(sourceFile: SourceFile): readonly PotentiallyUnusedIdentifier[] { + return allPotentiallyUnusedIdentifiers.get(sourceFile.path) || emptyArray; } // Fully type check a source file and collect the relevant diagnostics. - function checkSourceFileWorker(node: ts.SourceFile) { + function checkSourceFileWorker(node: SourceFile) { const links = getNodeLinks(node); - if (!(links.flags & ts.NodeCheckFlags.TypeChecked)) { - if (ts.skipTypeChecking(node, compilerOptions, host)) { + if (!(links.flags & NodeCheckFlags.TypeChecked)) { + if (skipTypeChecking(node, compilerOptions, host)) { return; } // Grammar checking checkGrammarSourceFile(node); - ts.clear(potentialThisCollisions); - ts.clear(potentialNewTargetCollisions); - ts.clear(potentialWeakMapSetCollisions); - ts.clear(potentialReflectCollisions); - ts.clear(potentialUnusedRenamedBindingElementsInTypes); + clear(potentialThisCollisions); + clear(potentialNewTargetCollisions); + clear(potentialWeakMapSetCollisions); + clear(potentialReflectCollisions); + clear(potentialUnusedRenamedBindingElementsInTypes); - ts.forEach(node.statements, checkSourceElement); + forEach(node.statements, checkSourceElement); checkSourceElement(node.endOfFileToken); checkDeferredNodes(node); - if (ts.isExternalOrCommonJsModule(node)) { + if (isExternalOrCommonJsModule(node)) { registerForUnusedIdentifiersCheck(node); } @@ -42416,7 +42614,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // This relies on the results of other lazy diagnostics, so must be computed after them if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) { checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (containingNode, kind, diag) => { - if (!ts.containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & ts.NodeFlags.Ambient))) { + if (!containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { diagnostics.add(diag); } }); @@ -42426,42 +42624,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } }); - if (compilerOptions.importsNotUsedAsValues === ts.ImportsNotUsedAsValues.Error && + if (compilerOptions.importsNotUsedAsValues === ImportsNotUsedAsValues.Error && !node.isDeclarationFile && - ts.isExternalModule(node) + isExternalModule(node) ) { checkImportsForTypeOnlyConversion(node); } - if (ts.isExternalOrCommonJsModule(node)) { + if (isExternalOrCommonJsModule(node)) { checkExternalModuleExports(node); } if (potentialThisCollisions.length) { - ts.forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope); - ts.clear(potentialThisCollisions); + forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope); + clear(potentialThisCollisions); } if (potentialNewTargetCollisions.length) { - ts.forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope); - ts.clear(potentialNewTargetCollisions); + forEach(potentialNewTargetCollisions, checkIfNewTargetIsCapturedInEnclosingScope); + clear(potentialNewTargetCollisions); } if (potentialWeakMapSetCollisions.length) { - ts.forEach(potentialWeakMapSetCollisions, checkWeakMapSetCollision); - ts.clear(potentialWeakMapSetCollisions); + forEach(potentialWeakMapSetCollisions, checkWeakMapSetCollision); + clear(potentialWeakMapSetCollisions); } if (potentialReflectCollisions.length) { - ts.forEach(potentialReflectCollisions, checkReflectCollision); - ts.clear(potentialReflectCollisions); + forEach(potentialReflectCollisions, checkReflectCollision); + clear(potentialReflectCollisions); } - links.flags |= ts.NodeCheckFlags.TypeChecked; + links.flags |= NodeCheckFlags.TypeChecked; } } - function getDiagnostics(sourceFile: ts.SourceFile, ct: ts.CancellationToken): ts.Diagnostic[] { + function getDiagnostics(sourceFile: SourceFile, ct: CancellationToken): Diagnostic[] { try { // Record the cancellation token so it can be checked later on during checkSourceElement. // Do this in a finally block so we can ensure that it gets reset back to nothing after @@ -42482,7 +42680,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { deferredDiagnosticsCallbacks = []; } - function checkSourceFileWithEagerDiagnostics(sourceFile: ts.SourceFile) { + function checkSourceFileWithEagerDiagnostics(sourceFile: SourceFile) { ensurePendingDiagnosticWorkComplete(); // then setup diagnostics for immediate invocation (as we are about to collect them, and // this avoids the overhead of longer-lived callbacks we don't need to allocate) @@ -42495,7 +42693,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { addLazyDiagnostic = oldAddLazyDiagnostics; } - function getDiagnosticsWorker(sourceFile: ts.SourceFile): ts.Diagnostic[] { + function getDiagnosticsWorker(sourceFile: SourceFile): Diagnostic[] { if (sourceFile) { ensurePendingDiagnosticWorkComplete(); // Some global diagnostics are deferred until they are needed and @@ -42510,14 +42708,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const currentGlobalDiagnostics = diagnostics.getGlobalDiagnostics(); if (currentGlobalDiagnostics !== previousGlobalDiagnostics) { // If the arrays are not the same reference, new diagnostics were added. - const deferredGlobalDiagnostics = ts.relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, ts.compareDiagnostics); - return ts.concatenate(deferredGlobalDiagnostics, semanticDiagnostics); + const deferredGlobalDiagnostics = relativeComplement(previousGlobalDiagnostics, currentGlobalDiagnostics, compareDiagnostics); + return concatenate(deferredGlobalDiagnostics, semanticDiagnostics); } else if (previousGlobalDiagnosticsSize === 0 && currentGlobalDiagnostics.length > 0) { // If the arrays are the same reference, but the length has changed, a single // new diagnostic was added as DiagnosticCollection attempts to reuse the // same array. - return ts.concatenate(currentGlobalDiagnostics, semanticDiagnostics); + return concatenate(currentGlobalDiagnostics, semanticDiagnostics); } return semanticDiagnostics; @@ -42525,29 +42723,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Global diagnostics are always added when a file is not provided to // getDiagnostics - ts.forEach(host.getSourceFiles(), checkSourceFileWithEagerDiagnostics); + forEach(host.getSourceFiles(), checkSourceFileWithEagerDiagnostics); return diagnostics.getDiagnostics(); } - function getGlobalDiagnostics(): ts.Diagnostic[] { + function getGlobalDiagnostics(): Diagnostic[] { ensurePendingDiagnosticWorkComplete(); return diagnostics.getGlobalDiagnostics(); } // Language service support - function getSymbolsInScope(location: ts.Node, meaning: ts.SymbolFlags): ts.Symbol[] { - if (location.flags & ts.NodeFlags.InWithStatement) { + function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] { + if (location.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return []; } - const symbols = ts.createSymbolTable(); + const symbols = createSymbolTable(); let isStaticSymbol = false; populateSymbols(); - symbols.delete(ts.InternalSymbolName.This); // Not a symbol, a keyword + symbols.delete(InternalSymbolName.This); // Not a symbol, a keyword return symbolsToArray(symbols); function populateSymbols() { @@ -42557,17 +42755,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } switch (location.kind) { - case ts.SyntaxKind.SourceFile: - if (!ts.isExternalModule(location as ts.SourceFile)) break; + case SyntaxKind.SourceFile: + if (!isExternalModule(location as SourceFile)) break; // falls through - case ts.SyntaxKind.ModuleDeclaration: - copyLocallyVisibleExportSymbols(getSymbolOfNode(location as ts.ModuleDeclaration | ts.SourceFile).exports!, meaning & ts.SymbolFlags.ModuleMember); + case SyntaxKind.ModuleDeclaration: + copyLocallyVisibleExportSymbols(getSymbolOfNode(location as ModuleDeclaration | SourceFile).exports!, meaning & SymbolFlags.ModuleMember); break; - case ts.SyntaxKind.EnumDeclaration: - copySymbols(getSymbolOfNode(location as ts.EnumDeclaration).exports!, meaning & ts.SymbolFlags.EnumMember); + case SyntaxKind.EnumDeclaration: + copySymbols(getSymbolOfNode(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember); break; - case ts.SyntaxKind.ClassExpression: - const className = (location as ts.ClassExpression).name; + case SyntaxKind.ClassExpression: + const className = (location as ClassExpression).name; if (className) { copySymbol(location.symbol, meaning); } @@ -42575,29 +42773,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // this fall-through is necessary because we would like to handle // type parameter inside class expression similar to how we handle it in classDeclaration and interface Declaration. // falls through - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: // If we didn't come from static member of class or interface, // add the type parameters into the symbol table // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. if (!isStaticSymbol) { - copySymbols(getMembersOfSymbol(getSymbolOfNode(location as ts.ClassDeclaration | ts.InterfaceDeclaration)), meaning & ts.SymbolFlags.Type); + copySymbols(getMembersOfSymbol(getSymbolOfNode(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type); } break; - case ts.SyntaxKind.FunctionExpression: - const funcName = (location as ts.FunctionExpression).name; + case SyntaxKind.FunctionExpression: + const funcName = (location as FunctionExpression).name; if (funcName) { copySymbol(location.symbol, meaning); } break; } - if (ts.introducesArgumentsExoticObject(location)) { + if (introducesArgumentsExoticObject(location)) { copySymbol(argumentsSymbol, meaning); } - isStaticSymbol = ts.isStatic(location); + isStaticSymbol = isStatic(location); location = location.parent; } @@ -42611,8 +42809,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * @param symbol the symbol to be added into symbol table * @param meaning meaning of symbol to filter by before adding to symbol table */ - function copySymbol(symbol: ts.Symbol, meaning: ts.SymbolFlags): void { - if (ts.getCombinedLocalAndExportSymbolFlags(symbol) & meaning) { + function copySymbol(symbol: Symbol, meaning: SymbolFlags): void { + if (getCombinedLocalAndExportSymbolFlags(symbol) & meaning) { const id = symbol.escapedName; // We will copy all symbol regardless of its reserved name because // symbolsToArray will check whether the key is a reserved name and @@ -42623,7 +42821,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function copySymbols(source: ts.SymbolTable, meaning: ts.SymbolFlags): void { + function copySymbols(source: SymbolTable, meaning: SymbolFlags): void { if (meaning) { source.forEach(symbol => { copySymbol(symbol, meaning); @@ -42631,11 +42829,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function copyLocallyVisibleExportSymbols(source: ts.SymbolTable, meaning: ts.SymbolFlags): void { + function copyLocallyVisibleExportSymbols(source: SymbolTable, meaning: SymbolFlags): void { if (meaning) { source.forEach(symbol => { // Similar condition as in `resolveNameHelper` - if (!ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ExportSpecifier) && !ts.getDeclarationOfKind(symbol, ts.SyntaxKind.NamespaceExport)) { + if (!getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier) && !getDeclarationOfKind(symbol, SyntaxKind.NamespaceExport)) { copySymbol(symbol, meaning); } }); @@ -42643,34 +42841,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function isTypeDeclarationName(name: ts.Node): boolean { - return name.kind === ts.SyntaxKind.Identifier && - ts.isTypeDeclaration(name.parent) && - ts.getNameOfDeclaration(name.parent) === name; + function isTypeDeclarationName(name: Node): boolean { + return name.kind === SyntaxKind.Identifier && + isTypeDeclaration(name.parent) && + getNameOfDeclaration(name.parent) === name; } // True if the given identifier is part of a type reference - function isTypeReferenceIdentifier(node: ts.EntityName): boolean { - while (node.parent.kind === ts.SyntaxKind.QualifiedName) { - node = node.parent as ts.QualifiedName; + function isTypeReferenceIdentifier(node: EntityName): boolean { + while (node.parent.kind === SyntaxKind.QualifiedName) { + node = node.parent as QualifiedName; } - return node.parent.kind === ts.SyntaxKind.TypeReference; + return node.parent.kind === SyntaxKind.TypeReference; } - function isHeritageClauseElementIdentifier(node: ts.Node): boolean { - while (node.parent.kind === ts.SyntaxKind.PropertyAccessExpression) { + function isHeritageClauseElementIdentifier(node: Node): boolean { + while (node.parent.kind === SyntaxKind.PropertyAccessExpression) { node = node.parent; } - return node.parent.kind === ts.SyntaxKind.ExpressionWithTypeArguments; + return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function forEachEnclosingClass(node: ts.Node, callback: (node: ts.Node) => T | undefined): T | undefined { + function forEachEnclosingClass(node: Node, callback: (node: Node) => T | undefined): T | undefined { let result: T | undefined; while (true) { - node = ts.getContainingClass(node)!; + node = getContainingClass(node)!; if (!node) break; if (result = callback(node)) break; } @@ -42678,12 +42876,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return result; } - function isNodeUsedDuringClassInitialization(node: ts.Node) { - return !!ts.findAncestor(node, element => { - if (ts.isConstructorDeclaration(element) && ts.nodeIsPresent(element.body) || ts.isPropertyDeclaration(element)) { + function isNodeUsedDuringClassInitialization(node: Node) { + return !!findAncestor(node, element => { + if (isConstructorDeclaration(element) && nodeIsPresent(element.body) || isPropertyDeclaration(element)) { return true; } - else if (ts.isClassLike(element) || ts.isFunctionLikeDeclaration(element)) { + else if (isClassLike(element) || isFunctionLikeDeclaration(element)) { return "quit"; } @@ -42691,65 +42889,65 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }); } - function isNodeWithinClass(node: ts.Node, classDeclaration: ts.ClassLikeDeclaration) { + function isNodeWithinClass(node: Node, classDeclaration: ClassLikeDeclaration) { return !!forEachEnclosingClass(node, n => n === classDeclaration); } - function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: ts.EntityName): ts.ImportEqualsDeclaration | ts.ExportAssignment | undefined { - while (nodeOnRightSide.parent.kind === ts.SyntaxKind.QualifiedName) { - nodeOnRightSide = nodeOnRightSide.parent as ts.QualifiedName; + function getLeftSideOfImportEqualsOrExportAssignment(nodeOnRightSide: EntityName): ImportEqualsDeclaration | ExportAssignment | undefined { + while (nodeOnRightSide.parent.kind === SyntaxKind.QualifiedName) { + nodeOnRightSide = nodeOnRightSide.parent as QualifiedName; } - if (nodeOnRightSide.parent.kind === ts.SyntaxKind.ImportEqualsDeclaration) { - return (nodeOnRightSide.parent as ts.ImportEqualsDeclaration).moduleReference === nodeOnRightSide ? nodeOnRightSide.parent as ts.ImportEqualsDeclaration : undefined; + if (nodeOnRightSide.parent.kind === SyntaxKind.ImportEqualsDeclaration) { + return (nodeOnRightSide.parent as ImportEqualsDeclaration).moduleReference === nodeOnRightSide ? nodeOnRightSide.parent as ImportEqualsDeclaration : undefined; } - if (nodeOnRightSide.parent.kind === ts.SyntaxKind.ExportAssignment) { - return (nodeOnRightSide.parent as ts.ExportAssignment).expression === nodeOnRightSide as ts.Node ? nodeOnRightSide.parent as ts.ExportAssignment : undefined; + if (nodeOnRightSide.parent.kind === SyntaxKind.ExportAssignment) { + return (nodeOnRightSide.parent as ExportAssignment).expression === nodeOnRightSide as Node ? nodeOnRightSide.parent as ExportAssignment : undefined; } return undefined; } - function isInRightSideOfImportOrExportAssignment(node: ts.EntityName) { + function isInRightSideOfImportOrExportAssignment(node: EntityName) { return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined; } - function getSpecialPropertyAssignmentSymbolFromEntityName(entityName: ts.EntityName | ts.PropertyAccessExpression) { - const specialPropertyAssignmentKind = ts.getAssignmentDeclarationKind(entityName.parent.parent as ts.BinaryExpression); + function getSpecialPropertyAssignmentSymbolFromEntityName(entityName: EntityName | PropertyAccessExpression) { + const specialPropertyAssignmentKind = getAssignmentDeclarationKind(entityName.parent.parent as BinaryExpression); switch (specialPropertyAssignmentKind) { - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.PrototypeProperty: + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.PrototypeProperty: return getSymbolOfNode(entityName.parent); - case ts.AssignmentDeclarationKind.ThisProperty: - case ts.AssignmentDeclarationKind.ModuleExports: - case ts.AssignmentDeclarationKind.Property: + case AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.Property: return getSymbolOfNode(entityName.parent.parent); } } - function isImportTypeQualifierPart(node: ts.EntityName): ts.ImportTypeNode | undefined { + function isImportTypeQualifierPart(node: EntityName): ImportTypeNode | undefined { let parent = node.parent; - while (ts.isQualifiedName(parent)) { + while (isQualifiedName(parent)) { node = parent; parent = parent.parent; } - if (parent && parent.kind === ts.SyntaxKind.ImportType && (parent as ts.ImportTypeNode).qualifier === node) { - return parent as ts.ImportTypeNode; + if (parent && parent.kind === SyntaxKind.ImportType && (parent as ImportTypeNode).qualifier === node) { + return parent as ImportTypeNode; } return undefined; } - function getSymbolOfNameOrPropertyAccessExpression(name: ts.EntityName | ts.PrivateIdentifier | ts.PropertyAccessExpression | ts.JSDocMemberName): ts.Symbol | undefined { - if (ts.isDeclarationName(name)) { + function getSymbolOfNameOrPropertyAccessExpression(name: EntityName | PrivateIdentifier | PropertyAccessExpression | JSDocMemberName): Symbol | undefined { + if (isDeclarationName(name)) { return getSymbolOfNode(name.parent); } - if (ts.isInJSFile(name) && - name.parent.kind === ts.SyntaxKind.PropertyAccessExpression && - name.parent === (name.parent.parent as ts.BinaryExpression).left) { + if (isInJSFile(name) && + name.parent.kind === SyntaxKind.PropertyAccessExpression && + name.parent === (name.parent.parent as BinaryExpression).left) { // Check if this is a special property assignment - if (!ts.isPrivateIdentifier(name) && !ts.isJSDocMemberName(name)) { + if (!isPrivateIdentifier(name) && !isJSDocMemberName(name)) { const specialPropertyAssignmentSymbol = getSpecialPropertyAssignmentSymbolFromEntityName(name); if (specialPropertyAssignmentSymbol) { return specialPropertyAssignmentSymbol; @@ -42757,22 +42955,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (name.parent.kind === ts.SyntaxKind.ExportAssignment && ts.isEntityNameExpression(name)) { + if (name.parent.kind === SyntaxKind.ExportAssignment && isEntityNameExpression(name)) { // Even an entity name expression that doesn't resolve as an entityname may still typecheck as a property access expression const success = resolveEntityName(name, - /*all meanings*/ ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias, /*ignoreErrors*/ true); + /*all meanings*/ SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*ignoreErrors*/ true); if (success && success !== unknownSymbol) { return success; } } - else if (ts.isEntityName(name) && isInRightSideOfImportOrExportAssignment(name)) { + else if (isEntityName(name) && isInRightSideOfImportOrExportAssignment(name)) { // Since we already checked for ExportAssignment, this really could only be an Import - const importEqualsDeclaration = ts.getAncestor(name, ts.SyntaxKind.ImportEqualsDeclaration); - ts.Debug.assert(importEqualsDeclaration !== undefined); + const importEqualsDeclaration = getAncestor(name, SyntaxKind.ImportEqualsDeclaration); + Debug.assert(importEqualsDeclaration !== undefined); return getSymbolOfPartOfRightHandSideOfImportEquals(name, /*dontResolveAlias*/ true); } - if (ts.isEntityName(name)) { + if (isEntityName(name)) { const possibleImportNode = isImportTypeQualifierPart(name); if (possibleImportNode) { getTypeFromTypeNode(possibleImportNode); @@ -42781,103 +42979,103 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - while (ts.isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(name)) { - name = name.parent as ts.QualifiedName | ts.PropertyAccessEntityNameExpression | ts.JSDocMemberName; + while (isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName(name)) { + name = name.parent as QualifiedName | PropertyAccessEntityNameExpression | JSDocMemberName; } if (isHeritageClauseElementIdentifier(name)) { - let meaning = ts.SymbolFlags.None; + let meaning = SymbolFlags.None; // In an interface or class, we're definitely interested in a type. - if (name.parent.kind === ts.SyntaxKind.ExpressionWithTypeArguments) { - meaning = ts.SymbolFlags.Type; + if (name.parent.kind === SyntaxKind.ExpressionWithTypeArguments) { + meaning = SymbolFlags.Type; // In a class 'extends' clause we are also looking for a value. - if (ts.isExpressionWithTypeArgumentsInClassExtendsClause(name.parent)) { - meaning |= ts.SymbolFlags.Value; + if (isExpressionWithTypeArgumentsInClassExtendsClause(name.parent)) { + meaning |= SymbolFlags.Value; } } else { - meaning = ts.SymbolFlags.Namespace; + meaning = SymbolFlags.Namespace; } - meaning |= ts.SymbolFlags.Alias; - const entityNameSymbol = ts.isEntityNameExpression(name) ? resolveEntityName(name, meaning) : undefined; + meaning |= SymbolFlags.Alias; + const entityNameSymbol = isEntityNameExpression(name) ? resolveEntityName(name, meaning) : undefined; if (entityNameSymbol) { return entityNameSymbol; } } - if (name.parent.kind === ts.SyntaxKind.JSDocParameterTag) { - return ts.getParameterSymbolFromJSDoc(name.parent as ts.JSDocParameterTag); + if (name.parent.kind === SyntaxKind.JSDocParameterTag) { + return getParameterSymbolFromJSDoc(name.parent as JSDocParameterTag); } - if (name.parent.kind === ts.SyntaxKind.TypeParameter && name.parent.parent.kind === ts.SyntaxKind.JSDocTemplateTag) { - ts.Debug.assert(!ts.isInJSFile(name)); // Otherwise `isDeclarationName` would have been true. - const typeParameter = ts.getTypeParameterFromJsDoc(name.parent as ts.TypeParameterDeclaration & { parent: ts.JSDocTemplateTag }); + if (name.parent.kind === SyntaxKind.TypeParameter && name.parent.parent.kind === SyntaxKind.JSDocTemplateTag) { + Debug.assert(!isInJSFile(name)); // Otherwise `isDeclarationName` would have been true. + const typeParameter = getTypeParameterFromJsDoc(name.parent as TypeParameterDeclaration & { parent: JSDocTemplateTag }); return typeParameter && typeParameter.symbol; } - if (ts.isExpressionNode(name)) { - if (ts.nodeIsMissing(name)) { + if (isExpressionNode(name)) { + if (nodeIsMissing(name)) { // Missing entity name. return undefined; } - const isJSDoc = ts.findAncestor(name, ts.or(ts.isJSDocLinkLike, ts.isJSDocNameReference, ts.isJSDocMemberName)); - const meaning = isJSDoc ? ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Value : ts.SymbolFlags.Value; - if (name.kind === ts.SyntaxKind.Identifier) { - if (ts.isJSXTagName(name) && isJsxIntrinsicIdentifier(name)) { - const symbol = getIntrinsicTagSymbol(name.parent as ts.JsxOpeningLikeElement); + const isJSDoc = findAncestor(name, or(isJSDocLinkLike, isJSDocNameReference, isJSDocMemberName)); + const meaning = isJSDoc ? SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value : SymbolFlags.Value; + if (name.kind === SyntaxKind.Identifier) { + if (isJSXTagName(name) && isJsxIntrinsicIdentifier(name)) { + const symbol = getIntrinsicTagSymbol(name.parent as JsxOpeningLikeElement); return symbol === unknownSymbol ? undefined : symbol; } - const result = resolveEntityName(name, meaning, /*ignoreErrors*/ false, /* dontResolveAlias */ true, ts.getHostSignatureFromJSDoc(name)); + const result = resolveEntityName(name, meaning, /*ignoreErrors*/ false, /* dontResolveAlias */ true, getHostSignatureFromJSDoc(name)); if (!result && isJSDoc) { - const container = ts.findAncestor(name, ts.or(ts.isClassLike, ts.isInterfaceDeclaration)); + const container = findAncestor(name, or(isClassLike, isInterfaceDeclaration)); if (container) { return resolveJSDocMemberName(name, /*ignoreErrors*/ false, getSymbolOfNode(container)); } } if (result && isJSDoc) { - const container = ts.getJSDocHost(name); - if (container && ts.isEnumMember(container) && container === result.valueDeclaration) { - return resolveEntityName(name, meaning, /*ignoreErrors*/ true, /* dontResolveAlias */ true, ts.getSourceFileOfNode(container)) || result; + const container = getJSDocHost(name); + if (container && isEnumMember(container) && container === result.valueDeclaration) { + return resolveEntityName(name, meaning, /*ignoreErrors*/ true, /* dontResolveAlias */ true, getSourceFileOfNode(container)) || result; } } return result; } - else if (ts.isPrivateIdentifier(name)) { + else if (isPrivateIdentifier(name)) { return getSymbolForPrivateIdentifierExpression(name); } - else if (name.kind === ts.SyntaxKind.PropertyAccessExpression || name.kind === ts.SyntaxKind.QualifiedName) { + else if (name.kind === SyntaxKind.PropertyAccessExpression || name.kind === SyntaxKind.QualifiedName) { const links = getNodeLinks(name); if (links.resolvedSymbol) { return links.resolvedSymbol; } - if (name.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (name.kind === SyntaxKind.PropertyAccessExpression) { checkPropertyAccessExpression(name, CheckMode.Normal); if (!links.resolvedSymbol) { const expressionType = checkExpressionCached(name.expression); const infos = getApplicableIndexInfos(expressionType, getLiteralTypeFromPropertyName(name.name)); - if (infos.length && (expressionType as ts.ObjectType).members) { - const resolved = resolveStructuredTypeMembers(expressionType as ts.ObjectType); - const symbol = resolved.members.get(ts.InternalSymbolName.Index); + if (infos.length && (expressionType as ObjectType).members) { + const resolved = resolveStructuredTypeMembers(expressionType as ObjectType); + const symbol = resolved.members.get(InternalSymbolName.Index); if (infos === getIndexInfosOfType(expressionType)) { links.resolvedSymbol = symbol; } else if (symbol) { const symbolLinks = getSymbolLinks(symbol); - const declarationList = ts.mapDefined(infos, i => i.declaration); - const nodeListId = ts.map(declarationList, getNodeId).join(","); + const declarationList = mapDefined(infos, i => i.declaration); + const nodeListId = map(declarationList, getNodeId).join(","); if (!symbolLinks.filteredIndexSymbolCache) { - symbolLinks.filteredIndexSymbolCache = new ts.Map(); + symbolLinks.filteredIndexSymbolCache = new Map(); } if (symbolLinks.filteredIndexSymbolCache.has(nodeListId)) { links.resolvedSymbol = symbolLinks.filteredIndexSymbolCache.get(nodeListId)!; } else { - const copy = createSymbol(ts.SymbolFlags.Signature, ts.InternalSymbolName.Index); - copy.declarations = ts.mapDefined(infos, i => i.declaration); + const copy = createSymbol(SymbolFlags.Signature, InternalSymbolName.Index); + copy.declarations = mapDefined(infos, i => i.declaration); copy.parent = expressionType.aliasSymbol ? expressionType.aliasSymbol : expressionType.symbol ? expressionType.symbol : getSymbolAtLocation(copy.declarations[0].parent); symbolLinks.filteredIndexSymbolCache.set(nodeListId, copy); links.resolvedSymbol = symbolLinks.filteredIndexSymbolCache.get(nodeListId)!; @@ -42889,22 +43087,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { checkQualifiedName(name, CheckMode.Normal); } - if (!links.resolvedSymbol && isJSDoc && ts.isQualifiedName(name)) { + if (!links.resolvedSymbol && isJSDoc && isQualifiedName(name)) { return resolveJSDocMemberName(name); } return links.resolvedSymbol; } - else if (ts.isJSDocMemberName(name)) { + else if (isJSDocMemberName(name)) { return resolveJSDocMemberName(name); } } - else if (isTypeReferenceIdentifier(name as ts.EntityName)) { - const meaning = name.parent.kind === ts.SyntaxKind.TypeReference ? ts.SymbolFlags.Type : ts.SymbolFlags.Namespace; - const symbol = resolveEntityName(name as ts.EntityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); - return symbol && symbol !== unknownSymbol ? symbol : getUnresolvedSymbolForEntityName(name as ts.EntityName); + else if (isTypeReferenceIdentifier(name as EntityName)) { + const meaning = name.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace; + const symbol = resolveEntityName(name as EntityName, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true); + return symbol && symbol !== unknownSymbol ? symbol : getUnresolvedSymbolForEntityName(name as EntityName); } - if (name.parent.kind === ts.SyntaxKind.TypePredicate) { - return resolveEntityName(name as ts.Identifier, /*meaning*/ ts.SymbolFlags.FunctionScopedVariable); + if (name.parent.kind === SyntaxKind.TypePredicate) { + return resolveEntityName(name as Identifier, /*meaning*/ SymbolFlags.FunctionScopedVariable); } return undefined; @@ -42918,35 +43116,35 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * * For unqualified names, a container K may be provided as a second argument. */ - function resolveJSDocMemberName(name: ts.EntityName | ts.JSDocMemberName, ignoreErrors?: boolean, container?: ts.Symbol): ts.Symbol | undefined { - if (ts.isEntityName(name)) { + function resolveJSDocMemberName(name: EntityName | JSDocMemberName, ignoreErrors?: boolean, container?: Symbol): Symbol | undefined { + if (isEntityName(name)) { // resolve static values first - const meaning = ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Value; - let symbol = resolveEntityName(name, meaning, ignoreErrors, /*dontResolveAlias*/ true, ts.getHostSignatureFromJSDoc(name)); - if (!symbol && ts.isIdentifier(name) && container) { + const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value; + let symbol = resolveEntityName(name, meaning, ignoreErrors, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name)); + if (!symbol && isIdentifier(name) && container) { symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(container), name.escapedText, meaning)); } if (symbol) { return symbol; } } - const left = ts.isIdentifier(name) ? container : resolveJSDocMemberName(name.left, ignoreErrors, container); - const right = ts.isIdentifier(name) ? name.escapedText : name.right.escapedText; + const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left, ignoreErrors, container); + const right = isIdentifier(name) ? name.escapedText : name.right.escapedText; if (left) { - const proto = left.flags & ts.SymbolFlags.Value && getPropertyOfType(getTypeOfSymbol(left), "prototype" as ts.__String); + const proto = left.flags & SymbolFlags.Value && getPropertyOfType(getTypeOfSymbol(left), "prototype" as __String); const t = proto ? getTypeOfSymbol(proto) : getDeclaredTypeOfSymbol(left); return getPropertyOfType(t, right); } } - function getSymbolAtLocation(node: ts.Node, ignoreErrors?: boolean): ts.Symbol | undefined { - if (node.kind === ts.SyntaxKind.SourceFile) { - return ts.isExternalModule(node as ts.SourceFile) ? getMergedSymbol(node.symbol) : undefined; + function getSymbolAtLocation(node: Node, ignoreErrors?: boolean): Symbol | undefined { + if (node.kind === SyntaxKind.SourceFile) { + return isExternalModule(node as SourceFile) ? getMergedSymbol(node.symbol) : undefined; } const { parent } = node; const grandParent = parent.parent; - if (node.flags & ts.NodeFlags.InWithStatement) { + if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } @@ -42954,30 +43152,30 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (isDeclarationNameOrImportPropertyName(node)) { // This is a declaration, call getSymbolOfNode const parentSymbol = getSymbolOfNode(parent)!; - return ts.isImportOrExportSpecifier(node.parent) && node.parent.propertyName === node + return isImportOrExportSpecifier(node.parent) && node.parent.propertyName === node ? getImmediateAliasedSymbol(parentSymbol) : parentSymbol; } - else if (ts.isLiteralComputedPropertyDeclarationName(node)) { + else if (isLiteralComputedPropertyDeclarationName(node)) { return getSymbolOfNode(parent.parent); } - if (node.kind === ts.SyntaxKind.Identifier) { - if (isInRightSideOfImportOrExportAssignment(node as ts.Identifier)) { - return getSymbolOfNameOrPropertyAccessExpression(node as ts.Identifier); + if (node.kind === SyntaxKind.Identifier) { + if (isInRightSideOfImportOrExportAssignment(node as Identifier)) { + return getSymbolOfNameOrPropertyAccessExpression(node as Identifier); } - else if (parent.kind === ts.SyntaxKind.BindingElement && - grandParent.kind === ts.SyntaxKind.ObjectBindingPattern && - node === (parent as ts.BindingElement).propertyName) { + else if (parent.kind === SyntaxKind.BindingElement && + grandParent.kind === SyntaxKind.ObjectBindingPattern && + node === (parent as BindingElement).propertyName) { const typeOfPattern = getTypeOfNode(grandParent); - const propertyDeclaration = getPropertyOfType(typeOfPattern, (node as ts.Identifier).escapedText); + const propertyDeclaration = getPropertyOfType(typeOfPattern, (node as Identifier).escapedText); if (propertyDeclaration) { return propertyDeclaration; } } - else if (ts.isMetaProperty(parent) && parent.name === node) { - if (parent.keywordToken === ts.SyntaxKind.NewKeyword && ts.idText(node as ts.Identifier) === "target") { + else if (isMetaProperty(parent) && parent.name === node) { + if (parent.keywordToken === SyntaxKind.NewKeyword && idText(node as Identifier) === "target") { // `target` in `new.target` return checkNewTargetMetaProperty(parent).symbol; } @@ -42985,8 +43183,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // we have a fake expression type made for other reasons already, whose transient `meta` // member should more exactly be the kind of (declarationless) symbol we want. // (See #44364 and #45031 for relevant implementation PRs) - if (parent.keywordToken === ts.SyntaxKind.ImportKeyword && ts.idText(node as ts.Identifier) === "meta") { - return getGlobalImportMetaExpressionType().members!.get("meta" as ts.__String); + if (parent.keywordToken === SyntaxKind.ImportKeyword && idText(node as Identifier) === "meta") { + return getGlobalImportMetaExpressionType().members!.get("meta" as __String); } // no other meta properties are valid syntax, thus no others should have symbols return undefined; @@ -42994,149 +43192,149 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } switch (node.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PrivateIdentifier: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.QualifiedName: - if (!ts.isThisInTypeQuery(node)) { - return getSymbolOfNameOrPropertyAccessExpression(node as ts.EntityName | ts.PrivateIdentifier | ts.PropertyAccessExpression); + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.QualifiedName: + if (!isThisInTypeQuery(node)) { + return getSymbolOfNameOrPropertyAccessExpression(node as EntityName | PrivateIdentifier | PropertyAccessExpression); } // falls through - case ts.SyntaxKind.ThisKeyword: - const container = ts.getThisContainer(node, /*includeArrowFunctions*/ false); - if (ts.isFunctionLike(container)) { + case SyntaxKind.ThisKeyword: + const container = getThisContainer(node, /*includeArrowFunctions*/ false); + if (isFunctionLike(container)) { const sig = getSignatureFromDeclaration(container); if (sig.thisParameter) { return sig.thisParameter; } } - if (ts.isInExpressionContext(node)) { - return checkExpression(node as ts.Expression).symbol; + if (isInExpressionContext(node)) { + return checkExpression(node as Expression).symbol; } // falls through - case ts.SyntaxKind.ThisType: - return getTypeFromThisTypeNode(node as ts.ThisExpression | ts.ThisTypeNode).symbol; + case SyntaxKind.ThisType: + return getTypeFromThisTypeNode(node as ThisExpression | ThisTypeNode).symbol; - case ts.SyntaxKind.SuperKeyword: - return checkExpression(node as ts.Expression).symbol; + case SyntaxKind.SuperKeyword: + return checkExpression(node as Expression).symbol; - case ts.SyntaxKind.ConstructorKeyword: + case SyntaxKind.ConstructorKeyword: // constructor keyword for an overload, should take us to the definition if it exist const constructorDeclaration = node.parent; - if (constructorDeclaration && constructorDeclaration.kind === ts.SyntaxKind.Constructor) { - return (constructorDeclaration.parent as ts.ClassDeclaration).symbol; + if (constructorDeclaration && constructorDeclaration.kind === SyntaxKind.Constructor) { + return (constructorDeclaration.parent as ClassDeclaration).symbol; } return undefined; - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: // 1). import x = require("./mo/*gotToDefinitionHere*/d") // 2). External module name in an import declaration // 3). Dynamic import call or require in javascript // 4). type A = import("./f/*gotToDefinitionHere*/oo") - if ((ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || - ((node.parent.kind === ts.SyntaxKind.ImportDeclaration || node.parent.kind === ts.SyntaxKind.ExportDeclaration) && (node.parent as ts.ImportDeclaration).moduleSpecifier === node) || - ((ts.isInJSFile(node) && ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || ts.isImportCall(node.parent)) || - (ts.isLiteralTypeNode(node.parent) && ts.isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent) + if ((isExternalModuleImportEqualsDeclaration(node.parent.parent) && getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node) || + ((node.parent.kind === SyntaxKind.ImportDeclaration || node.parent.kind === SyntaxKind.ExportDeclaration) && (node.parent as ImportDeclaration).moduleSpecifier === node) || + ((isInJSFile(node) && isRequireCall(node.parent, /*checkArgumentIsStringLiteralLike*/ false)) || isImportCall(node.parent)) || + (isLiteralTypeNode(node.parent) && isLiteralImportTypeNode(node.parent.parent) && node.parent.parent.argument === node.parent) ) { - return resolveExternalModuleName(node, node as ts.LiteralExpression, ignoreErrors); + return resolveExternalModuleName(node, node as LiteralExpression, ignoreErrors); } - if (ts.isCallExpression(parent) && ts.isBindableObjectDefinePropertyCall(parent) && parent.arguments[1] === node) { + if (isCallExpression(parent) && isBindableObjectDefinePropertyCall(parent) && parent.arguments[1] === node) { return getSymbolOfNode(parent); } // falls through - case ts.SyntaxKind.NumericLiteral: + case SyntaxKind.NumericLiteral: // index access - const objectType = ts.isElementAccessExpression(parent) + const objectType = isElementAccessExpression(parent) ? parent.argumentExpression === node ? getTypeOfExpression(parent.expression) : undefined - : ts.isLiteralTypeNode(parent) && ts.isIndexedAccessTypeNode(grandParent) + : isLiteralTypeNode(parent) && isIndexedAccessTypeNode(grandParent) ? getTypeFromTypeNode(grandParent.objectType) : undefined; - return objectType && getPropertyOfType(objectType, ts.escapeLeadingUnderscores((node as ts.StringLiteral | ts.NumericLiteral).text)); + return objectType && getPropertyOfType(objectType, escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text)); - case ts.SyntaxKind.DefaultKeyword: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.EqualsGreaterThanToken: - case ts.SyntaxKind.ClassKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ClassKeyword: return getSymbolOfNode(node.parent); - case ts.SyntaxKind.ImportType: - return ts.isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal, ignoreErrors) : undefined; + case SyntaxKind.ImportType: + return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal, ignoreErrors) : undefined; - case ts.SyntaxKind.ExportKeyword: - return ts.isExportAssignment(node.parent) ? ts.Debug.checkDefined(node.parent.symbol) : undefined; + case SyntaxKind.ExportKeyword: + return isExportAssignment(node.parent) ? Debug.checkDefined(node.parent.symbol) : undefined; - case ts.SyntaxKind.ImportKeyword: - case ts.SyntaxKind.NewKeyword: - return ts.isMetaProperty(node.parent) ? checkMetaPropertyKeyword(node.parent).symbol : undefined; - case ts.SyntaxKind.MetaProperty: - return checkExpression(node as ts.Expression).symbol; + case SyntaxKind.ImportKeyword: + case SyntaxKind.NewKeyword: + return isMetaProperty(node.parent) ? checkMetaPropertyKeyword(node.parent).symbol : undefined; + case SyntaxKind.MetaProperty: + return checkExpression(node as Expression).symbol; default: return undefined; } } - function getIndexInfosAtLocation(node: ts.Node): readonly ts.IndexInfo[] | undefined { - if (ts.isIdentifier(node) && ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) { + function getIndexInfosAtLocation(node: Node): readonly IndexInfo[] | undefined { + if (isIdentifier(node) && isPropertyAccessExpression(node.parent) && node.parent.name === node) { const keyType = getLiteralTypeFromPropertyName(node); const objectType = getTypeOfExpression(node.parent.expression); - const objectTypes = objectType.flags & ts.TypeFlags.Union ? (objectType as ts.UnionType).types : [objectType]; - return ts.flatMap(objectTypes, t => ts.filter(getIndexInfosOfType(t), info => isApplicableIndexType(keyType, info.keyType))); + const objectTypes = objectType.flags & TypeFlags.Union ? (objectType as UnionType).types : [objectType]; + return flatMap(objectTypes, t => filter(getIndexInfosOfType(t), info => isApplicableIndexType(keyType, info.keyType))); } return undefined; } - function getShorthandAssignmentValueSymbol(location: ts.Node | undefined): ts.Symbol | undefined { - if (location && location.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { - return resolveEntityName((location as ts.ShorthandPropertyAssignment).name, ts.SymbolFlags.Value | ts.SymbolFlags.Alias); + function getShorthandAssignmentValueSymbol(location: Node | undefined): Symbol | undefined { + if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { + return resolveEntityName((location as ShorthandPropertyAssignment).name, SymbolFlags.Value | SymbolFlags.Alias); } return undefined; } /** Returns the target of an export specifier without following aliases */ - function getExportSpecifierLocalTargetSymbol(node: ts.ExportSpecifier | ts.Identifier): ts.Symbol | undefined { - if (ts.isExportSpecifier(node)) { + function getExportSpecifierLocalTargetSymbol(node: ExportSpecifier | Identifier): Symbol | undefined { + if (isExportSpecifier(node)) { return node.parent.parent.moduleSpecifier ? getExternalModuleMember(node.parent.parent, node) : - resolveEntityName(node.propertyName || node.name, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias); + resolveEntityName(node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } else { - return resolveEntityName(node, ts.SymbolFlags.Value | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias); + return resolveEntityName(node, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } } - function getTypeOfNode(node: ts.Node): ts.Type { - if (ts.isSourceFile(node) && !ts.isExternalModule(node)) { + function getTypeOfNode(node: Node): Type { + if (isSourceFile(node) && !isExternalModule(node)) { return errorType; } - if (node.flags & ts.NodeFlags.InWithStatement) { + if (node.flags & NodeFlags.InWithStatement) { // We cannot answer semantic questions within a with block, do not proceed any further return errorType; } - const classDecl = ts.tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node); + const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node); const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class)); - if (ts.isPartOfTypeNode(node)) { - const typeFromTypeNode = getTypeFromTypeNode(node as ts.TypeNode); + if (isPartOfTypeNode(node)) { + const typeFromTypeNode = getTypeFromTypeNode(node as TypeNode); return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode; } - if (ts.isExpressionNode(node)) { - return getRegularTypeOfExpression(node as ts.Expression); + if (isExpressionNode(node)) { + return getRegularTypeOfExpression(node as Expression); } if (classType && !classDecl.isImplements) { // A SyntaxKind.ExpressionWithTypeArguments is considered a type node, except when it occurs in the // extends clause of a class. We handle that case here. - const baseType = ts.firstOrUndefined(getBaseTypes(classType)); + const baseType = firstOrUndefined(getBaseTypes(classType)); return baseType ? getTypeWithThisArgument(baseType, classType.thisType) : errorType; } - if (ts.isTypeDeclaration(node)) { + if (isTypeDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration const symbol = getSymbolOfNode(node); return getDeclaredTypeOfSymbol(symbol); @@ -43147,7 +43345,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; } - if (ts.isDeclaration(node)) { + if (isDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration const symbol = getSymbolOfNode(node); return symbol ? getTypeOfSymbol(symbol) : errorType; @@ -43161,11 +43359,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return errorType; } - if (ts.isBindingPattern(node)) { + if (isBindingPattern(node)) { return getTypeForVariableLikeDeclaration(node.parent, /*includeOptionality*/ true, CheckMode.Normal) || errorType; } - if (isInRightSideOfImportOrExportAssignment(node as ts.Identifier)) { + if (isInRightSideOfImportOrExportAssignment(node as Identifier)) { const symbol = getSymbolAtLocation(node); if (symbol) { const declaredType = getDeclaredTypeOfSymbol(symbol); @@ -43173,7 +43371,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isMetaProperty(node.parent) && node.parent.keywordToken === node.kind) { + if (isMetaProperty(node.parent) && node.parent.keywordToken === node.kind) { return checkMetaPropertyKeyword(node.parent); } @@ -43186,31 +43384,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // } // [ a ] from // [a] = [ some array ...] - function getTypeOfAssignmentPattern(expr: ts.AssignmentPattern): ts.Type | undefined { - ts.Debug.assert(expr.kind === ts.SyntaxKind.ObjectLiteralExpression || expr.kind === ts.SyntaxKind.ArrayLiteralExpression); + function getTypeOfAssignmentPattern(expr: AssignmentPattern): Type | undefined { + Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression); // If this is from "for of" // for ( { a } of elems) { // } - if (expr.parent.kind === ts.SyntaxKind.ForOfStatement) { - const iteratedType = checkRightHandSideOfForOf(expr.parent as ts.ForOfStatement); + if (expr.parent.kind === SyntaxKind.ForOfStatement) { + const iteratedType = checkRightHandSideOfForOf(expr.parent as ForOfStatement); return checkDestructuringAssignment(expr, iteratedType || errorType); } // If this is from "for" initializer // for ({a } = elems[0];.....) { } - if (expr.parent.kind === ts.SyntaxKind.BinaryExpression) { - const iteratedType = getTypeOfExpression((expr.parent as ts.BinaryExpression).right); + if (expr.parent.kind === SyntaxKind.BinaryExpression) { + const iteratedType = getTypeOfExpression((expr.parent as BinaryExpression).right); return checkDestructuringAssignment(expr, iteratedType || errorType); } // If this is from nested object binding pattern // for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) { - if (expr.parent.kind === ts.SyntaxKind.PropertyAssignment) { - const node = ts.cast(expr.parent.parent, ts.isObjectLiteralExpression); + if (expr.parent.kind === SyntaxKind.PropertyAssignment) { + const node = cast(expr.parent.parent, isObjectLiteralExpression); const typeOfParentObjectLiteral = getTypeOfAssignmentPattern(node) || errorType; - const propertyIndex = ts.indexOfNode(node.properties, expr.parent); + const propertyIndex = indexOfNode(node.properties, expr.parent); return checkObjectLiteralDestructuringPropertyAssignment(node, typeOfParentObjectLiteral, propertyIndex); } // Array literal assignment - array destructuring pattern - const node = ts.cast(expr.parent, ts.isArrayLiteralExpression); + const node = cast(expr.parent, isArrayLiteralExpression); // [{ property1: p1, property2 }] = elems; const typeOfArrayLiteral = getTypeOfAssignmentPattern(node) || errorType; const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring, typeOfArrayLiteral, undefinedType, expr.parent) || errorType; @@ -43223,15 +43421,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // } // 'property1' at location 'a' from: // [a] = [ property1, property2 ] - function getPropertySymbolOfDestructuringAssignment(location: ts.Identifier) { + function getPropertySymbolOfDestructuringAssignment(location: Identifier) { // Get the type of the object or array literal and then look for property of given name in the type - const typeOfObjectLiteral = getTypeOfAssignmentPattern(ts.cast(location.parent.parent, ts.isAssignmentPattern)); + const typeOfObjectLiteral = getTypeOfAssignmentPattern(cast(location.parent.parent, isAssignmentPattern)); return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.escapedText); } - function getRegularTypeOfExpression(expr: ts.Expression): ts.Type { - if (ts.isRightSideOfQualifiedNameOrPropertyAccess(expr)) { - expr = expr.parent as ts.Expression; + function getRegularTypeOfExpression(expr: Expression): Type { + if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) { + expr = expr.parent as Expression; } return getRegularTypeOfLiteralType(getTypeOfExpression(expr)); } @@ -43240,39 +43438,39 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * Gets either the static or instance type of a class element, based on * whether the element is declared as "static". */ - function getParentTypeOfClassElement(node: ts.ClassElement) { + function getParentTypeOfClassElement(node: ClassElement) { const classSymbol = getSymbolOfNode(node.parent)!; - return ts.isStatic(node) + return isStatic(node) ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } - function getClassElementPropertyKeyType(element: ts.ClassElement) { + function getClassElementPropertyKeyType(element: ClassElement) { const name = element.name!; switch (name.kind) { - case ts.SyntaxKind.Identifier: - return getStringLiteralType(ts.idText(name)); - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.StringLiteral: + case SyntaxKind.Identifier: + return getStringLiteralType(idText(name)); + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: return getStringLiteralType(name.text); - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.ComputedPropertyName: const nameType = checkComputedPropertyName(name); - return isTypeAssignableToKind(nameType, ts.TypeFlags.ESSymbolLike) ? nameType : stringType; + return isTypeAssignableToKind(nameType, TypeFlags.ESSymbolLike) ? nameType : stringType; default: - return ts.Debug.fail("Unsupported property name."); + return Debug.fail("Unsupported property name."); } } // Return the list of properties of the given type, augmented with properties from Function // if the type has call or construct signatures - function getAugmentedPropertiesOfType(type: ts.Type): ts.Symbol[] { + function getAugmentedPropertiesOfType(type: Type): Symbol[] { type = getApparentType(type); - const propsByName = ts.createSymbolTable(getPropertiesOfType(type)); - const functionType = getSignaturesOfType(type, ts.SignatureKind.Call).length ? globalCallableFunctionType : - getSignaturesOfType(type, ts.SignatureKind.Construct).length ? globalNewableFunctionType : + const propsByName = createSymbolTable(getPropertiesOfType(type)); + const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType : + getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType : undefined; if (functionType) { - ts.forEach(getPropertiesOfType(functionType), p => { + forEach(getPropertiesOfType(functionType), p => { if (!propsByName.has(p.escapedName)) { propsByName.set(p.escapedName, p); } @@ -43281,29 +43479,29 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return getNamedMembers(propsByName); } - function typeHasCallOrConstructSignatures(type: ts.Type): boolean { + function typeHasCallOrConstructSignatures(type: Type): boolean { return ts.typeHasCallOrConstructSignatures(type, checker); } - function getRootSymbols(symbol: ts.Symbol): readonly ts.Symbol[] { + function getRootSymbols(symbol: Symbol): readonly Symbol[] { const roots = getImmediateRootSymbols(symbol); - return roots ? ts.flatMap(roots, getRootSymbols) : [symbol]; + return roots ? flatMap(roots, getRootSymbols) : [symbol]; } - function getImmediateRootSymbols(symbol: ts.Symbol): readonly ts.Symbol[] | undefined { - if (ts.getCheckFlags(symbol) & ts.CheckFlags.Synthetic) { - return ts.mapDefined(getSymbolLinks(symbol).containingType!.types, type => getPropertyOfType(type, symbol.escapedName)); + function getImmediateRootSymbols(symbol: Symbol): readonly Symbol[] | undefined { + if (getCheckFlags(symbol) & CheckFlags.Synthetic) { + return mapDefined(getSymbolLinks(symbol).containingType!.types, type => getPropertyOfType(type, symbol.escapedName)); } - else if (symbol.flags & ts.SymbolFlags.Transient) { - const { leftSpread, rightSpread, syntheticOrigin } = symbol as ts.TransientSymbol; + else if (symbol.flags & SymbolFlags.Transient) { + const { leftSpread, rightSpread, syntheticOrigin } = symbol as TransientSymbol; return leftSpread ? [leftSpread, rightSpread!] : syntheticOrigin ? [syntheticOrigin] - : ts.singleElementArray(tryGetTarget(symbol)); + : singleElementArray(tryGetTarget(symbol)); } return undefined; } - function tryGetTarget(symbol: ts.Symbol): ts.Symbol | undefined { - let target: ts.Symbol | undefined; - let next: ts.Symbol | undefined = symbol; + function tryGetTarget(symbol: Symbol): Symbol | undefined { + let target: Symbol | undefined; + let next: Symbol | undefined = symbol; while (next = getSymbolLinks(next).target) { target = next; } @@ -43312,22 +43510,22 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Emitter support - function isArgumentsLocalBinding(nodeIn: ts.Identifier): boolean { + function isArgumentsLocalBinding(nodeIn: Identifier): boolean { // Note: does not handle isShorthandPropertyAssignment (and probably a few more) - if (ts.isGeneratedIdentifier(nodeIn)) return false; - const node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); + if (isGeneratedIdentifier(nodeIn)) return false; + const node = getParseTreeNode(nodeIn, isIdentifier); if (!node) return false; const parent = node.parent; if (!parent) return false; - const isPropertyName = ((ts.isPropertyAccessExpression(parent) - || ts.isPropertyAssignment(parent)) + const isPropertyName = ((isPropertyAccessExpression(parent) + || isPropertyAssignment(parent)) && parent.name === node); return !isPropertyName && getReferencedValueSymbol(node) === argumentsSymbol; } - function moduleExportsSomeValue(moduleReferenceExpression: ts.Expression): boolean { + function moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean { let moduleSymbol = resolveExternalModuleName(moduleReferenceExpression.parent, moduleReferenceExpression); - if (!moduleSymbol || ts.isShorthandAmbientModuleSymbol(moduleSymbol)) { + if (!moduleSymbol || isShorthandAmbientModuleSymbol(moduleSymbol)) { // If the module is not found or is shorthand, assume that it may export a value. return true; } @@ -43342,26 +43540,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // for export assignments - check if resolved symbol for RHS is itself a value // otherwise - check if at least one export is value symbolLinks.exportsSomeValue = hasExportAssignment - ? !!(moduleSymbol.flags & ts.SymbolFlags.Value) - : ts.forEachEntry(getExportsOfModule(moduleSymbol), isValue); + ? !!(moduleSymbol.flags & SymbolFlags.Value) + : forEachEntry(getExportsOfModule(moduleSymbol), isValue); } return symbolLinks.exportsSomeValue!; - function isValue(s: ts.Symbol): boolean { + function isValue(s: Symbol): boolean { s = resolveSymbol(s); - return s && !!(getAllSymbolFlags(s) & ts.SymbolFlags.Value); + return s && !!(getAllSymbolFlags(s) & SymbolFlags.Value); } } - function isNameOfModuleOrEnumDeclaration(node: ts.Identifier) { - return ts.isModuleOrEnumDeclaration(node.parent) && node === node.parent.name; + function isNameOfModuleOrEnumDeclaration(node: Identifier) { + return isModuleOrEnumDeclaration(node.parent) && node === node.parent.name; } // When resolved as an expression identifier, if the given node references an exported entity, return the declaration // node of the exported entity's container. Otherwise, return undefined. - function getReferencedExportContainer(nodeIn: ts.Identifier, prefixLocals?: boolean): ts.SourceFile | ts.ModuleDeclaration | ts.EnumDeclaration | undefined { - const node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); + function getReferencedExportContainer(nodeIn: Identifier, prefixLocals?: boolean): SourceFile | ModuleDeclaration | EnumDeclaration | undefined { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { // When resolving the export container for the name of a module or enum // declaration, we need to start resolution at the declaration's container. @@ -43369,26 +43567,26 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // declaration if it contains an exported member with the same name. let symbol = getReferencedValueSymbol(node, /*startInDeclarationContainer*/ isNameOfModuleOrEnumDeclaration(node)); if (symbol) { - if (symbol.flags & ts.SymbolFlags.ExportValue) { + if (symbol.flags & SymbolFlags.ExportValue) { // If we reference an exported entity within the same module declaration, then whether // we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the // kinds that we do NOT prefix. const exportSymbol = getMergedSymbol(symbol.exportSymbol!); - if (!prefixLocals && exportSymbol.flags & ts.SymbolFlags.ExportHasLocal && !(exportSymbol.flags & ts.SymbolFlags.Variable)) { + if (!prefixLocals && exportSymbol.flags & SymbolFlags.ExportHasLocal && !(exportSymbol.flags & SymbolFlags.Variable)) { return undefined; } symbol = exportSymbol; } const parentSymbol = getParentOfSymbol(symbol); if (parentSymbol) { - if (parentSymbol.flags & ts.SymbolFlags.ValueModule && parentSymbol.valueDeclaration?.kind === ts.SyntaxKind.SourceFile) { - const symbolFile = parentSymbol.valueDeclaration as ts.SourceFile; - const referenceFile = ts.getSourceFileOfNode(node); + if (parentSymbol.flags & SymbolFlags.ValueModule && parentSymbol.valueDeclaration?.kind === SyntaxKind.SourceFile) { + const symbolFile = parentSymbol.valueDeclaration as SourceFile; + const referenceFile = getSourceFileOfNode(node); // If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return undefined. const symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } - return ts.findAncestor(node.parent, (n): n is ts.ModuleDeclaration | ts.EnumDeclaration => ts.isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol); + return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol); } } } @@ -43396,17 +43594,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. - function getReferencedImportDeclaration(nodeIn: ts.Identifier): ts.Declaration | undefined { + function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined { if (nodeIn.generatedImportReference) { return nodeIn.generatedImportReference; } - const node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const symbol = getReferencedValueOrAliasSymbol(node); // We should only get the declaration of an alias if there isn't a local value // declaration for the symbol - if (isNonLocalAlias(symbol, /*excludes*/ ts.SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol, ts.SymbolFlags.Value)) { + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value)) { return getDeclarationOfAliasSymbol(symbol); } } @@ -43414,24 +43612,24 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isSymbolOfDestructuredElementOfCatchBinding(symbol: ts.Symbol) { + function isSymbolOfDestructuredElementOfCatchBinding(symbol: Symbol) { return symbol.valueDeclaration - && ts.isBindingElement(symbol.valueDeclaration) - && ts.walkUpBindingElementsAndPatterns(symbol.valueDeclaration).parent.kind === ts.SyntaxKind.CatchClause; + && isBindingElement(symbol.valueDeclaration) + && walkUpBindingElementsAndPatterns(symbol.valueDeclaration).parent.kind === SyntaxKind.CatchClause; } - function isSymbolOfDeclarationWithCollidingName(symbol: ts.Symbol): boolean { - if (symbol.flags & ts.SymbolFlags.BlockScoped && symbol.valueDeclaration && !ts.isSourceFile(symbol.valueDeclaration)) { + function isSymbolOfDeclarationWithCollidingName(symbol: Symbol): boolean { + if (symbol.flags & SymbolFlags.BlockScoped && symbol.valueDeclaration && !isSourceFile(symbol.valueDeclaration)) { const links = getSymbolLinks(symbol); if (links.isDeclarationWithCollidingName === undefined) { - const container = ts.getEnclosingBlockScopeContainer(symbol.valueDeclaration); - if (ts.isStatementWithLocals(container) || isSymbolOfDestructuredElementOfCatchBinding(symbol)) { + const container = getEnclosingBlockScopeContainer(symbol.valueDeclaration); + if (isStatementWithLocals(container) || isSymbolOfDestructuredElementOfCatchBinding(symbol)) { const nodeLinks = getNodeLinks(symbol.valueDeclaration); - if (resolveName(container.parent, symbol.escapedName, ts.SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { + if (resolveName(container.parent, symbol.escapedName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false)) { // redeclaration - always should be renamed links.isDeclarationWithCollidingName = true; } - else if (nodeLinks.flags & ts.NodeCheckFlags.CapturedBlockScopedBinding) { + else if (nodeLinks.flags & NodeCheckFlags.CapturedBlockScopedBinding) { // binding is captured in the function // should be renamed if: // - binding is not top level - top level bindings never collide with anything @@ -43447,11 +43645,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // * variables from initializer are passed to rewritten loop body as parameters so they are not captured directly // * variables that are declared immediately in loop body will become top level variable after loop is rewritten and thus // they will not collide with anything - const isDeclaredInLoop = nodeLinks.flags & ts.NodeCheckFlags.BlockScopedBindingInLoop; - const inLoopInitializer = ts.isIterationStatement(container, /*lookInLabeledStatements*/ false); - const inLoopBodyBlock = container.kind === ts.SyntaxKind.Block && ts.isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); + const isDeclaredInLoop = nodeLinks.flags & NodeCheckFlags.BlockScopedBindingInLoop; + const inLoopInitializer = isIterationStatement(container, /*lookInLabeledStatements*/ false); + const inLoopBodyBlock = container.kind === SyntaxKind.Block && isIterationStatement(container.parent, /*lookInLabeledStatements*/ false); - links.isDeclarationWithCollidingName = !ts.isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); + links.isDeclarationWithCollidingName = !isBlockScopedContainerTopLevel(container) && (!isDeclaredInLoop || (!inLoopInitializer && !inLoopBodyBlock)); } else { links.isDeclarationWithCollidingName = false; @@ -43466,9 +43664,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // When resolved as an expression identifier, if the given node references a nested block scoped entity with // a name that either hides an existing name or might hide it when compiled downlevel, // return the declaration of that entity. Otherwise, return undefined. - function getReferencedDeclarationWithCollidingName(nodeIn: ts.Identifier): ts.Declaration | undefined { - if (!ts.isGeneratedIdentifier(nodeIn)) { - const node = ts.getParseTreeNode(nodeIn, ts.isIdentifier); + function getReferencedDeclarationWithCollidingName(nodeIn: Identifier): Declaration | undefined { + if (!isGeneratedIdentifier(nodeIn)) { + const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); if (symbol && isSymbolOfDeclarationWithCollidingName(symbol)) { @@ -43482,8 +43680,8 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // Return true if the given node is a declaration of a nested block scoped entity with a name that either hides an // existing name or might hide a name when compiled downlevel - function isDeclarationWithCollidingName(nodeIn: ts.Declaration): boolean { - const node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); + function isDeclarationWithCollidingName(nodeIn: Declaration): boolean { + const node = getParseTreeNode(nodeIn, isDeclaration); if (node) { const symbol = getSymbolOfNode(node); if (symbol) { @@ -43494,42 +43692,42 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isValueAliasDeclaration(node: ts.Node): boolean { + function isValueAliasDeclaration(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return isAliasResolvedToValue(getSymbolOfNode(node)); - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: const symbol = getSymbolOfNode(node); - return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, ts.SymbolFlags.Value); - case ts.SyntaxKind.ExportDeclaration: - const exportClause = (node as ts.ExportDeclaration).exportClause; + return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value); + case SyntaxKind.ExportDeclaration: + const exportClause = (node as ExportDeclaration).exportClause; return !!exportClause && ( - ts.isNamespaceExport(exportClause) || - ts.some(exportClause.elements, isValueAliasDeclaration) + isNamespaceExport(exportClause) || + some(exportClause.elements, isValueAliasDeclaration) ); - case ts.SyntaxKind.ExportAssignment: - return (node as ts.ExportAssignment).expression && (node as ts.ExportAssignment).expression.kind === ts.SyntaxKind.Identifier ? + case SyntaxKind.ExportAssignment: + return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ? isAliasResolvedToValue(getSymbolOfNode(node)) : true; } return false; } - function isTopLevelValueImportEqualsWithEntityName(nodeIn: ts.ImportEqualsDeclaration): boolean { - const node = ts.getParseTreeNode(nodeIn, ts.isImportEqualsDeclaration); - if (node === undefined || node.parent.kind !== ts.SyntaxKind.SourceFile || !ts.isInternalModuleImportEqualsDeclaration(node)) { + function isTopLevelValueImportEqualsWithEntityName(nodeIn: ImportEqualsDeclaration): boolean { + const node = getParseTreeNode(nodeIn, isImportEqualsDeclaration); + if (node === undefined || node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) { // parent is not source file or it is not reference to internal module return false; } const isValue = isAliasResolvedToValue(getSymbolOfNode(node)); - return isValue && node.moduleReference && !ts.nodeIsMissing(node.moduleReference); + return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } - function isAliasResolvedToValue(symbol: ts.Symbol | undefined): boolean { + function isAliasResolvedToValue(symbol: Symbol | undefined): boolean { if (!symbol) { return false; } @@ -43539,15 +43737,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // const enums and modules that contain only const enums are not considered values from the emit perspective // unless 'preserveConstEnums' option is set to true - return !!((getAllSymbolFlags(target) ?? -1) & ts.SymbolFlags.Value) && - (ts.shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); + return !!((getAllSymbolFlags(target) ?? -1) & SymbolFlags.Value) && + (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target)); } - function isConstEnumOrConstEnumOnlyModule(s: ts.Symbol): boolean { + function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean { return isConstEnumSymbol(s) || !!s.constEnumOnlyModule; } - function isReferencedAliasDeclaration(node: ts.Node, checkChildren?: boolean): boolean { + function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { if (isAliasSymbolDeclaration(node)) { const symbol = getSymbolOfNode(node); const links = symbol && getSymbolLinks(symbol); @@ -43555,23 +43753,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return true; } const target = getSymbolLinks(symbol!).aliasTarget; // TODO: GH#18217 - if (target && ts.getEffectiveModifierFlags(node) & ts.ModifierFlags.Export && - getAllSymbolFlags(target) & ts.SymbolFlags.Value && - (ts.shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { + if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && + getAllSymbolFlags(target) & SymbolFlags.Value && + (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { // An `export import ... =` of a value symbol is always considered referenced return true; } } if (checkChildren) { - return !!ts.forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); + return !!forEachChild(node, node => isReferencedAliasDeclaration(node, checkChildren)); } return false; } - function isImplementationOfOverload(node: ts.SignatureDeclaration) { - if (ts.nodeIsPresent((node as ts.FunctionLikeDeclaration).body)) { - if (ts.isGetAccessor(node) || ts.isSetAccessor(node)) return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures + function isImplementationOfOverload(node: SignatureDeclaration) { + if (nodeIsPresent((node as FunctionLikeDeclaration).body)) { + if (isGetAccessor(node) || isSetAccessor(node)) return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures const symbol = getSymbolOfNode(node); const signaturesOfSymbol = getSignaturesOfSymbol(symbol); // If this function body corresponds to function with multiple signature, it is implementation of overload @@ -43591,73 +43789,73 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isRequiredInitializedParameter(parameter: ts.ParameterDeclaration | ts.JSDocParameterTag): boolean { + function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean { return !!strictNullChecks && !isOptionalParameter(parameter) && - !ts.isJSDocParameterTag(parameter) && + !isJSDocParameterTag(parameter) && !!parameter.initializer && - !ts.hasSyntacticModifier(parameter, ts.ModifierFlags.ParameterPropertyModifier); + !hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); } - function isOptionalUninitializedParameterProperty(parameter: ts.ParameterDeclaration) { + function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration) { return strictNullChecks && isOptionalParameter(parameter) && !parameter.initializer && - ts.hasSyntacticModifier(parameter, ts.ModifierFlags.ParameterPropertyModifier); + hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); } - function isExpandoFunctionDeclaration(node: ts.Declaration): boolean { - const declaration = ts.getParseTreeNode(node, ts.isFunctionDeclaration); + function isExpandoFunctionDeclaration(node: Declaration): boolean { + const declaration = getParseTreeNode(node, isFunctionDeclaration); if (!declaration) { return false; } const symbol = getSymbolOfNode(declaration); - if (!symbol || !(symbol.flags & ts.SymbolFlags.Function)) { + if (!symbol || !(symbol.flags & SymbolFlags.Function)) { return false; } - return !!ts.forEachEntry(getExportsOfSymbol(symbol), p => p.flags & ts.SymbolFlags.Value && p.valueDeclaration && ts.isPropertyAccessExpression(p.valueDeclaration)); + return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration)); } - function getPropertiesOfContainerFunction(node: ts.Declaration): ts.Symbol[] { - const declaration = ts.getParseTreeNode(node, ts.isFunctionDeclaration); + function getPropertiesOfContainerFunction(node: Declaration): Symbol[] { + const declaration = getParseTreeNode(node, isFunctionDeclaration); if (!declaration) { - return ts.emptyArray; + return emptyArray; } const symbol = getSymbolOfNode(declaration); - return symbol && getPropertiesOfType(getTypeOfSymbol(symbol)) || ts.emptyArray; + return symbol && getPropertiesOfType(getTypeOfSymbol(symbol)) || emptyArray; } - function getNodeCheckFlags(node: ts.Node): ts.NodeCheckFlags { + function getNodeCheckFlags(node: Node): NodeCheckFlags { const nodeId = node.id || 0; if (nodeId < 0 || nodeId >= nodeLinks.length) return 0; return nodeLinks[nodeId]?.flags || 0; } - function getEnumMemberValue(node: ts.EnumMember): string | number | undefined { + function getEnumMemberValue(node: EnumMember): string | number | undefined { computeEnumMemberValues(node.parent); return getNodeLinks(node).enumMemberValue; } - function canHaveConstantValue(node: ts.Node): node is ts.EnumMember | ts.AccessExpression { + function canHaveConstantValue(node: Node): node is EnumMember | AccessExpression { switch (node.kind) { - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.EnumMember: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return true; } return false; } - function getConstantValue(node: ts.EnumMember | ts.AccessExpression): string | number | undefined { - if (node.kind === ts.SyntaxKind.EnumMember) { + function getConstantValue(node: EnumMember | AccessExpression): string | number | undefined { + if (node.kind === SyntaxKind.EnumMember) { return getEnumMemberValue(node); } const symbol = getNodeLinks(node).resolvedSymbol; - if (symbol && (symbol.flags & ts.SymbolFlags.EnumMember)) { + if (symbol && (symbol.flags & SymbolFlags.EnumMember)) { // inline property\index accesses only for const enums - const member = symbol.valueDeclaration as ts.EnumMember; - if (ts.isEnumConst(member.parent)) { + const member = symbol.valueDeclaration as EnumMember; + if (isEnumConst(member.parent)) { return getEnumMemberValue(member); } } @@ -43665,146 +43863,146 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isFunctionType(type: ts.Type): boolean { - return !!(type.flags & ts.TypeFlags.Object) && getSignaturesOfType(type, ts.SignatureKind.Call).length > 0; + function isFunctionType(type: Type): boolean { + return !!(type.flags & TypeFlags.Object) && getSignaturesOfType(type, SignatureKind.Call).length > 0; } - function getTypeReferenceSerializationKind(typeNameIn: ts.EntityName, location?: ts.Node): ts.TypeReferenceSerializationKind { + function getTypeReferenceSerializationKind(typeNameIn: EntityName, location?: Node): TypeReferenceSerializationKind { // ensure both `typeName` and `location` are parse tree nodes. - const typeName = ts.getParseTreeNode(typeNameIn, ts.isEntityName); - if (!typeName) return ts.TypeReferenceSerializationKind.Unknown; + const typeName = getParseTreeNode(typeNameIn, isEntityName); + if (!typeName) return TypeReferenceSerializationKind.Unknown; if (location) { - location = ts.getParseTreeNode(location); - if (!location) return ts.TypeReferenceSerializationKind.Unknown; + location = getParseTreeNode(location); + if (!location) return TypeReferenceSerializationKind.Unknown; } // Resolve the symbol as a value to ensure the type can be reached at runtime during emit. let isTypeOnly = false; - if (ts.isQualifiedName(typeName)) { - const rootValueSymbol = resolveEntityName(ts.getFirstIdentifier(typeName), ts.SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); - isTypeOnly = !!rootValueSymbol?.declarations?.every(ts.isTypeOnlyImportOrExportDeclaration); + if (isQualifiedName(typeName)) { + const rootValueSymbol = resolveEntityName(getFirstIdentifier(typeName), SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); + isTypeOnly = !!rootValueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration); } - const valueSymbol = resolveEntityName(typeName, ts.SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); - const resolvedSymbol = valueSymbol && valueSymbol.flags & ts.SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol; - isTypeOnly ||= !!valueSymbol?.declarations?.every(ts.isTypeOnlyImportOrExportDeclaration); + const valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true, /*dontResolveAlias*/ true, location); + const resolvedSymbol = valueSymbol && valueSymbol.flags & SymbolFlags.Alias ? resolveAlias(valueSymbol) : valueSymbol; + isTypeOnly ||= !!valueSymbol?.declarations?.every(isTypeOnlyImportOrExportDeclaration); // Resolve the symbol as a type so that we can provide a more useful hint for the type serializer. - const typeSymbol = resolveEntityName(typeName, ts.SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); + const typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true, /*dontResolveAlias*/ false, location); if (resolvedSymbol && resolvedSymbol === typeSymbol) { const globalPromiseSymbol = getGlobalPromiseConstructorSymbol(/*reportErrors*/ false); if (globalPromiseSymbol && resolvedSymbol === globalPromiseSymbol) { - return ts.TypeReferenceSerializationKind.Promise; + return TypeReferenceSerializationKind.Promise; } const constructorType = getTypeOfSymbol(resolvedSymbol); if (constructorType && isConstructorType(constructorType)) { - return isTypeOnly ? ts.TypeReferenceSerializationKind.TypeWithCallSignature : ts.TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; + return isTypeOnly ? TypeReferenceSerializationKind.TypeWithCallSignature : TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue; } } // We might not be able to resolve type symbol so use unknown type in that case (eg error case) if (!typeSymbol) { - return isTypeOnly ? ts.TypeReferenceSerializationKind.ObjectType : ts.TypeReferenceSerializationKind.Unknown; + return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown; } const type = getDeclaredTypeOfSymbol(typeSymbol); if (isErrorType(type)) { - return isTypeOnly ? ts.TypeReferenceSerializationKind.ObjectType : ts.TypeReferenceSerializationKind.Unknown; + return isTypeOnly ? TypeReferenceSerializationKind.ObjectType : TypeReferenceSerializationKind.Unknown; } - else if (type.flags & ts.TypeFlags.AnyOrUnknown) { - return ts.TypeReferenceSerializationKind.ObjectType; + else if (type.flags & TypeFlags.AnyOrUnknown) { + return TypeReferenceSerializationKind.ObjectType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.Void | ts.TypeFlags.Nullable | ts.TypeFlags.Never)) { - return ts.TypeReferenceSerializationKind.VoidNullableOrNeverType; + else if (isTypeAssignableToKind(type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) { + return TypeReferenceSerializationKind.VoidNullableOrNeverType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.BooleanLike)) { - return ts.TypeReferenceSerializationKind.BooleanType; + else if (isTypeAssignableToKind(type, TypeFlags.BooleanLike)) { + return TypeReferenceSerializationKind.BooleanType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.NumberLike)) { - return ts.TypeReferenceSerializationKind.NumberLikeType; + else if (isTypeAssignableToKind(type, TypeFlags.NumberLike)) { + return TypeReferenceSerializationKind.NumberLikeType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.BigIntLike)) { - return ts.TypeReferenceSerializationKind.BigIntLikeType; + else if (isTypeAssignableToKind(type, TypeFlags.BigIntLike)) { + return TypeReferenceSerializationKind.BigIntLikeType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.StringLike)) { - return ts.TypeReferenceSerializationKind.StringLikeType; + else if (isTypeAssignableToKind(type, TypeFlags.StringLike)) { + return TypeReferenceSerializationKind.StringLikeType; } else if (isTupleType(type)) { - return ts.TypeReferenceSerializationKind.ArrayLikeType; + return TypeReferenceSerializationKind.ArrayLikeType; } - else if (isTypeAssignableToKind(type, ts.TypeFlags.ESSymbolLike)) { - return ts.TypeReferenceSerializationKind.ESSymbolType; + else if (isTypeAssignableToKind(type, TypeFlags.ESSymbolLike)) { + return TypeReferenceSerializationKind.ESSymbolType; } else if (isFunctionType(type)) { - return ts.TypeReferenceSerializationKind.TypeWithCallSignature; + return TypeReferenceSerializationKind.TypeWithCallSignature; } else if (isArrayType(type)) { - return ts.TypeReferenceSerializationKind.ArrayLikeType; + return TypeReferenceSerializationKind.ArrayLikeType; } else { - return ts.TypeReferenceSerializationKind.ObjectType; + return TypeReferenceSerializationKind.ObjectType; } } - function createTypeOfDeclaration(declarationIn: ts.AccessorDeclaration | ts.VariableLikeDeclaration | ts.PropertyAccessExpression, enclosingDeclaration: ts.Node, flags: ts.NodeBuilderFlags, tracker: ts.SymbolTracker, addUndefined?: boolean) { - const declaration = ts.getParseTreeNode(declarationIn, ts.isVariableLikeOrAccessor); + function createTypeOfDeclaration(declarationIn: AccessorDeclaration | VariableLikeDeclaration | PropertyAccessExpression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker, addUndefined?: boolean) { + const declaration = getParseTreeNode(declarationIn, isVariableLikeOrAccessor); if (!declaration) { - return ts.factory.createToken(ts.SyntaxKind.AnyKeyword) as ts.KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } // Get type of the symbol if this is the valid symbol otherwise get type at location const symbol = getSymbolOfNode(declaration); - let type = symbol && !(symbol.flags & (ts.SymbolFlags.TypeLiteral | ts.SymbolFlags.Signature)) + let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; - if (type.flags & ts.TypeFlags.UniqueESSymbol && + if (type.flags & TypeFlags.UniqueESSymbol && type.symbol === symbol) { - flags |= ts.NodeBuilderFlags.AllowUniqueESSymbolType; + flags |= NodeBuilderFlags.AllowUniqueESSymbolType; } if (addUndefined) { type = getOptionalType(type); } - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | ts.NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } - function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: ts.SignatureDeclaration, enclosingDeclaration: ts.Node, flags: ts.NodeBuilderFlags, tracker: ts.SymbolTracker) { - const signatureDeclaration = ts.getParseTreeNode(signatureDeclarationIn, ts.isFunctionLike); + function createReturnTypeOfSignatureDeclaration(signatureDeclarationIn: SignatureDeclaration, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + const signatureDeclaration = getParseTreeNode(signatureDeclarationIn, isFunctionLike); if (!signatureDeclaration) { - return ts.factory.createToken(ts.SyntaxKind.AnyKeyword) as ts.KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const signature = getSignatureFromDeclaration(signatureDeclaration); - return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | ts.NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode(getReturnTypeOfSignature(signature), enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } - function createTypeOfExpression(exprIn: ts.Expression, enclosingDeclaration: ts.Node, flags: ts.NodeBuilderFlags, tracker: ts.SymbolTracker) { - const expr = ts.getParseTreeNode(exprIn, ts.isExpression); + function createTypeOfExpression(exprIn: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker) { + const expr = getParseTreeNode(exprIn, isExpression); if (!expr) { - return ts.factory.createToken(ts.SyntaxKind.AnyKeyword) as ts.KeywordTypeNode; + return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } const type = getWidenedType(getRegularTypeOfExpression(expr)); - return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | ts.NodeBuilderFlags.MultilineObjectLiterals, tracker); + return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } function hasGlobalName(name: string): boolean { - return globals.has(ts.escapeLeadingUnderscores(name)); + return globals.has(escapeLeadingUnderscores(name)); } - function getReferencedValueSymbol(reference: ts.Identifier, startInDeclarationContainer?: boolean): ts.Symbol | undefined { + function getReferencedValueSymbol(reference: Identifier, startInDeclarationContainer?: boolean): Symbol | undefined { const resolvedSymbol = getNodeLinks(reference).resolvedSymbol; if (resolvedSymbol) { return resolvedSymbol; } - let location: ts.Node = reference; + let location: Node = reference; if (startInDeclarationContainer) { // When resolving the name of a declaration as a value, we need to start resolution // at a point outside of the declaration. const parent = reference.parent; - if (ts.isDeclaration(parent) && reference === parent.name) { + if (isDeclaration(parent) && reference === parent.name) { location = getDeclarationContainer(parent); } } - return resolveName(location, reference.escapedText, ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue | ts.SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); + return resolveName(location, reference.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); } /** @@ -43814,7 +44012,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * This is because when caching the resolved symbol, we only consider value symbols, but here * we want to also get an alias symbol if one exists. */ - function getReferencedValueOrAliasSymbol(reference: ts.Identifier): ts.Symbol | undefined { + function getReferencedValueOrAliasSymbol(reference: Identifier): Symbol | undefined { const resolvedSymbol = getNodeLinks(reference).resolvedSymbol; if (resolvedSymbol && resolvedSymbol !== unknownSymbol) { return resolvedSymbol; @@ -43823,7 +44021,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return resolveName( reference, reference.escapedText, - ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue | ts.SymbolFlags.Alias, + SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true, @@ -43831,9 +44029,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { /*getSpellingSuggestions*/ undefined); } - function getReferencedValueDeclaration(referenceIn: ts.Identifier): ts.Declaration | undefined { - if (!ts.isGeneratedIdentifier(referenceIn)) { - const reference = ts.getParseTreeNode(referenceIn, ts.isIdentifier); + function getReferencedValueDeclaration(referenceIn: Identifier): Declaration | undefined { + if (!isGeneratedIdentifier(referenceIn)) { + const reference = getParseTreeNode(referenceIn, isIdentifier); if (reference) { const symbol = getReferencedValueSymbol(reference); if (symbol) { @@ -43845,61 +44043,61 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return undefined; } - function isLiteralConstDeclaration(node: ts.VariableDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.ParameterDeclaration): boolean { - if (ts.isDeclarationReadonly(node) || ts.isVariableDeclaration(node) && ts.isVarConst(node)) { + function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { + if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) { return isFreshLiteralType(getTypeOfSymbol(getSymbolOfNode(node))); } return false; } - function literalTypeToNode(type: ts.FreshableType, enclosing: ts.Node, tracker: ts.SymbolTracker): ts.Expression { - const enumResult = type.flags & ts.TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, ts.SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) - : type === trueType ? ts.factory.createTrue() : type === falseType && ts.factory.createFalse(); + function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression { + const enumResult = type.flags & TypeFlags.EnumLiteral ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker) + : type === trueType ? factory.createTrue() : type === falseType && factory.createFalse(); if (enumResult) return enumResult; - const literalValue = (type as ts.LiteralType).value; - return typeof literalValue === "object" ? ts.factory.createBigIntLiteral(literalValue) : - typeof literalValue === "number" ? ts.factory.createNumericLiteral(literalValue) : - ts.factory.createStringLiteral(literalValue); + const literalValue = (type as LiteralType).value; + return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) : + typeof literalValue === "number" ? factory.createNumericLiteral(literalValue) : + factory.createStringLiteral(literalValue); } - function createLiteralConstValue(node: ts.VariableDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.ParameterDeclaration, tracker: ts.SymbolTracker) { + function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) { const type = getTypeOfSymbol(getSymbolOfNode(node)); - return literalTypeToNode(type as ts.FreshableType, node, tracker); + return literalTypeToNode(type as FreshableType, node, tracker); } - function getJsxFactoryEntity(location: ts.Node): ts.EntityName | undefined { - return location ? (getJsxNamespace(location), (ts.getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity; + function getJsxFactoryEntity(location: Node): EntityName | undefined { + return location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity; } - function getJsxFragmentFactoryEntity(location: ts.Node): ts.EntityName | undefined { + function getJsxFragmentFactoryEntity(location: Node): EntityName | undefined { if (location) { - const file = ts.getSourceFileOfNode(location); + const file = getSourceFileOfNode(location); if (file) { if (file.localJsxFragmentFactory) { return file.localJsxFragmentFactory; } const jsxFragPragmas = file.pragmas.get("jsxfrag"); - const jsxFragPragma = ts.isArray(jsxFragPragmas) ? jsxFragPragmas[0] : jsxFragPragmas; + const jsxFragPragma = isArray(jsxFragPragmas) ? jsxFragPragmas[0] : jsxFragPragmas; if (jsxFragPragma) { - file.localJsxFragmentFactory = ts.parseIsolatedEntityName(jsxFragPragma.arguments.factory, languageVersion); + file.localJsxFragmentFactory = parseIsolatedEntityName(jsxFragPragma.arguments.factory, languageVersion); return file.localJsxFragmentFactory; } } } if (compilerOptions.jsxFragmentFactory) { - return ts.parseIsolatedEntityName(compilerOptions.jsxFragmentFactory, languageVersion); + return parseIsolatedEntityName(compilerOptions.jsxFragmentFactory, languageVersion); } } - function createResolver(): ts.EmitResolver { + function createResolver(): EmitResolver { // this variable and functions that use it are deliberately moved here from the outer scope // to avoid scope pollution const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives(); - let fileToDirective: ts.ESMap; + let fileToDirective: ESMap; if (resolvedTypeReferenceDirectives) { // populate reverse mapping: file path -> type reference directive that was resolved to this file - fileToDirective = new ts.Map(); + fileToDirective = new Map(); resolvedTypeReferenceDirectives.forEach((resolvedDirective, key, mode) => { if (!resolvedDirective || !resolvedDirective.resolvedFileName) { return; @@ -43919,18 +44117,18 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { getReferencedDeclarationWithCollidingName, isDeclarationWithCollidingName, isValueAliasDeclaration: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); // Synthesized nodes are always treated like values. return node ? isValueAliasDeclaration(node) : true; }, hasGlobalName, isReferencedAliasDeclaration: (nodeIn, checkChildren?) => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); // Synthesized nodes are always treated as referenced. return node ? isReferencedAliasDeclaration(node, checkChildren) : true; }, getNodeCheckFlags: nodeIn => { - const node = ts.getParseTreeNode(nodeIn); + const node = getParseTreeNode(nodeIn); return node ? getNodeCheckFlags(node) : 0; }, isTopLevelValueImportEqualsWithEntityName, @@ -43947,7 +44145,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isSymbolAccessible, isEntityNameVisible, getConstantValue: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, canHaveConstantValue); + const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; }, collectLinkedAliases, @@ -43957,27 +44155,27 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { moduleExportsSomeValue, isArgumentsLocalBinding, getExternalModuleFileFromDeclaration: nodeIn => { - const node = ts.getParseTreeNode(nodeIn, ts.hasPossibleExternalModuleReference); + const node = getParseTreeNode(nodeIn, hasPossibleExternalModuleReference); return node && getExternalModuleFileFromDeclaration(node); }, getTypeReferenceDirectivesForEntityName, getTypeReferenceDirectivesForSymbol, isLiteralConstDeclaration, - isLateBound: (nodeIn: ts.Declaration): nodeIn is ts.LateBoundDeclaration => { - const node = ts.getParseTreeNode(nodeIn, ts.isDeclaration); + isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => { + const node = getParseTreeNode(nodeIn, isDeclaration); const symbol = node && getSymbolOfNode(node); - return !!(symbol && ts.getCheckFlags(symbol) & ts.CheckFlags.Late); + return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late); }, getJsxFactoryEntity, getJsxFragmentFactoryEntity, - getAllAccessorDeclarations(accessor: ts.AccessorDeclaration): ts.AllAccessorDeclarations { - accessor = ts.getParseTreeNode(accessor, ts.isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 - const otherKind = accessor.kind === ts.SyntaxKind.SetAccessor ? ts.SyntaxKind.GetAccessor : ts.SyntaxKind.SetAccessor; - const otherAccessor = ts.getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); + getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { + accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 + const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; - const setAccessor = accessor.kind === ts.SyntaxKind.SetAccessor ? accessor : otherAccessor as ts.SetAccessorDeclaration; - const getAccessor = accessor.kind === ts.SyntaxKind.GetAccessor ? accessor : otherAccessor as ts.GetAccessorDeclaration; + const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration; + const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor as GetAccessorDeclaration; return { firstAccessor, secondAccessor, @@ -43987,13 +44185,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { }, getSymbolOfExternalModuleSpecifier: moduleName => resolveExternalModuleNameWorker(moduleName, moduleName, /*moduleNotFoundError*/ undefined), isBindingCapturedByNode: (node, decl) => { - const parseNode = ts.getParseTreeNode(node); - const parseDecl = ts.getParseTreeNode(decl); - return !!parseNode && !!parseDecl && (ts.isVariableDeclaration(parseDecl) || ts.isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl); + const parseNode = getParseTreeNode(node); + const parseDecl = getParseTreeNode(decl); + return !!parseNode && !!parseDecl && (isVariableDeclaration(parseDecl) || isBindingElement(parseDecl)) && isBindingCapturedByNode(parseNode, parseDecl); }, getDeclarationStatementsForSourceFile: (node, flags, tracker, bundled) => { - const n = ts.getParseTreeNode(node) as ts.SourceFile; - ts.Debug.assert(n && n.kind === ts.SyntaxKind.SourceFile, "Non-sourcefile node passed into getDeclarationsForSourceFile"); + const n = getParseTreeNode(node) as SourceFile; + Debug.assert(n && n.kind === SyntaxKind.SourceFile, "Non-sourcefile node passed into getDeclarationsForSourceFile"); const sym = getSymbolOfNode(node); if (!sym) { return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled); @@ -44003,19 +44201,19 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { isImportRequiredByAugmentation, }; - function isImportRequiredByAugmentation(node: ts.ImportDeclaration) { - const file = ts.getSourceFileOfNode(node); + function isImportRequiredByAugmentation(node: ImportDeclaration) { + const file = getSourceFileOfNode(node); if (!file.symbol) return false; const importTarget = getExternalModuleFileFromDeclaration(node); if (!importTarget) return false; if (importTarget === file) return false; const exports = getExportsOfModule(file.symbol); - for (const s of ts.arrayFrom(exports.values())) { + for (const s of arrayFrom(exports.values())) { if (s.mergeId) { const merged = getMergedSymbol(s); if (merged.declarations) { for (const d of merged.declarations) { - const declFile = ts.getSourceFileOfNode(d); + const declFile = getSourceFileOfNode(d); if (declFile === importTarget) { return true; } @@ -44026,12 +44224,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function isInHeritageClause(node: ts.PropertyAccessEntityNameExpression) { - return node.parent && node.parent.kind === ts.SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === ts.SyntaxKind.HeritageClause; + function isInHeritageClause(node: PropertyAccessEntityNameExpression) { + return node.parent && node.parent.kind === SyntaxKind.ExpressionWithTypeArguments && node.parent.parent && node.parent.parent.kind === SyntaxKind.HeritageClause; } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForEntityName(node: ts.EntityNameOrEntityNameExpression): [specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined][] | undefined { + function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective) { return undefined; @@ -44041,13 +44239,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // qualified names can only be used as types\namespaces // identifiers are treated as values only if they appear in type queries let meaning; - if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) { - meaning = ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue; + if (node.parent.kind === SyntaxKind.ComputedPropertyName) { + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } else { - meaning = ts.SymbolFlags.Type | ts.SymbolFlags.Namespace; - if ((node.kind === ts.SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === ts.SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) { - meaning = ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue; + meaning = SymbolFlags.Type | SymbolFlags.Namespace; + if ((node.kind === SyntaxKind.Identifier && isInTypeQuery(node)) || (node.kind === SyntaxKind.PropertyAccessExpression && !isInHeritageClause(node))) { + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; } } @@ -44056,17 +44254,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // defined here to avoid outer scope pollution - function getTypeReferenceDirectivesForSymbol(symbol: ts.Symbol, meaning?: ts.SymbolFlags): [specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined][] | undefined { + function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined { // program does not have any files with type reference directives - bail out if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) { return undefined; } // check what declarations in the symbol can contribute to the target meaning - let typeReferenceDirectives: [specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined][] | undefined; + let typeReferenceDirectives: [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined; for (const decl of symbol.declarations!) { // check meaning of the local symbol to see if declaration needs to be analyzed further if (decl.symbol && decl.symbol.flags & meaning!) { - const file = ts.getSourceFileOfNode(decl); + const file = getSourceFileOfNode(decl); const typeReferenceDirective = fileToDirective.get(file.path); if (typeReferenceDirective) { (typeReferenceDirectives || (typeReferenceDirectives = [])).push(typeReferenceDirective); @@ -44080,7 +44278,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return typeReferenceDirectives; } - function isSymbolFromTypeDeclarationFile(symbol: ts.Symbol): boolean { + function isSymbolFromTypeDeclarationFile(symbol: Symbol): boolean { // bail out if symbol does not have associated declarations (i.e. this is transient symbol created for property in binding pattern) if (!symbol.declarations) { return false; @@ -44099,13 +44297,13 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (current.valueDeclaration && current.valueDeclaration.kind === ts.SyntaxKind.SourceFile && current.flags & ts.SymbolFlags.ValueModule) { + if (current.valueDeclaration && current.valueDeclaration.kind === SyntaxKind.SourceFile && current.flags & SymbolFlags.ValueModule) { return false; } // check that at least one declaration of top level symbol originates from type declaration file for (const decl of symbol.declarations) { - const file = ts.getSourceFileOfNode(decl); + const file = getSourceFileOfNode(decl); if (fileToDirective.has(file.path)) { return true; } @@ -44113,11 +44311,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function addReferencedFilesToTypeDirective(file: ts.SourceFile, key: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined) { + function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: SourceFile["impliedNodeFormat"] | undefined) { if (fileToDirective.has(file.path)) return; fileToDirective.set(file.path, [key, mode]); for (const { fileName, resolutionMode } of file.referencedFiles) { - const resolvedFile = ts.resolveTripleslashReference(fileName, file.fileName); + const resolvedFile = resolveTripleslashReference(fileName, file.fileName); const referencedFile = host.getSourceFile(resolvedFile); if (referencedFile) { addReferencedFilesToTypeDirective(referencedFile, key, resolutionMode || file.impliedNodeFormat); @@ -44126,36 +44324,36 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getExternalModuleFileFromDeclaration(declaration: ts.AnyImportOrReExport | ts.ModuleDeclaration | ts.ImportTypeNode | ts.ImportCall): ts.SourceFile | undefined { - const specifier = declaration.kind === ts.SyntaxKind.ModuleDeclaration ? ts.tryCast(declaration.name, ts.isStringLiteral) : ts.getExternalModuleName(declaration); + function getExternalModuleFileFromDeclaration(declaration: AnyImportOrReExport | ModuleDeclaration | ImportTypeNode | ImportCall): SourceFile | undefined { + const specifier = declaration.kind === SyntaxKind.ModuleDeclaration ? tryCast(declaration.name, isStringLiteral) : getExternalModuleName(declaration); const moduleSymbol = resolveExternalModuleNameWorker(specifier!, specifier!, /*moduleNotFoundError*/ undefined); // TODO: GH#18217 if (!moduleSymbol) { return undefined; } - return ts.getDeclarationOfKind(moduleSymbol, ts.SyntaxKind.SourceFile); + return getDeclarationOfKind(moduleSymbol, SyntaxKind.SourceFile); } function initializeTypeChecker() { // Bind all source files and propagate errors for (const file of host.getSourceFiles()) { - ts.bindSourceFile(file, compilerOptions); + bindSourceFile(file, compilerOptions); } - amalgamatedDuplicates = new ts.Map(); + amalgamatedDuplicates = new Map(); // Initialize global symbol table - let augmentations: (readonly (ts.StringLiteral | ts.Identifier)[])[] | undefined; + let augmentations: (readonly (StringLiteral | Identifier)[])[] | undefined; for (const file of host.getSourceFiles()) { if (file.redirectInfo) { continue; } - if (!ts.isExternalOrCommonJsModule(file)) { + if (!isExternalOrCommonJsModule(file)) { // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`. // We can't use `builtinGlobals` for this due to synthetic expando-namespace generation in JS files. - const fileGlobalThisSymbol = file.locals!.get("globalThis" as ts.__String); + const fileGlobalThisSymbol = file.locals!.get("globalThis" as __String); if (fileGlobalThisSymbol?.declarations) { for (const declaration of fileGlobalThisSymbol.declarations) { - diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")); + diagnostics.add(createDiagnosticForNode(declaration, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")); } } mergeSymbolTable(globals, file.locals!); @@ -44164,7 +44362,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { mergeSymbolTable(globals, file.jsGlobalAugmentations); } if (file.patternAmbientModules && file.patternAmbientModules.length) { - patternAmbientModules = ts.concatenate(patternAmbientModules, file.patternAmbientModules); + patternAmbientModules = concatenate(patternAmbientModules, file.patternAmbientModules); } if (file.moduleAugmentations.length) { (augmentations || (augmentations = [])).push(file.moduleAugmentations); @@ -44191,48 +44389,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (const list of augmentations) { for (const augmentation of list) { - if (!ts.isGlobalScopeAugmentation(augmentation.parent as ts.ModuleDeclaration)) continue; + if (!isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue; mergeModuleAugmentation(augmentation); } } } // Setup global builtins - addToSymbolTable(globals, builtinGlobals, ts.Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); + addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); getSymbolLinks(undefinedSymbol).type = undefinedWideningType; - getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); + getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; - getSymbolLinks(globalThisSymbol).type = createObjectType(ts.ObjectFlags.Anonymous, globalThisSymbol); + getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol); // Initialize special types - globalArrayType = getGlobalType("Array" as ts.__String, /*arity*/ 1, /*reportErrors*/ true); - globalObjectType = getGlobalType("Object" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); - globalFunctionType = getGlobalType("Function" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); - globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as ts.__String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; - globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as ts.__String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; - globalStringType = getGlobalType("String" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); - globalNumberType = getGlobalType("Number" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); - globalBooleanType = getGlobalType("Boolean" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); - globalRegExpType = getGlobalType("RegExp" as ts.__String, /*arity*/ 0, /*reportErrors*/ true); + globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); + globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; + globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; + globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true); + globalRegExpType = getGlobalType("RegExp" as __String, /*arity*/ 0, /*reportErrors*/ true); anyArrayType = createArrayType(anyType); autoArrayType = createArrayType(autoType); if (autoArrayType === emptyObjectType) { // autoArrayType is used as a marker, so even if global Array type is not defined, it needs to be a unique type - autoArrayType = createAnonymousType(undefined, emptySymbols, ts.emptyArray, ts.emptyArray, ts.emptyArray); + autoArrayType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray); } - globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as ts.__String, /*arity*/ 1) as ts.GenericType || globalArrayType; + globalReadonlyArrayType = getGlobalTypeOrUndefined("ReadonlyArray" as __String, /*arity*/ 1) as GenericType || globalArrayType; anyReadonlyArrayType = globalReadonlyArrayType ? createTypeFromGenericGlobalType(globalReadonlyArrayType, [anyType]) : anyArrayType; - globalThisType = getGlobalTypeOrUndefined("ThisType" as ts.__String, /*arity*/ 1) as ts.GenericType; + globalThisType = getGlobalTypeOrUndefined("ThisType" as __String, /*arity*/ 1) as GenericType; if (augmentations) { // merge _nonglobal_ module augmentations. // this needs to be done after global symbol table is initialized to make sure that all ambient modules are indexed for (const list of augmentations) { for (const augmentation of list) { - if (ts.isGlobalScopeAugmentation(augmentation.parent as ts.ModuleDeclaration)) continue; + if (isGlobalScopeAugmentation(augmentation.parent as ModuleDeclaration)) continue; mergeModuleAugmentation(augmentation); } } @@ -44242,7 +44440,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // If not many things conflict, issue individual errors if (conflictingSymbols.size < 8) { conflictingSymbols.forEach(({ isBlockScoped, firstFileLocations, secondFileLocations }, symbolName) => { - const message = isBlockScoped ? ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0 : ts.Diagnostics.Duplicate_identifier_0; + const message = isBlockScoped ? Diagnostics.Cannot_redeclare_block_scoped_variable_0 : Diagnostics.Duplicate_identifier_0; for (const node of firstFileLocations) { addDuplicateDeclarationError(node, message, symbolName, secondFileLocations); } @@ -44253,47 +44451,47 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { // Otherwise issue top-level error since the files appear very identical in terms of what they contain - const list = ts.arrayFrom(conflictingSymbols.keys()).join(", "); - diagnostics.add(ts.addRelatedInfo( - ts.createDiagnosticForNode(firstFile, ts.Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), - ts.createDiagnosticForNode(secondFile, ts.Diagnostics.Conflicts_are_in_this_file) + const list = arrayFrom(conflictingSymbols.keys()).join(", "); + diagnostics.add(addRelatedInfo( + createDiagnosticForNode(firstFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), + createDiagnosticForNode(secondFile, Diagnostics.Conflicts_are_in_this_file) )); - diagnostics.add(ts.addRelatedInfo( - ts.createDiagnosticForNode(secondFile, ts.Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), - ts.createDiagnosticForNode(firstFile, ts.Diagnostics.Conflicts_are_in_this_file) + diagnostics.add(addRelatedInfo( + createDiagnosticForNode(secondFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), + createDiagnosticForNode(firstFile, Diagnostics.Conflicts_are_in_this_file) )); } }); amalgamatedDuplicates = undefined; } - function checkExternalEmitHelpers(location: ts.Node, helpers: ts.ExternalEmitHelpers) { + function checkExternalEmitHelpers(location: Node, helpers: ExternalEmitHelpers) { if ((requestedExternalEmitHelpers & helpers) !== helpers && compilerOptions.importHelpers) { - const sourceFile = ts.getSourceFileOfNode(location); - if (ts.isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & ts.NodeFlags.Ambient)) { + const sourceFile = getSourceFileOfNode(location); + if (isEffectiveExternalModule(sourceFile, compilerOptions) && !(location.flags & NodeFlags.Ambient)) { const helpersModule = resolveHelpersModule(sourceFile, location); if (helpersModule !== unknownSymbol) { const uncheckedHelpers = helpers & ~requestedExternalEmitHelpers; - for (let helper = ts.ExternalEmitHelpers.FirstEmitHelper; helper <= ts.ExternalEmitHelpers.LastEmitHelper; helper <<= 1) { + for (let helper = ExternalEmitHelpers.FirstEmitHelper; helper <= ExternalEmitHelpers.LastEmitHelper; helper <<= 1) { if (uncheckedHelpers & helper) { const name = getHelperName(helper); - const symbol = getSymbol(helpersModule.exports!, ts.escapeLeadingUnderscores(name), ts.SymbolFlags.Value); + const symbol = getSymbol(helpersModule.exports!, escapeLeadingUnderscores(name), SymbolFlags.Value); if (!symbol) { - error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, ts.externalHelpersModuleNameText, name); + error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name); } - else if (helper & ts.ExternalEmitHelpers.ClassPrivateFieldGet) { - if (!ts.some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) { - error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, ts.externalHelpersModuleNameText, name, 4); + else if (helper & ExternalEmitHelpers.ClassPrivateFieldGet) { + if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 3)) { + error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 4); } } - else if (helper & ts.ExternalEmitHelpers.ClassPrivateFieldSet) { - if (!ts.some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) { - error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, ts.externalHelpersModuleNameText, name, 5); + else if (helper & ExternalEmitHelpers.ClassPrivateFieldSet) { + if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 4)) { + error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 5); } } - else if (helper & ts.ExternalEmitHelpers.SpreadArray) { - if (!ts.some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) { - error(location, ts.Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, ts.externalHelpersModuleNameText, name, 3); + else if (helper & ExternalEmitHelpers.SpreadArray) { + if (!some(getSignaturesOfSymbol(symbol), signature => getParameterCount(signature) > 2)) { + error(location, Diagnostics.This_syntax_requires_an_imported_helper_named_1_with_2_parameters_which_is_not_compatible_with_the_one_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name, 3); } } } @@ -44304,371 +44502,371 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function getHelperName(helper: ts.ExternalEmitHelpers) { + function getHelperName(helper: ExternalEmitHelpers) { switch (helper) { - case ts.ExternalEmitHelpers.Extends: return "__extends"; - case ts.ExternalEmitHelpers.Assign: return "__assign"; - case ts.ExternalEmitHelpers.Rest: return "__rest"; - case ts.ExternalEmitHelpers.Decorate: return "__decorate"; - case ts.ExternalEmitHelpers.Metadata: return "__metadata"; - case ts.ExternalEmitHelpers.Param: return "__param"; - case ts.ExternalEmitHelpers.Awaiter: return "__awaiter"; - case ts.ExternalEmitHelpers.Generator: return "__generator"; - case ts.ExternalEmitHelpers.Values: return "__values"; - case ts.ExternalEmitHelpers.Read: return "__read"; - case ts.ExternalEmitHelpers.SpreadArray: return "__spreadArray"; - case ts.ExternalEmitHelpers.Await: return "__await"; - case ts.ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator"; - case ts.ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator"; - case ts.ExternalEmitHelpers.AsyncValues: return "__asyncValues"; - case ts.ExternalEmitHelpers.ExportStar: return "__exportStar"; - case ts.ExternalEmitHelpers.ImportStar: return "__importStar"; - case ts.ExternalEmitHelpers.ImportDefault: return "__importDefault"; - case ts.ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject"; - case ts.ExternalEmitHelpers.ClassPrivateFieldGet: return "__classPrivateFieldGet"; - case ts.ExternalEmitHelpers.ClassPrivateFieldSet: return "__classPrivateFieldSet"; - case ts.ExternalEmitHelpers.ClassPrivateFieldIn: return "__classPrivateFieldIn"; - case ts.ExternalEmitHelpers.CreateBinding: return "__createBinding"; - default: return ts.Debug.fail("Unrecognized helper"); - } - } - - function resolveHelpersModule(node: ts.SourceFile, errorNode: ts.Node) { + case ExternalEmitHelpers.Extends: return "__extends"; + case ExternalEmitHelpers.Assign: return "__assign"; + case ExternalEmitHelpers.Rest: return "__rest"; + case ExternalEmitHelpers.Decorate: return "__decorate"; + case ExternalEmitHelpers.Metadata: return "__metadata"; + case ExternalEmitHelpers.Param: return "__param"; + case ExternalEmitHelpers.Awaiter: return "__awaiter"; + case ExternalEmitHelpers.Generator: return "__generator"; + case ExternalEmitHelpers.Values: return "__values"; + case ExternalEmitHelpers.Read: return "__read"; + case ExternalEmitHelpers.SpreadArray: return "__spreadArray"; + case ExternalEmitHelpers.Await: return "__await"; + case ExternalEmitHelpers.AsyncGenerator: return "__asyncGenerator"; + case ExternalEmitHelpers.AsyncDelegator: return "__asyncDelegator"; + case ExternalEmitHelpers.AsyncValues: return "__asyncValues"; + case ExternalEmitHelpers.ExportStar: return "__exportStar"; + case ExternalEmitHelpers.ImportStar: return "__importStar"; + case ExternalEmitHelpers.ImportDefault: return "__importDefault"; + case ExternalEmitHelpers.MakeTemplateObject: return "__makeTemplateObject"; + case ExternalEmitHelpers.ClassPrivateFieldGet: return "__classPrivateFieldGet"; + case ExternalEmitHelpers.ClassPrivateFieldSet: return "__classPrivateFieldSet"; + case ExternalEmitHelpers.ClassPrivateFieldIn: return "__classPrivateFieldIn"; + case ExternalEmitHelpers.CreateBinding: return "__createBinding"; + default: return Debug.fail("Unrecognized helper"); + } + } + + function resolveHelpersModule(node: SourceFile, errorNode: Node) { if (!externalHelpersModule) { - externalHelpersModule = resolveExternalModule(node, ts.externalHelpersModuleNameText, ts.Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol; + externalHelpersModule = resolveExternalModule(node, externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol; } return externalHelpersModule; } // GRAMMAR CHECKING - function checkGrammarDecoratorsAndModifiers(node: ts.HasModifiers | ts.HasDecorators | ts.HasIllegalModifiers | ts.HasIllegalDecorators): boolean { + function checkGrammarDecoratorsAndModifiers(node: HasModifiers | HasDecorators | HasIllegalModifiers | HasIllegalDecorators): boolean { return checkGrammarDecorators(node) || checkGrammarModifiers(node); } - function checkGrammarDecorators(node: ts.Node): boolean { - if (ts.canHaveIllegalDecorators(node) && ts.some(node.illegalDecorators)) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here); + function checkGrammarDecorators(node: Node): boolean { + if (canHaveIllegalDecorators(node) && some(node.illegalDecorators)) { + return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here); } - if (!ts.canHaveDecorators(node) || !ts.hasDecorators(node)) { + if (!canHaveDecorators(node) || !hasDecorators(node)) { return false; } - if (!ts.nodeCanBeDecorated(node, node.parent, node.parent.parent)) { - if (node.kind === ts.SyntaxKind.MethodDeclaration && !ts.nodeIsPresent(node.body)) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); + if (!nodeCanBeDecorated(node, node.parent, node.parent.parent)) { + if (node.kind === SyntaxKind.MethodDeclaration && !nodeIsPresent(node.body)) { + return grammarErrorOnFirstToken(node, Diagnostics.A_decorator_can_only_decorate_a_method_implementation_not_an_overload); } else { - return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_are_not_valid_here); + return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here); } } - else if (node.kind === ts.SyntaxKind.GetAccessor || node.kind === ts.SyntaxKind.SetAccessor) { - const accessors = ts.getAllAccessorDeclarations((node.parent as ts.ClassDeclaration).members, node as ts.AccessorDeclaration); - if (ts.hasDecorators(accessors.firstAccessor) && node === accessors.secondAccessor) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); + else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) { + const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node as AccessorDeclaration); + if (hasDecorators(accessors.firstAccessor) && node === accessors.secondAccessor) { + return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name); } } return false; } - function checkGrammarModifiers(node: ts.HasModifiers | ts.HasIllegalModifiers): boolean { + function checkGrammarModifiers(node: HasModifiers | HasIllegalModifiers): boolean { const quickResult = reportObviousModifierErrors(node); if (quickResult !== undefined) { return quickResult; } - let lastStatic: ts.Node | undefined, lastDeclare: ts.Node | undefined, lastAsync: ts.Node | undefined, lastOverride: ts.Node | undefined; - let flags = ts.ModifierFlags.None; + let lastStatic: Node | undefined, lastDeclare: Node | undefined, lastAsync: Node | undefined, lastOverride: Node | undefined; + let flags = ModifierFlags.None; for (const modifier of node.modifiers!) { - if (ts.isDecorator(modifier)) continue; - if (modifier.kind !== ts.SyntaxKind.ReadonlyKeyword) { - if (node.kind === ts.SyntaxKind.PropertySignature || node.kind === ts.SyntaxKind.MethodSignature) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_type_member, ts.tokenToString(modifier.kind)); + if (isDecorator(modifier)) continue; + if (modifier.kind !== SyntaxKind.ReadonlyKeyword) { + if (node.kind === SyntaxKind.PropertySignature || node.kind === SyntaxKind.MethodSignature) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_member, tokenToString(modifier.kind)); } - if (node.kind === ts.SyntaxKind.IndexSignature && (modifier.kind !== ts.SyntaxKind.StaticKeyword || !ts.isClassLike(node.parent))) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_an_index_signature, ts.tokenToString(modifier.kind)); + if (node.kind === SyntaxKind.IndexSignature && (modifier.kind !== SyntaxKind.StaticKeyword || !isClassLike(node.parent))) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_an_index_signature, tokenToString(modifier.kind)); } } - if (modifier.kind !== ts.SyntaxKind.InKeyword && modifier.kind !== ts.SyntaxKind.OutKeyword) { - if (node.kind === ts.SyntaxKind.TypeParameter) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_type_parameter, ts.tokenToString(modifier.kind)); + if (modifier.kind !== SyntaxKind.InKeyword && modifier.kind !== SyntaxKind.OutKeyword) { + if (node.kind === SyntaxKind.TypeParameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_type_parameter, tokenToString(modifier.kind)); } } switch (modifier.kind) { - case ts.SyntaxKind.ConstKeyword: - if (node.kind !== ts.SyntaxKind.EnumDeclaration) { - return grammarErrorOnNode(node, ts.Diagnostics.A_class_member_cannot_have_the_0_keyword, ts.tokenToString(ts.SyntaxKind.ConstKeyword)); + case SyntaxKind.ConstKeyword: + if (node.kind !== SyntaxKind.EnumDeclaration) { + return grammarErrorOnNode(node, Diagnostics.A_class_member_cannot_have_the_0_keyword, tokenToString(SyntaxKind.ConstKeyword)); } break; - case ts.SyntaxKind.OverrideKeyword: + case SyntaxKind.OverrideKeyword: // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property. - if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "override"); + if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "override"); } - else if (flags & ts.ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "override", "declare"); + else if (flags & ModifierFlags.Ambient) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "override", "declare"); } - else if (flags & ts.ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly"); + else if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "readonly"); } - else if (flags & ts.ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "override", "accessor"); + else if (flags & ModifierFlags.Accessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "accessor"); } - else if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "override", "async"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "override", "async"); } - flags |= ts.ModifierFlags.Override; + flags |= ModifierFlags.Override; lastOverride = modifier; break; - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.PrivateKeyword: - const text = visibilityToString(ts.modifierToFlag(modifier.kind)); + case SyntaxKind.PublicKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PrivateKeyword: + const text = visibilityToString(modifierToFlag(modifier.kind)); - if (flags & ts.ModifierFlags.AccessibilityModifier) { - return grammarErrorOnNode(modifier, ts.Diagnostics.Accessibility_modifier_already_seen); + if (flags & ModifierFlags.AccessibilityModifier) { + return grammarErrorOnNode(modifier, Diagnostics.Accessibility_modifier_already_seen); } - else if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "override"); + else if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "override"); } - else if (flags & ts.ModifierFlags.Static) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); + else if (flags & ModifierFlags.Static) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static"); } - else if (flags & ts.ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "accessor"); + else if (flags & ModifierFlags.Accessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "accessor"); } - else if (flags & ts.ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); + else if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "readonly"); } - else if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async"); } - else if (node.parent.kind === ts.SyntaxKind.ModuleBlock || node.parent.kind === ts.SyntaxKind.SourceFile) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); + else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, text); } - else if (flags & ts.ModifierFlags.Abstract) { - if (modifier.kind === ts.SyntaxKind.PrivateKeyword) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); + else if (flags & ModifierFlags.Abstract) { + if (modifier.kind === SyntaxKind.PrivateKeyword) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, text, "abstract"); } else { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, text, "abstract"); + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "abstract"); } } - else if (ts.isPrivateIdentifierClassElementDeclaration(node)) { - return grammarErrorOnNode(modifier, ts.Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier); + else if (isPrivateIdentifierClassElementDeclaration(node)) { + return grammarErrorOnNode(modifier, Diagnostics.An_accessibility_modifier_cannot_be_used_with_a_private_identifier); } - flags |= ts.modifierToFlag(modifier.kind); + flags |= modifierToFlag(modifier.kind); break; - case ts.SyntaxKind.StaticKeyword: - if (flags & ts.ModifierFlags.Static) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "static"); + case SyntaxKind.StaticKeyword: + if (flags & ModifierFlags.Static) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static"); } - else if (flags & ts.ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); + else if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "readonly"); } - else if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async"); } - else if (flags & ts.ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "accessor"); + else if (flags & ModifierFlags.Accessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "accessor"); } - else if (node.parent.kind === ts.SyntaxKind.ModuleBlock || node.parent.kind === ts.SyntaxKind.SourceFile) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static"); + else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element, "static"); } - else if (node.kind === ts.SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); + else if (node.kind === SyntaxKind.Parameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "static"); } - else if (flags & ts.ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); + else if (flags & ModifierFlags.Abstract) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - else if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "static", "override"); + else if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "override"); } - flags |= ts.ModifierFlags.Static; + flags |= ModifierFlags.Static; lastStatic = modifier; break; - case ts.SyntaxKind.AccessorKeyword: - if (flags & ts.ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "accessor"); + case SyntaxKind.AccessorKeyword: + if (flags & ModifierFlags.Accessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "accessor"); } - else if (flags & ts.ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "readonly"); + else if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "readonly"); } - else if (flags & ts.ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "declare"); + else if (flags & ModifierFlags.Ambient) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "accessor", "declare"); } - else if (node.kind !== ts.SyntaxKind.PropertyDeclaration) { - return grammarErrorOnNode(modifier, ts.Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration); + else if (node.kind !== SyntaxKind.PropertyDeclaration) { + return grammarErrorOnNode(modifier, Diagnostics.accessor_modifier_can_only_appear_on_a_property_declaration); } - flags |= ts.ModifierFlags.Accessor; + flags |= ModifierFlags.Accessor; break; - case ts.SyntaxKind.ReadonlyKeyword: - if (flags & ts.ModifierFlags.Readonly) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "readonly"); + case SyntaxKind.ReadonlyKeyword: + if (flags & ModifierFlags.Readonly) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "readonly"); } - else if (node.kind !== ts.SyntaxKind.PropertyDeclaration && node.kind !== ts.SyntaxKind.PropertySignature && node.kind !== ts.SyntaxKind.IndexSignature && node.kind !== ts.SyntaxKind.Parameter) { + else if (node.kind !== SyntaxKind.PropertyDeclaration && node.kind !== SyntaxKind.PropertySignature && node.kind !== SyntaxKind.IndexSignature && node.kind !== SyntaxKind.Parameter) { // If node.kind === SyntaxKind.Parameter, checkParameter reports an error if it's not a parameter property. - return grammarErrorOnNode(modifier, ts.Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); + return grammarErrorOnNode(modifier, Diagnostics.readonly_modifier_can_only_appear_on_a_property_declaration_or_index_signature); } - flags |= ts.ModifierFlags.Readonly; + flags |= ModifierFlags.Readonly; break; - case ts.SyntaxKind.ExportKeyword: - if (flags & ts.ModifierFlags.Export) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "export"); + case SyntaxKind.ExportKeyword: + if (flags & ModifierFlags.Export) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "export"); } - else if (flags & ts.ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); + else if (flags & ModifierFlags.Ambient) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare"); } - else if (flags & ts.ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); + else if (flags & ModifierFlags.Abstract) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "abstract"); } - else if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async"); } - else if (ts.isClassLike(node.parent)) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "export"); + else if (isClassLike(node.parent)) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "export"); } - else if (node.kind === ts.SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); + else if (node.kind === SyntaxKind.Parameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "export"); } - flags |= ts.ModifierFlags.Export; + flags |= ModifierFlags.Export; break; - case ts.SyntaxKind.DefaultKeyword: - const container = node.parent.kind === ts.SyntaxKind.SourceFile ? node.parent : node.parent.parent; - if (container.kind === ts.SyntaxKind.ModuleDeclaration && !ts.isAmbientModule(container)) { - return grammarErrorOnNode(modifier, ts.Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); + case SyntaxKind.DefaultKeyword: + const container = node.parent.kind === SyntaxKind.SourceFile ? node.parent : node.parent.parent; + if (container.kind === SyntaxKind.ModuleDeclaration && !isAmbientModule(container)) { + return grammarErrorOnNode(modifier, Diagnostics.A_default_export_can_only_be_used_in_an_ECMAScript_style_module); } - else if (!(flags & ts.ModifierFlags.Export)) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "export", "default"); + else if (!(flags & ModifierFlags.Export)) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "default"); } - flags |= ts.ModifierFlags.Default; + flags |= ModifierFlags.Default; break; - case ts.SyntaxKind.DeclareKeyword: - if (flags & ts.ModifierFlags.Ambient) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "declare"); + case SyntaxKind.DeclareKeyword: + if (flags & ModifierFlags.Ambient) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare"); } - else if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); + else if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "override"); + else if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "override"); } - else if (ts.isClassLike(node.parent) && !ts.isPropertyDeclaration(node)) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "declare"); + else if (isClassLike(node.parent) && !isPropertyDeclaration(node)) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind, "declare"); } - else if (node.kind === ts.SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); + else if (node.kind === SyntaxKind.Parameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "declare"); } - else if ((node.parent.flags & ts.NodeFlags.Ambient) && node.parent.kind === ts.SyntaxKind.ModuleBlock) { - return grammarErrorOnNode(modifier, ts.Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); + else if ((node.parent.flags & NodeFlags.Ambient) && node.parent.kind === SyntaxKind.ModuleBlock) { + return grammarErrorOnNode(modifier, Diagnostics.A_declare_modifier_cannot_be_used_in_an_already_ambient_context); } - else if (ts.isPrivateIdentifierClassElementDeclaration(node)) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "declare"); + else if (isPrivateIdentifierClassElementDeclaration(node)) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "declare"); } - flags |= ts.ModifierFlags.Ambient; + flags |= ModifierFlags.Ambient; lastDeclare = modifier; break; - case ts.SyntaxKind.AbstractKeyword: - if (flags & ts.ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "abstract"); + case SyntaxKind.AbstractKeyword: + if (flags & ModifierFlags.Abstract) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "abstract"); } - if (node.kind !== ts.SyntaxKind.ClassDeclaration && - node.kind !== ts.SyntaxKind.ConstructorType) { - if (node.kind !== ts.SyntaxKind.MethodDeclaration && - node.kind !== ts.SyntaxKind.PropertyDeclaration && - node.kind !== ts.SyntaxKind.GetAccessor && - node.kind !== ts.SyntaxKind.SetAccessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); + if (node.kind !== SyntaxKind.ClassDeclaration && + node.kind !== SyntaxKind.ConstructorType) { + if (node.kind !== SyntaxKind.MethodDeclaration && + node.kind !== SyntaxKind.PropertyDeclaration && + node.kind !== SyntaxKind.GetAccessor && + node.kind !== SyntaxKind.SetAccessor) { + return grammarErrorOnNode(modifier, Diagnostics.abstract_modifier_can_only_appear_on_a_class_method_or_property_declaration); } - if (!(node.parent.kind === ts.SyntaxKind.ClassDeclaration && ts.hasSyntacticModifier(node.parent, ts.ModifierFlags.Abstract))) { - return grammarErrorOnNode(modifier, ts.Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); + if (!(node.parent.kind === SyntaxKind.ClassDeclaration && hasSyntacticModifier(node.parent, ModifierFlags.Abstract))) { + return grammarErrorOnNode(modifier, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); } - if (flags & ts.ModifierFlags.Static) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); + if (flags & ModifierFlags.Static) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract"); } - if (flags & ts.ModifierFlags.Private) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); + if (flags & ModifierFlags.Private) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "private", "abstract"); } - if (flags & ts.ModifierFlags.Async && lastAsync) { - return grammarErrorOnNode(lastAsync, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); + if (flags & ModifierFlags.Async && lastAsync) { + return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); } - if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "override"); + if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "override"); } - if (flags & ts.ModifierFlags.Accessor) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "accessor"); + if (flags & ModifierFlags.Accessor) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "abstract", "accessor"); } } - if (ts.isNamedDeclaration(node) && node.name.kind === ts.SyntaxKind.PrivateIdentifier) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "abstract"); + if (isNamedDeclaration(node) && node.name.kind === SyntaxKind.PrivateIdentifier) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "abstract"); } - flags |= ts.ModifierFlags.Abstract; + flags |= ModifierFlags.Abstract; break; - case ts.SyntaxKind.AsyncKeyword: - if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, "async"); + case SyntaxKind.AsyncKeyword: + if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async"); } - else if (flags & ts.ModifierFlags.Ambient || node.parent.flags & ts.NodeFlags.Ambient) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); + else if (flags & ModifierFlags.Ambient || node.parent.flags & NodeFlags.Ambient) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async"); } - else if (node.kind === ts.SyntaxKind.Parameter) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); + else if (node.kind === SyntaxKind.Parameter) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async"); } - if (flags & ts.ModifierFlags.Abstract) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); + if (flags & ModifierFlags.Abstract) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "async", "abstract"); } - flags |= ts.ModifierFlags.Async; + flags |= ModifierFlags.Async; lastAsync = modifier; break; - case ts.SyntaxKind.InKeyword: - case ts.SyntaxKind.OutKeyword: - const inOutFlag = modifier.kind === ts.SyntaxKind.InKeyword ? ts.ModifierFlags.In : ts.ModifierFlags.Out; - const inOutText = modifier.kind === ts.SyntaxKind.InKeyword ? "in" : "out"; - if (node.kind !== ts.SyntaxKind.TypeParameter || !(ts.isInterfaceDeclaration(node.parent) || ts.isClassLike(node.parent) || ts.isTypeAliasDeclaration(node.parent))) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, inOutText); + case SyntaxKind.InKeyword: + case SyntaxKind.OutKeyword: + const inOutFlag = modifier.kind === SyntaxKind.InKeyword ? ModifierFlags.In : ModifierFlags.Out; + const inOutText = modifier.kind === SyntaxKind.InKeyword ? "in" : "out"; + if (node.kind !== SyntaxKind.TypeParameter || !(isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent))) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_can_only_appear_on_a_type_parameter_of_a_class_interface_or_type_alias, inOutText); } if (flags & inOutFlag) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_already_seen, inOutText); + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, inOutText); } - if (inOutFlag & ts.ModifierFlags.In && flags & ts.ModifierFlags.Out) { - return grammarErrorOnNode(modifier, ts.Diagnostics._0_modifier_must_precede_1_modifier, "in", "out"); + if (inOutFlag & ModifierFlags.In && flags & ModifierFlags.Out) { + return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "in", "out"); } flags |= inOutFlag; break; } } - if (node.kind === ts.SyntaxKind.Constructor) { - if (flags & ts.ModifierFlags.Static) { - return grammarErrorOnNode(lastStatic!, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); + if (node.kind === SyntaxKind.Constructor) { + if (flags & ModifierFlags.Static) { + return grammarErrorOnNode(lastStatic!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "static"); } - if (flags & ts.ModifierFlags.Override) { - return grammarErrorOnNode(lastOverride!, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "override"); // TODO: GH#18217 + if (flags & ModifierFlags.Override) { + return grammarErrorOnNode(lastOverride!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "override"); // TODO: GH#18217 } - if (flags & ts.ModifierFlags.Async) { - return grammarErrorOnNode(lastAsync!, ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); + if (flags & ModifierFlags.Async) { + return grammarErrorOnNode(lastAsync!, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async"); } return false; } - else if ((node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration) && flags & ts.ModifierFlags.Ambient) { - return grammarErrorOnNode(lastDeclare!, ts.Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); + else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & ModifierFlags.Ambient) { + return grammarErrorOnNode(lastDeclare!, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare"); } - else if (node.kind === ts.SyntaxKind.Parameter && (flags & ts.ModifierFlags.ParameterPropertyModifier) && ts.isBindingPattern(node.name)) { - return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); + else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && isBindingPattern(node.name)) { + return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_declared_using_a_binding_pattern); } - else if (node.kind === ts.SyntaxKind.Parameter && (flags & ts.ModifierFlags.ParameterPropertyModifier) && node.dotDotDotToken) { - return grammarErrorOnNode(node, ts.Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); + else if (node.kind === SyntaxKind.Parameter && (flags & ModifierFlags.ParameterPropertyModifier) && node.dotDotDotToken) { + return grammarErrorOnNode(node, Diagnostics.A_parameter_property_cannot_be_declared_using_a_rest_parameter); } - if (flags & ts.ModifierFlags.Async) { + if (flags & ModifierFlags.Async) { return checkGrammarAsyncModifier(node, lastAsync!); } return false; @@ -44678,101 +44876,101 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * true | false: Early return this value from checkGrammarModifiers. * undefined: Need to do full checking on the modifiers. */ - function reportObviousModifierErrors(node: ts.HasModifiers | ts.HasIllegalModifiers): boolean | undefined { + function reportObviousModifierErrors(node: HasModifiers | HasIllegalModifiers): boolean | undefined { return !node.modifiers ? false : shouldReportBadModifier(node) - ? grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here) + ? grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here) : undefined; } - function shouldReportBadModifier(node: ts.HasModifiers | ts.HasIllegalModifiers): boolean { + function shouldReportBadModifier(node: HasModifiers | HasIllegalModifiers): boolean { switch (node.kind) { - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.TypeParameter: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.Constructor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.Parameter: + case SyntaxKind.TypeParameter: return false; - case ts.SyntaxKind.ClassStaticBlockDeclaration: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.NamespaceExportDeclaration: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.MissingDeclaration: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.FunctionType: + case SyntaxKind.MissingDeclaration: return true; default: - if (node.parent.kind === ts.SyntaxKind.ModuleBlock || node.parent.kind === ts.SyntaxKind.SourceFile) { + if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { return false; } switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return nodeHasAnyModifiersExcept(node, ts.SyntaxKind.AsyncKeyword); - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ConstructorType: - return nodeHasAnyModifiersExcept(node, ts.SyntaxKind.AbstractKeyword); - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.FunctionDeclaration: + return nodeHasAnyModifiersExcept(node, SyntaxKind.AsyncKeyword); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ConstructorType: + return nodeHasAnyModifiersExcept(node, SyntaxKind.AbstractKeyword); + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.TypeAliasDeclaration: return true; - case ts.SyntaxKind.EnumDeclaration: - return nodeHasAnyModifiersExcept(node, ts.SyntaxKind.ConstKeyword); + case SyntaxKind.EnumDeclaration: + return nodeHasAnyModifiersExcept(node, SyntaxKind.ConstKeyword); default: - ts.Debug.assertNever(node); + Debug.assertNever(node); } } } - function nodeHasAnyModifiersExcept(node: ts.HasModifiers, allowedModifier: ts.SyntaxKind): boolean { + function nodeHasAnyModifiersExcept(node: HasModifiers, allowedModifier: SyntaxKind): boolean { for (const modifier of node.modifiers!) { - if (ts.isDecorator(modifier)) continue; + if (isDecorator(modifier)) continue; return modifier.kind !== allowedModifier; } return false; } - function checkGrammarAsyncModifier(node: ts.Node, asyncModifier: ts.Node): boolean { + function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: return false; } - return grammarErrorOnNode(asyncModifier, ts.Diagnostics._0_modifier_cannot_be_used_here, "async"); + return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async"); } - function checkGrammarForDisallowedTrailingComma(list: ts.NodeArray | undefined, diag = ts.Diagnostics.Trailing_comma_not_allowed): boolean { + function checkGrammarForDisallowedTrailingComma(list: NodeArray | undefined, diag = Diagnostics.Trailing_comma_not_allowed): boolean { if (list && list.hasTrailingComma) { return grammarErrorAtPos(list[0], list.end - ",".length, ",".length, diag); } return false; } - function checkGrammarTypeParameterList(typeParameters: ts.NodeArray | undefined, file: ts.SourceFile): boolean { + function checkGrammarTypeParameterList(typeParameters: NodeArray | undefined, file: SourceFile): boolean { if (typeParameters && typeParameters.length === 0) { const start = typeParameters.pos - "<".length; - const end = ts.skipTrivia(file.text, typeParameters.end) + ">".length; - return grammarErrorAtPos(file, start, end - start, ts.Diagnostics.Type_parameter_list_cannot_be_empty); + const end = skipTrivia(file.text, typeParameters.end) + ">".length; + return grammarErrorAtPos(file, start, end - start, Diagnostics.Type_parameter_list_cannot_be_empty); } return false; } - function checkGrammarParameterList(parameters: ts.NodeArray) { + function checkGrammarParameterList(parameters: NodeArray) { let seenOptionalParameter = false; const parameterCount = parameters.length; @@ -44780,53 +44978,53 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { const parameter = parameters[i]; if (parameter.dotDotDotToken) { if (i !== (parameterCount - 1)) { - return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list); } - if (!(parameter.flags & ts.NodeFlags.Ambient)) { // Allow `...foo,` in ambient declarations; see GH#23070 - checkGrammarForDisallowedTrailingComma(parameters, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + if (!(parameter.flags & NodeFlags.Ambient)) { // Allow `...foo,` in ambient declarations; see GH#23070 + checkGrammarForDisallowedTrailingComma(parameters, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); } if (parameter.questionToken) { - return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_rest_parameter_cannot_be_optional); + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_rest_parameter_cannot_be_optional); } if (parameter.initializer) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_rest_parameter_cannot_have_an_initializer); + return grammarErrorOnNode(parameter.name, Diagnostics.A_rest_parameter_cannot_have_an_initializer); } } else if (isOptionalParameter(parameter)) { seenOptionalParameter = true; if (parameter.questionToken && parameter.initializer) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.Parameter_cannot_have_question_mark_and_initializer); + return grammarErrorOnNode(parameter.name, Diagnostics.Parameter_cannot_have_question_mark_and_initializer); } } else if (seenOptionalParameter && !parameter.initializer) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter); + return grammarErrorOnNode(parameter.name, Diagnostics.A_required_parameter_cannot_follow_an_optional_parameter); } } } - function getNonSimpleParameters(parameters: readonly ts.ParameterDeclaration[]): readonly ts.ParameterDeclaration[] { - return ts.filter(parameters, parameter => !!parameter.initializer || ts.isBindingPattern(parameter.name) || ts.isRestParameter(parameter)); + function getNonSimpleParameters(parameters: readonly ParameterDeclaration[]): readonly ParameterDeclaration[] { + return filter(parameters, parameter => !!parameter.initializer || isBindingPattern(parameter.name) || isRestParameter(parameter)); } - function checkGrammarForUseStrictSimpleParameterList(node: ts.FunctionLikeDeclaration): boolean { - if (languageVersion >= ts.ScriptTarget.ES2016) { - const useStrictDirective = node.body && ts.isBlock(node.body) && ts.findUseStrictPrologue(node.body.statements); + function checkGrammarForUseStrictSimpleParameterList(node: FunctionLikeDeclaration): boolean { + if (languageVersion >= ScriptTarget.ES2016) { + const useStrictDirective = node.body && isBlock(node.body) && findUseStrictPrologue(node.body.statements); if (useStrictDirective) { const nonSimpleParameters = getNonSimpleParameters(node.parameters); - if (ts.length(nonSimpleParameters)) { - ts.forEach(nonSimpleParameters, parameter => { - ts.addRelatedInfo( - error(parameter, ts.Diagnostics.This_parameter_is_not_allowed_with_use_strict_directive), - ts.createDiagnosticForNode(useStrictDirective, ts.Diagnostics.use_strict_directive_used_here) + if (length(nonSimpleParameters)) { + forEach(nonSimpleParameters, parameter => { + addRelatedInfo( + error(parameter, Diagnostics.This_parameter_is_not_allowed_with_use_strict_directive), + createDiagnosticForNode(useStrictDirective, Diagnostics.use_strict_directive_used_here) ); }); const diagnostics = nonSimpleParameters.map((parameter, index) => ( - index === 0 ? ts.createDiagnosticForNode(parameter, ts.Diagnostics.Non_simple_parameter_declared_here) : ts.createDiagnosticForNode(parameter, ts.Diagnostics.and_here) - )) as [ts.DiagnosticWithLocation, ...ts.DiagnosticWithLocation[]]; - ts.addRelatedInfo(error(useStrictDirective, ts.Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics); + index === 0 ? createDiagnosticForNode(parameter, Diagnostics.Non_simple_parameter_declared_here) : createDiagnosticForNode(parameter, Diagnostics.and_here) + )) as [DiagnosticWithLocation, ...DiagnosticWithLocation[]]; + addRelatedInfo(error(useStrictDirective, Diagnostics.use_strict_directive_cannot_be_used_with_non_simple_parameter_list), ...diagnostics); return true; } } @@ -44834,149 +45032,149 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarFunctionLikeDeclaration(node: ts.FunctionLikeDeclaration | ts.MethodSignature): boolean { + function checkGrammarFunctionLikeDeclaration(node: FunctionLikeDeclaration | MethodSignature): boolean { // Prevent cascading error by short-circuit - const file = ts.getSourceFileOfNode(node); + const file = getSourceFileOfNode(node); return checkGrammarDecoratorsAndModifiers(node) || checkGrammarTypeParameterList(node.typeParameters, file) || checkGrammarParameterList(node.parameters) || checkGrammarArrowFunction(node, file) || - (ts.isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node)); + (isFunctionLikeDeclaration(node) && checkGrammarForUseStrictSimpleParameterList(node)); } - function checkGrammarClassLikeDeclaration(node: ts.ClassLikeDeclaration): boolean { - const file = ts.getSourceFileOfNode(node); + function checkGrammarClassLikeDeclaration(node: ClassLikeDeclaration): boolean { + const file = getSourceFileOfNode(node); return checkGrammarClassDeclarationHeritageClauses(node) || checkGrammarTypeParameterList(node.typeParameters, file); } - function checkGrammarArrowFunction(node: ts.Node, file: ts.SourceFile): boolean { - if (!ts.isArrowFunction(node)) { + function checkGrammarArrowFunction(node: Node, file: SourceFile): boolean { + if (!isArrowFunction(node)) { return false; } - if (node.typeParameters && !(ts.length(node.typeParameters) > 1 || node.typeParameters.hasTrailingComma || node.typeParameters[0].constraint)) { - if (file && ts.fileExtensionIsOneOf(file.fileName, [ts.Extension.Mts, ts.Extension.Cts])) { - grammarErrorOnNode(node.typeParameters[0], ts.Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint); + if (node.typeParameters && !(length(node.typeParameters) > 1 || node.typeParameters.hasTrailingComma || node.typeParameters[0].constraint)) { + if (file && fileExtensionIsOneOf(file.fileName, [Extension.Mts, Extension.Cts])) { + grammarErrorOnNode(node.typeParameters[0], Diagnostics.This_syntax_is_reserved_in_files_with_the_mts_or_cts_extension_Add_a_trailing_comma_or_explicit_constraint); } } const { equalsGreaterThanToken } = node; - const startLine = ts.getLineAndCharacterOfPosition(file, equalsGreaterThanToken.pos).line; - const endLine = ts.getLineAndCharacterOfPosition(file, equalsGreaterThanToken.end).line; - return startLine !== endLine && grammarErrorOnNode(equalsGreaterThanToken, ts.Diagnostics.Line_terminator_not_permitted_before_arrow); + const startLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.pos).line; + const endLine = getLineAndCharacterOfPosition(file, equalsGreaterThanToken.end).line; + return startLine !== endLine && grammarErrorOnNode(equalsGreaterThanToken, Diagnostics.Line_terminator_not_permitted_before_arrow); } - function checkGrammarIndexSignatureParameters(node: ts.SignatureDeclaration): boolean { + function checkGrammarIndexSignatureParameters(node: SignatureDeclaration): boolean { const parameter = node.parameters[0]; if (node.parameters.length !== 1) { if (parameter) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter); + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_must_have_exactly_one_parameter); } else { - return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_exactly_one_parameter); + return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_exactly_one_parameter); } } - checkGrammarForDisallowedTrailingComma(node.parameters, ts.Diagnostics.An_index_signature_cannot_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma(node.parameters, Diagnostics.An_index_signature_cannot_have_a_trailing_comma); if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.An_index_signature_cannot_have_a_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.An_index_signature_cannot_have_a_rest_parameter); } - if (ts.hasEffectiveModifiers(parameter)) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); + if (hasEffectiveModifiers(parameter)) { + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_accessibility_modifier); } if (parameter.questionToken) { - return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); + return grammarErrorOnNode(parameter.questionToken, Diagnostics.An_index_signature_parameter_cannot_have_a_question_mark); } if (parameter.initializer) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_cannot_have_an_initializer); + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_cannot_have_an_initializer); } if (!parameter.type) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_must_have_a_type_annotation); + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_must_have_a_type_annotation); } const type = getTypeFromTypeNode(parameter.type); - if (someType(type, t => !!(t.flags & ts.TypeFlags.StringOrNumberLiteralOrUnique)) || isGenericType(type)) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead); + if (someType(type, t => !!(t.flags & TypeFlags.StringOrNumberLiteralOrUnique)) || isGenericType(type)) { + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_cannot_be_a_literal_type_or_generic_type_Consider_using_a_mapped_object_type_instead); } if (!everyType(type, isValidIndexKeyType)) { - return grammarErrorOnNode(parameter.name, ts.Diagnostics.An_index_signature_parameter_type_must_be_string_number_symbol_or_a_template_literal_type); + return grammarErrorOnNode(parameter.name, Diagnostics.An_index_signature_parameter_type_must_be_string_number_symbol_or_a_template_literal_type); } if (!node.type) { - return grammarErrorOnNode(node, ts.Diagnostics.An_index_signature_must_have_a_type_annotation); + return grammarErrorOnNode(node, Diagnostics.An_index_signature_must_have_a_type_annotation); } return false; } - function checkGrammarIndexSignature(node: ts.IndexSignatureDeclaration) { + function checkGrammarIndexSignature(node: IndexSignatureDeclaration) { // Prevent cascading error by short-circuit return checkGrammarDecoratorsAndModifiers(node) || checkGrammarIndexSignatureParameters(node); } - function checkGrammarForAtLeastOneTypeArgument(node: ts.Node, typeArguments: ts.NodeArray | undefined): boolean { + function checkGrammarForAtLeastOneTypeArgument(node: Node, typeArguments: NodeArray | undefined): boolean { if (typeArguments && typeArguments.length === 0) { - const sourceFile = ts.getSourceFileOfNode(node); + const sourceFile = getSourceFileOfNode(node); const start = typeArguments.pos - "<".length; - const end = ts.skipTrivia(sourceFile.text, typeArguments.end) + ">".length; - return grammarErrorAtPos(sourceFile, start, end - start, ts.Diagnostics.Type_argument_list_cannot_be_empty); + const end = skipTrivia(sourceFile.text, typeArguments.end) + ">".length; + return grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.Type_argument_list_cannot_be_empty); } return false; } - function checkGrammarTypeArguments(node: ts.Node, typeArguments: ts.NodeArray | undefined): boolean { + function checkGrammarTypeArguments(node: Node, typeArguments: NodeArray | undefined): boolean { return checkGrammarForDisallowedTrailingComma(typeArguments) || checkGrammarForAtLeastOneTypeArgument(node, typeArguments); } - function checkGrammarTaggedTemplateChain(node: ts.TaggedTemplateExpression): boolean { - if (node.questionDotToken || node.flags & ts.NodeFlags.OptionalChain) { - return grammarErrorOnNode(node.template, ts.Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain); + function checkGrammarTaggedTemplateChain(node: TaggedTemplateExpression): boolean { + if (node.questionDotToken || node.flags & NodeFlags.OptionalChain) { + return grammarErrorOnNode(node.template, Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain); } return false; } - function checkGrammarHeritageClause(node: ts.HeritageClause): boolean { + function checkGrammarHeritageClause(node: HeritageClause): boolean { const types = node.types; if (checkGrammarForDisallowedTrailingComma(types)) { return true; } if (types && types.length === 0) { - const listType = ts.tokenToString(node.token); - return grammarErrorAtPos(node, types.pos, 0, ts.Diagnostics._0_list_cannot_be_empty, listType); + const listType = tokenToString(node.token); + return grammarErrorAtPos(node, types.pos, 0, Diagnostics._0_list_cannot_be_empty, listType); } - return ts.some(types, checkGrammarExpressionWithTypeArguments); + return some(types, checkGrammarExpressionWithTypeArguments); } - function checkGrammarExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments | ts.TypeQueryNode) { - if (ts.isExpressionWithTypeArguments(node) && ts.isImportKeyword(node.expression) && node.typeArguments) { - return grammarErrorOnNode(node, ts.Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); + function checkGrammarExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { + if (isExpressionWithTypeArguments(node) && isImportKeyword(node.expression) && node.typeArguments) { + return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); } return checkGrammarTypeArguments(node, node.typeArguments); } - function checkGrammarClassDeclarationHeritageClauses(node: ts.ClassLikeDeclaration) { + function checkGrammarClassDeclarationHeritageClauses(node: ClassLikeDeclaration) { let seenExtendsClause = false; let seenImplementsClause = false; if (!checkGrammarDecoratorsAndModifiers(node) && node.heritageClauses) { for (const heritageClause of node.heritageClauses) { - if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) { + if (heritageClause.token === SyntaxKind.ExtendsKeyword) { if (seenExtendsClause) { - return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); + return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen); } if (seenImplementsClause) { - return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_must_precede_implements_clause); + return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_must_precede_implements_clause); } if (heritageClause.types.length > 1) { - return grammarErrorOnFirstToken(heritageClause.types[1], ts.Diagnostics.Classes_can_only_extend_a_single_class); + return grammarErrorOnFirstToken(heritageClause.types[1], Diagnostics.Classes_can_only_extend_a_single_class); } seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === ts.SyntaxKind.ImplementsKeyword); + Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword); if (seenImplementsClause) { - return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.implements_clause_already_seen); + return grammarErrorOnFirstToken(heritageClause, Diagnostics.implements_clause_already_seen); } seenImplementsClause = true; @@ -44988,21 +45186,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function checkGrammarInterfaceDeclaration(node: ts.InterfaceDeclaration) { + function checkGrammarInterfaceDeclaration(node: InterfaceDeclaration) { let seenExtendsClause = false; if (node.heritageClauses) { for (const heritageClause of node.heritageClauses) { - if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) { + if (heritageClause.token === SyntaxKind.ExtendsKeyword) { if (seenExtendsClause) { - return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.extends_clause_already_seen); + return grammarErrorOnFirstToken(heritageClause, Diagnostics.extends_clause_already_seen); } seenExtendsClause = true; } else { - ts.Debug.assert(heritageClause.token === ts.SyntaxKind.ImplementsKeyword); - return grammarErrorOnFirstToken(heritageClause, ts.Diagnostics.Interface_declaration_cannot_have_implements_clause); + Debug.assert(heritageClause.token === SyntaxKind.ImplementsKeyword); + return grammarErrorOnFirstToken(heritageClause, Diagnostics.Interface_declaration_cannot_have_implements_clause); } // Grammar checking heritageClause inside class declaration @@ -45012,83 +45210,83 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarComputedPropertyName(node: ts.Node): boolean { + function checkGrammarComputedPropertyName(node: Node): boolean { // If node is not a computedPropertyName, just skip the grammar checking - if (node.kind !== ts.SyntaxKind.ComputedPropertyName) { + if (node.kind !== SyntaxKind.ComputedPropertyName) { return false; } - const computedPropertyName = node as ts.ComputedPropertyName; - if (computedPropertyName.expression.kind === ts.SyntaxKind.BinaryExpression && (computedPropertyName.expression as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken) { - return grammarErrorOnNode(computedPropertyName.expression, ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); + const computedPropertyName = node as ComputedPropertyName; + if (computedPropertyName.expression.kind === SyntaxKind.BinaryExpression && (computedPropertyName.expression as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken) { + return grammarErrorOnNode(computedPropertyName.expression, Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name); } return false; } - function checkGrammarForGenerator(node: ts.FunctionLikeDeclaration) { + function checkGrammarForGenerator(node: FunctionLikeDeclaration) { if (node.asteriskToken) { - ts.Debug.assert( - node.kind === ts.SyntaxKind.FunctionDeclaration || - node.kind === ts.SyntaxKind.FunctionExpression || - node.kind === ts.SyntaxKind.MethodDeclaration); - if (node.flags & ts.NodeFlags.Ambient) { - return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.Generators_are_not_allowed_in_an_ambient_context); + Debug.assert( + node.kind === SyntaxKind.FunctionDeclaration || + node.kind === SyntaxKind.FunctionExpression || + node.kind === SyntaxKind.MethodDeclaration); + if (node.flags & NodeFlags.Ambient) { + return grammarErrorOnNode(node.asteriskToken, Diagnostics.Generators_are_not_allowed_in_an_ambient_context); } if (!node.body) { - return grammarErrorOnNode(node.asteriskToken, ts.Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator); + return grammarErrorOnNode(node.asteriskToken, Diagnostics.An_overload_signature_cannot_be_declared_as_a_generator); } } } - function checkGrammarForInvalidQuestionMark(questionToken: ts.QuestionToken | undefined, message: ts.DiagnosticMessage): boolean { + function checkGrammarForInvalidQuestionMark(questionToken: QuestionToken | undefined, message: DiagnosticMessage): boolean { return !!questionToken && grammarErrorOnNode(questionToken, message); } - function checkGrammarForInvalidExclamationToken(exclamationToken: ts.ExclamationToken | undefined, message: ts.DiagnosticMessage): boolean { + function checkGrammarForInvalidExclamationToken(exclamationToken: ExclamationToken | undefined, message: DiagnosticMessage): boolean { return !!exclamationToken && grammarErrorOnNode(exclamationToken, message); } - function checkGrammarObjectLiteralExpression(node: ts.ObjectLiteralExpression, inDestructuring: boolean) { - const seen = new ts.Map(); + function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { + const seen = new Map<__String, DeclarationMeaning>(); for (const prop of node.properties) { - if (prop.kind === ts.SyntaxKind.SpreadAssignment) { + if (prop.kind === SyntaxKind.SpreadAssignment) { if (inDestructuring) { // a rest property cannot be destructured any further - const expression = ts.skipParentheses(prop.expression); - if (ts.isArrayLiteralExpression(expression) || ts.isObjectLiteralExpression(expression)) { - return grammarErrorOnNode(prop.expression, ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); + const expression = skipParentheses(prop.expression); + if (isArrayLiteralExpression(expression) || isObjectLiteralExpression(expression)) { + return grammarErrorOnNode(prop.expression, Diagnostics.A_rest_element_cannot_contain_a_binding_pattern); } } continue; } const name = prop.name; - if (name.kind === ts.SyntaxKind.ComputedPropertyName) { + if (name.kind === SyntaxKind.ComputedPropertyName) { // If the name is not a ComputedPropertyName, the grammar checking will skip it checkGrammarComputedPropertyName(name); } - if (prop.kind === ts.SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) { + if (prop.kind === SyntaxKind.ShorthandPropertyAssignment && !inDestructuring && prop.objectAssignmentInitializer) { // having objectAssignmentInitializer is only valid in ObjectAssignmentPattern // outside of destructuring it is a syntax error - grammarErrorOnNode(prop.equalsToken!, ts.Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern); + grammarErrorOnNode(prop.equalsToken!, Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern); } - if (name.kind === ts.SyntaxKind.PrivateIdentifier) { - grammarErrorOnNode(name, ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + if (name.kind === SyntaxKind.PrivateIdentifier) { + grammarErrorOnNode(name, Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); } // Modifiers are never allowed on properties except for 'async' on a method declaration - if (ts.canHaveModifiers(prop) && prop.modifiers) { + if (canHaveModifiers(prop) && prop.modifiers) { for (const mod of prop.modifiers) { - if (ts.isModifier(mod) && (mod.kind !== ts.SyntaxKind.AsyncKeyword || prop.kind !== ts.SyntaxKind.MethodDeclaration)) { - grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + if (isModifier(mod) && (mod.kind !== SyntaxKind.AsyncKeyword || prop.kind !== SyntaxKind.MethodDeclaration)) { + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } } } - else if (ts.canHaveIllegalModifiers(prop) && prop.modifiers) { + else if (canHaveIllegalModifiers(prop) && prop.modifiers) { for (const mod of prop.modifiers) { - grammarErrorOnNode(mod, ts.Diagnostics._0_modifier_cannot_be_used_here, ts.getTextOfNode(mod)); + grammarErrorOnNode(mod, Diagnostics._0_modifier_cannot_be_used_here, getTextOfNode(mod)); } } @@ -45102,31 +45300,31 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // and either both previous and propId.descriptor have[[Get]] fields or both previous and propId.descriptor have[[Set]] fields let currentKind: DeclarationMeaning; switch (prop.kind) { - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyAssignment: // Grammar checking for computedPropertyName and shorthandPropertyAssignment - checkGrammarForInvalidExclamationToken(prop.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); - checkGrammarForInvalidQuestionMark(prop.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional); - if (name.kind === ts.SyntaxKind.NumericLiteral) { + checkGrammarForInvalidExclamationToken(prop.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context); + checkGrammarForInvalidQuestionMark(prop.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional); + if (name.kind === SyntaxKind.NumericLiteral) { checkGrammarNumericLiteral(name); } currentKind = DeclarationMeaning.PropertyAssignment; break; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: currentKind = DeclarationMeaning.Method; break; - case ts.SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessor: currentKind = DeclarationMeaning.GetAccessor; break; - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessor: currentKind = DeclarationMeaning.SetAccessor; break; default: - throw ts.Debug.assertNever(prop, "Unexpected syntax kind:" + (prop as ts.Node).kind); + throw Debug.assertNever(prop, "Unexpected syntax kind:" + (prop as Node).kind); } if (!inDestructuring) { - const effectiveName = ts.getPropertyNameForPropertyNameNode(name); + const effectiveName = getPropertyNameForPropertyNameNode(name); if (effectiveName === undefined) { continue; } @@ -45137,34 +45335,34 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } else { if ((currentKind & DeclarationMeaning.Method) && (existingKind & DeclarationMeaning.Method)) { - grammarErrorOnNode(name, ts.Diagnostics.Duplicate_identifier_0, ts.getTextOfNode(name)); + grammarErrorOnNode(name, Diagnostics.Duplicate_identifier_0, getTextOfNode(name)); } else if ((currentKind & DeclarationMeaning.PropertyAssignment) && (existingKind & DeclarationMeaning.PropertyAssignment)) { - grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, ts.getTextOfNode(name)); + grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, getTextOfNode(name)); } else if ((currentKind & DeclarationMeaning.GetOrSetAccessor) && (existingKind & DeclarationMeaning.GetOrSetAccessor)) { if (existingKind !== DeclarationMeaning.GetOrSetAccessor && currentKind !== existingKind) { seen.set(effectiveName, currentKind | existingKind); } else { - return grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); + return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name); } } else { - return grammarErrorOnNode(name, ts.Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); + return grammarErrorOnNode(name, Diagnostics.An_object_literal_cannot_have_property_and_accessor_with_the_same_name); } } } } } - function checkGrammarJsxElement(node: ts.JsxOpeningLikeElement) { + function checkGrammarJsxElement(node: JsxOpeningLikeElement) { checkGrammarJsxName(node.tagName); checkGrammarTypeArguments(node, node.typeArguments); - const seen = new ts.Map(); + const seen = new Map<__String, boolean>(); for (const attr of node.attributes.properties) { - if (attr.kind === ts.SyntaxKind.JsxSpreadAttribute) { + if (attr.kind === SyntaxKind.JsxSpreadAttribute) { continue; } @@ -45173,79 +45371,79 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { seen.set(name.escapedText, true); } else { - return grammarErrorOnNode(name, ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); + return grammarErrorOnNode(name, Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name); } - if (initializer && initializer.kind === ts.SyntaxKind.JsxExpression && !initializer.expression) { - return grammarErrorOnNode(initializer, ts.Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression); + if (initializer && initializer.kind === SyntaxKind.JsxExpression && !initializer.expression) { + return grammarErrorOnNode(initializer, Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression); } } } - function checkGrammarJsxName(node: ts.JsxTagNameExpression) { - if (ts.isPropertyAccessExpression(node)) { - let propName: ts.JsxTagNameExpression = node; + function checkGrammarJsxName(node: JsxTagNameExpression) { + if (isPropertyAccessExpression(node)) { + let propName: JsxTagNameExpression = node; do { const check = checkGrammarJsxNestedIdentifier(propName.name); if (check) { return check; } propName = propName.expression; - } while (ts.isPropertyAccessExpression(propName)); + } while (isPropertyAccessExpression(propName)); const check = checkGrammarJsxNestedIdentifier(propName); if (check) { return check; } } - function checkGrammarJsxNestedIdentifier(name: ts.MemberName | ts.ThisExpression) { - if (ts.isIdentifier(name) && ts.idText(name).indexOf(":") !== -1) { - return grammarErrorOnNode(name, ts.Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names); + function checkGrammarJsxNestedIdentifier(name: MemberName | ThisExpression) { + if (isIdentifier(name) && idText(name).indexOf(":") !== -1) { + return grammarErrorOnNode(name, Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names); } } } - function checkGrammarJsxExpression(node: ts.JsxExpression) { - if (node.expression && ts.isCommaSequence(node.expression)) { - return grammarErrorOnNode(node.expression, ts.Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array); + function checkGrammarJsxExpression(node: JsxExpression) { + if (node.expression && isCommaSequence(node.expression)) { + return grammarErrorOnNode(node.expression, Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array); } } - function checkGrammarForInOrForOfStatement(forInOrOfStatement: ts.ForInOrOfStatement): boolean { + function checkGrammarForInOrForOfStatement(forInOrOfStatement: ForInOrOfStatement): boolean { if (checkGrammarStatementInAmbientContext(forInOrOfStatement)) { return true; } - if (forInOrOfStatement.kind === ts.SyntaxKind.ForOfStatement && forInOrOfStatement.awaitModifier) { - if (!(forInOrOfStatement.flags & ts.NodeFlags.AwaitContext)) { - const sourceFile = ts.getSourceFileOfNode(forInOrOfStatement); - if (ts.isInTopLevelContext(forInOrOfStatement)) { + if (forInOrOfStatement.kind === SyntaxKind.ForOfStatement && forInOrOfStatement.awaitModifier) { + if (!(forInOrOfStatement.flags & NodeFlags.AwaitContext)) { + const sourceFile = getSourceFileOfNode(forInOrOfStatement); + if (isInTopLevelContext(forInOrOfStatement)) { if (!hasParseDiagnostics(sourceFile)) { - if (!ts.isEffectiveExternalModule(sourceFile, compilerOptions)) { - diagnostics.add(ts.createDiagnosticForNode(forInOrOfStatement.awaitModifier, - ts.Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module)); + if (!isEffectiveExternalModule(sourceFile, compilerOptions)) { + diagnostics.add(createDiagnosticForNode(forInOrOfStatement.awaitModifier, + Diagnostics.for_await_loops_are_only_allowed_at_the_top_level_of_a_file_when_that_file_is_a_module_but_this_file_has_no_imports_or_exports_Consider_adding_an_empty_export_to_make_this_file_a_module)); } switch (moduleKind) { - case ts.ModuleKind.Node16: - case ts.ModuleKind.NodeNext: - if (sourceFile.impliedNodeFormat === ts.ModuleKind.CommonJS) { + case ModuleKind.Node16: + case ModuleKind.NodeNext: + if (sourceFile.impliedNodeFormat === ModuleKind.CommonJS) { diagnostics.add( - ts.createDiagnosticForNode(forInOrOfStatement.awaitModifier, ts.Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level) + createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.The_current_file_is_a_CommonJS_module_and_cannot_use_await_at_the_top_level) ); break; } // fallthrough - case ts.ModuleKind.ES2022: - case ts.ModuleKind.ESNext: - case ts.ModuleKind.System: - if (languageVersion >= ts.ScriptTarget.ES2017) { + case ModuleKind.ES2022: + case ModuleKind.ESNext: + case ModuleKind.System: + if (languageVersion >= ScriptTarget.ES2017) { break; } // fallthrough default: diagnostics.add( - ts.createDiagnosticForNode(forInOrOfStatement.awaitModifier, - ts.Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher + createDiagnosticForNode(forInOrOfStatement.awaitModifier, + Diagnostics.Top_level_for_await_loops_are_only_allowed_when_the_module_option_is_set_to_es2022_esnext_system_node16_or_nodenext_and_the_target_option_is_set_to_es2017_or_higher ) ); break; @@ -45255,12 +45453,12 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { else { // use of 'for-await-of' in non-async function if (!hasParseDiagnostics(sourceFile)) { - const diagnostic = ts.createDiagnosticForNode(forInOrOfStatement.awaitModifier, ts.Diagnostics.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); - const func = ts.getContainingFunction(forInOrOfStatement); - if (func && func.kind !== ts.SyntaxKind.Constructor) { - ts.Debug.assert((ts.getFunctionFlags(func) & ts.FunctionFlags.Async) === 0, "Enclosing function should never be an async function."); - const relatedInfo = ts.createDiagnosticForNode(func, ts.Diagnostics.Did_you_mean_to_mark_this_function_as_async); - ts.addRelatedInfo(diagnostic, relatedInfo); + const diagnostic = createDiagnosticForNode(forInOrOfStatement.awaitModifier, Diagnostics.for_await_loops_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules); + const func = getContainingFunction(forInOrOfStatement); + if (func && func.kind !== SyntaxKind.Constructor) { + Debug.assert((getFunctionFlags(func) & FunctionFlags.Async) === 0, "Enclosing function should never be an async function."); + const relatedInfo = createDiagnosticForNode(func, Diagnostics.Did_you_mean_to_mark_this_function_as_async); + addRelatedInfo(diagnostic, relatedInfo); } diagnostics.add(diagnostic); return true; @@ -45270,14 +45468,14 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isForOfStatement(forInOrOfStatement) && !(forInOrOfStatement.flags & ts.NodeFlags.AwaitContext) && - ts.isIdentifier(forInOrOfStatement.initializer) && forInOrOfStatement.initializer.escapedText === "async") { - grammarErrorOnNode(forInOrOfStatement.initializer, ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async); + if (isForOfStatement(forInOrOfStatement) && !(forInOrOfStatement.flags & NodeFlags.AwaitContext) && + isIdentifier(forInOrOfStatement.initializer) && forInOrOfStatement.initializer.escapedText === "async") { + grammarErrorOnNode(forInOrOfStatement.initializer, Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async); return false; } - if (forInOrOfStatement.initializer.kind === ts.SyntaxKind.VariableDeclarationList) { - const variableList = forInOrOfStatement.initializer as ts.VariableDeclarationList; + if (forInOrOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) { + const variableList = forInOrOfStatement.initializer as VariableDeclarationList; if (!checkGrammarVariableDeclarationList(variableList)) { const declarations = variableList.declarations; @@ -45293,23 +45491,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (declarations.length > 1) { - const diagnostic = forInOrOfStatement.kind === ts.SyntaxKind.ForInStatement - ? ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement - : ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement; + const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement + ? Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement + : Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement; return grammarErrorOnFirstToken(variableList.declarations[1], diagnostic); } const firstDeclaration = declarations[0]; if (firstDeclaration.initializer) { - const diagnostic = forInOrOfStatement.kind === ts.SyntaxKind.ForInStatement - ? ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer - : ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer; + const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement + ? Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer + : Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer; return grammarErrorOnNode(firstDeclaration.name, diagnostic); } if (firstDeclaration.type) { - const diagnostic = forInOrOfStatement.kind === ts.SyntaxKind.ForInStatement - ? ts.Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation - : ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation; + const diagnostic = forInOrOfStatement.kind === SyntaxKind.ForInStatement + ? Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_use_a_type_annotation + : Diagnostics.The_left_hand_side_of_a_for_of_statement_cannot_use_a_type_annotation; return grammarErrorOnNode(firstDeclaration, diagnostic); } } @@ -45318,48 +45516,48 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarAccessor(accessor: ts.AccessorDeclaration): boolean { - if (!(accessor.flags & ts.NodeFlags.Ambient) && (accessor.parent.kind !== ts.SyntaxKind.TypeLiteral) && (accessor.parent.kind !== ts.SyntaxKind.InterfaceDeclaration)) { - if (languageVersion < ts.ScriptTarget.ES5) { - return grammarErrorOnNode(accessor.name, ts.Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); + function checkGrammarAccessor(accessor: AccessorDeclaration): boolean { + if (!(accessor.flags & NodeFlags.Ambient) && (accessor.parent.kind !== SyntaxKind.TypeLiteral) && (accessor.parent.kind !== SyntaxKind.InterfaceDeclaration)) { + if (languageVersion < ScriptTarget.ES5) { + return grammarErrorOnNode(accessor.name, Diagnostics.Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher); } - if (languageVersion < ts.ScriptTarget.ES2015 && ts.isPrivateIdentifier(accessor.name)) { - return grammarErrorOnNode(accessor.name, ts.Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(accessor.name)) { + return grammarErrorOnNode(accessor.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (accessor.body === undefined && !ts.hasSyntacticModifier(accessor, ts.ModifierFlags.Abstract)) { - return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); + if (accessor.body === undefined && !hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { + return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{"); } } if (accessor.body) { - if (ts.hasSyntacticModifier(accessor, ts.ModifierFlags.Abstract)) { - return grammarErrorOnNode(accessor, ts.Diagnostics.An_abstract_accessor_cannot_have_an_implementation); + if (hasSyntacticModifier(accessor, ModifierFlags.Abstract)) { + return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation); } - if (accessor.parent.kind === ts.SyntaxKind.TypeLiteral || accessor.parent.kind === ts.SyntaxKind.InterfaceDeclaration) { - return grammarErrorOnNode(accessor.body, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); + if (accessor.parent.kind === SyntaxKind.TypeLiteral || accessor.parent.kind === SyntaxKind.InterfaceDeclaration) { + return grammarErrorOnNode(accessor.body, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); } } if (accessor.typeParameters) { - return grammarErrorOnNode(accessor.name, ts.Diagnostics.An_accessor_cannot_have_type_parameters); + return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters); } if (!doesAccessorHaveCorrectParameterCount(accessor)) { return grammarErrorOnNode(accessor.name, - accessor.kind === ts.SyntaxKind.GetAccessor ? - ts.Diagnostics.A_get_accessor_cannot_have_parameters : - ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter); + accessor.kind === SyntaxKind.GetAccessor ? + Diagnostics.A_get_accessor_cannot_have_parameters : + Diagnostics.A_set_accessor_must_have_exactly_one_parameter); } - if (accessor.kind === ts.SyntaxKind.SetAccessor) { + if (accessor.kind === SyntaxKind.SetAccessor) { if (accessor.type) { - return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); + return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_cannot_have_a_return_type_annotation); } - const parameter = ts.Debug.checkDefined(ts.getSetAccessorValueParameter(accessor), "Return value does not match parameter count assertion."); + const parameter = Debug.checkDefined(getSetAccessorValueParameter(accessor), "Return value does not match parameter count assertion."); if (parameter.dotDotDotToken) { - return grammarErrorOnNode(parameter.dotDotDotToken, ts.Diagnostics.A_set_accessor_cannot_have_rest_parameter); + return grammarErrorOnNode(parameter.dotDotDotToken, Diagnostics.A_set_accessor_cannot_have_rest_parameter); } if (parameter.questionToken) { - return grammarErrorOnNode(parameter.questionToken, ts.Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); + return grammarErrorOnNode(parameter.questionToken, Diagnostics.A_set_accessor_cannot_have_an_optional_parameter); } if (parameter.initializer) { - return grammarErrorOnNode(accessor.name, ts.Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer); + return grammarErrorOnNode(accessor.name, Diagnostics.A_set_accessor_parameter_cannot_have_an_initializer); } } return false; @@ -45369,91 +45567,91 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { * A get accessor has no parameters or a single `this` parameter. * A set accessor has one parameter or a `this` parameter and one more parameter. */ - function doesAccessorHaveCorrectParameterCount(accessor: ts.AccessorDeclaration) { - return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === ts.SyntaxKind.GetAccessor ? 0 : 1); + function doesAccessorHaveCorrectParameterCount(accessor: AccessorDeclaration) { + return getAccessorThisParameter(accessor) || accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 0 : 1); } - function getAccessorThisParameter(accessor: ts.AccessorDeclaration): ts.ParameterDeclaration | undefined { - if (accessor.parameters.length === (accessor.kind === ts.SyntaxKind.GetAccessor ? 1 : 2)) { - return ts.getThisParameter(accessor); + function getAccessorThisParameter(accessor: AccessorDeclaration): ParameterDeclaration | undefined { + if (accessor.parameters.length === (accessor.kind === SyntaxKind.GetAccessor ? 1 : 2)) { + return getThisParameter(accessor); } } - function checkGrammarTypeOperatorNode(node: ts.TypeOperatorNode) { - if (node.operator === ts.SyntaxKind.UniqueKeyword) { - if (node.type.kind !== ts.SyntaxKind.SymbolKeyword) { - return grammarErrorOnNode(node.type, ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.SymbolKeyword)); + function checkGrammarTypeOperatorNode(node: TypeOperatorNode) { + if (node.operator === SyntaxKind.UniqueKeyword) { + if (node.type.kind !== SyntaxKind.SymbolKeyword) { + return grammarErrorOnNode(node.type, Diagnostics._0_expected, tokenToString(SyntaxKind.SymbolKeyword)); } - let parent = ts.walkUpParenthesizedTypes(node.parent); - if (ts.isInJSFile(parent) && ts.isJSDocTypeExpression(parent)) { - const host = ts.getJSDocHost(parent); + let parent = walkUpParenthesizedTypes(node.parent); + if (isInJSFile(parent) && isJSDocTypeExpression(parent)) { + const host = getJSDocHost(parent); if (host) { - parent = ts.getSingleVariableOfVariableStatement(host) || host; + parent = getSingleVariableOfVariableStatement(host) || host; } } switch (parent.kind) { - case ts.SyntaxKind.VariableDeclaration: - const decl = parent as ts.VariableDeclaration; - if (decl.name.kind !== ts.SyntaxKind.Identifier) { - return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name); + case SyntaxKind.VariableDeclaration: + const decl = parent as VariableDeclaration; + if (decl.name.kind !== SyntaxKind.Identifier) { + return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_may_not_be_used_on_a_variable_declaration_with_a_binding_name); } - if (!ts.isVariableDeclarationInVariableStatement(decl)) { - return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement); + if (!isVariableDeclarationInVariableStatement(decl)) { + return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_only_allowed_on_variables_in_a_variable_statement); } - if (!(decl.parent.flags & ts.NodeFlags.Const)) { - return grammarErrorOnNode((parent as ts.VariableDeclaration).name, ts.Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const); + if (!(decl.parent.flags & NodeFlags.Const)) { + return grammarErrorOnNode((parent as VariableDeclaration).name, Diagnostics.A_variable_whose_type_is_a_unique_symbol_type_must_be_const); } break; - case ts.SyntaxKind.PropertyDeclaration: - if (!ts.isStatic(parent) || - !ts.hasEffectiveReadonlyModifier(parent)) { - return grammarErrorOnNode((parent as ts.PropertyDeclaration).name, ts.Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly); + case SyntaxKind.PropertyDeclaration: + if (!isStatic(parent) || + !hasEffectiveReadonlyModifier(parent)) { + return grammarErrorOnNode((parent as PropertyDeclaration).name, Diagnostics.A_property_of_a_class_whose_type_is_a_unique_symbol_type_must_be_both_static_and_readonly); } break; - case ts.SyntaxKind.PropertySignature: - if (!ts.hasSyntacticModifier(parent, ts.ModifierFlags.Readonly)) { - return grammarErrorOnNode((parent as ts.PropertySignature).name, ts.Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly); + case SyntaxKind.PropertySignature: + if (!hasSyntacticModifier(parent, ModifierFlags.Readonly)) { + return grammarErrorOnNode((parent as PropertySignature).name, Diagnostics.A_property_of_an_interface_or_type_literal_whose_type_is_a_unique_symbol_type_must_be_readonly); } break; default: - return grammarErrorOnNode(node, ts.Diagnostics.unique_symbol_types_are_not_allowed_here); + return grammarErrorOnNode(node, Diagnostics.unique_symbol_types_are_not_allowed_here); } } - else if (node.operator === ts.SyntaxKind.ReadonlyKeyword) { - if (node.type.kind !== ts.SyntaxKind.ArrayType && node.type.kind !== ts.SyntaxKind.TupleType) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_literal_types, ts.tokenToString(ts.SyntaxKind.SymbolKeyword)); + else if (node.operator === SyntaxKind.ReadonlyKeyword) { + if (node.type.kind !== SyntaxKind.ArrayType && node.type.kind !== SyntaxKind.TupleType) { + return grammarErrorOnFirstToken(node, Diagnostics.readonly_type_modifier_is_only_permitted_on_array_and_tuple_literal_types, tokenToString(SyntaxKind.SymbolKeyword)); } } } - function checkGrammarForInvalidDynamicName(node: ts.DeclarationName, message: ts.DiagnosticMessage) { + function checkGrammarForInvalidDynamicName(node: DeclarationName, message: DiagnosticMessage) { if (isNonBindableDynamicName(node)) { return grammarErrorOnNode(node, message); } } - function checkGrammarMethod(node: ts.MethodDeclaration | ts.MethodSignature) { + function checkGrammarMethod(node: MethodDeclaration | MethodSignature) { if (checkGrammarFunctionLikeDeclaration(node)) { return true; } - if (node.kind === ts.SyntaxKind.MethodDeclaration) { - if (node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) { + if (node.kind === SyntaxKind.MethodDeclaration) { + if (node.parent.kind === SyntaxKind.ObjectLiteralExpression) { // We only disallow modifier on a method declaration if it is a property of object-literal-expression - if (node.modifiers && !(node.modifiers.length === 1 && ts.first(node.modifiers).kind === ts.SyntaxKind.AsyncKeyword)) { - return grammarErrorOnFirstToken(node, ts.Diagnostics.Modifiers_cannot_appear_here); + if (node.modifiers && !(node.modifiers.length === 1 && first(node.modifiers).kind === SyntaxKind.AsyncKeyword)) { + return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here); } - else if (checkGrammarForInvalidQuestionMark(node.questionToken, ts.Diagnostics.An_object_member_cannot_be_declared_optional)) { + else if (checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_object_member_cannot_be_declared_optional)) { return true; } - else if (checkGrammarForInvalidExclamationToken(node.exclamationToken, ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context)) { + else if (checkGrammarForInvalidExclamationToken(node.exclamationToken, Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context)) { return true; } else if (node.body === undefined) { - return grammarErrorAtPos(node, node.end - 1, ";".length, ts.Diagnostics._0_expected, "{"); + return grammarErrorAtPos(node, node.end - 1, ";".length, Diagnostics._0_expected, "{"); } } if (checkGrammarForGenerator(node)) { @@ -45461,60 +45659,60 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - if (ts.isClassLike(node.parent)) { - if (languageVersion < ts.ScriptTarget.ES2015 && ts.isPrivateIdentifier(node.name)) { - return grammarErrorOnNode(node.name, ts.Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + if (isClassLike(node.parent)) { + if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { + return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } // Technically, computed properties in ambient contexts is disallowed // for property declarations and accessors too, not just methods. // However, property declarations disallow computed names in general, // and accessors are not allowed in ambient contexts in general, // so this error only really matters for methods. - if (node.flags & ts.NodeFlags.Ambient) { - return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + if (node.flags & NodeFlags.Ambient) { + return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_ambient_context_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.kind === ts.SyntaxKind.MethodDeclaration && !node.body) { - return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + else if (node.kind === SyntaxKind.MethodDeclaration && !node.body) { + return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_method_overload_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } - else if (node.parent.kind === ts.SyntaxKind.InterfaceDeclaration) { - return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) { + return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } - else if (node.parent.kind === ts.SyntaxKind.TypeLiteral) { - return checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); + else if (node.parent.kind === SyntaxKind.TypeLiteral) { + return checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type); } } - function checkGrammarBreakOrContinueStatement(node: ts.BreakOrContinueStatement): boolean { - let current: ts.Node = node; + function checkGrammarBreakOrContinueStatement(node: BreakOrContinueStatement): boolean { + let current: Node = node; while (current) { - if (ts.isFunctionLikeOrClassStaticBlockDeclaration(current)) { - return grammarErrorOnNode(node, ts.Diagnostics.Jump_target_cannot_cross_function_boundary); + if (isFunctionLikeOrClassStaticBlockDeclaration(current)) { + return grammarErrorOnNode(node, Diagnostics.Jump_target_cannot_cross_function_boundary); } switch (current.kind) { - case ts.SyntaxKind.LabeledStatement: - if (node.label && (current as ts.LabeledStatement).label.escapedText === node.label.escapedText) { + case SyntaxKind.LabeledStatement: + if (node.label && (current as LabeledStatement).label.escapedText === node.label.escapedText) { // found matching label - verify that label usage is correct // continue can only target labels that are on iteration statements - const isMisplacedContinueLabel = node.kind === ts.SyntaxKind.ContinueStatement - && !ts.isIterationStatement((current as ts.LabeledStatement).statement, /*lookInLabeledStatement*/ true); + const isMisplacedContinueLabel = node.kind === SyntaxKind.ContinueStatement + && !isIterationStatement((current as LabeledStatement).statement, /*lookInLabeledStatement*/ true); if (isMisplacedContinueLabel) { - return grammarErrorOnNode(node, ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement); + return grammarErrorOnNode(node, Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement); } return false; } break; - case ts.SyntaxKind.SwitchStatement: - if (node.kind === ts.SyntaxKind.BreakStatement && !node.label) { + case SyntaxKind.SwitchStatement: + if (node.kind === SyntaxKind.BreakStatement && !node.label) { // unlabeled break within switch statement - ok return false; } break; default: - if (ts.isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) { + if (isIterationStatement(current, /*lookInLabeledStatement*/ false) && !node.label) { // unlabeled break or continue within iteration statement - ok return false; } @@ -45525,109 +45723,109 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } if (node.label) { - const message = node.kind === ts.SyntaxKind.BreakStatement - ? ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement - : ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; + const message = node.kind === SyntaxKind.BreakStatement + ? Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement + : Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); } else { - const message = node.kind === ts.SyntaxKind.BreakStatement - ? ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement - : ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; + const message = node.kind === SyntaxKind.BreakStatement + ? Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement + : Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement; return grammarErrorOnNode(node, message); } } - function checkGrammarBindingElement(node: ts.BindingElement) { + function checkGrammarBindingElement(node: BindingElement) { if (node.dotDotDotToken) { const elements = node.parent.elements; - if (node !== ts.last(elements)) { - return grammarErrorOnNode(node, ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); + if (node !== last(elements)) { + return grammarErrorOnNode(node, Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern); } - checkGrammarForDisallowedTrailingComma(elements, ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); + checkGrammarForDisallowedTrailingComma(elements, Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma); if (node.propertyName) { - return grammarErrorOnNode(node.name, ts.Diagnostics.A_rest_element_cannot_have_a_property_name); + return grammarErrorOnNode(node.name, Diagnostics.A_rest_element_cannot_have_a_property_name); } } if (node.dotDotDotToken && node.initializer) { // Error on equals token which immediately precedes the initializer - return grammarErrorAtPos(node, node.initializer.pos - 1, 1, ts.Diagnostics.A_rest_element_cannot_have_an_initializer); + return grammarErrorAtPos(node, node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer); } } - function isStringOrNumberLiteralExpression(expr: ts.Expression) { - return ts.isStringOrNumericLiteralLike(expr) || - expr.kind === ts.SyntaxKind.PrefixUnaryExpression && (expr as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.MinusToken && - (expr as ts.PrefixUnaryExpression).operand.kind === ts.SyntaxKind.NumericLiteral; + function isStringOrNumberLiteralExpression(expr: Expression) { + return isStringOrNumericLiteralLike(expr) || + expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken && + (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.NumericLiteral; } - function isBigIntLiteralExpression(expr: ts.Expression) { - return expr.kind === ts.SyntaxKind.BigIntLiteral || - expr.kind === ts.SyntaxKind.PrefixUnaryExpression && (expr as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.MinusToken && - (expr as ts.PrefixUnaryExpression).operand.kind === ts.SyntaxKind.BigIntLiteral; + function isBigIntLiteralExpression(expr: Expression) { + return expr.kind === SyntaxKind.BigIntLiteral || + expr.kind === SyntaxKind.PrefixUnaryExpression && (expr as PrefixUnaryExpression).operator === SyntaxKind.MinusToken && + (expr as PrefixUnaryExpression).operand.kind === SyntaxKind.BigIntLiteral; } - function isSimpleLiteralEnumReference(expr: ts.Expression) { - if ((ts.isPropertyAccessExpression(expr) || (ts.isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) && - ts.isEntityNameExpression(expr.expression)) { - return !!(checkExpressionCached(expr).flags & ts.TypeFlags.EnumLiteral); + function isSimpleLiteralEnumReference(expr: Expression) { + if ((isPropertyAccessExpression(expr) || (isElementAccessExpression(expr) && isStringOrNumberLiteralExpression(expr.argumentExpression))) && + isEntityNameExpression(expr.expression)) { + return !!(checkExpressionCached(expr).flags & TypeFlags.EnumLiteral); } } - function checkAmbientInitializer(node: ts.VariableDeclaration | ts.PropertyDeclaration | ts.PropertySignature) { + function checkAmbientInitializer(node: VariableDeclaration | PropertyDeclaration | PropertySignature) { const initializer = node.initializer; if (initializer) { const isInvalidInitializer = !( isStringOrNumberLiteralExpression(initializer) || isSimpleLiteralEnumReference(initializer) || - initializer.kind === ts.SyntaxKind.TrueKeyword || initializer.kind === ts.SyntaxKind.FalseKeyword || + initializer.kind === SyntaxKind.TrueKeyword || initializer.kind === SyntaxKind.FalseKeyword || isBigIntLiteralExpression(initializer) ); - const isConstOrReadonly = ts.isDeclarationReadonly(node) || ts.isVariableDeclaration(node) && ts.isVarConst(node); + const isConstOrReadonly = isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node); if (isConstOrReadonly && !node.type) { if (isInvalidInitializer) { - return grammarErrorOnNode(initializer, ts.Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_reference); + return grammarErrorOnNode(initializer, Diagnostics.A_const_initializer_in_an_ambient_context_must_be_a_string_or_numeric_literal_or_literal_enum_reference); } } else { - return grammarErrorOnNode(initializer, ts.Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); + return grammarErrorOnNode(initializer, Diagnostics.Initializers_are_not_allowed_in_ambient_contexts); } } } - function checkGrammarVariableDeclaration(node: ts.VariableDeclaration) { - if (node.parent.parent.kind !== ts.SyntaxKind.ForInStatement && node.parent.parent.kind !== ts.SyntaxKind.ForOfStatement) { - if (node.flags & ts.NodeFlags.Ambient) { + function checkGrammarVariableDeclaration(node: VariableDeclaration) { + if (node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) { + if (node.flags & NodeFlags.Ambient) { checkAmbientInitializer(node); } else if (!node.initializer) { - if (ts.isBindingPattern(node.name) && !ts.isBindingPattern(node.parent)) { - return grammarErrorOnNode(node, ts.Diagnostics.A_destructuring_declaration_must_have_an_initializer); + if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) { + return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer); } - if (ts.isVarConst(node)) { - return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_must_be_initialized); + if (isVarConst(node)) { + return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized); } } } - if (node.exclamationToken && (node.parent.parent.kind !== ts.SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & ts.NodeFlags.Ambient)) { + if (node.exclamationToken && (node.parent.parent.kind !== SyntaxKind.VariableStatement || !node.type || node.initializer || node.flags & NodeFlags.Ambient)) { const message = node.initializer - ? ts.Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions + ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions : !node.type - ? ts.Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations - : ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context; + ? Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations + : Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context; return grammarErrorOnNode(node.exclamationToken, message); } - if ((moduleKind < ts.ModuleKind.ES2015 || ts.getSourceFileOfNode(node).impliedNodeFormat === ts.ModuleKind.CommonJS) && moduleKind !== ts.ModuleKind.System && - !(node.parent.parent.flags & ts.NodeFlags.Ambient) && ts.hasSyntacticModifier(node.parent.parent, ts.ModifierFlags.Export)) { + if ((moduleKind < ModuleKind.ES2015 || getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.CommonJS) && moduleKind !== ModuleKind.System && + !(node.parent.parent.flags & NodeFlags.Ambient) && hasSyntacticModifier(node.parent.parent, ModifierFlags.Export)) { checkESModuleMarker(node.name); } - const checkLetConstNames = (ts.isLet(node) || ts.isVarConst(node)); + const checkLetConstNames = (isLet(node) || isVarConst(node)); // 1. LexicalDeclaration : LetOrConst BindingList ; // It is a Syntax Error if the BoundNames of BindingList contains "let". @@ -45639,16 +45837,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return checkLetConstNames && checkGrammarNameInLetOrConstDeclarations(node.name); } - function checkESModuleMarker(name: ts.Identifier | ts.BindingPattern): boolean { - if (name.kind === ts.SyntaxKind.Identifier) { - if (ts.idText(name) === "__esModule") { - return grammarErrorOnNodeSkippedOn("noEmit", name, ts.Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); + function checkESModuleMarker(name: Identifier | BindingPattern): boolean { + if (name.kind === SyntaxKind.Identifier) { + if (idText(name) === "__esModule") { + return grammarErrorOnNodeSkippedOn("noEmit", name, Diagnostics.Identifier_expected_esModule_is_reserved_as_an_exported_marker_when_transforming_ECMAScript_modules); } } else { const elements = name.elements; for (const element of elements) { - if (!ts.isOmittedExpression(element)) { + if (!isOmittedExpression(element)) { return checkESModuleMarker(element.name); } } @@ -45656,16 +45854,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarNameInLetOrConstDeclarations(name: ts.Identifier | ts.BindingPattern): boolean { - if (name.kind === ts.SyntaxKind.Identifier) { - if (name.originalKeywordKind === ts.SyntaxKind.LetKeyword) { - return grammarErrorOnNode(name, ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); + function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { + if (name.kind === SyntaxKind.Identifier) { + if (name.originalKeywordKind === SyntaxKind.LetKeyword) { + return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); } } else { const elements = name.elements; for (const element of elements) { - if (!ts.isOmittedExpression(element)) { + if (!isOmittedExpression(element)) { checkGrammarNameInLetOrConstDeclarations(element.name); } } @@ -45673,87 +45871,87 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarVariableDeclarationList(declarationList: ts.VariableDeclarationList): boolean { + function checkGrammarVariableDeclarationList(declarationList: VariableDeclarationList): boolean { const declarations = declarationList.declarations; if (checkGrammarForDisallowedTrailingComma(declarationList.declarations)) { return true; } if (!declarationList.declarations.length) { - return grammarErrorAtPos(declarationList, declarations.pos, declarations.end - declarations.pos, ts.Diagnostics.Variable_declaration_list_cannot_be_empty); + return grammarErrorAtPos(declarationList, declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty); } return false; } - function allowLetAndConstDeclarations(parent: ts.Node): boolean { + function allowLetAndConstDeclarations(parent: Node): boolean { switch (parent.kind) { - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.WithStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: return false; - case ts.SyntaxKind.LabeledStatement: + case SyntaxKind.LabeledStatement: return allowLetAndConstDeclarations(parent.parent); } return true; } - function checkGrammarForDisallowedLetOrConstStatement(node: ts.VariableStatement) { + function checkGrammarForDisallowedLetOrConstStatement(node: VariableStatement) { if (!allowLetAndConstDeclarations(node.parent)) { - if (ts.isLet(node.declarationList)) { - return grammarErrorOnNode(node, ts.Diagnostics.let_declarations_can_only_be_declared_inside_a_block); + if (isLet(node.declarationList)) { + return grammarErrorOnNode(node, Diagnostics.let_declarations_can_only_be_declared_inside_a_block); } - else if (ts.isVarConst(node.declarationList)) { - return grammarErrorOnNode(node, ts.Diagnostics.const_declarations_can_only_be_declared_inside_a_block); + else if (isVarConst(node.declarationList)) { + return grammarErrorOnNode(node, Diagnostics.const_declarations_can_only_be_declared_inside_a_block); } } } - function checkGrammarMetaProperty(node: ts.MetaProperty) { + function checkGrammarMetaProperty(node: MetaProperty) { const escapedText = node.name.escapedText; switch (node.keywordToken) { - case ts.SyntaxKind.NewKeyword: + case SyntaxKind.NewKeyword: if (escapedText !== "target") { - return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "target"); + return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "target"); } break; - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: if (escapedText !== "meta") { - return grammarErrorOnNode(node.name, ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, ts.tokenToString(node.keywordToken), "meta"); + return grammarErrorOnNode(node.name, Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2, node.name.escapedText, tokenToString(node.keywordToken), "meta"); } break; } } - function hasParseDiagnostics(sourceFile: ts.SourceFile): boolean { + function hasParseDiagnostics(sourceFile: SourceFile): boolean { return sourceFile.parseDiagnostics.length > 0; } - function grammarErrorOnFirstToken(node: ts.Node, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { - const sourceFile = ts.getSourceFileOfNode(node); + function grammarErrorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - const span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2)); + const span = getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, message, arg0, arg1, arg2)); return true; } return false; } - function grammarErrorAtPos(nodeForSourceFile: ts.Node, start: number, length: number, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { - const sourceFile = ts.getSourceFileOfNode(nodeForSourceFile); + function grammarErrorAtPos(nodeForSourceFile: Node, start: number, length: number, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { + const sourceFile = getSourceFileOfNode(nodeForSourceFile); if (!hasParseDiagnostics(sourceFile)) { - diagnostics.add(ts.createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2)); + diagnostics.add(createFileDiagnostic(sourceFile, start, length, message, arg0, arg1, arg2)); return true; } return false; } - function grammarErrorOnNodeSkippedOn(key: keyof ts.CompilerOptions, node: ts.Node, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { - const sourceFile = ts.getSourceFileOfNode(node); + function grammarErrorOnNodeSkippedOn(key: keyof CompilerOptions, node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { errorSkippedOn(key, node, message, arg0, arg1, arg2); return true; @@ -45761,92 +45959,92 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function grammarErrorOnNode(node: ts.Node, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { - const sourceFile = ts.getSourceFileOfNode(node); + function grammarErrorOnNode(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - diagnostics.add(ts.createDiagnosticForNode(node, message, arg0, arg1, arg2)); + diagnostics.add(createDiagnosticForNode(node, message, arg0, arg1, arg2)); return true; } return false; } - function checkGrammarConstructorTypeParameters(node: ts.ConstructorDeclaration) { - const jsdocTypeParameters = ts.isInJSFile(node) ? ts.getJSDocTypeParameterDeclarations(node) : undefined; - const range = node.typeParameters || jsdocTypeParameters && ts.firstOrUndefined(jsdocTypeParameters); + function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { + const jsdocTypeParameters = isInJSFile(node) ? getJSDocTypeParameterDeclarations(node) : undefined; + const range = node.typeParameters || jsdocTypeParameters && firstOrUndefined(jsdocTypeParameters); if (range) { - const pos = range.pos === range.end ? range.pos : ts.skipTrivia(ts.getSourceFileOfNode(node).text, range.pos); - return grammarErrorAtPos(node, pos, range.end - pos, ts.Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); + const pos = range.pos === range.end ? range.pos : skipTrivia(getSourceFileOfNode(node).text, range.pos); + return grammarErrorAtPos(node, pos, range.end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); } } - function checkGrammarConstructorTypeAnnotation(node: ts.ConstructorDeclaration) { - const type = node.type || ts.getEffectiveReturnTypeNode(node); + function checkGrammarConstructorTypeAnnotation(node: ConstructorDeclaration) { + const type = node.type || getEffectiveReturnTypeNode(node); if (type) { - return grammarErrorOnNode(type, ts.Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration); + return grammarErrorOnNode(type, Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration); } } - function checkGrammarProperty(node: ts.PropertyDeclaration | ts.PropertySignature) { - if (ts.isComputedPropertyName(node.name) && ts.isBinaryExpression(node.name.expression) && node.name.expression.operatorToken.kind === ts.SyntaxKind.InKeyword) { + function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) { + if (isComputedPropertyName(node.name) && isBinaryExpression(node.name.expression) && node.name.expression.operatorToken.kind === SyntaxKind.InKeyword) { return grammarErrorOnNode( - (node.parent as ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.TypeLiteralNode).members[0], - ts.Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); + (node.parent as ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode).members[0], + Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); } - if (ts.isClassLike(node.parent)) { - if (ts.isStringLiteral(node.name) && node.name.text === "constructor") { - return grammarErrorOnNode(node.name, ts.Diagnostics.Classes_may_not_have_a_field_named_constructor); + if (isClassLike(node.parent)) { + if (isStringLiteral(node.name) && node.name.text === "constructor") { + return grammarErrorOnNode(node.name, Diagnostics.Classes_may_not_have_a_field_named_constructor); } - if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_have_a_simple_literal_type_or_a_unique_symbol_type)) { + if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_class_property_declaration_must_have_a_simple_literal_type_or_a_unique_symbol_type)) { return true; } - if (languageVersion < ts.ScriptTarget.ES2015 && ts.isPrivateIdentifier(node.name)) { - return grammarErrorOnNode(node.name, ts.Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); + if (languageVersion < ScriptTarget.ES2015 && isPrivateIdentifier(node.name)) { + return grammarErrorOnNode(node.name, Diagnostics.Private_identifiers_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (languageVersion < ts.ScriptTarget.ES2015 && ts.isAutoAccessorPropertyDeclaration(node)) { - return grammarErrorOnNode(node.name, ts.Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher); + if (languageVersion < ScriptTarget.ES2015 && isAutoAccessorPropertyDeclaration(node)) { + return grammarErrorOnNode(node.name, Diagnostics.Properties_with_the_accessor_modifier_are_only_available_when_targeting_ECMAScript_2015_and_higher); } - if (ts.isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, ts.Diagnostics.An_accessor_property_cannot_be_declared_optional)) { + if (isAutoAccessorPropertyDeclaration(node) && checkGrammarForInvalidQuestionMark(node.questionToken, Diagnostics.An_accessor_property_cannot_be_declared_optional)) { return true; } } - else if (node.parent.kind === ts.SyntaxKind.InterfaceDeclaration) { - if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { + else if (node.parent.kind === SyntaxKind.InterfaceDeclaration) { + if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_an_interface_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } // Interfaces cannot contain property declarations - ts.Debug.assertNode(node, ts.isPropertySignature); + Debug.assertNode(node, isPropertySignature); if (node.initializer) { - return grammarErrorOnNode(node.initializer, ts.Diagnostics.An_interface_property_cannot_have_an_initializer); + return grammarErrorOnNode(node.initializer, Diagnostics.An_interface_property_cannot_have_an_initializer); } } - else if (ts.isTypeLiteralNode(node.parent)) { - if (checkGrammarForInvalidDynamicName(node.name, ts.Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { + else if (isTypeLiteralNode(node.parent)) { + if (checkGrammarForInvalidDynamicName(node.name, Diagnostics.A_computed_property_name_in_a_type_literal_must_refer_to_an_expression_whose_type_is_a_literal_type_or_a_unique_symbol_type)) { return true; } // Type literals cannot contain property declarations - ts.Debug.assertNode(node, ts.isPropertySignature); + Debug.assertNode(node, isPropertySignature); if (node.initializer) { - return grammarErrorOnNode(node.initializer, ts.Diagnostics.A_type_literal_property_cannot_have_an_initializer); + return grammarErrorOnNode(node.initializer, Diagnostics.A_type_literal_property_cannot_have_an_initializer); } } - if (node.flags & ts.NodeFlags.Ambient) { + if (node.flags & NodeFlags.Ambient) { checkAmbientInitializer(node); } - if (ts.isPropertyDeclaration(node) && node.exclamationToken && (!ts.isClassLike(node.parent) || !node.type || node.initializer || - node.flags & ts.NodeFlags.Ambient || ts.isStatic(node) || ts.hasAbstractModifier(node))) { + if (isPropertyDeclaration(node) && node.exclamationToken && (!isClassLike(node.parent) || !node.type || node.initializer || + node.flags & NodeFlags.Ambient || isStatic(node) || hasAbstractModifier(node))) { const message = node.initializer - ? ts.Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions + ? Diagnostics.Declarations_with_initializers_cannot_also_have_definite_assignment_assertions : !node.type - ? ts.Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations - : ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context; + ? Diagnostics.Declarations_with_definite_assignment_assertions_must_also_have_type_annotations + : Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context; return grammarErrorOnNode(node.exclamationToken, message); } } - function checkGrammarTopLevelElementForRequiredDeclareModifier(node: ts.Node): boolean { + function checkGrammarTopLevelElementForRequiredDeclareModifier(node: Node): boolean { // A declare modifier is required for any top level .d.ts declaration except export=, export default, export as namespace // interfaces and imports categories: // @@ -45859,23 +46057,23 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // export_opt AmbientDeclaration // // TODO: The spec needs to be amended to reflect this grammar. - if (node.kind === ts.SyntaxKind.InterfaceDeclaration || - node.kind === ts.SyntaxKind.TypeAliasDeclaration || - node.kind === ts.SyntaxKind.ImportDeclaration || - node.kind === ts.SyntaxKind.ImportEqualsDeclaration || - node.kind === ts.SyntaxKind.ExportDeclaration || - node.kind === ts.SyntaxKind.ExportAssignment || - node.kind === ts.SyntaxKind.NamespaceExportDeclaration || - ts.hasSyntacticModifier(node, ts.ModifierFlags.Ambient | ts.ModifierFlags.Export | ts.ModifierFlags.Default)) { + if (node.kind === SyntaxKind.InterfaceDeclaration || + node.kind === SyntaxKind.TypeAliasDeclaration || + node.kind === SyntaxKind.ImportDeclaration || + node.kind === SyntaxKind.ImportEqualsDeclaration || + node.kind === SyntaxKind.ExportDeclaration || + node.kind === SyntaxKind.ExportAssignment || + node.kind === SyntaxKind.NamespaceExportDeclaration || + hasSyntacticModifier(node, ModifierFlags.Ambient | ModifierFlags.Export | ModifierFlags.Default)) { return false; } - return grammarErrorOnFirstToken(node, ts.Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier); + return grammarErrorOnFirstToken(node, Diagnostics.Top_level_declarations_in_d_ts_files_must_start_with_either_a_declare_or_export_modifier); } - function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: ts.SourceFile): boolean { + function checkGrammarTopLevelElementsForRequiredDeclareModifier(file: SourceFile): boolean { for (const decl of file.statements) { - if (ts.isDeclaration(decl) || decl.kind === ts.SyntaxKind.VariableStatement) { + if (isDeclaration(decl) || decl.kind === SyntaxKind.VariableStatement) { if (checkGrammarTopLevelElementForRequiredDeclareModifier(decl)) { return true; } @@ -45884,16 +46082,16 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarSourceFile(node: ts.SourceFile): boolean { - return !!(node.flags & ts.NodeFlags.Ambient) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); + function checkGrammarSourceFile(node: SourceFile): boolean { + return !!(node.flags & NodeFlags.Ambient) && checkGrammarTopLevelElementsForRequiredDeclareModifier(node); } - function checkGrammarStatementInAmbientContext(node: ts.Node): boolean { - if (node.flags & ts.NodeFlags.Ambient) { + function checkGrammarStatementInAmbientContext(node: Node): boolean { + if (node.flags & NodeFlags.Ambient) { // Find containing block which is either Block, ModuleBlock, SourceFile const links = getNodeLinks(node); - if (!links.hasReportedStatementInAmbientContext && (ts.isFunctionLike(node.parent) || ts.isAccessor(node.parent))) { - return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); + if (!links.hasReportedStatementInAmbientContext && (isFunctionLike(node.parent) || isAccessor(node.parent))) { + return getNodeLinks(node).hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts); } // We are either parented by another statement, or some sort of block. @@ -45901,11 +46099,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { // to prevent noisiness. So use a bit on the block to indicate if // this has already been reported, and don't report if it has. // - if (node.parent.kind === ts.SyntaxKind.Block || node.parent.kind === ts.SyntaxKind.ModuleBlock || node.parent.kind === ts.SyntaxKind.SourceFile) { + if (node.parent.kind === SyntaxKind.Block || node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) { const links = getNodeLinks(node.parent); // Check if the containing block ever report this error if (!links.hasReportedStatementInAmbientContext) { - return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, ts.Diagnostics.Statements_are_not_allowed_in_ambient_contexts); + return links.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts); } } else { @@ -45917,21 +46115,21 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkGrammarNumericLiteral(node: ts.NumericLiteral): boolean { + function checkGrammarNumericLiteral(node: NumericLiteral): boolean { // Grammar checking - if (node.numericLiteralFlags & ts.TokenFlags.Octal) { - let diagnosticMessage: ts.DiagnosticMessage | undefined; - if (languageVersion >= ts.ScriptTarget.ES5) { - diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; + if (node.numericLiteralFlags & TokenFlags.Octal) { + let diagnosticMessage: DiagnosticMessage | undefined; + if (languageVersion >= ScriptTarget.ES5) { + diagnosticMessage = Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, ts.SyntaxKind.LiteralType)) { - diagnosticMessage = ts.Diagnostics.Octal_literal_types_must_use_ES2015_syntax_Use_the_syntax_0; + else if (isChildOfNodeWithKind(node, SyntaxKind.LiteralType)) { + diagnosticMessage = Diagnostics.Octal_literal_types_must_use_ES2015_syntax_Use_the_syntax_0; } - else if (ts.isChildOfNodeWithKind(node, ts.SyntaxKind.EnumMember)) { - diagnosticMessage = ts.Diagnostics.Octal_literals_are_not_allowed_in_enums_members_initializer_Use_the_syntax_0; + else if (isChildOfNodeWithKind(node, SyntaxKind.EnumMember)) { + diagnosticMessage = Diagnostics.Octal_literals_are_not_allowed_in_enums_members_initializer_Use_the_syntax_0; } if (diagnosticMessage) { - const withMinus = ts.isPrefixUnaryExpression(node.parent) && node.parent.operator === ts.SyntaxKind.MinusToken; + const withMinus = isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.MinusToken; const literal = (withMinus ? "-" : "") + "0o" + node.text; return grammarErrorOnNode(withMinus ? node.parent : node, diagnosticMessage, literal); } @@ -45943,11 +46141,11 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function checkNumericLiteralValueSize(node: ts.NumericLiteral) { + function checkNumericLiteralValueSize(node: NumericLiteral) { // We should test against `getTextOfNode(node)` rather than `node.text`, because `node.text` for large numeric literals can contain "." // e.g. `node.text` for numeric literal `1100000000000000000000` is `1.1e21`. - const isFractional = ts.getTextOfNode(node).indexOf(".") !== -1; - const isScientific = node.numericLiteralFlags & ts.TokenFlags.Scientific; + const isFractional = getTextOfNode(node).indexOf(".") !== -1; + const isScientific = node.numericLiteralFlags & TokenFlags.Scientific; // Scientific notation (e.g. 2e54 and 1e00000000010) can't be converted to bigint // Fractional numbers (e.g. 9000000000000000.001) are inherently imprecise anyway @@ -45965,15 +46163,15 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return; } - addErrorOrSuggestion(/*isError*/ false, ts.createDiagnosticForNode(node, ts.Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers)); + addErrorOrSuggestion(/*isError*/ false, createDiagnosticForNode(node, Diagnostics.Numeric_literals_with_absolute_values_equal_to_2_53_or_greater_are_too_large_to_be_represented_accurately_as_integers)); } - function checkGrammarBigIntLiteral(node: ts.BigIntLiteral): boolean { - const literalType = ts.isLiteralTypeNode(node.parent) || - ts.isPrefixUnaryExpression(node.parent) && ts.isLiteralTypeNode(node.parent.parent); + function checkGrammarBigIntLiteral(node: BigIntLiteral): boolean { + const literalType = isLiteralTypeNode(node.parent) || + isPrefixUnaryExpression(node.parent) && isLiteralTypeNode(node.parent.parent); if (!literalType) { - if (languageVersion < ts.ScriptTarget.ES2020) { - if (grammarErrorOnNode(node, ts.Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020)) { + if (languageVersion < ScriptTarget.ES2020) { + if (grammarErrorOnNode(node, Diagnostics.BigInt_literals_are_not_available_when_targeting_lower_than_ES2020)) { return true; } } @@ -45981,17 +46179,17 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return false; } - function grammarErrorAfterFirstToken(node: ts.Node, message: ts.DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { - const sourceFile = ts.getSourceFileOfNode(node); + function grammarErrorAfterFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any): boolean { + const sourceFile = getSourceFileOfNode(node); if (!hasParseDiagnostics(sourceFile)) { - const span = ts.getSpanOfTokenAtPosition(sourceFile, node.pos); - diagnostics.add(ts.createFileDiagnostic(sourceFile, ts.textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); + const span = getSpanOfTokenAtPosition(sourceFile, node.pos); + diagnostics.add(createFileDiagnostic(sourceFile, textSpanEnd(span), /*length*/ 0, message, arg0, arg1, arg2)); return true; } return false; } - function getAmbientModules(): ts.Symbol[] { + function getAmbientModules(): Symbol[] { if (!ambientModulesCache) { ambientModulesCache = []; globals.forEach((global, sym) => { @@ -46004,72 +46202,72 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return ambientModulesCache; } - function checkGrammarImportClause(node: ts.ImportClause): boolean { + function checkGrammarImportClause(node: ImportClause): boolean { if (node.isTypeOnly && node.name && node.namedBindings) { - return grammarErrorOnNode(node, ts.Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both); + return grammarErrorOnNode(node, Diagnostics.A_type_only_import_can_specify_a_default_import_or_named_bindings_but_not_both); } - if (node.isTypeOnly && node.namedBindings?.kind === ts.SyntaxKind.NamedImports) { + if (node.isTypeOnly && node.namedBindings?.kind === SyntaxKind.NamedImports) { return checkGrammarNamedImportsOrExports(node.namedBindings); } return false; } - function checkGrammarNamedImportsOrExports(namedBindings: ts.NamedImportsOrExports): boolean { - return !!ts.forEach(namedBindings.elements, specifier => { + function checkGrammarNamedImportsOrExports(namedBindings: NamedImportsOrExports): boolean { + return !!forEach(namedBindings.elements, specifier => { if (specifier.isTypeOnly) { return grammarErrorOnFirstToken( specifier, - specifier.kind === ts.SyntaxKind.ImportSpecifier - ? ts.Diagnostics.The_type_modifier_cannot_be_used_on_a_named_import_when_import_type_is_used_on_its_import_statement - : ts.Diagnostics.The_type_modifier_cannot_be_used_on_a_named_export_when_export_type_is_used_on_its_export_statement); + specifier.kind === SyntaxKind.ImportSpecifier + ? Diagnostics.The_type_modifier_cannot_be_used_on_a_named_import_when_import_type_is_used_on_its_import_statement + : Diagnostics.The_type_modifier_cannot_be_used_on_a_named_export_when_export_type_is_used_on_its_export_statement); } }); } - function checkGrammarImportCallExpression(node: ts.ImportCall): boolean { - if (moduleKind === ts.ModuleKind.ES2015) { - return grammarErrorOnNode(node, ts.Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext); + function checkGrammarImportCallExpression(node: ImportCall): boolean { + if (moduleKind === ModuleKind.ES2015) { + return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_are_only_supported_when_the_module_flag_is_set_to_es2020_es2022_esnext_commonjs_amd_system_umd_node16_or_nodenext); } if (node.typeArguments) { - return grammarErrorOnNode(node, ts.Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); + return grammarErrorOnNode(node, Diagnostics.This_use_of_import_is_invalid_import_calls_can_be_written_but_they_must_have_parentheses_and_cannot_have_type_arguments); } const nodeArguments = node.arguments; - if (moduleKind !== ts.ModuleKind.ESNext && moduleKind !== ts.ModuleKind.NodeNext && moduleKind !== ts.ModuleKind.Node16) { + if (moduleKind !== ModuleKind.ESNext && moduleKind !== ModuleKind.NodeNext && moduleKind !== ModuleKind.Node16) { // We are allowed trailing comma after proposal-import-assertions. checkGrammarForDisallowedTrailingComma(nodeArguments); if (nodeArguments.length > 1) { const assertionArgument = nodeArguments[1]; - return grammarErrorOnNode(assertionArgument, ts.Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext); + return grammarErrorOnNode(assertionArgument, Diagnostics.Dynamic_imports_only_support_a_second_argument_when_the_module_option_is_set_to_esnext_node16_or_nodenext); } } if (nodeArguments.length === 0 || nodeArguments.length > 2) { - return grammarErrorOnNode(node, ts.Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments); + return grammarErrorOnNode(node, Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments); } // see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import. // parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import. - const spreadElement = ts.find(nodeArguments, ts.isSpreadElement); + const spreadElement = find(nodeArguments, isSpreadElement); if (spreadElement) { - return grammarErrorOnNode(spreadElement, ts.Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element); + return grammarErrorOnNode(spreadElement, Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element); } return false; } - function findMatchingTypeReferenceOrTypeAliasReference(source: ts.Type, unionTarget: ts.UnionOrIntersectionType) { - const sourceObjectFlags = ts.getObjectFlags(source); - if (sourceObjectFlags & (ts.ObjectFlags.Reference | ts.ObjectFlags.Anonymous) && unionTarget.flags & ts.TypeFlags.Union) { - return ts.find(unionTarget.types, target => { - if (target.flags & ts.TypeFlags.Object) { - const overlapObjFlags = sourceObjectFlags & ts.getObjectFlags(target); - if (overlapObjFlags & ts.ObjectFlags.Reference) { - return (source as ts.TypeReference).target === (target as ts.TypeReference).target; + function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) { + const sourceObjectFlags = getObjectFlags(source); + if (sourceObjectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) { + return find(unionTarget.types, target => { + if (target.flags & TypeFlags.Object) { + const overlapObjFlags = sourceObjectFlags & getObjectFlags(target); + if (overlapObjFlags & ObjectFlags.Reference) { + return (source as TypeReference).target === (target as TypeReference).target; } - if (overlapObjFlags & ts.ObjectFlags.Anonymous) { - return !!(source as ts.AnonymousType).aliasSymbol && (source as ts.AnonymousType).aliasSymbol === (target as ts.AnonymousType).aliasSymbol; + if (overlapObjFlags & ObjectFlags.Anonymous) { + return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol; } } return false; @@ -46077,37 +46275,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } - function findBestTypeForObjectLiteral(source: ts.Type, unionTarget: ts.UnionOrIntersectionType) { - if (ts.getObjectFlags(source) & ts.ObjectFlags.ObjectLiteral && someType(unionTarget, isArrayLikeType)) { - return ts.find(unionTarget.types, t => !isArrayLikeType(t)); + function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) { + if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && someType(unionTarget, isArrayLikeType)) { + return find(unionTarget.types, t => !isArrayLikeType(t)); } } - function findBestTypeForInvokable(source: ts.Type, unionTarget: ts.UnionOrIntersectionType) { - let signatureKind = ts.SignatureKind.Call; + function findBestTypeForInvokable(source: Type, unionTarget: UnionOrIntersectionType) { + let signatureKind = SignatureKind.Call; const hasSignatures = getSignaturesOfType(source, signatureKind).length > 0 || - (signatureKind = ts.SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); + (signatureKind = SignatureKind.Construct, getSignaturesOfType(source, signatureKind).length > 0); if (hasSignatures) { - return ts.find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0); + return find(unionTarget.types, t => getSignaturesOfType(t, signatureKind).length > 0); } } - function findMostOverlappyType(source: ts.Type, unionTarget: ts.UnionOrIntersectionType) { - let bestMatch: ts.Type | undefined; - if (!(source.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.InstantiablePrimitive))) { + function findMostOverlappyType(source: Type, unionTarget: UnionOrIntersectionType) { + let bestMatch: Type | undefined; + if (!(source.flags & (TypeFlags.Primitive | TypeFlags.InstantiablePrimitive))) { let matchingCount = 0; for (const target of unionTarget.types) { - if (!(target.flags & (ts.TypeFlags.Primitive | ts.TypeFlags.InstantiablePrimitive))) { + if (!(target.flags & (TypeFlags.Primitive | TypeFlags.InstantiablePrimitive))) { const overlap = getIntersectionType([getIndexType(source), getIndexType(target)]); - if (overlap.flags & ts.TypeFlags.Index) { + if (overlap.flags & TypeFlags.Index) { // perfect overlap of keys return target; } - else if (isUnitType(overlap) || overlap.flags & ts.TypeFlags.Union) { + else if (isUnitType(overlap) || overlap.flags & TypeFlags.Union) { // We only want to account for literal types otherwise. // If we have a union of index types, it seems likely that we // needed to elaborate between two generic mapped types anyway. - const len = overlap.flags & ts.TypeFlags.Union ? ts.countWhere((overlap as ts.UnionType).types, isUnitType) : 1; + const len = overlap.flags & TypeFlags.Union ? countWhere((overlap as UnionType).types, isUnitType) : 1; if (len >= matchingCount) { bestMatch = target; matchingCount = len; @@ -46119,10 +46317,10 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { return bestMatch; } - function filterPrimitivesIfContainsNonPrimitive(type: ts.UnionType) { - if (maybeTypeOfKind(type, ts.TypeFlags.NonPrimitive)) { - const result = filterType(type, t => !(t.flags & ts.TypeFlags.Primitive)); - if (!(result.flags & ts.TypeFlags.Never)) { + function filterPrimitivesIfContainsNonPrimitive(type: UnionType) { + if (maybeTypeOfKind(type, TypeFlags.NonPrimitive)) { + const result = filterType(type, t => !(t.flags & TypeFlags.Primitive)); + if (!(result.flags & TypeFlags.Never)) { return result; } } @@ -46130,9 +46328,9 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly - function findMatchingDiscriminantType(source: ts.Type, target: ts.Type, isRelatedTo: (source: ts.Type, target: ts.Type) => ts.Ternary, skipPartial?: boolean) { - if (target.flags & ts.TypeFlags.Union && source.flags & (ts.TypeFlags.Intersection | ts.TypeFlags.Object)) { - const match = getMatchingUnionConstituentForType(target as ts.UnionType, source); + function findMatchingDiscriminantType(source: Type, target: Type, isRelatedTo: (source: Type, target: Type) => Ternary, skipPartial?: boolean) { + if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) { + const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { return match; } @@ -46140,7 +46338,7 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { if (sourceProperties) { const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); if (sourcePropertiesFiltered) { - return discriminateTypeByDiscriminableItems(target as ts.UnionType, ts.map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => ts.Type, ts.__String])), isRelatedTo, /*defaultValue*/ undefined, skipPartial); + return discriminateTypeByDiscriminableItems(target as UnionType, map(sourcePropertiesFiltered, p => ([() => getTypeOfSymbol(p), p.escapedName] as [() => Type, __String])), isRelatedTo, /*defaultValue*/ undefined, skipPartial); } } } @@ -46148,37 +46346,37 @@ export function createTypeChecker(host: ts.TypeCheckerHost): ts.TypeChecker { } } -function isNotAccessor(declaration: ts.Declaration): boolean { +function isNotAccessor(declaration: Declaration): boolean { // Accessors check for their own matching duplicates, and in contexts where they are valid, there are already duplicate identifier checks - return !ts.isAccessor(declaration); + return !isAccessor(declaration); } -function isNotOverload(declaration: ts.Declaration): boolean { - return (declaration.kind !== ts.SyntaxKind.FunctionDeclaration && declaration.kind !== ts.SyntaxKind.MethodDeclaration) || - !!(declaration as ts.FunctionDeclaration).body; +function isNotOverload(declaration: Declaration): boolean { + return (declaration.kind !== SyntaxKind.FunctionDeclaration && declaration.kind !== SyntaxKind.MethodDeclaration) || + !!(declaration as FunctionDeclaration).body; } /** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */ -function isDeclarationNameOrImportPropertyName(name: ts.Node): boolean { +function isDeclarationNameOrImportPropertyName(name: Node): boolean { switch (name.parent.kind) { - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - return ts.isIdentifier(name); + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + return isIdentifier(name); default: - return ts.isDeclarationName(name); + return isDeclarationName(name); } } namespace JsxNames { - export const JSX = "JSX" as ts.__String; - export const IntrinsicElements = "IntrinsicElements" as ts.__String; - export const ElementClass = "ElementClass" as ts.__String; - export const ElementAttributesPropertyNameContainer = "ElementAttributesProperty" as ts.__String; // TODO: Deprecate and remove support - export const ElementChildrenAttributeNameContainer = "ElementChildrenAttribute" as ts.__String; - export const Element = "Element" as ts.__String; - export const IntrinsicAttributes = "IntrinsicAttributes" as ts.__String; - export const IntrinsicClassAttributes = "IntrinsicClassAttributes" as ts.__String; - export const LibraryManagedAttributes = "LibraryManagedAttributes" as ts.__String; + export const JSX = "JSX" as __String; + export const IntrinsicElements = "IntrinsicElements" as __String; + export const ElementClass = "ElementClass" as __String; + export const ElementAttributesPropertyNameContainer = "ElementAttributesProperty" as __String; // TODO: Deprecate and remove support + export const ElementChildrenAttributeNameContainer = "ElementChildrenAttribute" as __String; + export const Element = "Element" as __String; + export const IntrinsicAttributes = "IntrinsicAttributes" as __String; + export const IntrinsicClassAttributes = "IntrinsicClassAttributes" as __String; + export const LibraryManagedAttributes = "LibraryManagedAttributes" as __String; } function getIterationTypesKeyFromIterationTypeKind(typeKind: IterationTypeKind) { @@ -46190,11 +46388,11 @@ function getIterationTypesKeyFromIterationTypeKind(typeKind: IterationTypeKind) } /** @internal */ -export function signatureHasRestParameter(s: ts.Signature) { - return !!(s.flags & ts.SignatureFlags.HasRestParameter); +export function signatureHasRestParameter(s: Signature) { + return !!(s.flags & SignatureFlags.HasRestParameter); } /** @internal */ -export function signatureHasLiteralTypes(s: ts.Signature) { - return !!(s.flags & ts.SignatureFlags.HasLiteralTypes); +export function signatureHasLiteralTypes(s: Signature) { + return !!(s.flags & SignatureFlags.HasLiteralTypes); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index c7a6e5e730cae..f10b4d11c6dda 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,22 +1,43 @@ -import * as ts from "./_namespaces/ts"; +import { + AlternateModeDiagnostics, append, arrayFrom, ArrayLiteralExpression, arrayToMap, assign, BuildOptions, + changeExtension, CharacterCodes, combinePaths, CommandLineOption, CommandLineOptionOfCustomType, + CommandLineOptionOfListType, CompilerOptions, CompilerOptionsValue, ConfigFileSpecs, containsPath, + convertToRelativePath, createCompilerDiagnostic, createDiagnosticForNodeInSourceFile, createGetCanonicalFileName, + Debug, Diagnostic, DiagnosticMessage, Diagnostics, DidYouMeanOptionsDiagnostics, directorySeparator, emptyArray, + endsWith, ensureTrailingDirectorySeparator, ESMap, every, Expression, extend, Extension, FileExtensionInfo, + fileExtensionIs, fileExtensionIsOneOf, filter, filterMutate, find, findIndex, firstDefined, flatten, forEach, + forEachEntry, getBaseFileName, getDirectoryPath, getEntries, getFileMatcherPatterns, getLocaleSpecificMessage, + getNormalizedAbsolutePath, getRegexFromPattern, getRegularExpressionForWildcard, getRegularExpressionsForWildcards, + getRelativePathFromFile, getSpellingSuggestion, getSupportedExtensions, + getSupportedExtensionsWithJsonIfResolveJsonModule, getTextOfPropertyName, getTsConfigPropArray, + getTsConfigPropArrayElementValue, hasExtension, hasProperty, ImportsNotUsedAsValues, isArray, + isArrayLiteralExpression, isComputedNonLiteralName, isImplicitGlob, isObjectLiteralExpression, isRootedDiskPath, + isString, isStringDoubleQuoted, isStringLiteral, JsonSourceFile, JsxEmit, length, map, Map, mapDefined, mapIterator, + MapLike, ModuleDetectionKind, ModuleKind, ModuleResolutionKind, NewLineKind, Node, NodeArray, + nodeModuleNameResolver, normalizePath, normalizeSlashes, NumericLiteral, ObjectLiteralExpression, ParseConfigHost, + ParsedCommandLine, parseJsonText, Path, PollingWatchKind, PrefixUnaryExpression, ProjectReference, PropertyName, + Push, removeTrailingDirectorySeparator, returnTrue, ScriptTarget, startsWith, StringLiteral, SyntaxKind, sys, + toFileNameLowerCase, toPath, tracing, trimString, TsConfigOnlyOption, TsConfigSourceFile, TypeAcquisition, + unescapeLeadingUnderscores, WatchDirectoryFlags, WatchDirectoryKind, WatchFileKind, WatchOptions, +} from "./_namespaces/ts"; /* @internal */ -export const compileOnSaveCommandLineOption: ts.CommandLineOption = { +export const compileOnSaveCommandLineOption: CommandLineOption = { name: "compileOnSave", type: "boolean", defaultValueDescription: false, }; -const jsxOptionMap = new ts.Map(ts.getEntries({ - "preserve": ts.JsxEmit.Preserve, - "react-native": ts.JsxEmit.ReactNative, - "react": ts.JsxEmit.React, - "react-jsx": ts.JsxEmit.ReactJSX, - "react-jsxdev": ts.JsxEmit.ReactJSXDev, +const jsxOptionMap = new Map(getEntries({ + "preserve": JsxEmit.Preserve, + "react-native": JsxEmit.ReactNative, + "react": JsxEmit.React, + "react-jsx": JsxEmit.ReactJSX, + "react-jsxdev": JsxEmit.ReactJSXDev, })); /* @internal */ -export const inverseJsxOptionMap = new ts.Map(ts.arrayFrom(ts.mapIterator(jsxOptionMap.entries(), ([key, value]: [string, ts.JsxEmit]) => ["" + value, key] as const))); +export const inverseJsxOptionMap = new Map(arrayFrom(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const))); // NOTE: The order here is important to default lib ordering as entries will have the same // order in the generated program (see `getDefaultLibPriority` in program.ts). This @@ -110,54 +131,54 @@ export const libs = libEntries.map(entry => entry[0]); * option as well as for resolving lib reference directives. */ /* @internal */ -export const libMap = new ts.Map(libEntries); +export const libMap = new Map(libEntries); // Watch related options /* @internal */ -export const optionsForWatch: ts.CommandLineOption[] = [ +export const optionsForWatch: CommandLineOption[] = [ { name: "watchFile", - type: new ts.Map(ts.getEntries({ - fixedpollinginterval: ts.WatchFileKind.FixedPollingInterval, - prioritypollinginterval: ts.WatchFileKind.PriorityPollingInterval, - dynamicprioritypolling: ts.WatchFileKind.DynamicPriorityPolling, - fixedchunksizepolling: ts.WatchFileKind.FixedChunkSizePolling, - usefsevents: ts.WatchFileKind.UseFsEvents, - usefseventsonparentdirectory: ts.WatchFileKind.UseFsEventsOnParentDirectory, + type: new Map(getEntries({ + fixedpollinginterval: WatchFileKind.FixedPollingInterval, + prioritypollinginterval: WatchFileKind.PriorityPollingInterval, + dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling, + fixedchunksizepolling: WatchFileKind.FixedChunkSizePolling, + usefsevents: WatchFileKind.UseFsEvents, + usefseventsonparentdirectory: WatchFileKind.UseFsEventsOnParentDirectory, })), - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Specify_how_the_TypeScript_watch_mode_works, - defaultValueDescription: ts.WatchFileKind.UseFsEvents, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Specify_how_the_TypeScript_watch_mode_works, + defaultValueDescription: WatchFileKind.UseFsEvents, }, { name: "watchDirectory", - type: new ts.Map(ts.getEntries({ - usefsevents: ts.WatchDirectoryKind.UseFsEvents, - fixedpollinginterval: ts.WatchDirectoryKind.FixedPollingInterval, - dynamicprioritypolling: ts.WatchDirectoryKind.DynamicPriorityPolling, - fixedchunksizepolling: ts.WatchDirectoryKind.FixedChunkSizePolling, + type: new Map(getEntries({ + usefsevents: WatchDirectoryKind.UseFsEvents, + fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval, + dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling, + fixedchunksizepolling: WatchDirectoryKind.FixedChunkSizePolling, })), - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, - defaultValueDescription: ts.WatchDirectoryKind.UseFsEvents, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality, + defaultValueDescription: WatchDirectoryKind.UseFsEvents, }, { name: "fallbackPolling", - type: new ts.Map(ts.getEntries({ - fixedinterval: ts.PollingWatchKind.FixedInterval, - priorityinterval: ts.PollingWatchKind.PriorityInterval, - dynamicpriority: ts.PollingWatchKind.DynamicPriority, - fixedchunksize: ts.PollingWatchKind.FixedChunkSize, + type: new Map(getEntries({ + fixedinterval: PollingWatchKind.FixedInterval, + priorityinterval: PollingWatchKind.PriorityInterval, + dynamicpriority: PollingWatchKind.DynamicPriority, + fixedchunksize: PollingWatchKind.FixedChunkSize, })), - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, - defaultValueDescription: ts.PollingWatchKind.PriorityInterval, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers, + defaultValueDescription: PollingWatchKind.PriorityInterval, }, { name: "synchronousWatchDirectory", type: "boolean", - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively, defaultValueDescription: false, }, { @@ -169,8 +190,8 @@ export const optionsForWatch: ts.CommandLineOption[] = [ isFilePath: true, extraValidation: specToDiagnostic }, - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Remove_a_list_of_directories_from_the_watch_process, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Remove_a_list_of_directories_from_the_watch_process, }, { name: "excludeFiles", @@ -181,21 +202,21 @@ export const optionsForWatch: ts.CommandLineOption[] = [ isFilePath: true, extraValidation: specToDiagnostic }, - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Remove_a_list_of_files_from_the_watch_mode_s_processing, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Remove_a_list_of_files_from_the_watch_mode_s_processing, }, ]; /* @internal */ -export const commonOptionsWithBuild: ts.CommandLineOption[] = [ +export const commonOptionsWithBuild: CommandLineOption[] = [ { name: "help", shortName: "h", type: "boolean", showInSimplifiedHelpView: true, isCommandLineOnly: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Print_this_message, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Print_this_message, defaultValueDescription: false, }, { @@ -203,7 +224,7 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ shortName: "?", type: "boolean", isCommandLineOnly: true, - category: ts.Diagnostics.Command_line_Options, + category: Diagnostics.Command_line_Options, defaultValueDescription: false, }, { @@ -212,75 +233,75 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ type: "boolean", showInSimplifiedHelpView: true, isCommandLineOnly: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Watch_input_files, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Watch_input_files, defaultValueDescription: false, }, { name: "preserveWatchOutput", type: "boolean", showInSimplifiedHelpView: false, - category: ts.Diagnostics.Output_Formatting, - description: ts.Diagnostics.Disable_wiping_the_console_in_watch_mode, + category: Diagnostics.Output_Formatting, + description: Diagnostics.Disable_wiping_the_console_in_watch_mode, defaultValueDescription: false, }, { name: "listFiles", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Print_all_of_the_files_read_during_the_compilation, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Print_all_of_the_files_read_during_the_compilation, defaultValueDescription: false, }, { name: "explainFiles", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Print_files_read_during_the_compilation_including_why_it_was_included, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Print_files_read_during_the_compilation_including_why_it_was_included, defaultValueDescription: false, }, { name: "listEmittedFiles", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Print_the_names_of_emitted_files_after_a_compilation, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Print_the_names_of_emitted_files_after_a_compilation, defaultValueDescription: false, }, { name: "pretty", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Output_Formatting, - description: ts.Diagnostics.Enable_color_and_formatting_in_TypeScript_s_output_to_make_compiler_errors_easier_to_read, + category: Diagnostics.Output_Formatting, + description: Diagnostics.Enable_color_and_formatting_in_TypeScript_s_output_to_make_compiler_errors_easier_to_read, defaultValueDescription: true, }, { name: "traceResolution", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Log_paths_used_during_the_moduleResolution_process, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Log_paths_used_during_the_moduleResolution_process, defaultValueDescription: false, }, { name: "diagnostics", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Output_compiler_performance_information_after_building, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Output_compiler_performance_information_after_building, defaultValueDescription: false, }, { name: "extendedDiagnostics", type: "boolean", - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Output_more_detailed_compiler_performance_information_after_building, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Output_more_detailed_compiler_performance_information_after_building, defaultValueDescription: false, }, { name: "generateCpuProfile", type: "string", isFilePath: true, - paramType: ts.Diagnostics.FILE_OR_DIRECTORY, - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging, + paramType: Diagnostics.FILE_OR_DIRECTORY, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging, defaultValueDescription: "profile.cpuprofile" }, { @@ -288,18 +309,18 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ type: "string", isFilePath: true, isCommandLineOnly: true, - paramType: ts.Diagnostics.DIRECTORY, - category: ts.Diagnostics.Compiler_Diagnostics, - description: ts.Diagnostics.Generates_an_event_trace_and_a_list_of_types + paramType: Diagnostics.DIRECTORY, + category: Diagnostics.Compiler_Diagnostics, + description: Diagnostics.Generates_an_event_trace_and_a_list_of_types }, { name: "incremental", shortName: "i", type: "boolean", - category: ts.Diagnostics.Projects, - description: ts.Diagnostics.Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects, + category: Diagnostics.Projects, + description: Diagnostics.Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects, transpileOptionValue: undefined, - defaultValueDescription: ts.Diagnostics.false_unless_composite_is_set + defaultValueDescription: Diagnostics.false_unless_composite_is_set }, { name: "declaration", @@ -308,10 +329,10 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, + category: Diagnostics.Emit, transpileOptionValue: undefined, - description: ts.Diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project, - defaultValueDescription: ts.Diagnostics.false_unless_composite_is_set, + description: Diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project, + defaultValueDescription: Diagnostics.false_unless_composite_is_set, }, { name: "declarationMap", @@ -319,10 +340,10 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, + category: Diagnostics.Emit, transpileOptionValue: undefined, defaultValueDescription: false, - description: ts.Diagnostics.Create_sourcemaps_for_d_ts_files + description: Diagnostics.Create_sourcemaps_for_d_ts_files }, { name: "emitDeclarationOnly", @@ -330,8 +351,8 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Only_output_d_ts_files_and_not_JavaScript_files, + category: Diagnostics.Emit, + description: Diagnostics.Only_output_d_ts_files_and_not_JavaScript_files, transpileOptionValue: undefined, defaultValueDescription: false, }, @@ -341,17 +362,17 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, + category: Diagnostics.Emit, defaultValueDescription: false, - description: ts.Diagnostics.Create_source_map_files_for_emitted_JavaScript_files, + description: Diagnostics.Create_source_map_files_for_emitted_JavaScript_files, }, { name: "inlineSourceMap", type: "boolean", // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript, + category: Diagnostics.Emit, + description: Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript, defaultValueDescription: false, }, { @@ -360,85 +381,85 @@ export const commonOptionsWithBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Watch_and_Build_Modes, - description: ts.Diagnostics.Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it, + category: Diagnostics.Watch_and_Build_Modes, + description: Diagnostics.Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it, defaultValueDescription: false, }, { name: "locale", type: "string", - category: ts.Diagnostics.Command_line_Options, + category: Diagnostics.Command_line_Options, isCommandLineOnly: true, - description: ts.Diagnostics.Set_the_language_of_the_messaging_from_TypeScript_This_does_not_affect_emit, - defaultValueDescription: ts.Diagnostics.Platform_specific + description: Diagnostics.Set_the_language_of_the_messaging_from_TypeScript_This_does_not_affect_emit, + defaultValueDescription: Diagnostics.Platform_specific }, ]; /* @internal */ -export const targetOptionDeclaration: ts.CommandLineOptionOfCustomType = { +export const targetOptionDeclaration: CommandLineOptionOfCustomType = { name: "target", shortName: "t", - type: new ts.Map(ts.getEntries({ - es3: ts.ScriptTarget.ES3, - es5: ts.ScriptTarget.ES5, - es6: ts.ScriptTarget.ES2015, - es2015: ts.ScriptTarget.ES2015, - es2016: ts.ScriptTarget.ES2016, - es2017: ts.ScriptTarget.ES2017, - es2018: ts.ScriptTarget.ES2018, - es2019: ts.ScriptTarget.ES2019, - es2020: ts.ScriptTarget.ES2020, - es2021: ts.ScriptTarget.ES2021, - es2022: ts.ScriptTarget.ES2022, - esnext: ts.ScriptTarget.ESNext, + type: new Map(getEntries({ + es3: ScriptTarget.ES3, + es5: ScriptTarget.ES5, + es6: ScriptTarget.ES2015, + es2015: ScriptTarget.ES2015, + es2016: ScriptTarget.ES2016, + es2017: ScriptTarget.ES2017, + es2018: ScriptTarget.ES2018, + es2019: ScriptTarget.ES2019, + es2020: ScriptTarget.ES2020, + es2021: ScriptTarget.ES2021, + es2022: ScriptTarget.ES2022, + esnext: ScriptTarget.ESNext, })), affectsSourceFile: true, affectsModuleResolution: true, affectsEmit: true, affectsBuildInfo: true, - paramType: ts.Diagnostics.VERSION, + paramType: Diagnostics.VERSION, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, - defaultValueDescription: ts.ScriptTarget.ES3, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, + defaultValueDescription: ScriptTarget.ES3, }; /*@internal*/ -export const moduleOptionDeclaration: ts.CommandLineOptionOfCustomType = { +export const moduleOptionDeclaration: CommandLineOptionOfCustomType = { name: "module", shortName: "m", - type: new ts.Map(ts.getEntries({ - none: ts.ModuleKind.None, - commonjs: ts.ModuleKind.CommonJS, - amd: ts.ModuleKind.AMD, - system: ts.ModuleKind.System, - umd: ts.ModuleKind.UMD, - es6: ts.ModuleKind.ES2015, - es2015: ts.ModuleKind.ES2015, - es2020: ts.ModuleKind.ES2020, - es2022: ts.ModuleKind.ES2022, - esnext: ts.ModuleKind.ESNext, - node16: ts.ModuleKind.Node16, - nodenext: ts.ModuleKind.NodeNext, + type: new Map(getEntries({ + none: ModuleKind.None, + commonjs: ModuleKind.CommonJS, + amd: ModuleKind.AMD, + system: ModuleKind.System, + umd: ModuleKind.UMD, + es6: ModuleKind.ES2015, + es2015: ModuleKind.ES2015, + es2020: ModuleKind.ES2020, + es2022: ModuleKind.ES2022, + esnext: ModuleKind.ESNext, + node16: ModuleKind.Node16, + nodenext: ModuleKind.NodeNext, })), affectsModuleResolution: true, affectsEmit: true, affectsBuildInfo: true, - paramType: ts.Diagnostics.KIND, + paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_what_module_code_is_generated, + category: Diagnostics.Modules, + description: Diagnostics.Specify_what_module_code_is_generated, defaultValueDescription: undefined, }; -const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ +const commandOptionsWithoutBuild: CommandLineOption[] = [ // CommandLine only options { name: "all", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Show_all_compiler_options, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Show_all_compiler_options, defaultValueDescription: false, }, { @@ -446,16 +467,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ shortName: "v", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Print_the_compiler_s_version, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Print_the_compiler_s_version, defaultValueDescription: false, }, { name: "init", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file, defaultValueDescription: false, }, { @@ -464,34 +485,34 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "string", isFilePath: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, - paramType: ts.Diagnostics.FILE_OR_DIRECTORY, - description: ts.Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json, + category: Diagnostics.Command_line_Options, + paramType: Diagnostics.FILE_OR_DIRECTORY, + description: Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json, }, { name: "build", type: "boolean", shortName: "b", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date, defaultValueDescription: false, }, { name: "showConfig", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Command_line_Options, + category: Diagnostics.Command_line_Options, isCommandLineOnly: true, - description: ts.Diagnostics.Print_the_final_configuration_instead_of_building, + description: Diagnostics.Print_the_final_configuration_instead_of_building, defaultValueDescription: false, }, { name: "listFilesOnly", type: "boolean", - category: ts.Diagnostics.Command_line_Options, + category: Diagnostics.Command_line_Options, isCommandLineOnly: true, - description: ts.Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing, + description: Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing, defaultValueDescription: false, }, @@ -508,8 +529,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ }, affectsProgramStructure: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_a_set_of_bundled_library_declaration_files_that_describe_the_target_runtime_environment, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_a_set_of_bundled_library_declaration_files_that_describe_the_target_runtime_environment, transpileOptionValue: undefined }, { @@ -517,16 +538,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsModuleResolution: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.JavaScript_Support, - description: ts.Diagnostics.Allow_JavaScript_files_to_be_a_part_of_your_program_Use_the_checkJS_option_to_get_errors_from_these_files, + category: Diagnostics.JavaScript_Support, + description: Diagnostics.Allow_JavaScript_files_to_be_a_part_of_your_program_Use_the_checkJS_option_to_get_errors_from_these_files, defaultValueDescription: false, }, { name: "checkJs", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.JavaScript_Support, - description: ts.Diagnostics.Enable_error_reporting_in_type_checked_JavaScript_files, + category: Diagnostics.JavaScript_Support, + description: Diagnostics.Enable_error_reporting_in_type_checked_JavaScript_files, defaultValueDescription: false, }, { @@ -536,10 +557,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, affectsModuleResolution: true, - paramType: ts.Diagnostics.KIND, + paramType: Diagnostics.KIND, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_what_JSX_code_is_generated, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_what_JSX_code_is_generated, defaultValueDescription: undefined, }, { @@ -549,10 +570,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBuildInfo: true, affectsDeclarationPath: true, isFilePath: true, - paramType: ts.Diagnostics.FILE, + paramType: Diagnostics.FILE, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Specify_a_file_that_bundles_all_outputs_into_one_JavaScript_file_If_declaration_is_true_also_designates_a_file_that_bundles_all_d_ts_output, + category: Diagnostics.Emit, + description: Diagnostics.Specify_a_file_that_bundles_all_outputs_into_one_JavaScript_file_If_declaration_is_true_also_designates_a_file_that_bundles_all_d_ts_output, transpileOptionValue: undefined, }, { @@ -562,10 +583,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBuildInfo: true, affectsDeclarationPath: true, isFilePath: true, - paramType: ts.Diagnostics.DIRECTORY, + paramType: Diagnostics.DIRECTORY, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Specify_an_output_folder_for_all_emitted_files, + category: Diagnostics.Emit, + description: Diagnostics.Specify_an_output_folder_for_all_emitted_files, }, { name: "rootDir", @@ -574,10 +595,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBuildInfo: true, affectsDeclarationPath: true, isFilePath: true, - paramType: ts.Diagnostics.LOCATION, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_the_root_folder_within_your_source_files, - defaultValueDescription: ts.Diagnostics.Computed_from_the_list_of_input_files + paramType: Diagnostics.LOCATION, + category: Diagnostics.Modules, + description: Diagnostics.Specify_the_root_folder_within_your_source_files, + defaultValueDescription: Diagnostics.Computed_from_the_list_of_input_files }, { name: "composite", @@ -585,10 +606,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ // Not setting affectsEmit because we calculate this flag might not affect full emit affectsBuildInfo: true, isTSConfigOnly: true, - category: ts.Diagnostics.Projects, + category: Diagnostics.Projects, transpileOptionValue: undefined, defaultValueDescription: false, - description: ts.Diagnostics.Enable_constraints_that_allow_a_TypeScript_project_to_be_used_with_project_references, + description: Diagnostics.Enable_constraints_that_allow_a_TypeScript_project_to_be_used_with_project_references, }, { name: "tsBuildInfoFile", @@ -596,11 +617,11 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, isFilePath: true, - paramType: ts.Diagnostics.FILE, - category: ts.Diagnostics.Projects, + paramType: Diagnostics.FILE, + category: Diagnostics.Projects, transpileOptionValue: undefined, defaultValueDescription: ".tsbuildinfo", - description: ts.Diagnostics.Specify_the_path_to_tsbuildinfo_incremental_compilation_file, + description: Diagnostics.Specify_the_path_to_tsbuildinfo_incremental_compilation_file, }, { name: "removeComments", @@ -608,16 +629,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, + category: Diagnostics.Emit, defaultValueDescription: false, - description: ts.Diagnostics.Disable_emitting_comments, + description: Diagnostics.Disable_emitting_comments, }, { name: "noEmit", type: "boolean", showInSimplifiedHelpView: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Disable_emitting_files_from_a_compilation, + category: Diagnostics.Emit, + description: Diagnostics.Disable_emitting_files_from_a_compilation, transpileOptionValue: undefined, defaultValueDescription: false, }, @@ -626,38 +647,38 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file, + category: Diagnostics.Emit, + description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file, defaultValueDescription: false, }, { name: "importsNotUsedAsValues", - type: new ts.Map(ts.getEntries({ - remove: ts.ImportsNotUsedAsValues.Remove, - preserve: ts.ImportsNotUsedAsValues.Preserve, - error: ts.ImportsNotUsedAsValues.Error, + type: new Map(getEntries({ + remove: ImportsNotUsedAsValues.Remove, + preserve: ImportsNotUsedAsValues.Preserve, + error: ImportsNotUsedAsValues.Error, })), affectsEmit: true, affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types, - defaultValueDescription: ts.ImportsNotUsedAsValues.Remove, + category: Diagnostics.Emit, + description: Diagnostics.Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types, + defaultValueDescription: ImportsNotUsedAsValues.Remove, }, { name: "downlevelIteration", type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Emit_more_compliant_but_verbose_and_less_performant_JavaScript_for_iteration, + category: Diagnostics.Emit, + description: Diagnostics.Emit_more_compliant_but_verbose_and_less_performant_JavaScript_for_iteration, defaultValueDescription: false, }, { name: "isolatedModules", type: "boolean", - category: ts.Diagnostics.Interop_Constraints, - description: ts.Diagnostics.Ensure_that_each_file_can_be_safely_transpiled_without_relying_on_other_imports, + category: Diagnostics.Interop_Constraints, + description: Diagnostics.Ensure_that_each_file_can_be_safely_transpiled_without_relying_on_other_imports, transpileOptionValue: true, defaultValueDescription: false, }, @@ -672,8 +693,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ // flags it controls (e.g. `strictNullChecks`) will be retrieved correctly affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_all_strict_type_checking_options, + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_all_strict_type_checking_options, defaultValueDescription: false, }, { @@ -682,9 +703,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_error_reporting_for_expressions_and_declarations_with_an_implied_any_type, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_error_reporting_for_expressions_and_declarations_with_an_implied_any_type, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "strictNullChecks", @@ -692,9 +713,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.When_type_checking_take_into_account_null_and_undefined, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.When_type_checking_take_into_account_null_and_undefined, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "strictFunctionTypes", @@ -702,9 +723,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "strictBindCallApply", @@ -712,9 +733,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Check_that_the_arguments_for_bind_call_and_apply_methods_match_the_original_function, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.Check_that_the_arguments_for_bind_call_and_apply_methods_match_the_original_function, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "strictPropertyInitialization", @@ -722,9 +743,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "noImplicitThis", @@ -732,9 +753,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_error_reporting_when_this_is_given_the_type_any, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_error_reporting_when_this_is_given_the_type_any, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, { name: "useUnknownInCatchVariables", @@ -742,8 +763,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Default_catch_clause_variables_as_unknown_instead_of_any, + category: Diagnostics.Type_Checking, + description: Diagnostics.Default_catch_clause_variables_as_unknown_instead_of_any, defaultValueDescription: false, }, { @@ -753,9 +774,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, strictFlag: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Ensure_use_strict_is_always_emitted, - defaultValueDescription: ts.Diagnostics.false_unless_strict_is_set + category: Diagnostics.Type_Checking, + description: Diagnostics.Ensure_use_strict_is_always_emitted, + defaultValueDescription: Diagnostics.false_unless_strict_is_set }, // Additional Checks @@ -764,8 +785,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_error_reporting_when_local_variables_aren_t_read, + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_error_reporting_when_local_variables_aren_t_read, defaultValueDescription: false, }, { @@ -773,8 +794,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Raise_an_error_when_a_function_parameter_isn_t_read, + category: Diagnostics.Type_Checking, + description: Diagnostics.Raise_an_error_when_a_function_parameter_isn_t_read, defaultValueDescription: false, }, { @@ -782,8 +803,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Interpret_optional_property_types_as_written_rather_than_adding_undefined, + category: Diagnostics.Type_Checking, + description: Diagnostics.Interpret_optional_property_types_as_written_rather_than_adding_undefined, defaultValueDescription: false, }, { @@ -791,8 +812,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_error_reporting_for_codepaths_that_do_not_explicitly_return_in_a_function, + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_error_reporting_for_codepaths_that_do_not_explicitly_return_in_a_function, defaultValueDescription: false, }, { @@ -801,8 +822,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enable_error_reporting_for_fallthrough_cases_in_switch_statements, + category: Diagnostics.Type_Checking, + description: Diagnostics.Enable_error_reporting_for_fallthrough_cases_in_switch_statements, defaultValueDescription: false, }, { @@ -810,8 +831,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Add_undefined_to_a_type_when_accessed_using_an_index, + category: Diagnostics.Type_Checking, + description: Diagnostics.Add_undefined_to_a_type_when_accessed_using_an_index, defaultValueDescription: false, }, { @@ -819,8 +840,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Ensure_overriding_members_in_derived_classes_are_marked_with_an_override_modifier, + category: Diagnostics.Type_Checking, + description: Diagnostics.Ensure_overriding_members_in_derived_classes_are_marked_with_an_override_modifier, defaultValueDescription: false, }, { @@ -829,33 +850,33 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsBuildInfo: true, showInSimplifiedHelpView: false, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type, + category: Diagnostics.Type_Checking, + description: Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type, defaultValueDescription: false, }, // Module Resolution { name: "moduleResolution", - type: new ts.Map(ts.getEntries({ - node: ts.ModuleResolutionKind.NodeJs, - classic: ts.ModuleResolutionKind.Classic, - node16: ts.ModuleResolutionKind.Node16, - nodenext: ts.ModuleResolutionKind.NodeNext, + type: new Map(getEntries({ + node: ModuleResolutionKind.NodeJs, + classic: ModuleResolutionKind.Classic, + node16: ModuleResolutionKind.Node16, + nodenext: ModuleResolutionKind.NodeNext, })), affectsModuleResolution: true, - paramType: ts.Diagnostics.STRATEGY, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_how_TypeScript_looks_up_a_file_from_a_given_module_specifier, - defaultValueDescription: ts.Diagnostics.module_AMD_or_UMD_or_System_or_ES6_then_Classic_Otherwise_Node + paramType: Diagnostics.STRATEGY, + category: Diagnostics.Modules, + description: Diagnostics.Specify_how_TypeScript_looks_up_a_file_from_a_given_module_specifier, + defaultValueDescription: Diagnostics.module_AMD_or_UMD_or_System_or_ES6_then_Classic_Otherwise_Node }, { name: "baseUrl", type: "string", affectsModuleResolution: true, isFilePath: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_the_base_directory_to_resolve_non_relative_module_names + category: Diagnostics.Modules, + description: Diagnostics.Specify_the_base_directory_to_resolve_non_relative_module_names }, { // this option can only be specified in tsconfig.json @@ -864,8 +885,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "object", affectsModuleResolution: true, isTSConfigOnly: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_a_set_of_entries_that_re_map_imports_to_additional_lookup_locations, + category: Diagnostics.Modules, + description: Diagnostics.Specify_a_set_of_entries_that_re_map_imports_to_additional_lookup_locations, transpileOptionValue: undefined }, { @@ -880,10 +901,10 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ isFilePath: true }, affectsModuleResolution: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Allow_multiple_folders_to_be_treated_as_one_when_resolving_modules, + category: Diagnostics.Modules, + description: Diagnostics.Allow_multiple_folders_to_be_treated_as_one_when_resolving_modules, transpileOptionValue: undefined, - defaultValueDescription: ts.Diagnostics.Computed_from_the_list_of_input_files + defaultValueDescription: Diagnostics.Computed_from_the_list_of_input_files }, { name: "typeRoots", @@ -894,8 +915,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ isFilePath: true }, affectsModuleResolution: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types + category: Diagnostics.Modules, + description: Diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types }, { name: "types", @@ -906,8 +927,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ }, affectsProgramStructure: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Specify_type_package_names_to_be_included_without_being_referenced_in_a_source_file, + category: Diagnostics.Modules, + description: Diagnostics.Specify_type_package_names_to_be_included_without_being_referenced_in_a_source_file, transpileOptionValue: undefined }, { @@ -915,9 +936,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Interop_Constraints, - description: ts.Diagnostics.Allow_import_x_from_y_when_a_module_doesn_t_have_a_default_export, - defaultValueDescription: ts.Diagnostics.module_system_or_esModuleInterop + category: Diagnostics.Interop_Constraints, + description: Diagnostics.Allow_import_x_from_y_when_a_module_doesn_t_have_a_default_export, + defaultValueDescription: Diagnostics.module_system_or_esModuleInterop }, { name: "esModuleInterop", @@ -926,15 +947,15 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, showInSimplifiedHelpView: true, - category: ts.Diagnostics.Interop_Constraints, - description: ts.Diagnostics.Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility, + category: Diagnostics.Interop_Constraints, + description: Diagnostics.Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility, defaultValueDescription: false, }, { name: "preserveSymlinks", type: "boolean", - category: ts.Diagnostics.Interop_Constraints, - description: ts.Diagnostics.Disable_resolving_symlinks_to_their_realpath_This_correlates_to_the_same_flag_in_node, + category: Diagnostics.Interop_Constraints, + description: Diagnostics.Disable_resolving_symlinks_to_their_realpath_This_correlates_to_the_same_flag_in_node, defaultValueDescription: false, }, { @@ -942,8 +963,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Allow_accessing_UMD_globals_from_modules, + category: Diagnostics.Modules, + description: Diagnostics.Allow_accessing_UMD_globals_from_modules, defaultValueDescription: false, }, { @@ -955,8 +976,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ }, listPreserveFalsyValues: true, affectsModuleResolution: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module, + category: Diagnostics.Modules, + description: Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module, }, // Source Maps @@ -965,26 +986,26 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "string", affectsEmit: true, affectsBuildInfo: true, - paramType: ts.Diagnostics.LOCATION, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Specify_the_root_path_for_debuggers_to_find_the_reference_source_code, + paramType: Diagnostics.LOCATION, + category: Diagnostics.Emit, + description: Diagnostics.Specify_the_root_path_for_debuggers_to_find_the_reference_source_code, }, { name: "mapRoot", type: "string", affectsEmit: true, affectsBuildInfo: true, - paramType: ts.Diagnostics.LOCATION, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, + paramType: Diagnostics.LOCATION, + category: Diagnostics.Emit, + description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, }, { name: "inlineSources", type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Include_source_code_in_the_sourcemaps_inside_the_emitted_JavaScript, + category: Diagnostics.Emit, + description: Diagnostics.Include_source_code_in_the_sourcemaps_inside_the_emitted_JavaScript, defaultValueDescription: false, }, @@ -994,8 +1015,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Enable_experimental_support_for_TC39_stage_2_draft_decorators, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Enable_experimental_support_for_TC39_stage_2_draft_decorators, defaultValueDescription: false, }, { @@ -1004,8 +1025,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Emit_design_type_metadata_for_decorated_declarations_in_source_files, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Emit_design_type_metadata_for_decorated_declarations_in_source_files, defaultValueDescription: false, }, @@ -1013,15 +1034,15 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ { name: "jsxFactory", type: "string", - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_the_JSX_factory_function_used_when_targeting_React_JSX_emit_e_g_React_createElement_or_h, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_the_JSX_factory_function_used_when_targeting_React_JSX_emit_e_g_React_createElement_or_h, defaultValueDescription: "`React.createElement`" }, { name: "jsxFragmentFactory", type: "string", - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_the_JSX_Fragment_reference_used_for_fragments_when_targeting_React_JSX_emit_e_g_React_Fragment_or_Fragment, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_the_JSX_Fragment_reference_used_for_fragments_when_targeting_React_JSX_emit_e_g_React_Fragment_or_Fragment, defaultValueDescription: "React.Fragment", }, { @@ -1031,16 +1052,16 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsEmit: true, affectsBuildInfo: true, affectsModuleResolution: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk, defaultValueDescription: "react" }, { name: "resolveJsonModule", type: "boolean", affectsModuleResolution: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Enable_importing_json_files, + category: Diagnostics.Modules, + description: Diagnostics.Enable_importing_json_files, defaultValueDescription: false, }, @@ -1052,18 +1073,18 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsDeclarationPath: true, isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files // for correct behaviour, please use outFile - category: ts.Diagnostics.Backwards_Compatibility, - paramType: ts.Diagnostics.FILE, + category: Diagnostics.Backwards_Compatibility, + paramType: Diagnostics.FILE, transpileOptionValue: undefined, - description: ts.Diagnostics.Deprecated_setting_Use_outFile_instead, + description: Diagnostics.Deprecated_setting_Use_outFile_instead, }, { name: "reactNamespace", type: "string", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit, + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit, defaultValueDescription: "`React`", }, { @@ -1071,15 +1092,15 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", // We need to store these to determine whether `lib` files need to be rechecked affectsBuildInfo: true, - category: ts.Diagnostics.Completeness, - description: ts.Diagnostics.Skip_type_checking_d_ts_files_that_are_included_with_TypeScript, + category: Diagnostics.Completeness, + description: Diagnostics.Skip_type_checking_d_ts_files_that_are_included_with_TypeScript, defaultValueDescription: false, }, { name: "charset", type: "string", - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.No_longer_supported_In_early_versions_manually_set_the_text_encoding_for_reading_files, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.No_longer_supported_In_early_versions_manually_set_the_text_encoding_for_reading_files, defaultValueDescription: "utf8" }, { @@ -1087,38 +1108,38 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Emit_a_UTF_8_Byte_Order_Mark_BOM_in_the_beginning_of_output_files, + category: Diagnostics.Emit, + description: Diagnostics.Emit_a_UTF_8_Byte_Order_Mark_BOM_in_the_beginning_of_output_files, defaultValueDescription: false, }, { name: "newLine", - type: new ts.Map(ts.getEntries({ - crlf: ts.NewLineKind.CarriageReturnLineFeed, - lf: ts.NewLineKind.LineFeed + type: new Map(getEntries({ + crlf: NewLineKind.CarriageReturnLineFeed, + lf: NewLineKind.LineFeed })), affectsEmit: true, affectsBuildInfo: true, - paramType: ts.Diagnostics.NEWLINE, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Set_the_newline_character_for_emitting_files, - defaultValueDescription: ts.Diagnostics.Platform_specific + paramType: Diagnostics.NEWLINE, + category: Diagnostics.Emit, + description: Diagnostics.Set_the_newline_character_for_emitting_files, + defaultValueDescription: Diagnostics.Platform_specific }, { name: "noErrorTruncation", type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Output_Formatting, - description: ts.Diagnostics.Disable_truncating_types_in_error_messages, + category: Diagnostics.Output_Formatting, + description: Diagnostics.Disable_truncating_types_in_error_messages, defaultValueDescription: false, }, { name: "noLib", type: "boolean", - category: ts.Diagnostics.Language_and_Environment, + category: Diagnostics.Language_and_Environment, affectsProgramStructure: true, - description: ts.Diagnostics.Disable_including_any_library_files_including_the_default_lib_d_ts, + description: Diagnostics.Disable_including_any_library_files_including_the_default_lib_d_ts, // We are not returning a sourceFile for lib file when asked by the program, // so pass --noLib to avoid reporting a file not found error. transpileOptionValue: true, @@ -1128,8 +1149,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "noResolve", type: "boolean", affectsModuleResolution: true, - category: ts.Diagnostics.Modules, - description: ts.Diagnostics.Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project, + category: Diagnostics.Modules, + description: Diagnostics.Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project, // We are not doing a full typecheck, we are not resolving the whole context, // so pass --noResolve to avoid reporting missing file errors. transpileOptionValue: true, @@ -1140,40 +1161,40 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Disable_emitting_declarations_that_have_internal_in_their_JSDoc_comments, + category: Diagnostics.Emit, + description: Diagnostics.Disable_emitting_declarations_that_have_internal_in_their_JSDoc_comments, defaultValueDescription: false, }, { name: "disableSizeLimit", type: "boolean", affectsProgramStructure: true, - category: ts.Diagnostics.Editor_Support, - description: ts.Diagnostics.Remove_the_20mb_cap_on_total_source_code_size_for_JavaScript_files_in_the_TypeScript_language_server, + category: Diagnostics.Editor_Support, + description: Diagnostics.Remove_the_20mb_cap_on_total_source_code_size_for_JavaScript_files_in_the_TypeScript_language_server, defaultValueDescription: false, }, { name: "disableSourceOfProjectReferenceRedirect", type: "boolean", isTSConfigOnly: true, - category: ts.Diagnostics.Projects, - description: ts.Diagnostics.Disable_preferring_source_files_instead_of_declaration_files_when_referencing_composite_projects, + category: Diagnostics.Projects, + description: Diagnostics.Disable_preferring_source_files_instead_of_declaration_files_when_referencing_composite_projects, defaultValueDescription: false, }, { name: "disableSolutionSearching", type: "boolean", isTSConfigOnly: true, - category: ts.Diagnostics.Projects, - description: ts.Diagnostics.Opt_a_project_out_of_multi_project_reference_checking_when_editing, + category: Diagnostics.Projects, + description: Diagnostics.Opt_a_project_out_of_multi_project_reference_checking_when_editing, defaultValueDescription: false, }, { name: "disableReferencedProjectLoad", type: "boolean", isTSConfigOnly: true, - category: ts.Diagnostics.Projects, - description: ts.Diagnostics.Reduce_the_number_of_projects_loaded_automatically_by_TypeScript, + category: Diagnostics.Projects, + description: Diagnostics.Reduce_the_number_of_projects_loaded_automatically_by_TypeScript, defaultValueDescription: false, }, { @@ -1181,8 +1202,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Disable_adding_use_strict_directives_in_emitted_JavaScript_files, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Disable_adding_use_strict_directives_in_emitted_JavaScript_files, defaultValueDescription: false, }, { @@ -1190,8 +1211,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Disable_generating_custom_helper_functions_like_extends_in_compiled_output, + category: Diagnostics.Emit, + description: Diagnostics.Disable_generating_custom_helper_functions_like_extends_in_compiled_output, defaultValueDescription: false, }, { @@ -1199,9 +1220,9 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, + category: Diagnostics.Emit, transpileOptionValue: undefined, - description: ts.Diagnostics.Disable_emitting_files_if_any_type_checking_errors_are_reported, + description: Diagnostics.Disable_emitting_files_if_any_type_checking_errors_are_reported, defaultValueDescription: false, }, { @@ -1209,8 +1230,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Disable_erasing_const_enum_declarations_in_generated_code, + category: Diagnostics.Emit, + description: Diagnostics.Disable_erasing_const_enum_declarations_in_generated_code, defaultValueDescription: false, }, { @@ -1220,18 +1241,18 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBuildInfo: true, affectsDeclarationPath: true, isFilePath: true, - paramType: ts.Diagnostics.DIRECTORY, - category: ts.Diagnostics.Emit, + paramType: Diagnostics.DIRECTORY, + category: Diagnostics.Emit, transpileOptionValue: undefined, - description: ts.Diagnostics.Specify_the_output_directory_for_generated_declaration_files, + description: Diagnostics.Specify_the_output_directory_for_generated_declaration_files, }, { name: "skipLibCheck", type: "boolean", // We need to store these to determine whether `lib` files need to be rechecked affectsBuildInfo: true, - category: ts.Diagnostics.Completeness, - description: ts.Diagnostics.Skip_type_checking_all_d_ts_files, + category: Diagnostics.Completeness, + description: Diagnostics.Skip_type_checking_all_d_ts_files, defaultValueDescription: false, }, { @@ -1240,8 +1261,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Disable_error_reporting_for_unused_labels, + category: Diagnostics.Type_Checking, + description: Diagnostics.Disable_error_reporting_for_unused_labels, defaultValueDescription: undefined, }, { @@ -1250,8 +1271,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsBindDiagnostics: true, affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Type_Checking, - description: ts.Diagnostics.Disable_error_reporting_for_unreachable_code, + category: Diagnostics.Type_Checking, + description: Diagnostics.Disable_error_reporting_for_unreachable_code, defaultValueDescription: undefined, }, { @@ -1259,8 +1280,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Disable_reporting_of_excess_property_errors_during_the_creation_of_object_literals, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Disable_reporting_of_excess_property_errors_during_the_creation_of_object_literals, defaultValueDescription: false, }, { @@ -1268,24 +1289,24 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Suppress_noImplicitAny_errors_when_indexing_objects_that_lack_index_signatures, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Suppress_noImplicitAny_errors_when_indexing_objects_that_lack_index_signatures, defaultValueDescription: false, }, { name: "forceConsistentCasingInFileNames", type: "boolean", affectsModuleResolution: true, - category: ts.Diagnostics.Interop_Constraints, - description: ts.Diagnostics.Ensure_that_casing_is_correct_in_imports, + category: Diagnostics.Interop_Constraints, + description: Diagnostics.Ensure_that_casing_is_correct_in_imports, defaultValueDescription: false, }, { name: "maxNodeModuleJsDepth", type: "number", affectsModuleResolution: true, - category: ts.Diagnostics.JavaScript_Support, - description: ts.Diagnostics.Specify_the_maximum_folder_depth_used_for_checking_JavaScript_files_from_node_modules_Only_applicable_with_allowJs, + category: Diagnostics.JavaScript_Support, + description: Diagnostics.Specify_the_maximum_folder_depth_used_for_checking_JavaScript_files_from_node_modules_Only_applicable_with_allowJs, defaultValueDescription: 0, }, { @@ -1293,8 +1314,8 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ type: "boolean", affectsSemanticDiagnostics: true, affectsBuildInfo: true, - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types, defaultValueDescription: false, }, { @@ -1303,25 +1324,25 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ affectsSemanticDiagnostics: true, affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Language_and_Environment, - description: ts.Diagnostics.Emit_ECMAScript_standard_compliant_class_fields, - defaultValueDescription: ts.Diagnostics.true_for_ES2022_and_above_including_ESNext + category: Diagnostics.Language_and_Environment, + description: Diagnostics.Emit_ECMAScript_standard_compliant_class_fields, + defaultValueDescription: Diagnostics.true_for_ES2022_and_above_including_ESNext }, { name: "preserveValueImports", type: "boolean", affectsEmit: true, affectsBuildInfo: true, - category: ts.Diagnostics.Emit, - description: ts.Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed, + category: Diagnostics.Emit, + description: Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed, defaultValueDescription: false, }, { name: "keyofStringsOnly", type: "boolean", - category: ts.Diagnostics.Backwards_Compatibility, - description: ts.Diagnostics.Make_keyof_only_return_strings_instead_of_string_numbers_or_symbols_Legacy_option, + category: Diagnostics.Backwards_Compatibility, + description: Diagnostics.Make_keyof_only_return_strings_instead_of_string_numbers_or_symbols_Legacy_option, defaultValueDescription: false, }, { @@ -1333,102 +1354,102 @@ const commandOptionsWithoutBuild: ts.CommandLineOption[] = [ name: "plugin", type: "object" }, - description: ts.Diagnostics.Specify_a_list_of_language_service_plugins_to_include, - category: ts.Diagnostics.Editor_Support, + description: Diagnostics.Specify_a_list_of_language_service_plugins_to_include, + category: Diagnostics.Editor_Support, }, { name: "moduleDetection", - type: new ts.Map(ts.getEntries({ - auto: ts.ModuleDetectionKind.Auto, - legacy: ts.ModuleDetectionKind.Legacy, - force: ts.ModuleDetectionKind.Force, + type: new Map(getEntries({ + auto: ModuleDetectionKind.Auto, + legacy: ModuleDetectionKind.Legacy, + force: ModuleDetectionKind.Force, })), affectsModuleResolution: true, - description: ts.Diagnostics.Control_what_method_is_used_to_detect_module_format_JS_files, - category: ts.Diagnostics.Language_and_Environment, - defaultValueDescription: ts.Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules, + description: Diagnostics.Control_what_method_is_used_to_detect_module_format_JS_files, + category: Diagnostics.Language_and_Environment, + defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules, } ]; /* @internal */ -export const optionDeclarations: ts.CommandLineOption[] = [ +export const optionDeclarations: CommandLineOption[] = [ ...commonOptionsWithBuild, ...commandOptionsWithoutBuild, ]; /* @internal */ -export const semanticDiagnosticsOptionDeclarations: readonly ts.CommandLineOption[] = +export const semanticDiagnosticsOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics); /* @internal */ -export const affectsEmitOptionDeclarations: readonly ts.CommandLineOption[] = +export const affectsEmitOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsEmit); /* @internal */ -export const affectsDeclarationPathOptionDeclarations: readonly ts.CommandLineOption[] = +export const affectsDeclarationPathOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsDeclarationPath); /* @internal */ -export const moduleResolutionOptionDeclarations: readonly ts.CommandLineOption[] = +export const moduleResolutionOptionDeclarations: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsModuleResolution); /* @internal */ -export const sourceFileAffectingCompilerOptions: readonly ts.CommandLineOption[] = optionDeclarations.filter(option => +export const sourceFileAffectingCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics); /* @internal */ -export const optionsAffectingProgramStructure: readonly ts.CommandLineOption[] = +export const optionsAffectingProgramStructure: readonly CommandLineOption[] = optionDeclarations.filter(option => !!option.affectsProgramStructure); /* @internal */ -export const transpileOptionValueCompilerOptions: readonly ts.CommandLineOption[] = optionDeclarations.filter(option => - ts.hasProperty(option, "transpileOptionValue")); +export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => + hasProperty(option, "transpileOptionValue")); // Build related options /* @internal */ -export const optionsForBuild: ts.CommandLineOption[] = [ +export const optionsForBuild: CommandLineOption[] = [ { name: "verbose", shortName: "v", - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Enable_verbose_logging, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Enable_verbose_logging, type: "boolean", defaultValueDescription: false, }, { name: "dry", shortName: "d", - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean, type: "boolean", defaultValueDescription: false, }, { name: "force", shortName: "f", - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date, type: "boolean", defaultValueDescription: false, }, { name: "clean", - category: ts.Diagnostics.Command_line_Options, - description: ts.Diagnostics.Delete_the_outputs_of_all_projects, + category: Diagnostics.Command_line_Options, + description: Diagnostics.Delete_the_outputs_of_all_projects, type: "boolean", defaultValueDescription: false, } ]; /* @internal */ -export const buildOpts: ts.CommandLineOption[] = [ +export const buildOpts: CommandLineOption[] = [ ...commonOptionsWithBuild, ...optionsForBuild ]; /* @internal */ -export const typeAcquisitionDeclarations: ts.CommandLineOption[] = [ +export const typeAcquisitionDeclarations: CommandLineOption[] = [ { /* @deprecated typingOptions.enableAutoDiscovery * Use typeAcquisition.enable instead. @@ -1467,15 +1488,15 @@ export const typeAcquisitionDeclarations: ts.CommandLineOption[] = [ /* @internal */ export interface OptionsNameMap { - optionsNameMap: ts.ESMap; - shortOptionNames: ts.ESMap; + optionsNameMap: ESMap; + shortOptionNames: ESMap; } /*@internal*/ -export function createOptionNameMap(optionDeclarations: readonly ts.CommandLineOption[]): OptionsNameMap { - const optionsNameMap = new ts.Map(); - const shortOptionNames = new ts.Map(); - ts.forEach(optionDeclarations, option => { +export function createOptionNameMap(optionDeclarations: readonly CommandLineOption[]): OptionsNameMap { + const optionsNameMap = new Map(); + const shortOptionNames = new Map(); + forEach(optionDeclarations, option => { optionsNameMap.set(option.name.toLowerCase(), option); if (option.shortName) { shortOptionNames.set(option.shortName, option.name); @@ -1492,15 +1513,15 @@ export function getOptionsNameMap(): OptionsNameMap { return optionsNameMapCache ||= createOptionNameMap(optionDeclarations); } -const compilerOptionsAlternateMode: ts.AlternateModeDiagnostics = { - diagnostic: ts.Diagnostics.Compiler_option_0_may_only_be_used_with_build, +const compilerOptionsAlternateMode: AlternateModeDiagnostics = { + diagnostic: Diagnostics.Compiler_option_0_may_only_be_used_with_build, getOptionsNameMap: getBuildOptionsNameMap }; /* @internal */ -export const defaultInitCompilerOptions: ts.CompilerOptions = { - module: ts.ModuleKind.CommonJS, - target: ts.ScriptTarget.ES2016, +export const defaultInitCompilerOptions: CompilerOptions = { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES2016, strict: true, esModuleInterop: true, forceConsistentCasingInFileNames: true, @@ -1508,7 +1529,7 @@ export const defaultInitCompilerOptions: ts.CompilerOptions = { }; /* @internal */ -export function convertEnableAutoDiscoveryToEnable(typeAcquisition: ts.TypeAcquisition): ts.TypeAcquisition { +export function convertEnableAutoDiscoveryToEnable(typeAcquisition: TypeAcquisition): TypeAcquisition { // Convert deprecated typingOptions.enableAutoDiscovery to typeAcquisition.enable if (typeAcquisition && typeAcquisition.enableAutoDiscovery !== undefined && typeAcquisition.enable === undefined) { return { @@ -1521,24 +1542,24 @@ export function convertEnableAutoDiscoveryToEnable(typeAcquisition: ts.TypeAcqui } /* @internal */ -export function createCompilerDiagnosticForInvalidCustomType(opt: ts.CommandLineOptionOfCustomType): ts.Diagnostic { - return createDiagnosticForInvalidCustomType(opt, ts.createCompilerDiagnostic); +export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic { + return createDiagnosticForInvalidCustomType(opt, createCompilerDiagnostic); } -function createDiagnosticForInvalidCustomType(opt: ts.CommandLineOptionOfCustomType, createDiagnostic: (message: ts.DiagnosticMessage, arg0: string, arg1: string) => ts.Diagnostic): ts.Diagnostic { - const namesOfType = ts.arrayFrom(opt.type.keys()).map(key => `'${key}'`).join(", "); - return createDiagnostic(ts.Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType); +function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic { + const namesOfType = arrayFrom(opt.type.keys()).map(key => `'${key}'`).join(", "); + return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType); } /* @internal */ -export function parseCustomTypeOption(opt: ts.CommandLineOptionOfCustomType, value: string, errors: ts.Push) { - return convertJsonOptionOfCustomType(opt, ts.trimString(value || ""), errors); +export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Push) { + return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors); } /* @internal */ -export function parseListTypeOption(opt: ts.CommandLineOptionOfListType, value = "", errors: ts.Push): (string | number)[] | undefined { - value = ts.trimString(value); - if (ts.startsWith(value, "-")) { +export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "", errors: Push): (string | number)[] | undefined { + value = trimString(value); + if (startsWith(value, "-")) { return undefined; } if (value === "") { @@ -1547,40 +1568,40 @@ export function parseListTypeOption(opt: ts.CommandLineOptionOfListType, value = const values = value.split(","); switch (opt.element.type) { case "number": - return ts.mapDefined(values, v => validateJsonOptionValue(opt.element, parseInt(v), errors)); + return mapDefined(values, v => validateJsonOptionValue(opt.element, parseInt(v), errors)); case "string": - return ts.mapDefined(values, v => validateJsonOptionValue(opt.element, v || "", errors)); + return mapDefined(values, v => validateJsonOptionValue(opt.element, v || "", errors)); default: - return ts.mapDefined(values, v => parseCustomTypeOption(opt.element as ts.CommandLineOptionOfCustomType, v, errors)); + return mapDefined(values, v => parseCustomTypeOption(opt.element as CommandLineOptionOfCustomType, v, errors)); } } /*@internal*/ export interface OptionsBase { - [option: string]: ts.CompilerOptionsValue | ts.TsConfigSourceFile | undefined; + [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined; } /*@internal*/ -export interface ParseCommandLineWorkerDiagnostics extends ts.DidYouMeanOptionsDiagnostics { +export interface ParseCommandLineWorkerDiagnostics extends DidYouMeanOptionsDiagnostics { getOptionsNameMap: () => OptionsNameMap; - optionTypeMismatchDiagnostic: ts.DiagnosticMessage; + optionTypeMismatchDiagnostic: DiagnosticMessage; } -function getOptionName(option: ts.CommandLineOption) { +function getOptionName(option: CommandLineOption) { return option.name; } function createUnknownOptionError( unknownOption: string, - diagnostics: ts.DidYouMeanOptionsDiagnostics, - createDiagnostics: (message: ts.DiagnosticMessage, arg0: string, arg1?: string) => ts.Diagnostic, + diagnostics: DidYouMeanOptionsDiagnostics, + createDiagnostics: (message: DiagnosticMessage, arg0: string, arg1?: string) => Diagnostic, unknownOptionErrorText?: string ) { if (diagnostics.alternateMode?.getOptionsNameMap().optionsNameMap.has(unknownOption.toLowerCase())) { return createDiagnostics(diagnostics.alternateMode.diagnostic, unknownOption); } - const possibleOption = ts.getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName); + const possibleOption = getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName); return possibleOption ? createDiagnostics(diagnostics.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) : createDiagnostics(diagnostics.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption); @@ -1592,9 +1613,9 @@ export function parseCommandLineWorker( commandLine: readonly string[], readFile?: (path: string) => string | undefined) { const options = {} as OptionsBase; - let watchOptions: ts.WatchOptions | undefined; + let watchOptions: WatchOptions | undefined; const fileNames: string[] = []; - const errors: ts.Diagnostic[] = []; + const errors: Diagnostic[] = []; parseStrings(commandLine); return { @@ -1609,11 +1630,11 @@ export function parseCommandLineWorker( while (i < args.length) { const s = args[i]; i++; - if (s.charCodeAt(0) === ts.CharacterCodes.at) { + if (s.charCodeAt(0) === CharacterCodes.at) { parseResponseFile(s.slice(1)); } - else if (s.charCodeAt(0) === ts.CharacterCodes.minus) { - const inputOptionName = s.slice(s.charCodeAt(1) === ts.CharacterCodes.minus ? 2 : 1); + else if (s.charCodeAt(0) === CharacterCodes.minus) { + const inputOptionName = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1); const opt = getOptionDeclarationFromName(diagnostics.getOptionsNameMap, inputOptionName, /*allowShort*/ true); if (opt) { i = parseOptionValue(args, i, diagnostics, opt, options, errors); @@ -1624,7 +1645,7 @@ export function parseCommandLineWorker( i = parseOptionValue(args, i, watchOptionsDidYouMeanDiagnostics, watchOpt, watchOptions || (watchOptions = {}), errors); } else { - errors.push(createUnknownOptionError(inputOptionName, diagnostics, ts.createCompilerDiagnostic, s)); + errors.push(createUnknownOptionError(inputOptionName, diagnostics, createCompilerDiagnostic, s)); } } } @@ -1635,8 +1656,8 @@ export function parseCommandLineWorker( } function parseResponseFile(fileName: string) { - const text = tryReadFile(fileName, readFile || (fileName => ts.sys.readFile(fileName))); - if (!ts.isString(text)) { + const text = tryReadFile(fileName, readFile || (fileName => sys.readFile(fileName))); + if (!isString(text)) { errors.push(text); return; } @@ -1644,22 +1665,22 @@ export function parseCommandLineWorker( const args: string[] = []; let pos = 0; while (true) { - while (pos < text.length && text.charCodeAt(pos) <= ts.CharacterCodes.space) pos++; + while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++; if (pos >= text.length) break; const start = pos; - if (text.charCodeAt(start) === ts.CharacterCodes.doubleQuote) { + if (text.charCodeAt(start) === CharacterCodes.doubleQuote) { pos++; - while (pos < text.length && text.charCodeAt(pos) !== ts.CharacterCodes.doubleQuote) pos++; + while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++; if (pos < text.length) { args.push(text.substring(start + 1, pos)); pos++; } else { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName)); + errors.push(createCompilerDiagnostic(Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName)); } } else { - while (text.charCodeAt(pos) > ts.CharacterCodes.space) pos++; + while (text.charCodeAt(pos) > CharacterCodes.space) pos++; args.push(text.substring(start, pos)); } } @@ -1671,9 +1692,9 @@ function parseOptionValue( args: readonly string[], i: number, diagnostics: ParseCommandLineWorkerDiagnostics, - opt: ts.CommandLineOption, + opt: CommandLineOption, options: OptionsBase, - errors: ts.Diagnostic[] + errors: Diagnostic[] ) { if (opt.isTSConfigOnly) { const optValue = args[i]; @@ -1688,18 +1709,18 @@ function parseOptionValue( } else { if (optValue === "true") i++; - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line, opt.name)); + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line, opt.name)); } } else { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, opt.name)); - if (optValue && !ts.startsWith(optValue, "-")) i++; + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, opt.name)); + if (optValue && !startsWith(optValue, "-")) i++; } } 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(ts.createCompilerDiagnostic(diagnostics.optionTypeMismatchDiagnostic, opt.name, getCompilerOptionValueTypeString(opt))); + errors.push(createCompilerDiagnostic(diagnostics.optionTypeMismatchDiagnostic, opt.name, getCompilerOptionValueTypeString(opt))); } if (args[i] !== "null") { @@ -1730,7 +1751,7 @@ function parseOptionValue( break; // If not a primitive, the possible types are specified in what is effectively a map of options. default: - options[opt.name] = parseCustomTypeOption(opt as ts.CommandLineOptionOfCustomType, args[i], errors); + options[opt.name] = parseCustomTypeOption(opt as CommandLineOptionOfCustomType, args[i], errors); i++; break; } @@ -1748,20 +1769,20 @@ export const compilerOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnos alternateMode: compilerOptionsAlternateMode, getOptionsNameMap, optionDeclarations, - unknownOptionDiagnostic: ts.Diagnostics.Unknown_compiler_option_0, - unknownDidYouMeanDiagnostic: ts.Diagnostics.Unknown_compiler_option_0_Did_you_mean_1, - optionTypeMismatchDiagnostic: ts.Diagnostics.Compiler_option_0_expects_an_argument + unknownOptionDiagnostic: Diagnostics.Unknown_compiler_option_0, + unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1, + optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument }; -export function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ts.ParsedCommandLine { +export function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ParsedCommandLine { return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile); } /** @internal */ -export function getOptionFromName(optionName: string, allowShort?: boolean): ts.CommandLineOption | undefined { +export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined { return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort); } -function getOptionDeclarationFromName(getOptionNameMap: () => OptionsNameMap, optionName: string, allowShort = false): ts.CommandLineOption | undefined { +function getOptionDeclarationFromName(getOptionNameMap: () => OptionsNameMap, optionName: string, allowShort = false): CommandLineOption | undefined { optionName = optionName.toLowerCase(); const { optionsNameMap, shortOptionNames } = getOptionNameMap(); // Try to translate short option names to their full equivalents. @@ -1776,10 +1797,10 @@ function getOptionDeclarationFromName(getOptionNameMap: () => OptionsNameMap, op /*@internal*/ export interface ParsedBuildCommand { - buildOptions: ts.BuildOptions; - watchOptions: ts.WatchOptions | undefined; + buildOptions: BuildOptions; + watchOptions: WatchOptions | undefined; projects: string[]; - errors: ts.Diagnostic[]; + errors: Diagnostic[]; } let buildOptionsNameMapCache: OptionsNameMap; @@ -1787,8 +1808,8 @@ function getBuildOptionsNameMap(): OptionsNameMap { return buildOptionsNameMapCache || (buildOptionsNameMapCache = createOptionNameMap(buildOpts)); } -const buildOptionsAlternateMode: ts.AlternateModeDiagnostics = { - diagnostic: ts.Diagnostics.Compiler_option_0_may_not_be_used_with_build, +const buildOptionsAlternateMode: AlternateModeDiagnostics = { + diagnostic: Diagnostics.Compiler_option_0_may_not_be_used_with_build, getOptionsNameMap }; @@ -1796,9 +1817,9 @@ const buildOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = { alternateMode: buildOptionsAlternateMode, getOptionsNameMap: getBuildOptionsNameMap, optionDeclarations: buildOpts, - unknownOptionDiagnostic: ts.Diagnostics.Unknown_build_option_0, - unknownDidYouMeanDiagnostic: ts.Diagnostics.Unknown_build_option_0_Did_you_mean_1, - optionTypeMismatchDiagnostic: ts.Diagnostics.Build_option_0_requires_a_value_of_type_1 + unknownOptionDiagnostic: Diagnostics.Unknown_build_option_0, + unknownDidYouMeanDiagnostic: Diagnostics.Unknown_build_option_0_Did_you_mean_1, + optionTypeMismatchDiagnostic: Diagnostics.Build_option_0_requires_a_value_of_type_1 }; /*@internal*/ @@ -1807,7 +1828,7 @@ export function parseBuildCommand(args: readonly string[]): ParsedBuildCommand { buildOptionsDidYouMeanDiagnostics, args ); - const buildOptions = options as ts.BuildOptions; + const buildOptions = options as BuildOptions; if (projects.length === 0) { // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ." @@ -1816,28 +1837,28 @@ export function parseBuildCommand(args: readonly string[]): ParsedBuildCommand { // Nonsensical combinations if (buildOptions.clean && buildOptions.force) { - errors.push(ts.createCompilerDiagnostic(ts.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.push(ts.createCompilerDiagnostic(ts.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.push(ts.createCompilerDiagnostic(ts.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.push(ts.createCompilerDiagnostic(ts.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, watchOptions, projects, errors }; } /* @internal */ -export function getDiagnosticText(_message: ts.DiagnosticMessage, ..._args: any[]): string { - const diagnostic = ts.createCompilerDiagnostic.apply(undefined, arguments); +export function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string { + const diagnostic = createCompilerDiagnostic.apply(undefined, arguments); return diagnostic.messageText as string; } -export type DiagnosticReporter = (diagnostic: ts.Diagnostic) => void; +export type DiagnosticReporter = (diagnostic: Diagnostic) => void; /** * Reports config file diagnostics */ @@ -1851,7 +1872,7 @@ export interface ConfigFileDiagnosticsReporter { /** * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors */ -export interface ParseConfigFileHost extends ts.ParseConfigHost, ConfigFileDiagnosticsReporter { +export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter { getCurrentDirectory(): string; } @@ -1860,29 +1881,29 @@ export interface ParseConfigFileHost extends ts.ParseConfigHost, ConfigFileDiagn */ export function getParsedCommandLineOfConfigFile( configFileName: string, - optionsToExtend: ts.CompilerOptions | undefined, + optionsToExtend: CompilerOptions | undefined, host: ParseConfigFileHost, - extendedConfigCache?: ts.Map, - watchOptionsToExtend?: ts.WatchOptions, - extraFileExtensions?: readonly ts.FileExtensionInfo[], -): ts.ParsedCommandLine | undefined { + extendedConfigCache?: Map, + watchOptionsToExtend?: WatchOptions, + extraFileExtensions?: readonly FileExtensionInfo[], +): ParsedCommandLine | undefined { const configFileText = tryReadFile(configFileName, fileName => host.readFile(fileName)); - if (!ts.isString(configFileText)) { + if (!isString(configFileText)) { host.onUnRecoverableConfigFileDiagnostic(configFileText); return undefined; } - const result = ts.parseJsonText(configFileName, configFileText); + const result = parseJsonText(configFileName, configFileText); const cwd = host.getCurrentDirectory(); - result.path = ts.toPath(configFileName, cwd, ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames)); + result.path = toPath(configFileName, cwd, createGetCanonicalFileName(host.useCaseSensitiveFileNames)); result.resolvedPath = result.path; result.originalFileName = result.fileName; return parseJsonSourceFileConfigFileContent( result, host, - ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), cwd), + getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd), optionsToExtend, - ts.getNormalizedAbsolutePath(configFileName, cwd), + getNormalizedAbsolutePath(configFileName, cwd), /*resolutionStack*/ undefined, extraFileExtensions, extendedConfigCache, @@ -1894,9 +1915,9 @@ export function getParsedCommandLineOfConfigFile( * Read tsconfig.json file * @param fileName The path to the config file */ -export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: ts.Diagnostic } { +export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic } { const textOrDiagnostic = tryReadFile(fileName, readFile); - return ts.isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; + return isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic }; } /** @@ -1904,8 +1925,8 @@ export function readConfigFile(fileName: string, readFile: (path: string) => str * @param fileName The path to the config file * @param jsonText The text of the config file */ -export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: ts.Diagnostic } { - const jsonSourceFile = ts.parseJsonText(fileName, jsonText); +export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } { + const jsonSourceFile = parseJsonText(fileName, jsonText); return { config: convertConfigFileToObject(jsonSourceFile, jsonSourceFile.parseDiagnostics, /*reportOptionsErrors*/ false, /*optionsIterator*/ undefined), error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined @@ -1916,31 +1937,31 @@ export function parseConfigFileTextToJson(fileName: string, jsonText: string): { * Read tsconfig.json file * @param fileName The path to the config file */ -export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): ts.TsConfigSourceFile { +export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): TsConfigSourceFile { const textOrDiagnostic = tryReadFile(fileName, readFile); - return ts.isString(textOrDiagnostic) ? ts.parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] } as ts.TsConfigSourceFile; + return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] } as TsConfigSourceFile; } /*@internal*/ -export function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | ts.Diagnostic { +export function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic { let text: string | undefined; try { text = readFile(fileName); } catch (e) { - return ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message); + return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message); } - return text === undefined ? ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_read_file_0, fileName) : text; + return text === undefined ? createCompilerDiagnostic(Diagnostics.Cannot_read_file_0, fileName) : text; } -function commandLineOptionsToMap(options: readonly ts.CommandLineOption[]) { - return ts.arrayToMap(options, getOptionName); +function commandLineOptionsToMap(options: readonly CommandLineOption[]) { + return arrayToMap(options, getOptionName); } -const typeAcquisitionDidYouMeanDiagnostics: ts.DidYouMeanOptionsDiagnostics = { +const typeAcquisitionDidYouMeanDiagnostics: DidYouMeanOptionsDiagnostics = { optionDeclarations: typeAcquisitionDeclarations, - unknownOptionDiagnostic: ts.Diagnostics.Unknown_type_acquisition_option_0, - unknownDidYouMeanDiagnostic: ts.Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1, + unknownOptionDiagnostic: Diagnostics.Unknown_type_acquisition_option_0, + unknownDidYouMeanDiagnostic: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1, }; let watchOptionsNameMapCache: OptionsNameMap; @@ -1950,25 +1971,25 @@ function getWatchOptionsNameMap(): OptionsNameMap { const watchOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = { getOptionsNameMap: getWatchOptionsNameMap, optionDeclarations: optionsForWatch, - unknownOptionDiagnostic: ts.Diagnostics.Unknown_watch_option_0, - unknownDidYouMeanDiagnostic: ts.Diagnostics.Unknown_watch_option_0_Did_you_mean_1, - optionTypeMismatchDiagnostic: ts.Diagnostics.Watch_option_0_requires_a_value_of_type_1 + unknownOptionDiagnostic: Diagnostics.Unknown_watch_option_0, + unknownDidYouMeanDiagnostic: Diagnostics.Unknown_watch_option_0_Did_you_mean_1, + optionTypeMismatchDiagnostic: Diagnostics.Watch_option_0_requires_a_value_of_type_1 }; -let commandLineCompilerOptionsMapCache: ts.ESMap; +let commandLineCompilerOptionsMapCache: ESMap; function getCommandLineCompilerOptionsMap() { return commandLineCompilerOptionsMapCache || (commandLineCompilerOptionsMapCache = commandLineOptionsToMap(optionDeclarations)); } -let commandLineWatchOptionsMapCache: ts.ESMap; +let commandLineWatchOptionsMapCache: ESMap; function getCommandLineWatchOptionsMap() { return commandLineWatchOptionsMapCache || (commandLineWatchOptionsMapCache = commandLineOptionsToMap(optionsForWatch)); } -let commandLineTypeAcquisitionMapCache: ts.ESMap; +let commandLineTypeAcquisitionMapCache: ESMap; function getCommandLineTypeAcquisitionMap() { return commandLineTypeAcquisitionMapCache || (commandLineTypeAcquisitionMapCache = commandLineOptionsToMap(typeAcquisitionDeclarations)); } -let _tsconfigRootOptions: ts.TsConfigOnlyOption; +let _tsconfigRootOptions: TsConfigOnlyOption; function getTsconfigRootOptionsMap() { if (_tsconfigRootOptions === undefined) { _tsconfigRootOptions = { @@ -2002,7 +2023,7 @@ function getTsconfigRootOptionsMap() { { name: "extends", type: "string", - category: ts.Diagnostics.File_Management, + category: Diagnostics.File_Management, }, { name: "references", @@ -2011,7 +2032,7 @@ function getTsconfigRootOptionsMap() { name: "references", type: "object" }, - category: ts.Diagnostics.Projects, + category: Diagnostics.Projects, }, { name: "files", @@ -2020,7 +2041,7 @@ function getTsconfigRootOptionsMap() { name: "files", type: "string" }, - category: ts.Diagnostics.File_Management, + category: Diagnostics.File_Management, }, { name: "include", @@ -2029,8 +2050,8 @@ function getTsconfigRootOptionsMap() { name: "include", type: "string" }, - category: ts.Diagnostics.File_Management, - defaultValueDescription: ts.Diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk + category: Diagnostics.File_Management, + defaultValueDescription: Diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk }, { name: "exclude", @@ -2039,8 +2060,8 @@ function getTsconfigRootOptionsMap() { name: "exclude", type: "string" }, - category: ts.Diagnostics.File_Management, - defaultValueDescription: ts.Diagnostics.node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified + category: Diagnostics.File_Management, + defaultValueDescription: Diagnostics.node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified }, compileOnSaveCommandLineOption ]) @@ -2059,7 +2080,7 @@ interface JsonConversionNotifier { * @param option option declaration which is being set with the value * @param value value of the option */ - onSetValidOptionKeyValueInParent(parentOption: string, option: ts.CommandLineOption, value: ts.CompilerOptionsValue): void; + onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue): void; /** * Notify when valid root key value option is being set * @param key option key @@ -2067,7 +2088,7 @@ interface JsonConversionNotifier { * @param value computed value of the key * @param ValueNode node corresponding to value in the source file */ - onSetValidOptionKeyValueInRoot(key: string, keyNode: ts.PropertyName, value: ts.CompilerOptionsValue, valueNode: ts.Expression): void; + onSetValidOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void; /** * Notify when unknown root key value option is being set * @param key option key @@ -2075,24 +2096,24 @@ interface JsonConversionNotifier { * @param value computed value of the key * @param ValueNode node corresponding to value in the source file */ - onSetUnknownOptionKeyValueInRoot(key: string, keyNode: ts.PropertyName, value: ts.CompilerOptionsValue, valueNode: ts.Expression): void; + onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void; } -function convertConfigFileToObject(sourceFile: ts.JsonSourceFile, errors: ts.Push, reportOptionsErrors: boolean, optionsIterator: JsonConversionNotifier | undefined): any { - const rootExpression: ts.Expression | undefined = sourceFile.statements[0]?.expression; +function convertConfigFileToObject(sourceFile: JsonSourceFile, errors: Push, reportOptionsErrors: boolean, optionsIterator: JsonConversionNotifier | undefined): any { + const rootExpression: Expression | undefined = sourceFile.statements[0]?.expression; const knownRootOptions = reportOptionsErrors ? getTsconfigRootOptionsMap() : undefined; - if (rootExpression && rootExpression.kind !== ts.SyntaxKind.ObjectLiteralExpression) { - errors.push(ts.createDiagnosticForNodeInSourceFile( + if (rootExpression && rootExpression.kind !== SyntaxKind.ObjectLiteralExpression) { + errors.push(createDiagnosticForNodeInSourceFile( sourceFile, rootExpression, - ts.Diagnostics.The_root_value_of_a_0_file_must_be_an_object, - ts.getBaseFileName(sourceFile.fileName) === "jsconfig.json" ? "jsconfig.json" : "tsconfig.json" + Diagnostics.The_root_value_of_a_0_file_must_be_an_object, + getBaseFileName(sourceFile.fileName) === "jsconfig.json" ? "jsconfig.json" : "tsconfig.json" )); // Last-ditch error recovery. Somewhat useful because the JSON parser will recover from some parse errors by // synthesizing a top-level array literal expression. There's a reasonable chance the first element of that // array is a well-formed configuration object, made into an array element by stray characters. - if (ts.isArrayLiteralExpression(rootExpression)) { - const firstObject = ts.find(rootExpression.elements, ts.isObjectLiteralExpression); + if (isArrayLiteralExpression(rootExpression)) { + const firstObject = find(rootExpression.elements, isObjectLiteralExpression); if (firstObject) { return convertToObjectWorker(sourceFile, firstObject, errors, /*returnValue*/ true, knownRootOptions, optionsIterator); } @@ -2105,7 +2126,7 @@ function convertConfigFileToObject(sourceFile: ts.JsonSourceFile, errors: ts.Pus /** * Convert the json syntax tree into the json value */ -export function convertToObject(sourceFile: ts.JsonSourceFile, errors: ts.Push): any { +export function convertToObject(sourceFile: JsonSourceFile, errors: Push): any { return convertToObjectWorker(sourceFile, sourceFile.statements[0]?.expression, errors, /*returnValue*/ true, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); } @@ -2116,11 +2137,11 @@ export function convertToObject(sourceFile: ts.JsonSourceFile, errors: ts.Push, + sourceFile: JsonSourceFile, + rootExpression: Expression | undefined, + errors: Push, returnValue: boolean, - knownRootOptions: ts.CommandLineOption | undefined, + knownRootOptions: CommandLineOption | undefined, jsonConversionNotifier: JsonConversionNotifier | undefined): any { if (!rootExpression) { return returnValue ? {} : undefined; @@ -2128,43 +2149,43 @@ export function convertToObjectWorker( return convertPropertyValueToJson(rootExpression, knownRootOptions); - function isRootOptionMap(knownOptions: ts.ESMap | undefined) { - return knownRootOptions && (knownRootOptions as ts.TsConfigOnlyOption).elementOptions === knownOptions; + function isRootOptionMap(knownOptions: ESMap | undefined) { + return knownRootOptions && (knownRootOptions as TsConfigOnlyOption).elementOptions === knownOptions; } function convertObjectLiteralExpressionToJson( - node: ts.ObjectLiteralExpression, - knownOptions: ts.ESMap | undefined, - extraKeyDiagnostics: ts.DidYouMeanOptionsDiagnostics | undefined, + node: ObjectLiteralExpression, + knownOptions: ESMap | undefined, + extraKeyDiagnostics: DidYouMeanOptionsDiagnostics | undefined, parentOption: string | undefined ): any { const result: any = returnValue ? {} : undefined; for (const element of node.properties) { - if (element.kind !== ts.SyntaxKind.PropertyAssignment) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element, ts.Diagnostics.Property_assignment_expected)); + if (element.kind !== SyntaxKind.PropertyAssignment) { + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element, Diagnostics.Property_assignment_expected)); continue; } if (element.questionToken) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element.questionToken, ts.Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.questionToken, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); } if (!isDoubleQuotedString(element.name)) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element.name, ts.Diagnostics.String_literal_with_double_quotes_expected)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected)); } - const textOfKey = ts.isComputedNonLiteralName(element.name) ? undefined : ts.getTextOfPropertyName(element.name); - const keyText = textOfKey && ts.unescapeLeadingUnderscores(textOfKey); + const textOfKey = isComputedNonLiteralName(element.name) ? undefined : getTextOfPropertyName(element.name); + const keyText = textOfKey && unescapeLeadingUnderscores(textOfKey); const option = keyText && knownOptions ? knownOptions.get(keyText) : undefined; if (keyText && extraKeyDiagnostics && !option) { if (knownOptions) { errors.push(createUnknownOptionError( keyText, extraKeyDiagnostics, - (message, arg0, arg1) => ts.createDiagnosticForNodeInSourceFile(sourceFile, element.name, message, arg0, arg1) + (message, arg0, arg1) => createDiagnosticForNodeInSourceFile(sourceFile, element.name, message, arg0, arg1) )); } else { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnostics.unknownOptionDiagnostic, keyText)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnostics.unknownOptionDiagnostic, keyText)); } } const value = convertPropertyValueToJson(element.initializer, option); @@ -2200,8 +2221,8 @@ export function convertToObjectWorker( } function convertArrayLiteralExpressionToJson( - elements: ts.NodeArray, - elementOption: ts.CommandLineOption | undefined + elements: NodeArray, + elementOption: CommandLineOption | undefined ) { if (!returnValue) { elements.forEach(element => convertPropertyValueToJson(element, elementOption)); @@ -2209,38 +2230,38 @@ export function convertToObjectWorker( } // Filter out invalid values - return ts.filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined); + return filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined); } - function convertPropertyValueToJson(valueExpression: ts.Expression, option: ts.CommandLineOption | undefined): any { + function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any { let invalidReported: boolean | undefined; switch (valueExpression.kind) { - case ts.SyntaxKind.TrueKeyword: + case SyntaxKind.TrueKeyword: reportInvalidOptionValue(option && option.type !== "boolean"); return validateValue(/*value*/ true); - case ts.SyntaxKind.FalseKeyword: + case SyntaxKind.FalseKeyword: reportInvalidOptionValue(option && option.type !== "boolean"); return validateValue(/*value*/ false); - case ts.SyntaxKind.NullKeyword: + case SyntaxKind.NullKeyword: reportInvalidOptionValue(option && option.name === "extends"); // "extends" is the only option we don't allow null/undefined for return validateValue(/*value*/ null); // eslint-disable-line no-null/no-null - case ts.SyntaxKind.StringLiteral: + case SyntaxKind.StringLiteral: if (!isDoubleQuotedString(valueExpression)) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.String_literal_with_double_quotes_expected)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.String_literal_with_double_quotes_expected)); } - reportInvalidOptionValue(option && (ts.isString(option.type) && option.type !== "string")); - const text = (valueExpression as ts.StringLiteral).text; - if (option && !ts.isString(option.type)) { - const customOption = option as ts.CommandLineOptionOfCustomType; + reportInvalidOptionValue(option && (isString(option.type) && option.type !== "string")); + const text = (valueExpression as StringLiteral).text; + if (option && !isString(option.type)) { + const customOption = option as CommandLineOptionOfCustomType; // Validate custom option type if (!customOption.type.has(text.toLowerCase())) { errors.push( createDiagnosticForInvalidCustomType( customOption, - (message, arg0, arg1) => ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1) + (message, arg0, arg1) => createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1) ) ); invalidReported = true; @@ -2248,20 +2269,20 @@ export function convertToObjectWorker( } return validateValue(text); - case ts.SyntaxKind.NumericLiteral: + case SyntaxKind.NumericLiteral: reportInvalidOptionValue(option && option.type !== "number"); - return validateValue(Number((valueExpression as ts.NumericLiteral).text)); + return validateValue(Number((valueExpression as NumericLiteral).text)); - case ts.SyntaxKind.PrefixUnaryExpression: - if ((valueExpression as ts.PrefixUnaryExpression).operator !== ts.SyntaxKind.MinusToken || (valueExpression as ts.PrefixUnaryExpression).operand.kind !== ts.SyntaxKind.NumericLiteral) { + case SyntaxKind.PrefixUnaryExpression: + if ((valueExpression as PrefixUnaryExpression).operator !== SyntaxKind.MinusToken || (valueExpression as PrefixUnaryExpression).operand.kind !== SyntaxKind.NumericLiteral) { break; // not valid JSON syntax } reportInvalidOptionValue(option && option.type !== "number"); - return validateValue(-Number(((valueExpression as ts.PrefixUnaryExpression).operand as ts.NumericLiteral).text)); + return validateValue(-Number(((valueExpression as PrefixUnaryExpression).operand as NumericLiteral).text)); - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: reportInvalidOptionValue(option && option.type !== "object"); - const objectLiteralExpression = valueExpression as ts.ObjectLiteralExpression; + const objectLiteralExpression = valueExpression as ObjectLiteralExpression; // Currently having element option declaration in the tsconfig with type "object" // determines if it needs onSetValidOptionKeyValueInParent callback or not @@ -2270,7 +2291,7 @@ export function convertToObjectWorker( // vs what we set in the json // If need arises, we can modify this interface and callbacks as needed if (option) { - const { elementOptions, extraKeyDiagnostics, name: optionName } = option as ts.TsConfigOnlyOption; + const { elementOptions, extraKeyDiagnostics, name: optionName } = option as TsConfigOnlyOption; return validateValue(convertObjectLiteralExpressionToJson(objectLiteralExpression, elementOptions, extraKeyDiagnostics, optionName)); } @@ -2280,11 +2301,11 @@ export function convertToObjectWorker( /*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined)); } - case ts.SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: reportInvalidOptionValue(option && option.type !== "list"); return validateValue(convertArrayLiteralExpressionToJson( - (valueExpression as ts.ArrayLiteralExpression).elements, - option && (option as ts.CommandLineOptionOfListType).element)); + (valueExpression as ArrayLiteralExpression).elements, + option && (option as CommandLineOptionOfListType).element)); } // Not in expected format @@ -2292,16 +2313,16 @@ export function convertToObjectWorker( reportInvalidOptionValue(/*isError*/ true); } else { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal)); } return undefined; - function validateValue(value: ts.CompilerOptionsValue) { + function validateValue(value: CompilerOptionsValue) { if (!invalidReported) { const diagnostic = option?.extraValidation?.(value); if (diagnostic) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ...diagnostic)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ...diagnostic)); return undefined; } } @@ -2310,30 +2331,30 @@ export function convertToObjectWorker( function reportInvalidOptionValue(isError: boolean | undefined) { if (isError) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option!.name, getCompilerOptionValueTypeString(option!))); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option!.name, getCompilerOptionValueTypeString(option!))); invalidReported = true; } } } - function isDoubleQuotedString(node: ts.Node): boolean { - return ts.isStringLiteral(node) && ts.isStringDoubleQuoted(node, sourceFile); + function isDoubleQuotedString(node: Node): boolean { + return isStringLiteral(node) && isStringDoubleQuoted(node, sourceFile); } } -function getCompilerOptionValueTypeString(option: ts.CommandLineOption) { +function getCompilerOptionValueTypeString(option: CommandLineOption) { return option.type === "list" ? "Array" : - ts.isString(option.type) ? option.type : "string"; + isString(option.type) ? option.type : "string"; } -function isCompilerOptionsValue(option: ts.CommandLineOption | undefined, value: any): value is ts.CompilerOptionsValue { +function isCompilerOptionsValue(option: CommandLineOption | undefined, value: any): value is CompilerOptionsValue { if (option) { if (isNullOrUndefined(value)) return true; // All options are undefinable/nullable if (option.type === "list") { - return ts.isArray(value); + return isArray(value); } - const expectedType = ts.isString(option.type) ? option.type : "string"; + const expectedType = isString(option.type) ? option.type : "string"; return typeof value === expectedType; } return false; @@ -2341,12 +2362,12 @@ function isCompilerOptionsValue(option: ts.CommandLineOption | undefined, value: /** @internal */ export interface TSConfig { - compilerOptions: ts.CompilerOptions; + compilerOptions: CompilerOptions; compileOnSave: boolean | undefined; exclude?: readonly string[]; files: readonly string[] | undefined; include?: readonly string[]; - references: readonly ts.ProjectReference[] | undefined; + references: readonly ProjectReference[] | undefined; } /** @internal */ @@ -2362,21 +2383,21 @@ export interface ConvertToTSConfigHost { * @param host provides current directory and case sensitivity services */ /** @internal */ -export function convertToTSConfig(configParseResult: ts.ParsedCommandLine, configFileName: string, host: ConvertToTSConfigHost): TSConfig { - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames); - const files = ts.map( - ts.filter( +export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: ConvertToTSConfigHost): TSConfig { + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames); + const files = map( + filter( configParseResult.fileNames, - !configParseResult.options.configFile?.configFileSpecs?.validatedIncludeSpecs ? ts.returnTrue : matchesSpecs( + !configParseResult.options.configFile?.configFileSpecs?.validatedIncludeSpecs ? returnTrue : matchesSpecs( configFileName, configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs, configParseResult.options.configFile.configFileSpecs.validatedExcludeSpecs, host, ) ), - f => ts.getRelativePathFromFile(ts.getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), ts.getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName) + f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName) ); - const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: ts.getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames }); + const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames }); const watchOptionMap = configParseResult.watchOptions && serializeWatchOptions(configParseResult.watchOptions); const config = { compilerOptions: { @@ -2393,8 +2414,8 @@ export function convertToTSConfig(configParseResult: ts.ParsedCommandLine, confi version: undefined, }, watchOptions: watchOptionMap && optionMapToObject(watchOptionMap), - references: ts.map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined })), - files: ts.length(files) ? files : undefined, + references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined })), + files: length(files) ? files : undefined, ...(configParseResult.options.configFile?.configFileSpecs ? { include: filterSameAsDefaultInclude(configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs), exclude: configParseResult.options.configFile.configFileSpecs.validatedExcludeSpecs @@ -2405,24 +2426,24 @@ export function convertToTSConfig(configParseResult: ts.ParsedCommandLine, confi } /*@internal*/ -export function optionMapToObject(optionMap: ts.ESMap): object { +export function optionMapToObject(optionMap: ESMap): object { return { - ...ts.arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), + ...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), }; } function filterSameAsDefaultInclude(specs: readonly string[] | undefined) { - if (!ts.length(specs)) return undefined; - if (ts.length(specs) !== 1) return specs; + if (!length(specs)) return undefined; + if (length(specs) !== 1) return specs; if (specs![0] === defaultIncludeSpec) return undefined; return specs; } function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, excludeSpecs: readonly string[] | undefined, host: ConvertToTSConfigHost): (path: string) => boolean { - if (!includeSpecs) return ts.returnTrue; - const patterns = ts.getFileMatcherPatterns(path, excludeSpecs, includeSpecs, host.useCaseSensitiveFileNames, host.getCurrentDirectory()); - const excludeRe = patterns.excludePattern && ts.getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames); - const includeRe = patterns.includeFilePattern && ts.getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames); + if (!includeSpecs) return returnTrue; + const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, host.useCaseSensitiveFileNames, host.getCurrentDirectory()); + const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames); + const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames); if (includeRe) { if (excludeRe) { return path => !(includeRe.test(path) && !excludeRe.test(path)); @@ -2432,10 +2453,10 @@ function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, if (excludeRe) { return path => excludeRe.test(path); } - return ts.returnTrue; + return returnTrue; } -function getCustomTypeMapOfCommandLineOption(optionDefinition: ts.CommandLineOption): ts.ESMap | undefined { +function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): ESMap | undefined { if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean" || optionDefinition.type === "object") { // this is of a type CommandLineOptionOfPrimitiveType return undefined; @@ -2449,9 +2470,9 @@ function getCustomTypeMapOfCommandLineOption(optionDefinition: ts.CommandLineOpt } /* @internal */ -export function getNameOfCompilerOptionValue(value: ts.CompilerOptionsValue, customTypeMap: ts.ESMap): string | undefined { +export function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: ESMap): string | undefined { // There is a typeMap associated with this command-line option so use it to map value back to its name - return ts.forEachEntry(customTypeMap, (mapValue, key) => { + return forEachEntry(customTypeMap, (mapValue, key) => { if (mapValue === value) { return key; } @@ -2460,13 +2481,13 @@ export function getNameOfCompilerOptionValue(value: ts.CompilerOptionsValue, cus /* @internal */ export function serializeCompilerOptions( - options: ts.CompilerOptions, + options: CompilerOptions, pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean } -): ts.ESMap { +): ESMap { return serializeOptionBaseObject(options, getOptionsNameMap(), pathOptions); } -function serializeWatchOptions(options: ts.WatchOptions) { +function serializeWatchOptions(options: WatchOptions) { return serializeOptionBaseObject(options, getWatchOptionsNameMap()); } @@ -2474,18 +2495,18 @@ function serializeOptionBaseObject( options: OptionsBase, { optionsNameMap }: OptionsNameMap, pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean } -): ts.ESMap { - const result = new ts.Map(); - const getCanonicalFileName = pathOptions && ts.createGetCanonicalFileName(pathOptions.useCaseSensitiveFileNames); +): ESMap { + const result = new Map(); + const getCanonicalFileName = pathOptions && createGetCanonicalFileName(pathOptions.useCaseSensitiveFileNames); for (const name in options) { - if (ts.hasProperty(options, name)) { + if (hasProperty(options, name)) { // tsconfig only options cannot be specified via command line, // so we can assume that only types that can appear here string | number | boolean - if (optionsNameMap.has(name) && (optionsNameMap.get(name)!.category === ts.Diagnostics.Command_line_Options || optionsNameMap.get(name)!.category === ts.Diagnostics.Output_Formatting)) { + if (optionsNameMap.has(name) && (optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options || optionsNameMap.get(name)!.category === Diagnostics.Output_Formatting)) { continue; } - const value = options[name] as ts.CompilerOptionsValue; + const value = options[name] as CompilerOptionsValue; const optionDefinition = optionsNameMap.get(name.toLowerCase()); if (optionDefinition) { const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition); @@ -2493,7 +2514,7 @@ function serializeOptionBaseObject( // There is no map associated with this compiler option then use the value as-is // This is the case if the value is expect to be string, number, boolean or list of string if (pathOptions && optionDefinition.isFilePath) { - result.set(name, ts.getRelativePathFromFile(pathOptions.configFilePath, ts.getNormalizedAbsolutePath(value as string, ts.getDirectoryPath(pathOptions.configFilePath)), getCanonicalFileName!)); + result.set(name, getRelativePathFromFile(pathOptions.configFilePath, getNormalizedAbsolutePath(value as string, getDirectoryPath(pathOptions.configFilePath)), getCanonicalFileName!)); } else { result.set(name, value); @@ -2518,7 +2539,7 @@ function serializeOptionBaseObject( * Generate a list of the compiler options whose value is not the default. * @param options compilerOptions to be evaluated. /** @internal */ -export function getCompilerOptionsDiffValue(options: ts.CompilerOptions, newLine: string): string { +export function getCompilerOptionsDiffValue(options: CompilerOptions, newLine: string): string { const compilerOptionsMap = getSerializedCompilerOption(options); return getOverwrittenDefaultOptions(); @@ -2539,7 +2560,7 @@ export function getCompilerOptionsDiffValue(options: ts.CompilerOptions, newLine if (newValue !== defaultValue) { result.push(`${tab}${cmd.name}: ${newValue}`); } - else if (ts.hasProperty(defaultInitCompilerOptions, cmd.name)) { + else if (hasProperty(defaultInitCompilerOptions, cmd.name)) { result.push(`${tab}${cmd.name}: ${defaultValue}`); } }); @@ -2551,8 +2572,8 @@ export function getCompilerOptionsDiffValue(options: ts.CompilerOptions, newLine * Get the compiler options to be written into the tsconfig.json. * @param options commandlineOptions to be included in the compileOptions. */ -function getSerializedCompilerOption(options: ts.CompilerOptions): ts.ESMap { - const compilerOptions = ts.extend(options, defaultInitCompilerOptions); +function getSerializedCompilerOption(options: CompilerOptions): ESMap { + const compilerOptions = extend(options, defaultInitCompilerOptions); return serializeCompilerOptions(compilerOptions); } /** @@ -2561,7 +2582,7 @@ function getSerializedCompilerOption(options: ts.CompilerOptions): ts.ESMap(); + const categorizedOptions = new Map(); // Set allowed categories in order - categorizedOptions.set(ts.Diagnostics.Projects, []); - categorizedOptions.set(ts.Diagnostics.Language_and_Environment, []); - categorizedOptions.set(ts.Diagnostics.Modules, []); - categorizedOptions.set(ts.Diagnostics.JavaScript_Support, []); - categorizedOptions.set(ts.Diagnostics.Emit, []); - categorizedOptions.set(ts.Diagnostics.Interop_Constraints, []); - categorizedOptions.set(ts.Diagnostics.Type_Checking, []); - categorizedOptions.set(ts.Diagnostics.Completeness, []); + categorizedOptions.set(Diagnostics.Projects, []); + categorizedOptions.set(Diagnostics.Language_and_Environment, []); + categorizedOptions.set(Diagnostics.Modules, []); + categorizedOptions.set(Diagnostics.JavaScript_Support, []); + categorizedOptions.set(Diagnostics.Emit, []); + categorizedOptions.set(Diagnostics.Interop_Constraints, []); + categorizedOptions.set(Diagnostics.Type_Checking, []); + categorizedOptions.set(Diagnostics.Completeness, []); for (const option of optionDeclarations) { if (isAllowedOptionForOutput(option)) { let listForCategory = categorizedOptions.get(option.category!); @@ -2603,7 +2624,7 @@ export function generateTSConfig(options: ts.CompilerOptions, fileNames: readonl if (entries.length !== 0) { entries.push({ value: "" }); } - entries.push({ value: `/* ${ts.getLocaleSpecificMessage(category)} */` }); + entries.push({ value: `/* ${getLocaleSpecificMessage(category)} */` }); for (const option of options) { let optionName; if (compilerOptionsMap.has(option.name)) { @@ -2614,7 +2635,7 @@ export function generateTSConfig(options: ts.CompilerOptions, fileNames: readonl } entries.push({ value: optionName, - description: `/* ${option.description && ts.getLocaleSpecificMessage(option.description) || option.name} */` + description: `/* ${option.description && getLocaleSpecificMessage(option.description) || option.name} */` }); marginLength = Math.max(optionName.length, marginLength); } @@ -2625,7 +2646,7 @@ export function generateTSConfig(options: ts.CompilerOptions, fileNames: readonl const result: string[] = []; result.push(`{`); result.push(`${tab}"compilerOptions": {`); - result.push(`${tab}${tab}/* ${ts.getLocaleSpecificMessage(ts.Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)} */`); + result.push(`${tab}${tab}/* ${getLocaleSpecificMessage(Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)} */`); result.push(""); // Print out each row, aligning all the descriptions on the same column. for (const entry of entries) { @@ -2650,15 +2671,15 @@ export function generateTSConfig(options: ts.CompilerOptions, fileNames: readonl } /* @internal */ -export function convertToOptionsWithAbsolutePaths(options: ts.CompilerOptions, toAbsolutePath: (path: string) => string) { - const result: ts.CompilerOptions = {}; +export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string) { + const result: CompilerOptions = {}; const optionsNameMap = getOptionsNameMap().optionsNameMap; for (const name in options) { - if (ts.hasProperty(options, name)) { + if (hasProperty(options, name)) { result[name] = convertToOptionValueWithAbsolutePaths( optionsNameMap.get(name.toLowerCase()), - options[name] as ts.CompilerOptionsValue, + options[name] as CompilerOptionsValue, toAbsolutePath ); } @@ -2669,7 +2690,7 @@ export function convertToOptionsWithAbsolutePaths(options: ts.CompilerOptions, t return result; } -function convertToOptionValueWithAbsolutePaths(option: ts.CommandLineOption | undefined, value: ts.CompilerOptionsValue, toAbsolutePath: (path: string) => string) { +function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) { if (option && !isNullOrUndefined(value)) { if (option.type === "list") { const values = value as readonly (string | number)[]; @@ -2691,7 +2712,7 @@ function convertToOptionValueWithAbsolutePaths(option: ts.CommandLineOption | un * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ -export function parseJsonConfigFileContent(json: any, host: ts.ParseConfigHost, basePath: string, existingOptions?: ts.CompilerOptions, configFileName?: string, resolutionStack?: ts.Path[], extraFileExtensions?: readonly ts.FileExtensionInfo[], extendedConfigCache?: ts.Map, existingWatchOptions?: ts.WatchOptions): ts.ParsedCommandLine { +export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine { return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache); } @@ -2702,15 +2723,15 @@ export function parseJsonConfigFileContent(json: any, host: ts.ParseConfigHost, * @param basePath A root directory to resolve relative path entries in the config * file to. e.g. outDir */ -export function parseJsonSourceFileConfigFileContent(sourceFile: ts.TsConfigSourceFile, host: ts.ParseConfigHost, basePath: string, existingOptions?: ts.CompilerOptions, configFileName?: string, resolutionStack?: ts.Path[], extraFileExtensions?: readonly ts.FileExtensionInfo[], extendedConfigCache?: ts.Map, existingWatchOptions?: ts.WatchOptions): ts.ParsedCommandLine { - ts.tracing?.push(ts.tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName }); +export function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map, existingWatchOptions?: WatchOptions): ParsedCommandLine { + tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName }); const result = parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache); - ts.tracing?.pop(); + tracing?.pop(); return result; } /*@internal*/ -export function setConfigFileInOptions(options: ts.CompilerOptions, configFile: ts.TsConfigSourceFile | undefined) { +export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined) { if (configFile) { Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile }); } @@ -2723,7 +2744,7 @@ function isNullOrUndefined(x: any): x is null | undefined { function directoryOfCombinedPath(fileName: string, basePath: string) { // Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical // until consistent casing errors are reported - return ts.getDirectoryPath(ts.getNormalizedAbsolutePath(fileName, basePath)); + return getDirectoryPath(getNormalizedAbsolutePath(fileName, basePath)); } /*@internal*/ @@ -2740,32 +2761,32 @@ export const defaultIncludeSpec = "**/*"; */ function parseJsonConfigFileContentWorker( json: any, - sourceFile: ts.TsConfigSourceFile | undefined, - host: ts.ParseConfigHost, + sourceFile: TsConfigSourceFile | undefined, + host: ParseConfigHost, basePath: string, - existingOptions: ts.CompilerOptions = {}, - existingWatchOptions: ts.WatchOptions | undefined, + existingOptions: CompilerOptions = {}, + existingWatchOptions: WatchOptions | undefined, configFileName?: string, - resolutionStack: ts.Path[] = [], - extraFileExtensions: readonly ts.FileExtensionInfo[] = [], - extendedConfigCache?: ts.ESMap -): ts.ParsedCommandLine { - ts.Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined)); - const errors: ts.Diagnostic[] = []; + resolutionStack: Path[] = [], + extraFileExtensions: readonly FileExtensionInfo[] = [], + extendedConfigCache?: ESMap +): ParsedCommandLine { + Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined)); + const errors: Diagnostic[] = []; const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors, extendedConfigCache); const { raw } = parsedConfig; - const options = ts.extend(existingOptions, parsedConfig.options || {}); + const options = extend(existingOptions, parsedConfig.options || {}); const watchOptions = existingWatchOptions && parsedConfig.watchOptions ? - ts.extend(existingWatchOptions, parsedConfig.watchOptions) : + extend(existingWatchOptions, parsedConfig.watchOptions) : parsedConfig.watchOptions || existingWatchOptions; - options.configFilePath = configFileName && ts.normalizeSlashes(configFileName); + options.configFilePath = configFileName && normalizeSlashes(configFileName); const configFileSpecs = getConfigFileSpecs(); if (sourceFile) sourceFile.configFileSpecs = configFileSpecs; setConfigFileInOptions(options, sourceFile); - const basePathForFileNames = ts.normalizePath(configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath); + const basePathForFileNames = normalizePath(configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath); return { options, watchOptions, @@ -2782,24 +2803,24 @@ function parseJsonConfigFileContentWorker( compileOnSave: !!raw.compileOnSave, }; - function getConfigFileSpecs(): ts.ConfigFileSpecs { - const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); + function getConfigFileSpecs(): ConfigFileSpecs { + const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); const filesSpecs = toPropValue(getSpecsFromRaw("files")); if (filesSpecs) { - const hasZeroOrNoReferences = referencesOfRaw === "no-prop" || ts.isArray(referencesOfRaw) && referencesOfRaw.length === 0; - const hasExtends = ts.hasProperty(raw, "extends"); + const hasZeroOrNoReferences = referencesOfRaw === "no-prop" || isArray(referencesOfRaw) && referencesOfRaw.length === 0; + const hasExtends = hasProperty(raw, "extends"); if (filesSpecs.length === 0 && hasZeroOrNoReferences && !hasExtends) { if (sourceFile) { const fileName = configFileName || "tsconfig.json"; - const diagnosticMessage = ts.Diagnostics.The_files_list_in_config_file_0_is_empty; - const nodeValue = ts.firstDefined(ts.getTsConfigPropArray(sourceFile, "files"), property => property.initializer); + const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty; + const nodeValue = firstDefined(getTsConfigPropArray(sourceFile, "files"), property => property.initializer); const error = nodeValue - ? ts.createDiagnosticForNodeInSourceFile(sourceFile, nodeValue, diagnosticMessage, fileName) - : ts.createCompilerDiagnostic(diagnosticMessage, fileName); + ? createDiagnosticForNodeInSourceFile(sourceFile, nodeValue, diagnosticMessage, fileName) + : createCompilerDiagnostic(diagnosticMessage, fileName); errors.push(error); } else { - createCompilerDiagnosticOnlyIfJson(ts.Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); + createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json"); } } } @@ -2840,7 +2861,7 @@ function parseJsonConfigFileContentWorker( filesSpecs, includeSpecs, excludeSpecs, - validatedFilesSpec: ts.filter(filesSpecs, ts.isString), + validatedFilesSpec: filter(filesSpecs, isString), validatedIncludeSpecs, validatedExcludeSpecs, pathPatterns: undefined, // Initialized on first use @@ -2856,17 +2877,17 @@ function parseJsonConfigFileContentWorker( return fileNames; } - function getProjectReferences(basePath: string): readonly ts.ProjectReference[] | undefined { - let projectReferences: ts.ProjectReference[] | undefined; - const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); - if (ts.isArray(referencesOfRaw)) { + function getProjectReferences(basePath: string): readonly ProjectReference[] | undefined { + let projectReferences: ProjectReference[] | undefined; + const referencesOfRaw = getPropFromRaw("references", element => typeof element === "object", "object"); + if (isArray(referencesOfRaw)) { for (const ref of referencesOfRaw) { if (typeof ref.path !== "string") { - createCompilerDiagnosticOnlyIfJson(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string"); + createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string"); } else { (projectReferences || (projectReferences = [])).push({ - path: ts.getNormalizedAbsolutePath(ref.path, basePath), + path: getNormalizedAbsolutePath(ref.path, basePath), originalPath: ref.path, prepend: ref.prepend, circular: ref.circular @@ -2879,75 +2900,75 @@ function parseJsonConfigFileContentWorker( type PropOfRaw = readonly T[] | "not-array" | "no-prop"; function toPropValue(specResult: PropOfRaw) { - return ts.isArray(specResult) ? specResult : undefined; + return isArray(specResult) ? specResult : undefined; } function getSpecsFromRaw(prop: "files" | "include" | "exclude"): PropOfRaw { - return getPropFromRaw(prop, ts.isString, "string"); + return getPropFromRaw(prop, isString, "string"); } function getPropFromRaw(prop: "files" | "include" | "exclude" | "references", validateElement: (value: unknown) => boolean, elementTypeName: string): PropOfRaw { - if (ts.hasProperty(raw, prop) && !isNullOrUndefined(raw[prop])) { - if (ts.isArray(raw[prop])) { + if (hasProperty(raw, prop) && !isNullOrUndefined(raw[prop])) { + if (isArray(raw[prop])) { const result = raw[prop] as T[]; - if (!sourceFile && !ts.every(result, validateElement)) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, elementTypeName)); + if (!sourceFile && !every(result, validateElement)) { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, elementTypeName)); } return result; } else { - createCompilerDiagnosticOnlyIfJson(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, "Array"); + createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, "Array"); return "not-array"; } } return "no-prop"; } - function createCompilerDiagnosticOnlyIfJson(message: ts.DiagnosticMessage, arg0?: string, arg1?: string) { + function createCompilerDiagnosticOnlyIfJson(message: DiagnosticMessage, arg0?: string, arg1?: string) { if (!sourceFile) { - errors.push(ts.createCompilerDiagnostic(message, arg0, arg1)); + errors.push(createCompilerDiagnostic(message, arg0, arg1)); } } } -function isErrorNoInputFiles(error: ts.Diagnostic) { - return error.code === ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code; +function isErrorNoInputFiles(error: Diagnostic) { + return error.code === Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code; } -function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ts.ConfigFileSpecs, configFileName: string | undefined) { - return ts.createCompilerDiagnostic( - ts.Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, +function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ConfigFileSpecs, configFileName: string | undefined) { + return createCompilerDiagnostic( + Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2, configFileName || "tsconfig.json", JSON.stringify(includeSpecs || []), JSON.stringify(excludeSpecs || [])); } -function shouldReportNoInputFiles(fileNames: string[], canJsonReportNoInutFiles: boolean, resolutionStack?: ts.Path[]) { +function shouldReportNoInputFiles(fileNames: string[], canJsonReportNoInutFiles: boolean, resolutionStack?: Path[]) { return fileNames.length === 0 && canJsonReportNoInutFiles && (!resolutionStack || resolutionStack.length === 0); } /*@internal*/ export function canJsonReportNoInputFiles(raw: any) { - return !ts.hasProperty(raw, "files") && !ts.hasProperty(raw, "references"); + return !hasProperty(raw, "files") && !hasProperty(raw, "references"); } /*@internal*/ -export function updateErrorForNoInputFiles(fileNames: string[], configFileName: string, configFileSpecs: ts.ConfigFileSpecs, configParseDiagnostics: ts.Diagnostic[], canJsonReportNoInutFiles: boolean) { +export function updateErrorForNoInputFiles(fileNames: string[], configFileName: string, configFileSpecs: ConfigFileSpecs, configParseDiagnostics: Diagnostic[], canJsonReportNoInutFiles: boolean) { const existingErrors = configParseDiagnostics.length; if (shouldReportNoInputFiles(fileNames, canJsonReportNoInutFiles)) { configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName)); } else { - ts.filterMutate(configParseDiagnostics, error => !isErrorNoInputFiles(error)); + filterMutate(configParseDiagnostics, error => !isErrorNoInputFiles(error)); } return existingErrors !== configParseDiagnostics.length; } export interface ParsedTsconfig { raw: any; - options?: ts.CompilerOptions; - watchOptions?: ts.WatchOptions; - typeAcquisition?: ts.TypeAcquisition; + options?: CompilerOptions; + watchOptions?: WatchOptions; + typeAcquisition?: TypeAcquisition; /** * Note that the case of the config path has not yet been normalized, as no files have been imported into the project yet */ @@ -2964,19 +2985,19 @@ function isSuccessfulParsedTsconfig(value: ParsedTsconfig) { */ function parseConfig( json: any, - sourceFile: ts.TsConfigSourceFile | undefined, - host: ts.ParseConfigHost, + sourceFile: TsConfigSourceFile | undefined, + host: ParseConfigHost, basePath: string, configFileName: string | undefined, resolutionStack: string[], - errors: ts.Push, - extendedConfigCache?: ts.ESMap + errors: Push, + extendedConfigCache?: ESMap ): ParsedTsconfig { - basePath = ts.normalizeSlashes(basePath); - const resolvedPath = ts.getNormalizedAbsolutePath(configFileName || "", basePath); + basePath = normalizeSlashes(basePath); + const resolvedPath = getNormalizedAbsolutePath(configFileName || "", basePath); if (resolutionStack.indexOf(resolvedPath) >= 0) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))); + errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> "))); return { raw: json || convertToObject(sourceFile!, errors) }; } @@ -3001,8 +3022,8 @@ function parseConfig( let relativeDifference: string | undefined ; const setPropertyInRawIfNotUndefined = (propertyName: string) => { if (!raw[propertyName] && baseRaw[propertyName]) { - raw[propertyName] = ts.map(baseRaw[propertyName], (path: string) => ts.isRootedDiskPath(path) ? path : ts.combinePaths( - relativeDifference ||= ts.convertToRelativePath(ts.getDirectoryPath(ownConfig.extendedConfigPath!), basePath, ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames)), + raw[propertyName] = map(baseRaw[propertyName], (path: string) => isRootedDiskPath(path) ? path : combinePaths( + relativeDifference ||= convertToRelativePath(getDirectoryPath(ownConfig.extendedConfigPath!), basePath, createGetCanonicalFileName(host.useCaseSensitiveFileNames)), path )); } @@ -3013,9 +3034,9 @@ function parseConfig( if (raw.compileOnSave === undefined) { raw.compileOnSave = baseRaw.compileOnSave; } - ownConfig.options = ts.assign({}, extendedConfig.options, ownConfig.options); + ownConfig.options = assign({}, extendedConfig.options, ownConfig.options); ownConfig.watchOptions = ownConfig.watchOptions && extendedConfig.watchOptions ? - ts.assign({}, extendedConfig.watchOptions, ownConfig.watchOptions) : + assign({}, extendedConfig.watchOptions, ownConfig.watchOptions) : ownConfig.watchOptions || extendedConfig.watchOptions; // TODO extend type typeAcquisition } @@ -3026,13 +3047,13 @@ function parseConfig( function parseOwnConfigOfJson( json: any, - host: ts.ParseConfigHost, + host: ParseConfigHost, basePath: string, configFileName: string | undefined, - errors: ts.Push + errors: Push ): ParsedTsconfig { - if (ts.hasProperty(json, "excludes")) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); + if (hasProperty(json, "excludes")) { + errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } const options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName); @@ -3044,32 +3065,32 @@ function parseOwnConfigOfJson( let extendedConfigPath: string | undefined; if (json.extends) { - if (!ts.isString(json.extends)) { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); + if (!isString(json.extends)) { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); } else { const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath; - extendedConfigPath = getExtendsConfigPath(json.extends, host, newBase, errors, ts.createCompilerDiagnostic); + extendedConfigPath = getExtendsConfigPath(json.extends, host, newBase, errors, createCompilerDiagnostic); } } return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath }; } function parseOwnConfigOfJsonSourceFile( - sourceFile: ts.TsConfigSourceFile, - host: ts.ParseConfigHost, + sourceFile: TsConfigSourceFile, + host: ParseConfigHost, basePath: string, configFileName: string | undefined, - errors: ts.Push + errors: Push ): ParsedTsconfig { const options = getDefaultCompilerOptions(configFileName); - let typeAcquisition: ts.TypeAcquisition | undefined, typingOptionstypeAcquisition: ts.TypeAcquisition | undefined; - let watchOptions: ts.WatchOptions | undefined; + let typeAcquisition: TypeAcquisition | undefined, typingOptionstypeAcquisition: TypeAcquisition | undefined; + let watchOptions: WatchOptions | undefined; let extendedConfigPath: string | undefined; - let rootCompilerOptions: ts.PropertyName[] | undefined; + let rootCompilerOptions: PropertyName[] | undefined; const optionsIterator: JsonConversionNotifier = { - onSetValidOptionKeyValueInParent(parentOption: string, option: ts.CommandLineOption, value: ts.CompilerOptionsValue) { + onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue) { let currentOption; switch (parentOption) { case "compilerOptions": @@ -3085,12 +3106,12 @@ function parseOwnConfigOfJsonSourceFile( currentOption = (typingOptionstypeAcquisition || (typingOptionstypeAcquisition = getDefaultTypeAcquisition(configFileName))); break; default: - ts.Debug.fail("Unknown option"); + Debug.fail("Unknown option"); } currentOption[option.name] = normalizeOptionValue(option, basePath, value); }, - onSetValidOptionKeyValueInRoot(key: string, _keyNode: ts.PropertyName, value: ts.CompilerOptionsValue, valueNode: ts.Expression) { + onSetValidOptionKeyValueInRoot(key: string, _keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression) { switch (key) { case "extends": const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath; @@ -3100,17 +3121,17 @@ function parseOwnConfigOfJsonSourceFile( newBase, errors, (message, arg0) => - ts.createDiagnosticForNodeInSourceFile(sourceFile, valueNode, message, arg0) + createDiagnosticForNodeInSourceFile(sourceFile, valueNode, message, arg0) ); return; } }, - onSetUnknownOptionKeyValueInRoot(key: string, keyNode: ts.PropertyName, _value: ts.CompilerOptionsValue, _valueNode: ts.Expression) { + onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, _value: CompilerOptionsValue, _valueNode: Expression) { if (key === "excludes") { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, keyNode, ts.Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, keyNode, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude)); } - if (ts.find(commandOptionsWithoutBuild, (opt) => opt.name === key)) { - rootCompilerOptions = ts.append(rootCompilerOptions, keyNode); + if (find(commandOptionsWithoutBuild, (opt) => opt.name === key)) { + rootCompilerOptions = append(rootCompilerOptions, keyNode); } } }; @@ -3132,7 +3153,7 @@ function parseOwnConfigOfJsonSourceFile( } if (rootCompilerOptions && json && json.compilerOptions === undefined) { - errors.push(ts.createDiagnosticForNodeInSourceFile(sourceFile, rootCompilerOptions[0], ts.Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, ts.getTextOfPropertyName(rootCompilerOptions[0]) as string)); + errors.push(createDiagnosticForNodeInSourceFile(sourceFile, rootCompilerOptions[0], Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, getTextOfPropertyName(rootCompilerOptions[0]) as string)); } return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath }; @@ -3140,47 +3161,47 @@ function parseOwnConfigOfJsonSourceFile( function getExtendsConfigPath( extendedConfig: string, - host: ts.ParseConfigHost, + host: ParseConfigHost, basePath: string, - errors: ts.Push, - createDiagnostic: (message: ts.DiagnosticMessage, arg1?: string) => ts.Diagnostic) { - extendedConfig = ts.normalizeSlashes(extendedConfig); - if (ts.isRootedDiskPath(extendedConfig) || ts.startsWith(extendedConfig, "./") || ts.startsWith(extendedConfig, "../")) { - let extendedConfigPath = ts.getNormalizedAbsolutePath(extendedConfig, basePath); - if (!host.fileExists(extendedConfigPath) && !ts.endsWith(extendedConfigPath, ts.Extension.Json)) { + errors: Push, + createDiagnostic: (message: DiagnosticMessage, arg1?: string) => Diagnostic) { + extendedConfig = normalizeSlashes(extendedConfig); + if (isRootedDiskPath(extendedConfig) || startsWith(extendedConfig, "./") || startsWith(extendedConfig, "../")) { + let extendedConfigPath = getNormalizedAbsolutePath(extendedConfig, basePath); + if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, Extension.Json)) { extendedConfigPath = `${extendedConfigPath}.json`; if (!host.fileExists(extendedConfigPath)) { - errors.push(createDiagnostic(ts.Diagnostics.File_0_not_found, extendedConfig)); + errors.push(createDiagnostic(Diagnostics.File_0_not_found, extendedConfig)); return undefined; } } return extendedConfigPath; } // If the path isn't a rooted or relative path, resolve like a module - const resolved = ts.nodeModuleNameResolver(extendedConfig, ts.combinePaths(basePath, "tsconfig.json"), { moduleResolution: ts.ModuleResolutionKind.NodeJs }, host, /*cache*/ undefined, /*projectRefs*/ undefined, /*lookupConfig*/ true); + const resolved = nodeModuleNameResolver(extendedConfig, combinePaths(basePath, "tsconfig.json"), { moduleResolution: ModuleResolutionKind.NodeJs }, host, /*cache*/ undefined, /*projectRefs*/ undefined, /*lookupConfig*/ true); if (resolved.resolvedModule) { return resolved.resolvedModule.resolvedFileName; } - errors.push(createDiagnostic(ts.Diagnostics.File_0_not_found, extendedConfig)); + errors.push(createDiagnostic(Diagnostics.File_0_not_found, extendedConfig)); return undefined; } export interface ExtendedConfigCacheEntry { - extendedResult: ts.TsConfigSourceFile; + extendedResult: TsConfigSourceFile; extendedConfig: ParsedTsconfig | undefined; } function getExtendedConfig( - sourceFile: ts.TsConfigSourceFile | undefined, + sourceFile: TsConfigSourceFile | undefined, extendedConfigPath: string, - host: ts.ParseConfigHost, + host: ParseConfigHost, resolutionStack: string[], - errors: ts.Push, - extendedConfigCache?: ts.ESMap + errors: Push, + extendedConfigCache?: ESMap ): ParsedTsconfig | undefined { - const path = host.useCaseSensitiveFileNames ? extendedConfigPath : ts.toFileNameLowerCase(extendedConfigPath); + const path = host.useCaseSensitiveFileNames ? extendedConfigPath : toFileNameLowerCase(extendedConfigPath); let value: ExtendedConfigCacheEntry | undefined; - let extendedResult: ts.TsConfigSourceFile; + let extendedResult: TsConfigSourceFile; let extendedConfig: ParsedTsconfig | undefined; if (extendedConfigCache && (value = extendedConfigCache.get(path))) { ({ extendedResult, extendedConfig } = value); @@ -3188,8 +3209,8 @@ function getExtendedConfig( else { extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path)); if (!extendedResult.parseDiagnostics.length) { - extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, ts.getDirectoryPath(extendedConfigPath), - ts.getBaseFileName(extendedConfigPath), resolutionStack, errors, extendedConfigCache); + extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, getDirectoryPath(extendedConfigPath), + getBaseFileName(extendedConfigPath), resolutionStack, errors, extendedConfigCache); } if (extendedConfigCache) { extendedConfigCache.set(path, { extendedResult, extendedConfig }); @@ -3208,50 +3229,50 @@ function getExtendedConfig( return extendedConfig!; } -function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: ts.Push): boolean { - if (!ts.hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) { +function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push): boolean { + if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) { return false; } const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption.compileOnSave, basePath, errors); return typeof result === "boolean" && result; } -export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: ts.CompilerOptions, errors: ts.Diagnostic[] } { - const errors: ts.Diagnostic[] = []; +export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; } -export function convertTypeAcquisitionFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: ts.TypeAcquisition, errors: ts.Diagnostic[] } { - const errors: ts.Diagnostic[] = []; +export function convertTypeAcquisitionFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: TypeAcquisition, errors: Diagnostic[] } { + const errors: Diagnostic[] = []; const options = convertTypeAcquisitionFromJsonWorker(jsonOptions, basePath, errors, configFileName); return { options, errors }; } function getDefaultCompilerOptions(configFileName?: string) { - const options: ts.CompilerOptions = configFileName && ts.getBaseFileName(configFileName) === "jsconfig.json" + const options: CompilerOptions = configFileName && getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true, skipLibCheck: true, noEmit: true } : {}; return options; } function convertCompilerOptionsFromJsonWorker(jsonOptions: any, - basePath: string, errors: ts.Push, configFileName?: string): ts.CompilerOptions { + basePath: string, errors: Push, configFileName?: string): CompilerOptions { const options = getDefaultCompilerOptions(configFileName); convertOptionsFromJson(getCommandLineCompilerOptionsMap(), jsonOptions, basePath, options, compilerOptionsDidYouMeanDiagnostics, errors); if (configFileName) { - options.configFilePath = ts.normalizeSlashes(configFileName); + options.configFilePath = normalizeSlashes(configFileName); } return options; } -function getDefaultTypeAcquisition(configFileName?: string): ts.TypeAcquisition { - return { enable: !!configFileName && ts.getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] }; +function getDefaultTypeAcquisition(configFileName?: string): TypeAcquisition { + return { enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] }; } function convertTypeAcquisitionFromJsonWorker(jsonOptions: any, - basePath: string, errors: ts.Push, configFileName?: string): ts.TypeAcquisition { + basePath: string, errors: Push, configFileName?: string): TypeAcquisition { const options = getDefaultTypeAcquisition(configFileName); const typeAcquisition = convertEnableAutoDiscoveryToEnable(jsonOptions); @@ -3260,16 +3281,16 @@ function convertTypeAcquisitionFromJsonWorker(jsonOptions: any, return options; } -function convertWatchOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: ts.Push): ts.WatchOptions | undefined { +function convertWatchOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Push): WatchOptions | undefined { return convertOptionsFromJson(getCommandLineWatchOptionsMap(), jsonOptions, basePath, /*defaultOptions*/ undefined, watchOptionsDidYouMeanDiagnostics, errors); } -function convertOptionsFromJson(optionsNameMap: ts.ESMap, jsonOptions: any, basePath: string, - defaultOptions: undefined, diagnostics: ts.DidYouMeanOptionsDiagnostics, errors: ts.Push): ts.WatchOptions | undefined; -function convertOptionsFromJson(optionsNameMap: ts.ESMap, jsonOptions: any, basePath: string, - defaultOptions: ts.CompilerOptions | ts.TypeAcquisition, diagnostics: ts.DidYouMeanOptionsDiagnostics, errors: ts.Push): ts.CompilerOptions | ts.TypeAcquisition; -function convertOptionsFromJson(optionsNameMap: ts.ESMap, jsonOptions: any, basePath: string, - defaultOptions: ts.CompilerOptions | ts.TypeAcquisition | ts.WatchOptions | undefined, diagnostics: ts.DidYouMeanOptionsDiagnostics, errors: ts.Push) { +function convertOptionsFromJson(optionsNameMap: ESMap, jsonOptions: any, basePath: string, + defaultOptions: undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push): WatchOptions | undefined; +function convertOptionsFromJson(optionsNameMap: ESMap, jsonOptions: any, basePath: string, + defaultOptions: CompilerOptions | TypeAcquisition, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push): CompilerOptions | TypeAcquisition; +function convertOptionsFromJson(optionsNameMap: ESMap, jsonOptions: any, basePath: string, + defaultOptions: CompilerOptions | TypeAcquisition | WatchOptions | undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push) { if (!jsonOptions) { return; @@ -3281,48 +3302,48 @@ function convertOptionsFromJson(optionsNameMap: ts.ESMap): ts.CompilerOptionsValue { +export function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Push): CompilerOptionsValue { if (isCompilerOptionsValue(opt, value)) { const optType = opt.type; - if (optType === "list" && ts.isArray(value)) { + if (optType === "list" && isArray(value)) { return convertJsonOptionOfListType(opt , value, basePath, errors); } - else if (!ts.isString(optType)) { - return convertJsonOptionOfCustomType(opt as ts.CommandLineOptionOfCustomType, value as string, errors); + else if (!isString(optType)) { + return convertJsonOptionOfCustomType(opt as CommandLineOptionOfCustomType, value as string, errors); } const validatedValue = validateJsonOptionValue(opt, value, errors); return isNullOrUndefined(validatedValue) ? validatedValue : normalizeNonListOptionValue(opt, basePath, validatedValue); } else { - errors.push(ts.createCompilerDiagnostic(ts.Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, getCompilerOptionValueTypeString(opt))); + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, getCompilerOptionValueTypeString(opt))); } } -function normalizeOptionValue(option: ts.CommandLineOption, basePath: string, value: any): ts.CompilerOptionsValue { +function normalizeOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue { if (isNullOrUndefined(value)) return undefined; if (option.type === "list") { const listOption = option; - if (listOption.element.isFilePath || !ts.isString(listOption.element.type)) { - return ts.filter(ts.map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => listOption.listPreserveFalsyValues ? true : !!v) as ts.CompilerOptionsValue; + if (listOption.element.isFilePath || !isString(listOption.element.type)) { + return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => listOption.listPreserveFalsyValues ? true : !!v) as CompilerOptionsValue; } return value; } - else if (!ts.isString(option.type)) { - return option.type.get(ts.isString(value) ? value.toLowerCase() : value); + else if (!isString(option.type)) { + return option.type.get(isString(value) ? value.toLowerCase() : value); } return normalizeNonListOptionValue(option, basePath, value); } -function normalizeNonListOptionValue(option: ts.CommandLineOption, basePath: string, value: any): ts.CompilerOptionsValue { +function normalizeNonListOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue { if (option.isFilePath) { - value = ts.getNormalizedAbsolutePath(value, basePath); + value = getNormalizedAbsolutePath(value, basePath); if (value === "") { value = "."; } @@ -3330,15 +3351,15 @@ function normalizeNonListOptionValue(option: ts.CommandLineOption, basePath: str return value; } -function validateJsonOptionValue(opt: ts.CommandLineOption, value: T, errors: ts.Push): T | undefined { +function validateJsonOptionValue(opt: CommandLineOption, value: T, errors: Push): T | undefined { if (isNullOrUndefined(value)) return undefined; const d = opt.extraValidation?.(value); if (!d) return value; - errors.push(ts.createCompilerDiagnostic(...d)); + errors.push(createCompilerDiagnostic(...d)); return undefined; } -function convertJsonOptionOfCustomType(opt: ts.CommandLineOptionOfCustomType, value: string, errors: ts.Push) { +function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Push) { if (isNullOrUndefined(value)) return undefined; const key = value.toLowerCase(); const val = opt.type.get(key); @@ -3350,8 +3371,8 @@ function convertJsonOptionOfCustomType(opt: ts.CommandLineOptionOfCustomType, va } } -function convertJsonOptionOfListType(option: ts.CommandLineOptionOfListType, values: readonly any[], basePath: string, errors: ts.Push): any[] { - return ts.filter(ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => option.listPreserveFalsyValues ? true : !!v); +function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: readonly any[], basePath: string, errors: Push): any[] { + return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => option.listPreserveFalsyValues ? true : !!v); } /** @@ -3392,57 +3413,57 @@ const wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/; */ /* @internal */ export function getFileNamesFromConfigSpecs( - configFileSpecs: ts.ConfigFileSpecs, + configFileSpecs: ConfigFileSpecs, basePath: string, - options: ts.CompilerOptions, - host: ts.ParseConfigHost, - extraFileExtensions: readonly ts.FileExtensionInfo[] = ts.emptyArray + options: CompilerOptions, + host: ParseConfigHost, + extraFileExtensions: readonly FileExtensionInfo[] = emptyArray ): string[] { - basePath = ts.normalizePath(basePath); + basePath = normalizePath(basePath); - const keyMapper = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames); + const keyMapper = createGetCanonicalFileName(host.useCaseSensitiveFileNames); // Literal file names (provided via the "files" array in tsconfig.json) are stored in a // file map with a possibly case insensitive key. We use this map later when when including // wildcard paths. - const literalFileMap = new ts.Map(); + const literalFileMap = new Map(); // Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a // file map with a possibly case insensitive key. We use this map to store paths matched // via wildcard, and to handle extension priority. - const wildcardFileMap = new ts.Map(); + const wildcardFileMap = new Map(); // Wildcard paths of json files (provided via the "includes" array in tsconfig.json) are stored in a // file map with a possibly case insensitive key. We use this map to store paths matched // via wildcard of *.json kind - const wildCardJsonFileMap = new ts.Map(); + const wildCardJsonFileMap = new Map(); const { validatedFilesSpec, validatedIncludeSpecs, validatedExcludeSpecs } = configFileSpecs; // Rather than re-query this for each file and filespec, we query the supported extensions // once and store it on the expansion context. - const supportedExtensions = ts.getSupportedExtensions(options, extraFileExtensions); - const supportedExtensionsWithJsonIfResolveJsonModule = ts.getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); + const supportedExtensions = getSupportedExtensions(options, extraFileExtensions); + const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); // Literal files are always included verbatim. An "include" or "exclude" specification cannot // remove a literal file. if (validatedFilesSpec) { for (const fileName of validatedFilesSpec) { - const file = ts.getNormalizedAbsolutePath(fileName, basePath); + const file = getNormalizedAbsolutePath(fileName, basePath); literalFileMap.set(keyMapper(file), file); } } let jsonOnlyIncludeRegexes: readonly RegExp[] | undefined; if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) { - for (const file of host.readDirectory(basePath, ts.flatten(supportedExtensionsWithJsonIfResolveJsonModule), validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) { - if (ts.fileExtensionIs(file, ts.Extension.Json)) { + for (const file of host.readDirectory(basePath, flatten(supportedExtensionsWithJsonIfResolveJsonModule), validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) { + if (fileExtensionIs(file, Extension.Json)) { // Valid only if *.json specified if (!jsonOnlyIncludeRegexes) { - const includes = validatedIncludeSpecs.filter(s => ts.endsWith(s, ts.Extension.Json)); - const includeFilePatterns = ts.map(ts.getRegularExpressionsForWildcards(includes, basePath, "files"), pattern => `^${pattern}$`); - jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => ts.getRegexFromPattern(pattern, host.useCaseSensitiveFileNames)) : ts.emptyArray; + const includes = validatedIncludeSpecs.filter(s => endsWith(s, Extension.Json)); + const includeFilePatterns = map(getRegularExpressionsForWildcards(includes, basePath, "files"), pattern => `^${pattern}$`); + jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => getRegexFromPattern(pattern, host.useCaseSensitiveFileNames)) : emptyArray; } - const includeIndex = ts.findIndex(jsonOnlyIncludeRegexes, re => re.test(file)); + const includeIndex = findIndex(jsonOnlyIncludeRegexes, re => re.test(file)); if (includeIndex !== -1) { const key = keyMapper(file); if (!literalFileMap.has(key) && !wildCardJsonFileMap.has(key)) { @@ -3474,29 +3495,29 @@ export function getFileNamesFromConfigSpecs( } } - const literalFiles = ts.arrayFrom(literalFileMap.values()); - const wildcardFiles = ts.arrayFrom(wildcardFileMap.values()); + const literalFiles = arrayFrom(literalFileMap.values()); + const wildcardFiles = arrayFrom(wildcardFileMap.values()); - return literalFiles.concat(wildcardFiles, ts.arrayFrom(wildCardJsonFileMap.values())); + return literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values())); } /* @internal */ export function isExcludedFile( pathToCheck: string, - spec: ts.ConfigFileSpecs, + spec: ConfigFileSpecs, basePath: string, useCaseSensitiveFileNames: boolean, currentDirectory: string ): boolean { const { validatedFilesSpec, validatedIncludeSpecs, validatedExcludeSpecs } = spec; - if (!ts.length(validatedIncludeSpecs) || !ts.length(validatedExcludeSpecs)) return false; + if (!length(validatedIncludeSpecs) || !length(validatedExcludeSpecs)) return false; - basePath = ts.normalizePath(basePath); + basePath = normalizePath(basePath); - const keyMapper = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const keyMapper = createGetCanonicalFileName(useCaseSensitiveFileNames); if (validatedFilesSpec) { for (const fileName of validatedFilesSpec) { - if (keyMapper(ts.getNormalizedAbsolutePath(fileName, basePath)) === pathToCheck) return false; + if (keyMapper(getNormalizedAbsolutePath(fileName, basePath)) === pathToCheck) return false; } } @@ -3509,11 +3530,11 @@ function invalidDotDotAfterRecursiveWildcard(s: string) { // can be matched in many arbitrary positions when multiple are present, resulting // in bad backtracking (and we don't care which is matched - just that some /.. segment // comes after some **/ segment). - const wildcardIndex = ts.startsWith(s, "**/") ? 0 : s.indexOf("/**/"); + const wildcardIndex = startsWith(s, "**/") ? 0 : s.indexOf("/**/"); if (wildcardIndex === -1) { return false; } - const lastDotIndex = ts.endsWith(s, "/..") ? s.length : s.lastIndexOf("/../"); + const lastDotIndex = endsWith(s, "/..") ? s.length : s.lastIndexOf("/../"); return lastDotIndex > wildcardIndex; } @@ -3526,7 +3547,7 @@ export function matchesExclude( ) { return matchesExcludeWorker( pathToCheck, - ts.filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)), + filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)), useCaseSensitiveFileNames, currentDirectory ); @@ -3539,16 +3560,16 @@ function matchesExcludeWorker( currentDirectory: string, basePath?: string ) { - const excludePattern = ts.getRegularExpressionForWildcard(excludeSpecs, ts.combinePaths(ts.normalizePath(currentDirectory), basePath), "exclude"); - const excludeRegex = excludePattern && ts.getRegexFromPattern(excludePattern, useCaseSensitiveFileNames); + const excludePattern = getRegularExpressionForWildcard(excludeSpecs, combinePaths(normalizePath(currentDirectory), basePath), "exclude"); + const excludeRegex = excludePattern && getRegexFromPattern(excludePattern, useCaseSensitiveFileNames); if (!excludeRegex) return false; if (excludeRegex.test(pathToCheck)) return true; - return !ts.hasExtension(pathToCheck) && excludeRegex.test(ts.ensureTrailingDirectorySeparator(pathToCheck)); + return !hasExtension(pathToCheck) && excludeRegex.test(ensureTrailingDirectorySeparator(pathToCheck)); } -function validateSpecs(specs: readonly string[], errors: ts.Push, disallowTrailingRecursion: boolean, jsonSourceFile: ts.TsConfigSourceFile | undefined, specKey: string): readonly string[] { +function validateSpecs(specs: readonly string[], errors: Push, disallowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile | undefined, specKey: string): readonly string[] { return specs.filter(spec => { - if (!ts.isString(spec)) return false; + if (!isString(spec)) return false; const diag = specToDiagnostic(spec, disallowTrailingRecursion); if (diag !== undefined) { errors.push(createDiagnostic(...diag)); @@ -3556,27 +3577,27 @@ function validateSpecs(specs: readonly string[], errors: ts.Push, return diag === undefined; }); - function createDiagnostic(message: ts.DiagnosticMessage, spec: string): ts.Diagnostic { - const element = ts.getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec); + function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic { + const element = getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec); return element ? - ts.createDiagnosticForNodeInSourceFile(jsonSourceFile!, element, message, spec) : - ts.createCompilerDiagnostic(message, spec); + createDiagnosticForNodeInSourceFile(jsonSourceFile!, element, message, spec) : + createCompilerDiagnostic(message, spec); } } -function specToDiagnostic(spec: string, disallowTrailingRecursion?: boolean): [ts.DiagnosticMessage, string] | undefined { +function specToDiagnostic(spec: string, disallowTrailingRecursion?: boolean): [DiagnosticMessage, string] | undefined { if (disallowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) { - return [ts.Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; + return [Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; } else if (invalidDotDotAfterRecursiveWildcard(spec)) { - return [ts.Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; + return [Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec]; } } /** * Gets directories in a set of include patterns that should be watched for changes. */ -function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ts.ConfigFileSpecs, path: string, useCaseSensitiveFileNames: boolean): ts.MapLike { +function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, path: string, useCaseSensitiveFileNames: boolean): MapLike { // We watch a directory recursively if it contains a wildcard anywhere in a directory segment // of the pattern: // @@ -3589,13 +3610,13 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu // // /a/b/* - Watch /a/b directly to catch any new file // /a/b/a?z - Watch /a/b directly to catch any new file matching a?z - const rawExcludeRegex = ts.getRegularExpressionForWildcard(exclude, path, "exclude"); + const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude"); const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i"); - const wildcardDirectories: ts.MapLike = {}; + const wildcardDirectories: MapLike = {}; if (include !== undefined) { const recursiveKeys: string[] = []; for (const file of include) { - const spec = ts.normalizePath(ts.combinePaths(path, file)); + const spec = normalizePath(combinePaths(path, file)); if (excludeRegex && excludeRegex.test(spec)) { continue; } @@ -3606,7 +3627,7 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu const existingFlags = wildcardDirectories[key]; if (existingFlags === undefined || existingFlags < flags) { wildcardDirectories[key] = flags; - if (flags === ts.WatchDirectoryFlags.Recursive) { + if (flags === WatchDirectoryFlags.Recursive) { recursiveKeys.push(key); } } @@ -3615,9 +3636,9 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu // Remove any subpaths under an existing recursively watched directory. for (const key in wildcardDirectories) { - if (ts.hasProperty(wildcardDirectories, key)) { + if (hasProperty(wildcardDirectories, key)) { for (const recursiveKey of recursiveKeys) { - if (key !== recursiveKey && ts.containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) { + if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) { delete wildcardDirectories[key]; } } @@ -3628,7 +3649,7 @@ function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExclu return wildcardDirectories; } -function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string, flags: ts.WatchDirectoryFlags } | undefined { +function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string, flags: WatchDirectoryFlags } | undefined { const match = wildcardDirectoryPattern.exec(spec); if (match) { // We check this with a few `indexOf` calls because 3 `indexOf`/`lastIndexOf` calls is @@ -3637,18 +3658,18 @@ function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: b // characters could match any of the central patterns, resulting in bad backtracking. const questionWildcardIndex = spec.indexOf("?"); const starWildcardIndex = spec.indexOf("*"); - const lastDirectorySeperatorIndex = spec.lastIndexOf(ts.directorySeparator); + const lastDirectorySeperatorIndex = spec.lastIndexOf(directorySeparator); return { - key: useCaseSensitiveFileNames ? match[0] : ts.toFileNameLowerCase(match[0]), + key: useCaseSensitiveFileNames ? match[0] : toFileNameLowerCase(match[0]), flags: (questionWildcardIndex !== -1 && questionWildcardIndex < lastDirectorySeperatorIndex) || (starWildcardIndex !== -1 && starWildcardIndex < lastDirectorySeperatorIndex) - ? ts.WatchDirectoryFlags.Recursive : ts.WatchDirectoryFlags.None + ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None }; } - if (ts.isImplicitGlob(spec.substring(spec.lastIndexOf(ts.directorySeparator) + 1))) { + if (isImplicitGlob(spec.substring(spec.lastIndexOf(directorySeparator) + 1))) { return { - key: ts.removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : ts.toFileNameLowerCase(spec)), - flags: ts.WatchDirectoryFlags.Recursive + key: removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec)), + flags: WatchDirectoryFlags.Recursive }; } return undefined; @@ -3660,18 +3681,18 @@ function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: b * * @param file The path to the file. */ -function hasFileWithHigherPriorityExtension(file: string, literalFiles: ts.ESMap, wildcardFiles: ts.ESMap, extensions: readonly string[][], keyMapper: (value: string) => string) { - const extensionGroup = ts.forEach(extensions, group => ts.fileExtensionIsOneOf(file, group) ? group : undefined); +function hasFileWithHigherPriorityExtension(file: string, literalFiles: ESMap, wildcardFiles: ESMap, extensions: readonly string[][], keyMapper: (value: string) => string) { + const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined); if (!extensionGroup) { return false; } for (const ext of extensionGroup) { - if (ts.fileExtensionIs(file, ext)) { + if (fileExtensionIs(file, ext)) { return false; } - const higherPriorityPath = keyMapper(ts.changeExtension(file, ext)); + const higherPriorityPath = keyMapper(changeExtension(file, ext)); if (literalFiles.has(higherPriorityPath) || wildcardFiles.has(higherPriorityPath)) { - if (ext === ts.Extension.Dts && (ts.fileExtensionIs(file, ts.Extension.Js) || ts.fileExtensionIs(file, ts.Extension.Jsx))) { + if (ext === Extension.Dts && (fileExtensionIs(file, Extension.Js) || fileExtensionIs(file, Extension.Jsx))) { // LEGACY BEHAVIOR: An off-by-one bug somewhere in the extension priority system for wildcard module loading allowed declaration // files to be loaded alongside their js(x) counterparts. We regard this as generally undesirable, but retain the behavior to // prevent breakage. @@ -3690,17 +3711,17 @@ function hasFileWithHigherPriorityExtension(file: string, literalFiles: ts.ESMap * * @param file The path to the file. */ -function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: ts.ESMap, extensions: readonly string[][], keyMapper: (value: string) => string) { - const extensionGroup = ts.forEach(extensions, group => ts.fileExtensionIsOneOf(file, group) ? group : undefined); +function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: ESMap, extensions: readonly string[][], keyMapper: (value: string) => string) { + const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined); if (!extensionGroup) { return; } for (let i = extensionGroup.length - 1; i >= 0; i--) { const ext = extensionGroup[i]; - if (ts.fileExtensionIs(file, ext)) { + if (fileExtensionIs(file, ext)) { return; } - const lowerPriorityPath = keyMapper(ts.changeExtension(file, ext)); + const lowerPriorityPath = keyMapper(changeExtension(file, ext)); wildcardFiles.delete(lowerPriorityPath); } } @@ -3710,10 +3731,10 @@ function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFil * Also converts enum values back to strings. */ /* @internal */ -export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts.CompilerOptions { - const out: ts.CompilerOptions = {}; +export function convertCompilerOptionsForTelemetry(opts: CompilerOptions): CompilerOptions { + const out: CompilerOptions = {}; for (const key in opts) { - if (ts.hasProperty(opts, key)) { + if (hasProperty(opts, key)) { const type = getOptionFromName(key); if (type !== undefined) { // Ignore unknown options out[key] = getOptionValueWithEmptyStrings(opts[key], type); @@ -3723,7 +3744,7 @@ export function convertCompilerOptionsForTelemetry(opts: ts.CompilerOptions): ts return out; } -function getOptionValueWithEmptyStrings(value: any, option: ts.CommandLineOption): {} { +function getOptionValueWithEmptyStrings(value: any, option: CommandLineOption): {} { switch (option.type) { case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "". return ""; @@ -3735,9 +3756,9 @@ function getOptionValueWithEmptyStrings(value: any, option: ts.CommandLineOption return typeof value === "boolean" ? value : ""; case "list": const elementType = option.element; - return ts.isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : ""; + return isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : ""; default: - return ts.forEachEntry(option.type, (optionEnumValue, optionStringValue) => { + return forEachEntry(option.type, (optionEnumValue, optionStringValue) => { if (optionEnumValue === value) { return optionStringValue; } @@ -3746,7 +3767,7 @@ function getOptionValueWithEmptyStrings(value: any, option: ts.CommandLineOption } -function getDefaultValueForOption(option: ts.CommandLineOption) { +function getDefaultValueForOption(option: CommandLineOption) { switch (option.type) { case "number": return 1; @@ -3762,6 +3783,6 @@ function getDefaultValueForOption(option: ts.CommandLineOption) { default: const iterResult = option.type.keys().next(); if (!iterResult.done) return iterResult.value; - return ts.Debug.fail("Expected 'option.type' to have entries."); + return Debug.fail("Expected 'option.type' to have entries."); } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ba8307d016a82..05a2b6bf085e3 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1,26 +1,30 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, CharacterCodes, Comparer, Comparison, Debug, EqualityComparer, ESMap, isWhiteSpaceLike, Iterator, Map, + MapLike, Push, Queue, ReadonlyESMap, ReadonlySet, Set, SortedArray, SortedReadonlyArray, TextSpan, + UnderscoreEscapedMap, +} from "./_namespaces/ts"; /** @internal */ -export function getIterator | ts.ReadonlyESMap | undefined>(iterable: I): ts.Iterator< - I extends ts.ReadonlyESMap ? [K, V] : - I extends ts.ReadonlySet ? T : +export function getIterator | ReadonlyESMap | undefined>(iterable: I): Iterator< + I extends ReadonlyESMap ? [K, V] : + I extends ReadonlySet ? T : I extends readonly (infer T)[] ? T : I extends undefined ? undefined : never>; /** @internal */ -export function getIterator(iterable: ts.ReadonlyESMap): ts.Iterator<[K, V]>; +export function getIterator(iterable: ReadonlyESMap): Iterator<[K, V]>; /** @internal */ -export function getIterator(iterable: ts.ReadonlyESMap | undefined): ts.Iterator<[K, V]> | undefined; +export function getIterator(iterable: ReadonlyESMap | undefined): Iterator<[K, V]> | undefined; /** @internal */ -export function getIterator(iterable: readonly T[] | ts.ReadonlySet): ts.Iterator; +export function getIterator(iterable: readonly T[] | ReadonlySet): Iterator; /** @internal */ -export function getIterator(iterable: readonly T[] | ts.ReadonlySet | undefined): ts.Iterator | undefined; +export function getIterator(iterable: readonly T[] | ReadonlySet | undefined): Iterator | undefined; /** @internal */ -export function getIterator(iterable: readonly any[] | ts.ReadonlySet | ts.ReadonlyESMap | undefined): ts.Iterator | undefined { +export function getIterator(iterable: readonly any[] | ReadonlySet | ReadonlyESMap | undefined): Iterator | undefined { if (iterable) { if (isArray(iterable)) return arrayIterator(iterable); - if (iterable instanceof ts.Map) return iterable.entries(); - if (iterable instanceof ts.Set) return iterable.values(); + if (iterable instanceof Map) return iterable.entries(); + if (iterable instanceof Set) return iterable.values(); throw new Error("Iteration not supported."); } } @@ -28,9 +32,9 @@ export function getIterator(iterable: readonly any[] | ts.ReadonlySet | ts. /** @internal */ export const emptyArray: never[] = [] as never[]; /** @internal */ -export const emptyMap: ts.ReadonlyESMap = new ts.Map(); +export const emptyMap: ReadonlyESMap = new Map(); /** @internal */ -export const emptySet: ts.ReadonlySet = new ts.Set(); +export const emptySet: ReadonlySet = new Set(); /** @internal */ export function length(array: readonly any[] | undefined): number { @@ -88,7 +92,7 @@ export function firstDefined(array: readonly T[] | undefined, callback: (e } /** @internal */ -export function firstDefinedIterator(iter: ts.Iterator, callback: (element: T) => U | undefined): U | undefined { +export function firstDefinedIterator(iter: Iterator, callback: (element: T) => U | undefined): U | undefined { while (true) { const iterResult = iter.next(); if (iterResult.done) { @@ -102,7 +106,7 @@ export function firstDefinedIterator(iter: ts.Iterator, callback: (elem } /** @internal */ -export function reduceLeftIterator(iterator: ts.Iterator | undefined, f: (memo: U, value: T, i: number) => U, initial: U): U { +export function reduceLeftIterator(iterator: Iterator | undefined, f: (memo: U, value: T, i: number) => U, initial: U): U { let result = initial; if (iterator) { for (let step = iterator.next(), pos = 0; !step.done; step = iterator.next(), pos++) { @@ -115,7 +119,7 @@ export function reduceLeftIterator(iterator: ts.Iterator | undefined, f /** @internal */ export function zipWith(arrayA: readonly T[], arrayB: readonly U[], callback: (a: T, b: U, index: number) => V): V[] { const result: V[] = []; - ts.Debug.assertEqual(arrayA.length, arrayB.length); + Debug.assertEqual(arrayA.length, arrayB.length); for (let i = 0; i < arrayA.length; i++) { result.push(callback(arrayA[i], arrayB[i], i)); } @@ -123,8 +127,8 @@ export function zipWith(arrayA: readonly T[], arrayB: readonly U[], cal } /** @internal */ -export function zipToIterator(arrayA: readonly T[], arrayB: readonly U[]): ts.Iterator<[T, U]> { - ts.Debug.assertEqual(arrayA.length, arrayB.length); +export function zipToIterator(arrayA: readonly T[], arrayB: readonly U[]): Iterator<[T, U]> { + Debug.assertEqual(arrayA.length, arrayB.length); let i = 0; return { next() { @@ -138,9 +142,9 @@ export function zipToIterator(arrayA: readonly T[], arrayB: readonly U[]): } /** @internal */ -export function zipToMap(keys: readonly K[], values: readonly V[]): ts.ESMap { - ts.Debug.assert(keys.length === values.length); - const map = new ts.Map(); +export function zipToMap(keys: readonly K[], values: readonly V[]): ESMap { + Debug.assert(keys.length === values.length); + const map = new Map(); for (let i = 0; i < keys.length; ++i) { map.set(keys[i], values[i]); } @@ -250,11 +254,11 @@ export function findMap(array: readonly T[], callback: (element: T, index: return result; } } - return ts.Debug.fail(); + return Debug.fail(); } /** @internal */ -export function contains(array: readonly T[] | undefined, value: T, equalityComparer: ts.EqualityComparer = equateValues): boolean { +export function contains(array: readonly T[] | undefined, value: T, equalityComparer: EqualityComparer = equateValues): boolean { if (array) { for (const v of array) { if (equalityComparer(v, value)) { @@ -266,7 +270,7 @@ export function contains(array: readonly T[] | undefined, value: T, equalityC } /** @internal */ -export function arraysEqual(a: readonly T[], b: readonly T[], equalityComparer: ts.EqualityComparer = equateValues): boolean { +export function arraysEqual(a: readonly T[], b: readonly T[], equalityComparer: EqualityComparer = equateValues): boolean { return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i])); } @@ -371,7 +375,7 @@ export function map(array: readonly T[] | undefined, f: (x: T, i: number) /** @internal */ -export function mapIterator(iter: ts.Iterator, mapFn: (x: T) => U): ts.Iterator { +export function mapIterator(iter: Iterator, mapFn: (x: T) => U): Iterator { return { next() { const iterRes = iter.next(); @@ -474,7 +478,7 @@ export function flatMapToMutable(array: readonly T[] | undefined, mapfn: ( } /** @internal */ -export function flatMapIterator(iter: ts.Iterator, mapfn: (x: T) => readonly U[] | ts.Iterator | undefined): ts.Iterator { +export function flatMapIterator(iter: Iterator, mapfn: (x: T) => readonly U[] | Iterator | undefined): Iterator { const first = iter.next(); if (first.done) { return emptyIterator; @@ -496,7 +500,7 @@ export function flatMapIterator(iter: ts.Iterator, mapfn: (x: T) => rea }, }; - function getIterator(x: T): ts.Iterator { + function getIterator(x: T): Iterator { const res = mapfn(x); return res === undefined ? emptyIterator : isArray(res) ? arrayIterator(res) : res; } @@ -564,7 +568,7 @@ export function mapDefined(array: readonly T[] | undefined, mapFn: (x: T, } /** @internal */ -export function mapDefinedIterator(iter: ts.Iterator, mapFn: (x: T) => U | undefined): ts.Iterator { +export function mapDefinedIterator(iter: Iterator, mapFn: (x: T) => U | undefined): Iterator { return { next() { while (true) { @@ -582,16 +586,16 @@ export function mapDefinedIterator(iter: ts.Iterator, mapFn: (x: T) => } /** @internal */ -export function mapDefinedEntries(map: ts.ReadonlyESMap, f: (key: K1, value: V1) => readonly [K2, V2] | undefined): ts.ESMap; +export function mapDefinedEntries(map: ReadonlyESMap, f: (key: K1, value: V1) => readonly [K2, V2] | undefined): ESMap; /** @internal */ -export function mapDefinedEntries(map: ts.ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): ts.ESMap | undefined; +export function mapDefinedEntries(map: ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): ESMap | undefined; /** @internal */ -export function mapDefinedEntries(map: ts.ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): ts.ESMap | undefined { +export function mapDefinedEntries(map: ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): ESMap | undefined { if (!map) { return undefined; } - const result = new ts.Map(); + const result = new Map(); map.forEach((value, key) => { const entry = f(key, value); if (entry !== undefined) { @@ -606,13 +610,13 @@ export function mapDefinedEntries(map: ts.ReadonlyESMap } /** @internal */ -export function mapDefinedValues(set: ts.ReadonlySet, f: (value: V1) => V2 | undefined): ts.Set; +export function mapDefinedValues(set: ReadonlySet, f: (value: V1) => V2 | undefined): Set; /** @internal */ -export function mapDefinedValues(set: ts.ReadonlySet | undefined, f: (value: V1) => V2 | undefined): ts.Set | undefined; +export function mapDefinedValues(set: ReadonlySet | undefined, f: (value: V1) => V2 | undefined): Set | undefined; /** @internal */ -export function mapDefinedValues(set: ts.ReadonlySet | undefined, f: (value: V1) => V2 | undefined): ts.Set | undefined { +export function mapDefinedValues(set: ReadonlySet | undefined, f: (value: V1) => V2 | undefined): Set | undefined { if (set) { - const result = new ts.Set(); + const result = new Set(); set.forEach(value => { const newValue = f(value); if (newValue !== undefined) { @@ -624,7 +628,7 @@ export function mapDefinedValues(set: ts.ReadonlySet | undefined, f: } /** @internal */ -export function getOrUpdate(map: ts.ESMap, key: K, callback: () => V) { +export function getOrUpdate(map: ESMap, key: K, callback: () => V) { if (map.has(key)) { return map.get(key)!; } @@ -634,7 +638,7 @@ export function getOrUpdate(map: ts.ESMap, key: K, callback: () => V } /** @internal */ -export function tryAddToSet(set: ts.Set, value: T) { +export function tryAddToSet(set: Set, value: T) { if (!set.has(value)) { set.add(value); return true; @@ -643,10 +647,10 @@ export function tryAddToSet(set: ts.Set, value: T) { } /** @internal */ -export const emptyIterator: ts.Iterator = { next: () => ({ value: undefined as never, done: true }) }; +export const emptyIterator: Iterator = { next: () => ({ value: undefined as never, done: true }) }; /** @internal */ -export function singleIterator(value: T): ts.Iterator { +export function singleIterator(value: T): Iterator { let done = false; return { next() { @@ -710,16 +714,16 @@ export function spanMap(array: readonly T[] | undefined, keyfn: (x: T, } /** @internal */ -export function mapEntries(map: ts.ReadonlyESMap, f: (key: K1, value: V1) => readonly [K2, V2]): ts.ESMap; +export function mapEntries(map: ReadonlyESMap, f: (key: K1, value: V1) => readonly [K2, V2]): ESMap; /** @internal */ -export function mapEntries(map: ts.ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): ts.ESMap | undefined; +export function mapEntries(map: ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): ESMap | undefined; /** @internal */ -export function mapEntries(map: ts.ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): ts.ESMap | undefined { +export function mapEntries(map: ReadonlyESMap | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): ESMap | undefined { if (!map) { return undefined; } - const result = new ts.Map(); + const result = new Map(); map.forEach((value, key) => { const [newKey, newValue] = f(key, value); result.set(newKey, newValue); @@ -790,7 +794,7 @@ export function indicesOf(array: readonly unknown[]): number[] { return array.map(selectIndex); } -function deduplicateRelational(array: readonly T[], equalityComparer: ts.EqualityComparer, comparer: ts.Comparer) { +function deduplicateRelational(array: readonly T[], equalityComparer: EqualityComparer, comparer: Comparer) { // Perform a stable sort of the array. This ensures the first entry in a list of // duplicates remains the first entry in the result. const indices = indicesOf(array); @@ -812,7 +816,7 @@ function deduplicateRelational(array: readonly T[], equalityComparer: ts.Equa return deduplicated.map(i => array[i]); } -function deduplicateEquality(array: readonly T[], equalityComparer: ts.EqualityComparer) { +function deduplicateEquality(array: readonly T[], equalityComparer: EqualityComparer) { const result: T[] = []; for (const item of array) { pushIfUnique(result, item, equalityComparer); @@ -827,7 +831,7 @@ function deduplicateEquality(array: readonly T[], equalityComparer: ts.Equali * @param comparer An optional `Comparer` used to sort entries before comparison, though the * result will remain in the original order in `array`. */ -export function deduplicate(array: readonly T[], equalityComparer: ts.EqualityComparer, comparer?: ts.Comparer): T[] { +export function deduplicate(array: readonly T[], equalityComparer: EqualityComparer, comparer?: Comparer): T[] { return array.length === 0 ? [] : array.length === 1 ? array.slice() : comparer ? deduplicateRelational(array, equalityComparer, comparer) : @@ -837,8 +841,8 @@ export function deduplicate(array: readonly T[], equalityComparer: ts.Equalit /** * Deduplicates an array that has already been sorted. */ -function deduplicateSorted(array: ts.SortedReadonlyArray, comparer: ts.EqualityComparer | ts.Comparer): ts.SortedReadonlyArray { - if (array.length === 0) return emptyArray as any as ts.SortedReadonlyArray; +function deduplicateSorted(array: SortedReadonlyArray, comparer: EqualityComparer | Comparer): SortedReadonlyArray { + if (array.length === 0) return emptyArray as any as SortedReadonlyArray; let last = array[0]; const deduplicated: T[] = [last]; @@ -850,27 +854,27 @@ function deduplicateSorted(array: ts.SortedReadonlyArray, comparer: ts.Equ // relational comparison // falls through - case ts.Comparison.EqualTo: + case Comparison.EqualTo: continue; - case ts.Comparison.LessThan: + case Comparison.LessThan: // If `array` is sorted, `next` should **never** be less than `last`. - return ts.Debug.fail("Array is unsorted."); + return Debug.fail("Array is unsorted."); } deduplicated.push(last = next); } - return deduplicated as any as ts.SortedReadonlyArray; + return deduplicated as any as SortedReadonlyArray; } /** @internal */ -export function createSortedArray(): ts.SortedArray { - return [] as any as ts.SortedArray; // TODO: GH#19873 +export function createSortedArray(): SortedArray { + return [] as any as SortedArray; // TODO: GH#19873 } /** @internal */ -export function insertSorted(array: ts.SortedArray, insert: T, compare: ts.Comparer, allowDuplicates?: boolean): boolean { +export function insertSorted(array: SortedArray, insert: T, compare: Comparer, allowDuplicates?: boolean): boolean { if (array.length === 0) { array.push(insert); return true; @@ -891,20 +895,20 @@ export function insertSorted(array: ts.SortedArray, insert: T, compare: ts } /** @internal */ -export function sortAndDeduplicate(array: readonly string[]): ts.SortedReadonlyArray; +export function sortAndDeduplicate(array: readonly string[]): SortedReadonlyArray; /** @internal */ -export function sortAndDeduplicate(array: readonly T[], comparer: ts.Comparer, equalityComparer?: ts.EqualityComparer): ts.SortedReadonlyArray; +export function sortAndDeduplicate(array: readonly T[], comparer: Comparer, equalityComparer?: EqualityComparer): SortedReadonlyArray; /** @internal */ -export function sortAndDeduplicate(array: readonly T[], comparer?: ts.Comparer, equalityComparer?: ts.EqualityComparer): ts.SortedReadonlyArray { - return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive as any as ts.Comparer); +export function sortAndDeduplicate(array: readonly T[], comparer?: Comparer, equalityComparer?: EqualityComparer): SortedReadonlyArray { + return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive as any as Comparer); } /** @internal */ -export function arrayIsSorted(array: readonly T[], comparer: ts.Comparer) { +export function arrayIsSorted(array: readonly T[], comparer: Comparer) { if (array.length < 2) return true; let prevElement = array[0]; for (const element of array.slice(1)) { - if (comparer(prevElement, element) === ts.Comparison.GreaterThan) { + if (comparer(prevElement, element) === Comparison.GreaterThan) { return false; } prevElement = element; @@ -968,35 +972,35 @@ export function compact(array: T[]): T[] { * are not present in `arrayA` but are present in `arrayB`. Assumes both arrays are sorted * based on the provided comparer. */ -export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: ts.Comparer): T[] | undefined { +export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | undefined, comparer: Comparer): T[] | undefined { if (!arrayB || !arrayA || arrayB.length === 0 || arrayA.length === 0) return arrayB; const result: T[] = []; loopB: for (let offsetA = 0, offsetB = 0; offsetB < arrayB.length; offsetB++) { if (offsetB > 0) { // Ensure `arrayB` is properly sorted. - ts.Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), ts.Comparison.EqualTo); + Debug.assertGreaterThanOrEqual(comparer(arrayB[offsetB], arrayB[offsetB - 1]), Comparison.EqualTo); } loopA: for (const startA = offsetA; offsetA < arrayA.length; offsetA++) { if (offsetA > startA) { // Ensure `arrayA` is properly sorted. We only need to perform this check if // `offsetA` has changed since we entered the loop. - ts.Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), ts.Comparison.EqualTo); + Debug.assertGreaterThanOrEqual(comparer(arrayA[offsetA], arrayA[offsetA - 1]), Comparison.EqualTo); } switch (comparer(arrayB[offsetB], arrayA[offsetA])) { - case ts.Comparison.LessThan: + case Comparison.LessThan: // If B is less than A, B does not exist in arrayA. Add B to the result and // move to the next element in arrayB without changing the current position // in arrayA. result.push(arrayB[offsetB]); continue loopB; - case ts.Comparison.EqualTo: + case Comparison.EqualTo: // If B is equal to A, B exists in arrayA. Move to the next element in // arrayB without adding B to the result or changing the current position // in arrayA. continue loopB; - case ts.Comparison.GreaterThan: + case Comparison.GreaterThan: // If B is greater than A, we need to keep looking for B in arrayA. Move to // the next element in arrayA and recheck. continue loopA; @@ -1032,7 +1036,7 @@ export function append(to: T[] | undefined, value: T): T[]; /** @internal */ export function append(to: T[] | undefined, value: T | undefined): T[] | undefined; /** @internal */ -export function append(to: ts.Push, value: T | undefined): void; +export function append(to: Push, value: T | undefined): void; /** @internal */ export function append(to: T[], value: T | undefined): T[] | undefined { if (value === undefined) return to; @@ -1106,7 +1110,7 @@ export function addRange(to: T[] | undefined, from: readonly T[] | undefined, /** * @return Whether the value was added. */ -export function pushIfUnique(array: T[], toAdd: T, equalityComparer?: ts.EqualityComparer): boolean { +export function pushIfUnique(array: T[], toAdd: T, equalityComparer?: EqualityComparer): boolean { if (contains(array, toAdd, equalityComparer)) { return false; } @@ -1120,7 +1124,7 @@ export function pushIfUnique(array: T[], toAdd: T, equalityComparer?: ts.Equa /** * Unlike `pushIfUnique`, this can take `undefined` as an input, and returns a new array. */ -export function appendIfUnique(array: T[] | undefined, toAdd: T, equalityComparer?: ts.EqualityComparer): T[] { +export function appendIfUnique(array: T[] | undefined, toAdd: T, equalityComparer?: EqualityComparer): T[] { if (array) { pushIfUnique(array, toAdd, equalityComparer); return array; @@ -1130,7 +1134,7 @@ export function appendIfUnique(array: T[] | undefined, toAdd: T, equalityComp } } -function stableSortIndices(array: readonly T[], indices: number[], comparer: ts.Comparer) { +function stableSortIndices(array: readonly T[], indices: number[], comparer: Comparer) { // sort indices by value then position indices.sort((x, y) => comparer(array[x], array[y]) || compareValues(x, y)); } @@ -1139,12 +1143,12 @@ function stableSortIndices(array: readonly T[], indices: number[], comparer: /** * Returns a new sorted array. */ -export function sort(array: readonly T[], comparer?: ts.Comparer): ts.SortedReadonlyArray { - return (array.length === 0 ? array : array.slice().sort(comparer)) as ts.SortedReadonlyArray; +export function sort(array: readonly T[], comparer?: Comparer): SortedReadonlyArray { + return (array.length === 0 ? array : array.slice().sort(comparer)) as SortedReadonlyArray; } /** @internal */ -export function arrayIterator(array: readonly T[]): ts.Iterator { +export function arrayIterator(array: readonly T[]): Iterator { let i = 0; return { next: () => { if (i === array.length) { @@ -1158,7 +1162,7 @@ export function arrayIterator(array: readonly T[]): ts.Iterator { } /** @internal */ -export function arrayReverseIterator(array: readonly T[]): ts.Iterator { +export function arrayReverseIterator(array: readonly T[]): Iterator { let i = array.length; return { next: () => { @@ -1177,10 +1181,10 @@ export function arrayReverseIterator(array: readonly T[]): ts.Iterator { /** * Stable sort of an array. Elements equal to each other maintain their relative position in the array. */ -export function stableSort(array: readonly T[], comparer: ts.Comparer): ts.SortedReadonlyArray { +export function stableSort(array: readonly T[], comparer: Comparer): SortedReadonlyArray { const indices = indicesOf(array); stableSortIndices(array, indices, comparer); - return indices.map(i => array[i]) as ts.SortedArray as ts.SortedReadonlyArray; + return indices.map(i => array[i]) as SortedArray as SortedReadonlyArray; } /** @internal */ @@ -1219,7 +1223,7 @@ export function firstOrUndefined(array: readonly T[] | undefined): T | undefi /** @internal */ export function first(array: readonly T[]): T { - ts.Debug.assert(array.length !== 0); + Debug.assert(array.length !== 0); return array[0]; } @@ -1233,7 +1237,7 @@ export function lastOrUndefined(array: readonly T[] | undefined): T | undefin /** @internal */ export function last(array: readonly T[]): T { - ts.Debug.assert(array.length !== 0); + Debug.assert(array.length !== 0); return array[array.length - 1]; } @@ -1252,7 +1256,7 @@ export function singleOrUndefined(array: readonly T[] | undefined): T | undef * Returns the only element of an array if it contains only one element; throws otherwise. */ export function single(array: readonly T[]): T { - return ts.Debug.checkDefined(singleOrUndefined(array)); + return Debug.checkDefined(singleOrUndefined(array)); } /** @internal */ @@ -1293,7 +1297,7 @@ export function replaceElement(array: readonly T[], index: number, value: T): * @param keyComparer A callback used to compare two keys in a sorted array. * @param offset An offset into `array` at which to start the search. */ -export function binarySearch(array: readonly T[], value: T, keySelector: (v: T) => U, keyComparer: ts.Comparer, offset?: number): number { +export function binarySearch(array: readonly T[], value: T, keySelector: (v: T) => U, keyComparer: Comparer, offset?: number): number { return binarySearchKey(array, keySelector(value), keySelector, keyComparer, offset); } @@ -1308,7 +1312,7 @@ export function binarySearch(array: readonly T[], value: T, keySelector: ( * @param keyComparer A callback used to compare two keys in a sorted array. * @param offset An offset into `array` at which to start the search. */ -export function binarySearchKey(array: readonly T[], key: U, keySelector: (v: T, i: number) => U, keyComparer: ts.Comparer, offset?: number): number { +export function binarySearchKey(array: readonly T[], key: U, keySelector: (v: T, i: number) => U, keyComparer: Comparer, offset?: number): number { if (!some(array)) { return -1; } @@ -1319,12 +1323,12 @@ export function binarySearchKey(array: readonly T[], key: U, keySelector: const middle = low + ((high - low) >> 1); const midKey = keySelector(array[middle], middle); switch (keyComparer(midKey, key)) { - case ts.Comparison.LessThan: + case Comparison.LessThan: low = middle + 1; break; - case ts.Comparison.EqualTo: + case Comparison.EqualTo: return middle; - case ts.Comparison.GreaterThan: + case Comparison.GreaterThan: high = middle - 1; break; } @@ -1371,7 +1375,7 @@ const hasOwnProperty = Object.prototype.hasOwnProperty; * @param map A map-like. * @param key A property key. */ -export function hasProperty(map: ts.MapLike, key: string): boolean { +export function hasProperty(map: MapLike, key: string): boolean { return hasOwnProperty.call(map, key); } @@ -1382,7 +1386,7 @@ export function hasProperty(map: ts.MapLike, key: string): boolean { * @param map A map-like. * @param key A property key. */ -export function getProperty(map: ts.MapLike, key: string): T | undefined { +export function getProperty(map: MapLike, key: string): T | undefined { return hasOwnProperty.call(map, key) ? map[key] : undefined; } @@ -1390,7 +1394,7 @@ export function getProperty(map: ts.MapLike, key: string): T | undefined { /** * Gets the owned, enumerable property keys of a map-like. */ -export function getOwnKeys(map: ts.MapLike): string[] { +export function getOwnKeys(map: MapLike): string[] { const keys: string[] = []; for (const key in map) { if (hasOwnProperty.call(map, key)) { @@ -1414,18 +1418,18 @@ export function getAllKeys(obj: object): string[] { } /** @internal */ -export function getOwnValues(collection: ts.MapLike | T[]): T[] { +export function getOwnValues(collection: MapLike | T[]): T[] { const values: T[] = []; for (const key in collection) { if (hasOwnProperty.call(collection, key)) { - values.push((collection as ts.MapLike)[key]); + values.push((collection as MapLike)[key]); } } return values; } -const _entries = Object.entries || ((obj: ts.MapLike) => { +const _entries = Object.entries || ((obj: MapLike) => { const keys = getOwnKeys(obj); const result: [string, T][] = Array(keys.length); for (let i = 0; i < keys.length; i++) { @@ -1435,7 +1439,7 @@ const _entries = Object.entries || ((obj: ts.MapLike) => { }); /** @internal */ -export function getEntries(obj: ts.MapLike): [string, T][] { +export function getEntries(obj: MapLike): [string, T][] { return obj ? _entries(obj) : []; } @@ -1450,11 +1454,11 @@ export function arrayOf(count: number, f: (index: number) => T): T[] { /** @internal */ /** Shims `Array.from`. */ -export function arrayFrom(iterator: ts.Iterator | IterableIterator, map: (t: T) => U): U[]; +export function arrayFrom(iterator: Iterator | IterableIterator, map: (t: T) => U): U[]; /** @internal */ -export function arrayFrom(iterator: ts.Iterator | IterableIterator): T[]; +export function arrayFrom(iterator: Iterator | IterableIterator): T[]; /** @internal */ -export function arrayFrom(iterator: ts.Iterator | IterableIterator, map?: (t: T) => U): (T | U)[] { +export function arrayFrom(iterator: Iterator | IterableIterator, map?: (t: T) => U): (T | U)[] { const result: (T | U)[] = []; for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { result.push(map ? map(iterResult.value) : iterResult.value); @@ -1483,7 +1487,7 @@ export function assign(t: T, ...args: (T | undefined)[]) { * @param left A map-like whose properties should be compared. * @param right A map-like whose properties should be compared. */ -export function equalOwnProperties(left: ts.MapLike | undefined, right: ts.MapLike | undefined, equalityComparer: ts.EqualityComparer = equateValues) { +export function equalOwnProperties(left: MapLike | undefined, right: MapLike | undefined, equalityComparer: EqualityComparer = equateValues) { if (left === right) return true; if (!left || !right) return false; for (const key in left) { @@ -1513,16 +1517,16 @@ export function equalOwnProperties(left: ts.MapLike | undefined, right: ts * the same key with the given 'makeKey' function, then the element with the higher * index in the array will be the one associated with the produced key. */ -export function arrayToMap(array: readonly V[], makeKey: (value: V) => K | undefined): ts.ESMap; +export function arrayToMap(array: readonly V[], makeKey: (value: V) => K | undefined): ESMap; /** @internal */ -export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V2): ts.ESMap; +export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V2): ESMap; /** @internal */ -export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined): ts.ESMap; +export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined): ESMap; /** @internal */ -export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined, makeValue: (value: T) => U): ts.ESMap; +export function arrayToMap(array: readonly T[], makeKey: (value: T) => string | undefined, makeValue: (value: T) => U): ESMap; /** @internal */ -export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V1 | V2 = identity): ts.ESMap { - const result = new ts.Map(); +export function arrayToMap(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V1 | V2 = identity): ESMap { + const result = new Map(); for (const value of array) { const key = makeKey(value); if (key !== undefined) result.set(key, makeValue(value)); @@ -1618,7 +1622,7 @@ export function maybeBind(obj: T, fn: ((this: T, ...args: } /** @internal */ -export interface MultiMap extends ts.ESMap { +export interface MultiMap extends ESMap { /** * Adds the value to an array of values associated with the key, and returns the array. * Creates the array if it does not already exist. @@ -1638,7 +1642,7 @@ export function createMultiMap(): MultiMap; export function createMultiMap(): MultiMap; /** @internal */ export function createMultiMap(): MultiMap { - const map = new ts.Map() as MultiMap; + const map = new Map() as MultiMap; map.add = multiMapAdd; map.remove = multiMapRemove; return map; @@ -1664,18 +1668,18 @@ function multiMapRemove(this: MultiMap, key: K, value: V) { } /** @internal */ -export interface UnderscoreEscapedMultiMap extends ts.UnderscoreEscapedMap { +export interface UnderscoreEscapedMultiMap extends UnderscoreEscapedMap { /** * Adds the value to an array of values associated with the key, and returns the array. * Creates the array if it does not already exist. */ - add(key: ts.__String, value: T): T[]; + add(key: __String, value: T): T[]; /** * Removes a value from an array of values associated with the key. * Does not preserve the order of those values. * Does nothing if `key` is not in `map`, or `value` is not in `map[key]`. */ - remove(key: ts.__String, value: T): void; + remove(key: __String, value: T): void; } /** @internal */ @@ -1684,7 +1688,7 @@ export function createUnderscoreEscapedMultiMap(): UnderscoreEscapedMultiMap< } /** @internal */ -export function createQueue(items?: readonly T[]): ts.Queue { +export function createQueue(items?: readonly T[]): Queue { const elements: (T | undefined)[] = items?.slice() || []; let headIndex = 0; @@ -1736,13 +1740,13 @@ export function createQueue(items?: readonly T[]): ts.Queue { * To facilitate a perf optimization (lazy allocation of bucket arrays), `TElement` is * assumed not to be an array type. */ -export function createSet(getHashCode: (element: TElement) => THash, equals: ts.EqualityComparer): ts.Set { - const multiMap = new ts.Map(); +export function createSet(getHashCode: (element: TElement) => THash, equals: EqualityComparer): Set { + const multiMap = new Map(); let size = 0; - function getElementIterator(): ts.Iterator { + function getElementIterator(): Iterator { const valueIt = multiMap.values(); - let arrayIt: ts.Iterator | undefined; + let arrayIt: Iterator | undefined; return { next: () => { while (true) { @@ -1768,7 +1772,7 @@ export function createSet(getHashCode: (element: TElem }; } - const set: ts.Set = { + const set: Set = { has(element: TElement): boolean { const hash = getHashCode(element); if (!multiMap.has(hash)) return false; @@ -1782,7 +1786,7 @@ export function createSet(getHashCode: (element: TElem } return false; }, - add(element: TElement): ts.Set { + add(element: TElement): Set { const hash = getHashCode(element); if (multiMap.has(hash)) { const values = multiMap.get(hash)!; @@ -1859,13 +1863,13 @@ export function createSet(getHashCode: (element: TElem } } }, - keys(): ts.Iterator { + keys(): Iterator { return getElementIterator(); }, - values(): ts.Iterator { + values(): Iterator { return getElementIterator(); }, - entries(): ts.Iterator<[TElement, TElement]> { + entries(): Iterator<[TElement, TElement]> { const it = getElementIterator(); return { next: () => { @@ -1921,7 +1925,7 @@ export function tryCast(value: T, test: (value: T) => boolean): T | undefined export function cast(value: TIn | undefined, test: (value: TIn) => value is TOut): TOut { if (value !== undefined && test(value)) return value; - return ts.Debug.fail(`Invalid cast. The supplied value ${value} did not pass the test '${ts.Debug.getFunctionName(test)}'.`); + return Debug.fail(`Invalid cast. The supplied value ${value} did not pass the test '${Debug.getFunctionName(test)}'.`); } /** @internal */ @@ -1929,7 +1933,7 @@ export function cast(value: TIn | undefined, test: export function noop(_?: unknown): void { } /** @internal */ -export const noopPush: ts.Push = { +export const noopPush: Push = { push: noop, length: 0 }; @@ -2026,7 +2030,7 @@ export function memoize(callback: () => T): () => T { /** @internal */ /** A version of `memoize` that supports a single primitive argument */ export function memoizeOne(callback: (arg: A) => T): (arg: A) => T { - const map = new ts.Map(); + const map = new Map(); return (arg: A) => { const key = `${typeof arg}:${arg}`; let value = map.get(key); @@ -2122,14 +2126,14 @@ export function equateStringsCaseSensitive(a: string, b: string) { return equateValues(a, b); } -function compareComparableValues(a: string | undefined, b: string | undefined): ts.Comparison; -function compareComparableValues(a: number | undefined, b: number | undefined): ts.Comparison; +function compareComparableValues(a: string | undefined, b: string | undefined): Comparison; +function compareComparableValues(a: number | undefined, b: number | undefined): Comparison; function compareComparableValues(a: string | number | undefined, b: string | number | undefined) { - return a === b ? ts.Comparison.EqualTo : - a === undefined ? ts.Comparison.LessThan : - b === undefined ? ts.Comparison.GreaterThan : - a < b ? ts.Comparison.LessThan : - ts.Comparison.GreaterThan; + return a === b ? Comparison.EqualTo : + a === undefined ? Comparison.LessThan : + b === undefined ? Comparison.GreaterThan : + a < b ? Comparison.LessThan : + Comparison.GreaterThan; } /** @internal */ @@ -2137,7 +2141,7 @@ function compareComparableValues(a: string | number | undefined, b: string | num * Compare two numeric values for their order relative to each other. * To compare strings, use any of the `compareStrings` functions. */ -export function compareValues(a: number | undefined, b: number | undefined): ts.Comparison { +export function compareValues(a: number | undefined, b: number | undefined): Comparison { return compareComparableValues(a, b); } @@ -2145,17 +2149,17 @@ export function compareValues(a: number | undefined, b: number | undefined): ts. /** * Compare two TextSpans, first by `start`, then by `length`. */ -export function compareTextSpans(a: Partial | undefined, b: Partial | undefined): ts.Comparison { +export function compareTextSpans(a: Partial | undefined, b: Partial | undefined): Comparison { return compareValues(a?.start, b?.start) || compareValues(a?.length, b?.length); } /** @internal */ -export function min(items: readonly [T, ...T[]], compare: ts.Comparer): T; +export function min(items: readonly [T, ...T[]], compare: Comparer): T; /** @internal */ -export function min(items: readonly T[], compare: ts.Comparer): T | undefined; +export function min(items: readonly T[], compare: Comparer): T | undefined; /** @internal */ -export function min(items: readonly T[], compare: ts.Comparer): T | undefined { - return reduceLeft(items, (x, y) => compare(x, y) === ts.Comparison.LessThan ? x : y); +export function min(items: readonly T[], compare: Comparer): T | undefined { + return reduceLeft(items, (x, y) => compare(x, y) === Comparison.LessThan ? x : y); } /** @internal */ @@ -2172,12 +2176,12 @@ export function min(items: readonly T[], compare: ts.Comparer): T | undefi * lowercase (such as `ẞ` (German sharp capital s)). */ export function compareStringsCaseInsensitive(a: string, b: string) { - if (a === b) return ts.Comparison.EqualTo; - if (a === undefined) return ts.Comparison.LessThan; - if (b === undefined) return ts.Comparison.GreaterThan; + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; a = a.toUpperCase(); b = b.toUpperCase(); - return a < b ? ts.Comparison.LessThan : a > b ? ts.Comparison.GreaterThan : ts.Comparison.EqualTo; + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; } /** @internal */ @@ -2191,7 +2195,7 @@ export function compareStringsCaseInsensitive(a: string, b: string) { * Case-sensitive comparisons compare both strings one code-point at a time using the integer * value of each code-point. */ -export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined): ts.Comparison { +export function compareStringsCaseSensitive(a: string | undefined, b: string | undefined): Comparison { return compareComparableValues(a, b); } @@ -2204,28 +2208,28 @@ export function getStringComparer(ignoreCase?: boolean) { * Creates a string comparer for use with string collation in the UI. */ const createUIStringComparer = (() => { - let defaultComparer: ts.Comparer | undefined; - let enUSComparer: ts.Comparer | undefined; + let defaultComparer: Comparer | undefined; + let enUSComparer: Comparer | undefined; const stringComparerFactory = getStringComparerFactory(); return createStringComparer; function compareWithCallback(a: string | undefined, b: string | undefined, comparer: (a: string, b: string) => number) { - if (a === b) return ts.Comparison.EqualTo; - if (a === undefined) return ts.Comparison.LessThan; - if (b === undefined) return ts.Comparison.GreaterThan; + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; const value = comparer(a, b); - return value < 0 ? ts.Comparison.LessThan : value > 0 ? ts.Comparison.GreaterThan : ts.Comparison.EqualTo; + return value < 0 ? Comparison.LessThan : value > 0 ? Comparison.GreaterThan : Comparison.EqualTo; } - function createIntlCollatorStringComparer(locale: string | undefined): ts.Comparer { + function createIntlCollatorStringComparer(locale: string | undefined): Comparer { // Intl.Collator.prototype.compare is bound to the collator. See NOTE in // http://www.ecma-international.org/ecma-402/2.0/#sec-Intl.Collator.prototype.compare const comparer = new Intl.Collator(locale, { usage: "sort", sensitivity: "variant" }).compare; return (a, b) => compareWithCallback(a, b, comparer); } - function createLocaleCompareStringComparer(locale: string | undefined): ts.Comparer { + function createLocaleCompareStringComparer(locale: string | undefined): Comparer { // if the locale is not the default locale (`undefined`), use the fallback comparer. if (locale !== undefined) return createFallbackStringComparer(); @@ -2236,7 +2240,7 @@ const createUIStringComparer = (() => { } } - function createFallbackStringComparer(): ts.Comparer { + function createFallbackStringComparer(): Comparer { // An ordinal comparison puts "A" after "b", but for the UI we want "A" before "b". // We first sort case insensitively. So "Aaa" will come before "baa". // Then we sort case sensitively, so "aaa" will come before "Aaa". @@ -2251,7 +2255,7 @@ const createUIStringComparer = (() => { } function compareStrings(a: string, b: string) { - return a < b ? ts.Comparison.LessThan : a > b ? ts.Comparison.GreaterThan : ts.Comparison.EqualTo; + return a < b ? Comparison.LessThan : a > b ? Comparison.GreaterThan : Comparison.EqualTo; } } @@ -2288,7 +2292,7 @@ const createUIStringComparer = (() => { } })(); -let uiComparerCaseSensitive: ts.Comparer | undefined; +let uiComparerCaseSensitive: Comparer | undefined; let uiLocale: string | undefined; /** @internal */ @@ -2321,16 +2325,16 @@ export function compareStringsCaseSensitiveUI(a: string, b: string) { } /** @internal */ -export function compareProperties(a: T | undefined, b: T | undefined, key: K, comparer: ts.Comparer): ts.Comparison { - return a === b ? ts.Comparison.EqualTo : - a === undefined ? ts.Comparison.LessThan : - b === undefined ? ts.Comparison.GreaterThan : +export function compareProperties(a: T | undefined, b: T | undefined, key: K, comparer: Comparer): Comparison { + return a === b ? Comparison.EqualTo : + a === undefined ? Comparison.LessThan : + b === undefined ? Comparison.GreaterThan : comparer(a[key], b[key]); } /** @internal */ /** True is greater than false. */ -export function compareBooleans(a: boolean, b: boolean): ts.Comparison { +export function compareBooleans(a: boolean, b: boolean): Comparison { return compareValues(a ? 1 : 0, b ? 1 : 0); } @@ -2368,7 +2372,7 @@ export function getSpellingSuggestion(name: string, candidates: T[], getName: continue; } - ts.Debug.assert(distance < bestDistance); // Else `levenshteinWithMax` should return undefined + Debug.assert(distance < bestDistance); // Else `levenshteinWithMax` should return undefined bestDistance = distance; bestCandidate = candidate; } @@ -2458,24 +2462,24 @@ export function removeMinAndVersionNumbers(fileName: string) { for (let pos = end - 1; pos > 0; pos--) { let ch: number = fileName.charCodeAt(pos); - if (ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9) { + if (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) { // Match a \d+ segment do { --pos; ch = fileName.charCodeAt(pos); - } while (pos > 0 && ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9); + } while (pos > 0 && ch >= CharacterCodes._0 && ch <= CharacterCodes._9); } - else if (pos > 4 && (ch === ts.CharacterCodes.n || ch === ts.CharacterCodes.N)) { + else if (pos > 4 && (ch === CharacterCodes.n || ch === CharacterCodes.N)) { // Looking for "min" or "min" // Already matched the 'n' --pos; ch = fileName.charCodeAt(pos); - if (ch !== ts.CharacterCodes.i && ch !== ts.CharacterCodes.I) { + if (ch !== CharacterCodes.i && ch !== CharacterCodes.I) { break; } --pos; ch = fileName.charCodeAt(pos); - if (ch !== ts.CharacterCodes.m && ch !== ts.CharacterCodes.M) { + if (ch !== CharacterCodes.m && ch !== CharacterCodes.M) { break; } --pos; @@ -2486,7 +2490,7 @@ export function removeMinAndVersionNumbers(fileName: string) { break; } - if (ch !== ts.CharacterCodes.minus && ch !== ts.CharacterCodes.dot) { + if (ch !== CharacterCodes.minus && ch !== CharacterCodes.dot) { break; } @@ -2568,7 +2572,7 @@ export function patternText({ prefix, suffix }: Pattern): string { * E.g.: matchedText(tryParsePattern("foo*baz"), "foobarbaz") === "bar" */ export function matchedText(pattern: Pattern, candidate: string): string { - ts.Debug.assert(isPatternMatch(pattern, candidate)); + Debug.assert(isPatternMatch(pattern, candidate)); return candidate.substring(pattern.prefix.length, candidate.length - pattern.suffix.length); } @@ -2651,7 +2655,7 @@ export function singleElementArray(t: T | undefined): T[] | undefined { } /** @internal */ -export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItems: readonly U[], comparer: (a: T, b: U) => ts.Comparison, inserted: (newItem: T) => void, deleted: (oldItem: U) => void, unchanged?: (oldItem: U, newItem: T) => void) { +export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItems: readonly U[], comparer: (a: T, b: U) => Comparison, inserted: (newItem: T) => void, deleted: (oldItem: U) => void, unchanged?: (oldItem: U, newItem: T) => void) { unchanged = unchanged || noop; let newIndex = 0; let oldIndex = 0; @@ -2662,12 +2666,12 @@ export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItem const newItem = newItems[newIndex]; const oldItem = oldItems[oldIndex]; const compareResult = comparer(newItem, oldItem); - if (compareResult === ts.Comparison.LessThan) { + if (compareResult === Comparison.LessThan) { inserted(newItem); newIndex++; hasChanges = true; } - else if (compareResult === ts.Comparison.GreaterThan) { + else if (compareResult === Comparison.GreaterThan) { deleted(oldItem); oldIndex++; hasChanges = true; @@ -2788,7 +2792,7 @@ export const trimStringStart = !!String.prototype.trimStart ? ((s: string) => s. function trimEndImpl(s: string) { let end = s.length - 1; while (end >= 0) { - if (!ts.isWhiteSpaceLike(s.charCodeAt(end))) break; + if (!isWhiteSpaceLike(s.charCodeAt(end))) break; end--; } return s.slice(0, end + 1); diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index 5c6a44d83a95a..591cd8945d28f 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -1,4 +1,21 @@ import * as ts from "./_namespaces/ts"; +import { + AnyFunction, AssertionLevel, BigIntLiteralType, CheckMode, compareValues, EmitFlags, every, FlowFlags, FlowNode, + FlowNodeBase, formatStringFromArgs, getDirectoryPath, getEffectiveModifierFlagsNoCache, getEmitFlags, getOwnKeys, + getParseTreeNode, getSourceFileOfNode, getSourceTextOfNodeFromSourceFile, hasProperty, idText, IntrinsicType, + isArrayTypeNode, isBigIntLiteral, isCallSignatureDeclaration, isConditionalTypeNode, isConstructorDeclaration, + isConstructorTypeNode, isConstructSignatureDeclaration, isFunctionTypeNode, isGeneratedIdentifier, + isGetAccessorDeclaration, isIdentifier, isImportTypeNode, isIndexedAccessTypeNode, isIndexSignatureDeclaration, + isInferTypeNode, isIntersectionTypeNode, isLiteralTypeNode, isMappedTypeNode, isNamedTupleMember, isNumericLiteral, + isOptionalTypeNode, isParameter, isParenthesizedTypeNode, isParseTreeNode, isPrivateIdentifier, isRestTypeNode, + isSetAccessorDeclaration, isStringLiteral, isThisTypeNode, isTupleTypeNode, isTypeLiteralNode, isTypeOperatorNode, + isTypeParameterDeclaration, isTypePredicateNode, isTypeQueryNode, isTypeReferenceNode, isUnionTypeNode, LiteralType, + map, Map, MatchingKeys, ModifierFlags, Node, NodeArray, NodeFlags, nodeIsSynthesized, noop, objectAllocator, + ObjectFlags, ObjectType, RelationComparisonResult, RequireResult, resolvePath, Signature, SignatureCheckMode, + SignatureFlags, SnippetKind, SortedReadonlyArray, stableSort, Symbol, SymbolFlags, symbolName, SyntaxKind, sys, + TransformFlags, Type, TypeFacts, TypeFlags, TypeMapKind, TypeMapper, unescapeLeadingUnderscores, VarianceFlags, + version, Version, zipWith, +} from "./_namespaces/ts"; /** @internal */ export enum LogLevel { @@ -18,28 +35,28 @@ export interface LoggingHost { export interface DeprecationOptions { message?: string; error?: boolean; - since?: ts.Version | string; - warnAfter?: ts.Version | string; - errorAfter?: ts.Version | string; - typeScriptVersion?: ts.Version | string; + since?: Version | string; + warnAfter?: Version | string; + errorAfter?: Version | string; + typeScriptVersion?: Version | string; name?: string; } /** @internal */ export namespace Debug { - let typeScriptVersion: ts.Version | undefined; + let typeScriptVersion: Version | undefined; /* eslint-disable prefer-const */ - let currentAssertionLevel = ts.AssertionLevel.None; + let currentAssertionLevel = AssertionLevel.None; export let currentLogLevel = LogLevel.Warning; export let isDebugging = false; export let loggingHost: LoggingHost | undefined; export let enableDeprecationWarnings = true; /* eslint-enable prefer-const */ - type AssertionKeys = ts.MatchingKeys; + type AssertionKeys = MatchingKeys; export function getTypeScriptVersion() { - return typeScriptVersion ?? (typeScriptVersion = new ts.Version(ts.version)); + return typeScriptVersion ?? (typeScriptVersion = new Version(version)); } export function shouldLog(level: LogLevel): boolean { @@ -74,19 +91,19 @@ export namespace Debug { } } - const assertionCache: Partial> = {}; + const assertionCache: Partial> = {}; export function getAssertionLevel() { return currentAssertionLevel; } - export function setAssertionLevel(level: ts.AssertionLevel) { + export function setAssertionLevel(level: AssertionLevel) { const prevAssertionLevel = currentAssertionLevel; currentAssertionLevel = level; if (level > prevAssertionLevel) { // restore assertion functions for the current assertion level (see `shouldAssertFunction`). - for (const key of ts.getOwnKeys(assertionCache) as AssertionKeys[]) { + for (const key of getOwnKeys(assertionCache) as AssertionKeys[]) { const cachedFunc = assertionCache[key]; if (cachedFunc !== undefined && Debug[key] !== cachedFunc.assertion && level >= cachedFunc.level) { (Debug as any)[key] = cachedFunc; @@ -96,7 +113,7 @@ export namespace Debug { } } - export function shouldAssert(level: ts.AssertionLevel): boolean { + export function shouldAssert(level: AssertionLevel): boolean { return currentAssertionLevel >= level; } @@ -106,16 +123,16 @@ export namespace Debug { * @param level The minimum assertion level required. * @param name The name of the current assertion function. */ - function shouldAssertFunction(level: ts.AssertionLevel, name: K): boolean { + function shouldAssertFunction(level: AssertionLevel, name: K): boolean { if (!shouldAssert(level)) { assertionCache[name] = { level, assertion: Debug[name] }; - (Debug as any)[name] = ts.noop; + (Debug as any)[name] = noop; return false; } return true; } - export function fail(message?: string, stackCrawlMark?: ts.AnyFunction): never { + export function fail(message?: string, stackCrawlMark?: AnyFunction): never { debugger; const e = new Error(message ? `Debug Failure. ${message}` : "Debug Failure."); if ((Error as any).captureStackTrace) { @@ -124,13 +141,13 @@ export namespace Debug { throw e; } - export function failBadSyntaxKind(node: ts.Node, message?: string, stackCrawlMark?: ts.AnyFunction): never { + export function failBadSyntaxKind(node: Node, message?: string, stackCrawlMark?: AnyFunction): never { return fail( `${message || "Unexpected node."}\r\nNode ${formatSyntaxKind(node.kind)} was unexpected.`, stackCrawlMark || failBadSyntaxKind); } - export function assert(expression: unknown, message?: string, verboseDebugInfo?: string | (() => string), stackCrawlMark?: ts.AnyFunction): asserts expression { + export function assert(expression: unknown, message?: string, verboseDebugInfo?: string | (() => string), stackCrawlMark?: AnyFunction): asserts expression { if (!expression) { message = message ? `False expression: ${message}` : "False expression."; if (verboseDebugInfo) { @@ -140,80 +157,80 @@ export namespace Debug { } } - export function assertEqual(a: T, b: T, msg?: string, msg2?: string, stackCrawlMark?: ts.AnyFunction): void { + export function assertEqual(a: T, b: T, msg?: string, msg2?: string, stackCrawlMark?: AnyFunction): void { if (a !== b) { const message = msg ? msg2 ? `${msg} ${msg2}` : msg : ""; fail(`Expected ${a} === ${b}. ${message}`, stackCrawlMark || assertEqual); } } - export function assertLessThan(a: number, b: number, msg?: string, stackCrawlMark?: ts.AnyFunction): void { + export function assertLessThan(a: number, b: number, msg?: string, stackCrawlMark?: AnyFunction): void { if (a >= b) { fail(`Expected ${a} < ${b}. ${msg || ""}`, stackCrawlMark || assertLessThan); } } - export function assertLessThanOrEqual(a: number, b: number, stackCrawlMark?: ts.AnyFunction): void { + export function assertLessThanOrEqual(a: number, b: number, stackCrawlMark?: AnyFunction): void { if (a > b) { fail(`Expected ${a} <= ${b}`, stackCrawlMark || assertLessThanOrEqual); } } - export function assertGreaterThanOrEqual(a: number, b: number, stackCrawlMark?: ts.AnyFunction): void { + export function assertGreaterThanOrEqual(a: number, b: number, stackCrawlMark?: AnyFunction): void { if (a < b) { fail(`Expected ${a} >= ${b}`, stackCrawlMark || assertGreaterThanOrEqual); } } - export function assertIsDefined(value: T, message?: string, stackCrawlMark?: ts.AnyFunction): asserts value is NonNullable { + export function assertIsDefined(value: T, message?: string, stackCrawlMark?: AnyFunction): asserts value is NonNullable { // eslint-disable-next-line no-null/no-null if (value === undefined || value === null) { fail(message, stackCrawlMark || assertIsDefined); } } - export function checkDefined(value: T | null | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): T { + export function checkDefined(value: T | null | undefined, message?: string, stackCrawlMark?: AnyFunction): T { assertIsDefined(value, message, stackCrawlMark || checkDefined); return value; } - export function assertEachIsDefined(value: ts.NodeArray, message?: string, stackCrawlMark?: ts.AnyFunction): asserts value is ts.NodeArray; - export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: ts.AnyFunction): asserts value is readonly NonNullable[]; - export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: ts.AnyFunction) { + export function assertEachIsDefined(value: NodeArray, message?: string, stackCrawlMark?: AnyFunction): asserts value is NodeArray; + export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: AnyFunction): asserts value is readonly NonNullable[]; + export function assertEachIsDefined(value: readonly T[], message?: string, stackCrawlMark?: AnyFunction) { for (const v of value) { assertIsDefined(v, message, stackCrawlMark || assertEachIsDefined); } } - export function checkEachDefined(value: A, message?: string, stackCrawlMark?: ts.AnyFunction): A { + export function checkEachDefined(value: A, message?: string, stackCrawlMark?: AnyFunction): A { assertEachIsDefined(value, message, stackCrawlMark || checkEachDefined); return value; } - export function assertNever(member: never, message = "Illegal value:", stackCrawlMark?: ts.AnyFunction): never { - const detail = typeof member === "object" && ts.hasProperty(member, "kind") && ts.hasProperty(member, "pos") ? "SyntaxKind: " + formatSyntaxKind((member as ts.Node).kind) : JSON.stringify(member); + export function assertNever(member: never, message = "Illegal value:", stackCrawlMark?: AnyFunction): never { + const detail = typeof member === "object" && hasProperty(member, "kind") && hasProperty(member, "pos") ? "SyntaxKind: " + formatSyntaxKind((member as Node).kind) : JSON.stringify(member); return fail(`${message} ${detail}`, stackCrawlMark || assertNever); } - export function assertEachNode(nodes: ts.NodeArray, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts nodes is ts.NodeArray; - export function assertEachNode(nodes: readonly T[], test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts nodes is readonly U[]; - export function assertEachNode(nodes: ts.NodeArray | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts nodes is ts.NodeArray | undefined; - export function assertEachNode(nodes: readonly T[] | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts nodes is readonly U[] | undefined; - export function assertEachNode(nodes: readonly ts.Node[], test: (node: ts.Node) => boolean, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertEachNode(nodes: readonly ts.Node[] | undefined, test: (node: ts.Node) => boolean, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertEachNode")) { + export function assertEachNode(nodes: NodeArray, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray; + export function assertEachNode(nodes: readonly T[], test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is readonly U[]; + export function assertEachNode(nodes: NodeArray | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray | undefined; + export function assertEachNode(nodes: readonly T[] | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is readonly U[] | undefined; + export function assertEachNode(nodes: readonly Node[], test: (node: Node) => boolean, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertEachNode(nodes: readonly Node[] | undefined, test: (node: Node) => boolean, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertEachNode")) { assert( - test === undefined || ts.every(nodes, test), + test === undefined || every(nodes, test), message || "Unexpected node.", () => `Node array did not pass test '${getFunctionName(test)}'.`, stackCrawlMark || assertEachNode); } } - export function assertNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is U; - export function assertNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertNode")) { + export function assertNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U; + export function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertNode")) { assert( node !== undefined && (test === undefined || test(node)), message || "Unexpected node.", @@ -222,10 +239,10 @@ export namespace Debug { } } - export function assertNotNode(node: T | undefined, test: (node: ts.Node) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is Exclude; - export function assertNotNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertNotNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertNotNode")) { + export function assertNotNode(node: T | undefined, test: (node: Node) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is Exclude; + export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertNotNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertNotNode")) { assert( node === undefined || test === undefined || !test(node), message || "Unexpected node.", @@ -234,11 +251,11 @@ export namespace Debug { } } - export function assertOptionalNode(node: T, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is U; - export function assertOptionalNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is U | undefined; - export function assertOptionalNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertOptionalNode(node: ts.Node | undefined, test: ((node: ts.Node) => boolean) | undefined, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertOptionalNode")) { + export function assertOptionalNode(node: T, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U; + export function assertOptionalNode(node: T | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts node is U | undefined; + export function assertOptionalNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertOptionalNode(node: Node | undefined, test: ((node: Node) => boolean) | undefined, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertOptionalNode")) { assert( test === undefined || node === undefined || test(node), message || "Unexpected node.", @@ -247,11 +264,11 @@ export namespace Debug { } } - export function assertOptionalToken(node: T, kind: K, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is Extract; - export function assertOptionalToken(node: T | undefined, kind: K, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is Extract | undefined; - export function assertOptionalToken(node: ts.Node | undefined, kind: ts.SyntaxKind | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): void; - export function assertOptionalToken(node: ts.Node | undefined, kind: ts.SyntaxKind | undefined, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertOptionalToken")) { + export function assertOptionalToken(node: T, kind: K, message?: string, stackCrawlMark?: AnyFunction): asserts node is Extract; + export function assertOptionalToken(node: T | undefined, kind: K, message?: string, stackCrawlMark?: AnyFunction): asserts node is Extract | undefined; + export function assertOptionalToken(node: Node | undefined, kind: SyntaxKind | undefined, message?: string, stackCrawlMark?: AnyFunction): void; + export function assertOptionalToken(node: Node | undefined, kind: SyntaxKind | undefined, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertOptionalToken")) { assert( kind === undefined || node === undefined || node.kind === kind, message || "Unexpected node.", @@ -260,9 +277,9 @@ export namespace Debug { } } - export function assertMissingNode(node: ts.Node | undefined, message?: string, stackCrawlMark?: ts.AnyFunction): asserts node is undefined; - export function assertMissingNode(node: ts.Node | undefined, message?: string, stackCrawlMark?: ts.AnyFunction) { - if (shouldAssertFunction(ts.AssertionLevel.Normal, "assertMissingNode")) { + export function assertMissingNode(node: Node | undefined, message?: string, stackCrawlMark?: AnyFunction): asserts node is undefined; + export function assertMissingNode(node: Node | undefined, message?: string, stackCrawlMark?: AnyFunction) { + if (shouldAssertFunction(AssertionLevel.Normal, "assertMissingNode")) { assert( node === undefined, message || "Unexpected node.", @@ -279,11 +296,11 @@ export namespace Debug { export function type(value: unknown): asserts value is T; export function type(_value: unknown) { } - export function getFunctionName(func: ts.AnyFunction) { + export function getFunctionName(func: AnyFunction) { if (typeof func !== "function") { return ""; } - else if (ts.hasProperty(func, "name")) { + else if (hasProperty(func, "name")) { return (func as any).name; } else { @@ -293,8 +310,8 @@ export namespace Debug { } } - export function formatSymbol(symbol: ts.Symbol): string { - return `{ name: ${ts.unescapeLeadingUnderscores(symbol.escapedName)}; flags: ${formatSymbolFlags(symbol.flags)}; declarations: ${ts.map(symbol.declarations, node => formatSyntaxKind(node.kind))} }`; + export function formatSymbol(symbol: Symbol): string { + return `{ name: ${unescapeLeadingUnderscores(symbol.escapedName)}; flags: ${formatSymbolFlags(symbol.flags)}; declarations: ${map(symbol.declarations, node => formatSyntaxKind(node.kind))} }`; } /** @@ -331,7 +348,7 @@ export namespace Debug { return value.toString(); } - const enumMemberCache = new ts.Map>(); + const enumMemberCache = new Map>(); function getEnumMembers(enumObject: any) { // Assuming enum objects do not change at runtime, we can cache the enum members list @@ -350,68 +367,68 @@ export namespace Debug { } } - const sorted = ts.stableSort<[number, string]>(result, (x, y) => ts.compareValues(x[0], y[0])); + const sorted = stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); enumMemberCache.set(enumObject, sorted); return sorted; } - export function formatSyntaxKind(kind: ts.SyntaxKind | undefined): string { + export function formatSyntaxKind(kind: SyntaxKind | undefined): string { return formatEnum(kind, (ts as any).SyntaxKind, /*isFlags*/ false); } - export function formatSnippetKind(kind: ts.SnippetKind | undefined): string { + export function formatSnippetKind(kind: SnippetKind | undefined): string { return formatEnum(kind, (ts as any).SnippetKind, /*isFlags*/ false); } - export function formatNodeFlags(flags: ts.NodeFlags | undefined): string { + export function formatNodeFlags(flags: NodeFlags | undefined): string { return formatEnum(flags, (ts as any).NodeFlags, /*isFlags*/ true); } - export function formatModifierFlags(flags: ts.ModifierFlags | undefined): string { + export function formatModifierFlags(flags: ModifierFlags | undefined): string { return formatEnum(flags, (ts as any).ModifierFlags, /*isFlags*/ true); } - export function formatTransformFlags(flags: ts.TransformFlags | undefined): string { + export function formatTransformFlags(flags: TransformFlags | undefined): string { return formatEnum(flags, (ts as any).TransformFlags, /*isFlags*/ true); } - export function formatEmitFlags(flags: ts.EmitFlags | undefined): string { + export function formatEmitFlags(flags: EmitFlags | undefined): string { return formatEnum(flags, (ts as any).EmitFlags, /*isFlags*/ true); } - export function formatSymbolFlags(flags: ts.SymbolFlags | undefined): string { + export function formatSymbolFlags(flags: SymbolFlags | undefined): string { return formatEnum(flags, (ts as any).SymbolFlags, /*isFlags*/ true); } - export function formatTypeFlags(flags: ts.TypeFlags | undefined): string { + export function formatTypeFlags(flags: TypeFlags | undefined): string { return formatEnum(flags, (ts as any).TypeFlags, /*isFlags*/ true); } - export function formatSignatureFlags(flags: ts.SignatureFlags | undefined): string { + export function formatSignatureFlags(flags: SignatureFlags | undefined): string { return formatEnum(flags, (ts as any).SignatureFlags, /*isFlags*/ true); } - export function formatObjectFlags(flags: ts.ObjectFlags | undefined): string { + export function formatObjectFlags(flags: ObjectFlags | undefined): string { return formatEnum(flags, (ts as any).ObjectFlags, /*isFlags*/ true); } - export function formatFlowFlags(flags: ts.FlowFlags | undefined): string { + export function formatFlowFlags(flags: FlowFlags | undefined): string { return formatEnum(flags, (ts as any).FlowFlags, /*isFlags*/ true); } - export function formatRelationComparisonResult(result: ts.RelationComparisonResult | undefined): string { + export function formatRelationComparisonResult(result: RelationComparisonResult | undefined): string { return formatEnum(result, (ts as any).RelationComparisonResult, /*isFlags*/ true); } - export function formatCheckMode(mode: ts.CheckMode | undefined): string { + export function formatCheckMode(mode: CheckMode | undefined): string { return formatEnum(mode, (ts as any).CheckMode, /*isFlags*/ true); } - export function formatSignatureCheckMode(mode: ts.SignatureCheckMode | undefined): string { + export function formatSignatureCheckMode(mode: SignatureCheckMode | undefined): string { return formatEnum(mode, (ts as any).SignatureCheckMode, /*isFlags*/ true); } - export function formatTypeFacts(facts: ts.TypeFacts | undefined): string { + export function formatTypeFacts(facts: TypeFacts | undefined): string { return formatEnum(facts, (ts as any).TypeFacts, /*isFlags*/ true); } @@ -419,7 +436,7 @@ export namespace Debug { interface ExtendedDebugModule { init(_ts: typeof ts): void; - formatControlFlowGraph(flowNode: ts.FlowNode): string; + formatControlFlowGraph(flowNode: FlowNode): string; } let extendedDebugModule: ExtendedDebugModule | undefined; @@ -432,52 +449,52 @@ export namespace Debug { return extendedDebugModule; } - export function printControlFlowGraph(flowNode: ts.FlowNode) { + export function printControlFlowGraph(flowNode: FlowNode) { return console.log(formatControlFlowGraph(flowNode)); } - export function formatControlFlowGraph(flowNode: ts.FlowNode) { + export function formatControlFlowGraph(flowNode: FlowNode) { return extendedDebug().formatControlFlowGraph(flowNode); } - let flowNodeProto: ts.FlowNodeBase | undefined; + let flowNodeProto: FlowNodeBase | undefined; - function attachFlowNodeDebugInfoWorker(flowNode: ts.FlowNodeBase) { + function attachFlowNodeDebugInfoWorker(flowNode: FlowNodeBase) { if (!("__debugFlowFlags" in flowNode)) { // eslint-disable-line local/no-in-operator Object.defineProperties(flowNode, { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { - value(this: ts.FlowNodeBase) { + value(this: FlowNodeBase) { const flowHeader = - this.flags & ts.FlowFlags.Start ? "FlowStart" : - this.flags & ts.FlowFlags.BranchLabel ? "FlowBranchLabel" : - this.flags & ts.FlowFlags.LoopLabel ? "FlowLoopLabel" : - this.flags & ts.FlowFlags.Assignment ? "FlowAssignment" : - this.flags & ts.FlowFlags.TrueCondition ? "FlowTrueCondition" : - this.flags & ts.FlowFlags.FalseCondition ? "FlowFalseCondition" : - this.flags & ts.FlowFlags.SwitchClause ? "FlowSwitchClause" : - this.flags & ts.FlowFlags.ArrayMutation ? "FlowArrayMutation" : - this.flags & ts.FlowFlags.Call ? "FlowCall" : - this.flags & ts.FlowFlags.ReduceLabel ? "FlowReduceLabel" : - this.flags & ts.FlowFlags.Unreachable ? "FlowUnreachable" : + this.flags & FlowFlags.Start ? "FlowStart" : + this.flags & FlowFlags.BranchLabel ? "FlowBranchLabel" : + this.flags & FlowFlags.LoopLabel ? "FlowLoopLabel" : + this.flags & FlowFlags.Assignment ? "FlowAssignment" : + this.flags & FlowFlags.TrueCondition ? "FlowTrueCondition" : + this.flags & FlowFlags.FalseCondition ? "FlowFalseCondition" : + this.flags & FlowFlags.SwitchClause ? "FlowSwitchClause" : + this.flags & FlowFlags.ArrayMutation ? "FlowArrayMutation" : + this.flags & FlowFlags.Call ? "FlowCall" : + this.flags & FlowFlags.ReduceLabel ? "FlowReduceLabel" : + this.flags & FlowFlags.Unreachable ? "FlowUnreachable" : "UnknownFlow"; - const remainingFlags = this.flags & ~(ts.FlowFlags.Referenced - 1); + const remainingFlags = this.flags & ~(FlowFlags.Referenced - 1); return `${flowHeader}${remainingFlags ? ` (${formatFlowFlags(remainingFlags)})`: ""}`; } }, - __debugFlowFlags: { get(this: ts.FlowNodeBase) { return formatEnum(this.flags, (ts as any).FlowFlags, /*isFlags*/ true); } }, - __debugToString: { value(this: ts.FlowNodeBase) { return formatControlFlowGraph(this); } } + __debugFlowFlags: { get(this: FlowNodeBase) { return formatEnum(this.flags, (ts as any).FlowFlags, /*isFlags*/ true); } }, + __debugToString: { value(this: FlowNodeBase) { return formatControlFlowGraph(this); } } }); } } - export function attachFlowNodeDebugInfo(flowNode: ts.FlowNodeBase) { + export function attachFlowNodeDebugInfo(flowNode: FlowNodeBase) { if (isDebugInfoEnabled) { if (typeof Object.setPrototypeOf === "function") { // if we're in es2015, attach the method to a shared prototype for `FlowNode` // so the method doesn't show up in the watch window. if (!flowNodeProto) { - flowNodeProto = Object.create(Object.prototype) as ts.FlowNodeBase; + flowNodeProto = Object.create(Object.prototype) as FlowNodeBase; attachFlowNodeDebugInfoWorker(flowNodeProto); } Object.setPrototypeOf(flowNode, flowNodeProto); @@ -489,13 +506,13 @@ export namespace Debug { } } - let nodeArrayProto: ts.NodeArray | undefined; + let nodeArrayProto: NodeArray | undefined; - function attachNodeArrayDebugInfoWorker(array: ts.NodeArray) { + function attachNodeArrayDebugInfoWorker(array: NodeArray) { if (!("__tsDebuggerDisplay" in array)) { // eslint-disable-line local/no-in-operator Object.defineProperties(array, { __tsDebuggerDisplay: { - value(this: ts.NodeArray, defaultValue: string) { + value(this: NodeArray, defaultValue: string) { // An `Array` with extra properties is rendered as `[A, B, prop1: 1, prop2: 2]`. Most of // these aren't immediately useful so we trim off the `prop1: ..., prop2: ...` part from the // formatted string. @@ -510,13 +527,13 @@ export namespace Debug { } } - export function attachNodeArrayDebugInfo(array: ts.NodeArray) { + export function attachNodeArrayDebugInfo(array: NodeArray) { if (isDebugInfoEnabled) { if (typeof Object.setPrototypeOf === "function") { // if we're in es2015, attach the method to a shared prototype for `NodeArray` // so the method doesn't show up in the watch window. if (!nodeArrayProto) { - nodeArrayProto = Object.create(Array.prototype) as ts.NodeArray; + nodeArrayProto = Object.create(Array.prototype) as NodeArray; attachNodeArrayDebugInfoWorker(nodeArrayProto); } Object.setPrototypeOf(array, nodeArrayProto); @@ -535,8 +552,8 @@ export namespace Debug { if (isDebugInfoEnabled) return; // avoid recomputing - let weakTypeTextMap: WeakMap | undefined; - let weakNodeTextMap: WeakMap | undefined; + let weakTypeTextMap: WeakMap | undefined; + let weakNodeTextMap: WeakMap | undefined; function getWeakTypeTextMap() { if (weakTypeTextMap === undefined) { @@ -554,56 +571,56 @@ export namespace Debug { // Add additional properties in debug mode to assist with debugging. - Object.defineProperties(ts.objectAllocator.getSymbolConstructor().prototype, { + Object.defineProperties(objectAllocator.getSymbolConstructor().prototype, { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { - value(this: ts.Symbol) { + value(this: Symbol) { const symbolHeader = - this.flags & ts.SymbolFlags.Transient ? "TransientSymbol" : + this.flags & SymbolFlags.Transient ? "TransientSymbol" : "Symbol"; - const remainingSymbolFlags = this.flags & ~ts.SymbolFlags.Transient; - return `${symbolHeader} '${ts.symbolName(this)}'${remainingSymbolFlags ? ` (${formatSymbolFlags(remainingSymbolFlags)})` : ""}`; + const remainingSymbolFlags = this.flags & ~SymbolFlags.Transient; + return `${symbolHeader} '${symbolName(this)}'${remainingSymbolFlags ? ` (${formatSymbolFlags(remainingSymbolFlags)})` : ""}`; } }, - __debugFlags: { get(this: ts.Symbol) { return formatSymbolFlags(this.flags); } } + __debugFlags: { get(this: Symbol) { return formatSymbolFlags(this.flags); } } }); - Object.defineProperties(ts.objectAllocator.getTypeConstructor().prototype, { + Object.defineProperties(objectAllocator.getTypeConstructor().prototype, { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { - value(this: ts.Type) { + value(this: Type) { const typeHeader = - this.flags & ts.TypeFlags.Nullable ? "NullableType" : - this.flags & ts.TypeFlags.StringOrNumberLiteral ? `LiteralType ${JSON.stringify((this as ts.LiteralType).value)}` : - this.flags & ts.TypeFlags.BigIntLiteral ? `LiteralType ${(this as ts.BigIntLiteralType).value.negative ? "-" : ""}${(this as ts.BigIntLiteralType).value.base10Value}n` : - this.flags & ts.TypeFlags.UniqueESSymbol ? "UniqueESSymbolType" : - this.flags & ts.TypeFlags.Enum ? "EnumType" : - this.flags & ts.TypeFlags.Intrinsic ? `IntrinsicType ${(this as ts.IntrinsicType).intrinsicName}` : - this.flags & ts.TypeFlags.Union ? "UnionType" : - this.flags & ts.TypeFlags.Intersection ? "IntersectionType" : - this.flags & ts.TypeFlags.Index ? "IndexType" : - this.flags & ts.TypeFlags.IndexedAccess ? "IndexedAccessType" : - this.flags & ts.TypeFlags.Conditional ? "ConditionalType" : - this.flags & ts.TypeFlags.Substitution ? "SubstitutionType" : - this.flags & ts.TypeFlags.TypeParameter ? "TypeParameter" : - this.flags & ts.TypeFlags.Object ? - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.ClassOrInterface ? "InterfaceType" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference ? "TypeReference" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.Tuple ? "TupleType" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.Anonymous ? "AnonymousType" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.Mapped ? "MappedType" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.ReverseMapped ? "ReverseMappedType" : - (this as ts.ObjectType).objectFlags & ts.ObjectFlags.EvolvingArray ? "EvolvingArrayType" : + this.flags & TypeFlags.Nullable ? "NullableType" : + this.flags & TypeFlags.StringOrNumberLiteral ? `LiteralType ${JSON.stringify((this as LiteralType).value)}` : + this.flags & TypeFlags.BigIntLiteral ? `LiteralType ${(this as BigIntLiteralType).value.negative ? "-" : ""}${(this as BigIntLiteralType).value.base10Value}n` : + this.flags & TypeFlags.UniqueESSymbol ? "UniqueESSymbolType" : + this.flags & TypeFlags.Enum ? "EnumType" : + this.flags & TypeFlags.Intrinsic ? `IntrinsicType ${(this as IntrinsicType).intrinsicName}` : + this.flags & TypeFlags.Union ? "UnionType" : + this.flags & TypeFlags.Intersection ? "IntersectionType" : + this.flags & TypeFlags.Index ? "IndexType" : + this.flags & TypeFlags.IndexedAccess ? "IndexedAccessType" : + this.flags & TypeFlags.Conditional ? "ConditionalType" : + this.flags & TypeFlags.Substitution ? "SubstitutionType" : + this.flags & TypeFlags.TypeParameter ? "TypeParameter" : + this.flags & TypeFlags.Object ? + (this as ObjectType).objectFlags & ObjectFlags.ClassOrInterface ? "InterfaceType" : + (this as ObjectType).objectFlags & ObjectFlags.Reference ? "TypeReference" : + (this as ObjectType).objectFlags & ObjectFlags.Tuple ? "TupleType" : + (this as ObjectType).objectFlags & ObjectFlags.Anonymous ? "AnonymousType" : + (this as ObjectType).objectFlags & ObjectFlags.Mapped ? "MappedType" : + (this as ObjectType).objectFlags & ObjectFlags.ReverseMapped ? "ReverseMappedType" : + (this as ObjectType).objectFlags & ObjectFlags.EvolvingArray ? "EvolvingArrayType" : "ObjectType" : "Type"; - const remainingObjectFlags = this.flags & ts.TypeFlags.Object ? (this as ts.ObjectType).objectFlags & ~ts.ObjectFlags.ObjectTypeKindMask : 0; - return `${typeHeader}${this.symbol ? ` '${ts.symbolName(this.symbol)}'` : ""}${remainingObjectFlags ? ` (${formatObjectFlags(remainingObjectFlags)})` : ""}`; + const remainingObjectFlags = this.flags & TypeFlags.Object ? (this as ObjectType).objectFlags & ~ObjectFlags.ObjectTypeKindMask : 0; + return `${typeHeader}${this.symbol ? ` '${symbolName(this.symbol)}'` : ""}${remainingObjectFlags ? ` (${formatObjectFlags(remainingObjectFlags)})` : ""}`; } }, - __debugFlags: { get(this: ts.Type) { return formatTypeFlags(this.flags); } }, - __debugObjectFlags: { get(this: ts.Type) { return this.flags & ts.TypeFlags.Object ? formatObjectFlags((this as ts.ObjectType).objectFlags) : ""; } }, + __debugFlags: { get(this: Type) { return formatTypeFlags(this.flags); } }, + __debugObjectFlags: { get(this: Type) { return this.flags & TypeFlags.Object ? formatObjectFlags((this as ObjectType).objectFlags) : ""; } }, __debugTypeToString: { - value(this: ts.Type) { + value(this: Type) { // avoid recomputing const map = getWeakTypeTextMap(); let text = map?.get(this); @@ -616,81 +633,81 @@ export namespace Debug { }, }); - Object.defineProperties(ts.objectAllocator.getSignatureConstructor().prototype, { - __debugFlags: { get(this: ts.Signature) { return formatSignatureFlags(this.flags); } }, - __debugSignatureToString: { value(this: ts.Signature) { return this.checker?.signatureToString(this); } } + Object.defineProperties(objectAllocator.getSignatureConstructor().prototype, { + __debugFlags: { get(this: Signature) { return formatSignatureFlags(this.flags); } }, + __debugSignatureToString: { value(this: Signature) { return this.checker?.signatureToString(this); } } }); const nodeConstructors = [ - ts.objectAllocator.getNodeConstructor(), - ts.objectAllocator.getIdentifierConstructor(), - ts.objectAllocator.getTokenConstructor(), - ts.objectAllocator.getSourceFileConstructor() + objectAllocator.getNodeConstructor(), + objectAllocator.getIdentifierConstructor(), + objectAllocator.getTokenConstructor(), + objectAllocator.getSourceFileConstructor() ]; for (const ctor of nodeConstructors) { - if (!ts.hasProperty(ctor.prototype, "__debugKind")) { + if (!hasProperty(ctor.prototype, "__debugKind")) { Object.defineProperties(ctor.prototype, { // for use with vscode-js-debug's new customDescriptionGenerator in launch.json __tsDebuggerDisplay: { - value(this: ts.Node) { + value(this: Node) { const nodeHeader = - ts.isGeneratedIdentifier(this) ? "GeneratedIdentifier" : - ts.isIdentifier(this) ? `Identifier '${ts.idText(this)}'` : - ts.isPrivateIdentifier(this) ? `PrivateIdentifier '${ts.idText(this)}'` : - ts.isStringLiteral(this) ? `StringLiteral ${JSON.stringify(this.text.length < 10 ? this.text : this.text.slice(10) + "...")}` : - ts.isNumericLiteral(this) ? `NumericLiteral ${this.text}` : - ts.isBigIntLiteral(this) ? `BigIntLiteral ${this.text}n` : - ts.isTypeParameterDeclaration(this) ? "TypeParameterDeclaration" : - ts.isParameter(this) ? "ParameterDeclaration" : - ts.isConstructorDeclaration(this) ? "ConstructorDeclaration" : - ts.isGetAccessorDeclaration(this) ? "GetAccessorDeclaration" : - ts.isSetAccessorDeclaration(this) ? "SetAccessorDeclaration" : - ts.isCallSignatureDeclaration(this) ? "CallSignatureDeclaration" : - ts.isConstructSignatureDeclaration(this) ? "ConstructSignatureDeclaration" : - ts.isIndexSignatureDeclaration(this) ? "IndexSignatureDeclaration" : - ts.isTypePredicateNode(this) ? "TypePredicateNode" : - ts.isTypeReferenceNode(this) ? "TypeReferenceNode" : - ts.isFunctionTypeNode(this) ? "FunctionTypeNode" : - ts.isConstructorTypeNode(this) ? "ConstructorTypeNode" : - ts.isTypeQueryNode(this) ? "TypeQueryNode" : - ts.isTypeLiteralNode(this) ? "TypeLiteralNode" : - ts.isArrayTypeNode(this) ? "ArrayTypeNode" : - ts.isTupleTypeNode(this) ? "TupleTypeNode" : - ts.isOptionalTypeNode(this) ? "OptionalTypeNode" : - ts.isRestTypeNode(this) ? "RestTypeNode" : - ts.isUnionTypeNode(this) ? "UnionTypeNode" : - ts.isIntersectionTypeNode(this) ? "IntersectionTypeNode" : - ts.isConditionalTypeNode(this) ? "ConditionalTypeNode" : - ts.isInferTypeNode(this) ? "InferTypeNode" : - ts.isParenthesizedTypeNode(this) ? "ParenthesizedTypeNode" : - ts.isThisTypeNode(this) ? "ThisTypeNode" : - ts.isTypeOperatorNode(this) ? "TypeOperatorNode" : - ts.isIndexedAccessTypeNode(this) ? "IndexedAccessTypeNode" : - ts.isMappedTypeNode(this) ? "MappedTypeNode" : - ts.isLiteralTypeNode(this) ? "LiteralTypeNode" : - ts.isNamedTupleMember(this) ? "NamedTupleMember" : - ts.isImportTypeNode(this) ? "ImportTypeNode" : + isGeneratedIdentifier(this) ? "GeneratedIdentifier" : + isIdentifier(this) ? `Identifier '${idText(this)}'` : + isPrivateIdentifier(this) ? `PrivateIdentifier '${idText(this)}'` : + isStringLiteral(this) ? `StringLiteral ${JSON.stringify(this.text.length < 10 ? this.text : this.text.slice(10) + "...")}` : + isNumericLiteral(this) ? `NumericLiteral ${this.text}` : + isBigIntLiteral(this) ? `BigIntLiteral ${this.text}n` : + isTypeParameterDeclaration(this) ? "TypeParameterDeclaration" : + isParameter(this) ? "ParameterDeclaration" : + isConstructorDeclaration(this) ? "ConstructorDeclaration" : + isGetAccessorDeclaration(this) ? "GetAccessorDeclaration" : + isSetAccessorDeclaration(this) ? "SetAccessorDeclaration" : + isCallSignatureDeclaration(this) ? "CallSignatureDeclaration" : + isConstructSignatureDeclaration(this) ? "ConstructSignatureDeclaration" : + isIndexSignatureDeclaration(this) ? "IndexSignatureDeclaration" : + isTypePredicateNode(this) ? "TypePredicateNode" : + isTypeReferenceNode(this) ? "TypeReferenceNode" : + isFunctionTypeNode(this) ? "FunctionTypeNode" : + isConstructorTypeNode(this) ? "ConstructorTypeNode" : + isTypeQueryNode(this) ? "TypeQueryNode" : + isTypeLiteralNode(this) ? "TypeLiteralNode" : + isArrayTypeNode(this) ? "ArrayTypeNode" : + isTupleTypeNode(this) ? "TupleTypeNode" : + isOptionalTypeNode(this) ? "OptionalTypeNode" : + isRestTypeNode(this) ? "RestTypeNode" : + isUnionTypeNode(this) ? "UnionTypeNode" : + isIntersectionTypeNode(this) ? "IntersectionTypeNode" : + isConditionalTypeNode(this) ? "ConditionalTypeNode" : + isInferTypeNode(this) ? "InferTypeNode" : + isParenthesizedTypeNode(this) ? "ParenthesizedTypeNode" : + isThisTypeNode(this) ? "ThisTypeNode" : + isTypeOperatorNode(this) ? "TypeOperatorNode" : + isIndexedAccessTypeNode(this) ? "IndexedAccessTypeNode" : + isMappedTypeNode(this) ? "MappedTypeNode" : + isLiteralTypeNode(this) ? "LiteralTypeNode" : + isNamedTupleMember(this) ? "NamedTupleMember" : + isImportTypeNode(this) ? "ImportTypeNode" : formatSyntaxKind(this.kind); return `${nodeHeader}${this.flags ? ` (${formatNodeFlags(this.flags)})` : ""}`; } }, - __debugKind: { get(this: ts.Node) { return formatSyntaxKind(this.kind); } }, - __debugNodeFlags: { get(this: ts.Node) { return formatNodeFlags(this.flags); } }, - __debugModifierFlags: { get(this: ts.Node) { return formatModifierFlags(ts.getEffectiveModifierFlagsNoCache(this)); } }, - __debugTransformFlags: { get(this: ts.Node) { return formatTransformFlags(this.transformFlags); } }, - __debugIsParseTreeNode: { get(this: ts.Node) { return ts.isParseTreeNode(this); } }, - __debugEmitFlags: { get(this: ts.Node) { return formatEmitFlags(ts.getEmitFlags(this)); } }, + __debugKind: { get(this: Node) { return formatSyntaxKind(this.kind); } }, + __debugNodeFlags: { get(this: Node) { return formatNodeFlags(this.flags); } }, + __debugModifierFlags: { get(this: Node) { return formatModifierFlags(getEffectiveModifierFlagsNoCache(this)); } }, + __debugTransformFlags: { get(this: Node) { return formatTransformFlags(this.transformFlags); } }, + __debugIsParseTreeNode: { get(this: Node) { return isParseTreeNode(this); } }, + __debugEmitFlags: { get(this: Node) { return formatEmitFlags(getEmitFlags(this)); } }, __debugGetText: { - value(this: ts.Node, includeTrivia?: boolean) { - if (ts.nodeIsSynthesized(this)) return ""; + value(this: Node, includeTrivia?: boolean) { + if (nodeIsSynthesized(this)) return ""; // avoid recomputing const map = getWeakNodeTextMap(); let text = map?.get(this); if (text === undefined) { - const parseNode = ts.getParseTreeNode(this); - const sourceFile = parseNode && ts.getSourceFileOfNode(parseNode); - text = sourceFile ? ts.getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; + const parseNode = getParseTreeNode(this); + const sourceFile = parseNode && getSourceFileOfNode(parseNode); + text = sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : ""; map?.set(this, text); } return text; @@ -702,9 +719,9 @@ export namespace Debug { // attempt to load extended debugging information try { - if (ts.sys && ts.sys.require) { - const basePath = ts.getDirectoryPath(ts.resolvePath(ts.sys.getExecutingFilePath())); - const result = ts.sys.require(basePath, "./compiler-debug") as ts.RequireResult; + if (sys && sys.require) { + const basePath = getDirectoryPath(resolvePath(sys.getExecutingFilePath())); + const result = sys.require(basePath, "./compiler-debug") as RequireResult; if (!result.error) { result.module.init(ts); extendedDebugModule = result.module; @@ -718,23 +735,23 @@ export namespace Debug { isDebugInfoEnabled = true; } - function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: ts.Version | undefined, since: ts.Version | undefined, message: string | undefined) { + function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: "; deprecationMessage += `'${name}' `; deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated"; deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : "."; - deprecationMessage += message ? ` ${ts.formatStringFromArgs(message, [name], 0)}` : ""; + deprecationMessage += message ? ` ${formatStringFromArgs(message, [name], 0)}` : ""; return deprecationMessage; } - function createErrorDeprecation(name: string, errorAfter: ts.Version | undefined, since: ts.Version | undefined, message: string | undefined) { + function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message); return () => { throw new TypeError(deprecationMessage); }; } - function createWarningDeprecation(name: string, errorAfter: ts.Version | undefined, since: ts.Version | undefined, message: string | undefined) { + function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) { let hasWrittenDeprecation = false; return () => { if (enableDeprecationWarnings && !hasWrittenDeprecation) { @@ -747,15 +764,15 @@ export namespace Debug { export function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never; export function createDeprecation(name: string, options?: DeprecationOptions): () => void; export function createDeprecation(name: string, options: DeprecationOptions = {}) { - const version = typeof options.typeScriptVersion === "string" ? new ts.Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion(); - const errorAfter = typeof options.errorAfter === "string" ? new ts.Version(options.errorAfter) : options.errorAfter; - const warnAfter = typeof options.warnAfter === "string" ? new ts.Version(options.warnAfter) : options.warnAfter; - const since = typeof options.since === "string" ? new ts.Version(options.since) : options.since ?? warnAfter; + const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion(); + const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter; + const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter; + const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter; const error = options.error || errorAfter && version.compareTo(errorAfter) <= 0; const warn = !warnAfter || version.compareTo(warnAfter) >= 0; return error ? createErrorDeprecation(name, errorAfter, since, options.message) : warn ? createWarningDeprecation(name, errorAfter, since, options.message) : - ts.noop; + noop; } function wrapFunction any>(deprecation: () => void, func: F): F { @@ -770,48 +787,48 @@ export namespace Debug { return wrapFunction(deprecation, func); } - export function formatVariance(varianceFlags: ts.VarianceFlags) { - const variance = varianceFlags & ts.VarianceFlags.VarianceMask; + export function formatVariance(varianceFlags: VarianceFlags) { + const variance = varianceFlags & VarianceFlags.VarianceMask; let result = - variance === ts.VarianceFlags.Invariant ? "in out" : - variance === ts.VarianceFlags.Bivariant ? "[bivariant]" : - variance === ts.VarianceFlags.Contravariant ? "in" : - variance === ts.VarianceFlags.Covariant ? "out" : - variance === ts.VarianceFlags.Independent ? "[independent]" : ""; - if (varianceFlags & ts.VarianceFlags.Unmeasurable) { + variance === VarianceFlags.Invariant ? "in out" : + variance === VarianceFlags.Bivariant ? "[bivariant]" : + variance === VarianceFlags.Contravariant ? "in" : + variance === VarianceFlags.Covariant ? "out" : + variance === VarianceFlags.Independent ? "[independent]" : ""; + if (varianceFlags & VarianceFlags.Unmeasurable) { result += " (unmeasurable)"; } - else if (varianceFlags & ts.VarianceFlags.Unreliable) { + else if (varianceFlags & VarianceFlags.Unreliable) { result += " (unreliable)"; } return result; } - export type DebugType = ts.Type & { __debugTypeToString(): string }; // eslint-disable-line @typescript-eslint/naming-convention + export type DebugType = Type & { __debugTypeToString(): string }; // eslint-disable-line @typescript-eslint/naming-convention export class DebugTypeMapper { - declare kind: ts.TypeMapKind; + declare kind: TypeMapKind; __debugToString(): string { // eslint-disable-line @typescript-eslint/naming-convention - type(this); + type(this); switch (this.kind) { - case ts.TypeMapKind.Function: return this.debugInfo?.() || "(function mapper)"; - case ts.TypeMapKind.Simple: return `${(this.source as DebugType).__debugTypeToString()} -> ${(this.target as DebugType).__debugTypeToString()}`; - case ts.TypeMapKind.Array: return ts.zipWith( + case TypeMapKind.Function: return this.debugInfo?.() || "(function mapper)"; + case TypeMapKind.Simple: return `${(this.source as DebugType).__debugTypeToString()} -> ${(this.target as DebugType).__debugTypeToString()}`; + case TypeMapKind.Array: return zipWith( this.sources as readonly DebugType[], - this.targets as readonly DebugType[] || ts.map(this.sources, () => "any"), + this.targets as readonly DebugType[] || map(this.sources, () => "any"), (s, t) => `${s.__debugTypeToString()} -> ${typeof t === "string" ? t : t.__debugTypeToString()}`).join(", "); - case ts.TypeMapKind.Deferred: return ts.zipWith( + case TypeMapKind.Deferred: return zipWith( this.sources, this.targets, (s, t) => `${(s as DebugType).__debugTypeToString()} -> ${(t() as DebugType).__debugTypeToString()}`).join(", "); - case ts.TypeMapKind.Merged: - case ts.TypeMapKind.Composite: return `m1: ${(this.mapper1 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ")} + case TypeMapKind.Merged: + case TypeMapKind.Composite: return `m1: ${(this.mapper1 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ")} m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n").join("\n ")}`; default: return assertNever(this); } } } - export function attachDebugPrototypeIfDebug(mapper: ts.TypeMapper): ts.TypeMapper { + export function attachDebugPrototypeIfDebug(mapper: TypeMapper): TypeMapper { if (isDebugging) { return Object.setPrototypeOf(mapper, DebugTypeMapper.prototype); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b704e6ebb3c8b..60e33b2eecdd3 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,10 +1,90 @@ import * as ts from "./_namespaces/ts"; +import { + AccessorDeclaration, ArrayBindingPattern, ArrayLiteralExpression, arrayToMap, ArrayTypeNode, ArrowFunction, + AsExpression, AssertClause, AssertEntry, AwaitExpression, base64encode, BigIntLiteral, BinaryExpression, + BinaryOperatorToken, BindingElement, BindingPattern, Block, BlockLike, BreakStatement, BuildInfo, Bundle, + BundleBuildInfo, BundleFileInfo, BundleFileSectionKind, BundleFileTextLike, BundleFileTextLikeKind, CallExpression, + CallSignatureDeclaration, CaseBlock, CaseClause, CaseOrDefaultClause, cast, CatchClause, changeExtension, + CharacterCodes, ClassDeclaration, ClassExpression, ClassStaticBlockDeclaration, clone, combinePaths, + CommaListExpression, CommentRange, compareEmitHelpers, comparePaths, Comparison, CompilerHost, CompilerOptions, + computeCommonSourceDirectoryOfFilenames, ComputedPropertyName, computeLineStarts, computeSignature, + ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, + ConstructSignatureDeclaration, contains, ContinueStatement, createBinaryExpressionTrampoline, + createDiagnosticCollection, createGetCanonicalFileName, createInputFilesWithFileTexts, createMultiMap, + createPrependNodes, createSourceMapGenerator, createTextWriter, CustomTransformers, Debug, DebuggerStatement, + DeclarationName, Decorator, DefaultClause, DeleteExpression, directorySeparator, DoStatement, DotToken, + ElementAccessExpression, emitDetachedComments, EmitFileNames, EmitFlags, EmitHint, EmitHost, + emitNewLineBeforeLeadingCommentOfPosition, EmitOnly, EmitResolver, EmitResult, EmitTextWriter, EmitTransformers, + emptyArray, ensurePathIsNonModuleName, ensureTrailingDirectorySeparator, EntityName, EnumDeclaration, EnumMember, + escapeJsxAttributeString, escapeLeadingUnderscores, escapeNonAsciiString, escapeString, ESMap, every, + ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, ExpressionStatement, ExpressionWithTypeArguments, + Extension, ExternalModuleReference, factory, fileExtensionIs, fileExtensionIsOneOf, FileReference, filter, + findIndex, firstOrUndefined, forEach, forEachChild, forEachLeadingCommentRange, forEachTrailingCommentRange, + ForInOrOfStatement, ForInStatement, formatGeneratedName, formatGeneratedNamePart, ForOfStatement, ForStatement, + FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, FunctionTypeNode, GeneratedIdentifier, + GeneratedIdentifierFlags, GeneratedNamePart, GeneratedPrivateIdentifier, getAreDeclarationMapsEnabled, + getBaseFileName, GetCanonicalFileName, getCommentRange, getConstantValue, getContainingNodeArray, + getDeclarationEmitExtensionForPath, getDeclarationEmitOutputFilePath, getDirectoryPath, getEmitDeclarations, + getEmitFlags, getEmitHelpers, getEmitModuleKind, getExternalHelpersModuleName, getExternalModuleName, + getLeadingCommentRanges, getLineAndCharacterOfPosition, getLinesBetweenPositionAndNextNonWhitespaceCharacter, + getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter, getLinesBetweenRangeEndAndRangeStart, getLineStarts, + getLiteralText, GetLiteralTextFlags, getNewLineCharacter, getNodeForGeneratedName, getNodeId, + getNormalizedAbsolutePath, getOriginalNode, getOwnEmitOutputFilePath, getParseTreeNode, + getRelativePathFromDirectory, getRelativePathToDirectoryOrUrl, getRootLength, getShebang, getSnippetElement, + getSourceFileOfNode, getSourceFilePathInNewDir, getSourceFilesToEmit, getSourceMapRange, + getSourceTextOfNodeFromSourceFile, getStartsOnNewLine, getSyntheticLeadingComments, getSyntheticTrailingComments, + getTextOfJSDocComment, getTrailingCommentRanges, getTrailingSemicolonDeferringWriter, getTransformers, getTypeNode, + guessIndentation, hasRecordedExternalHelpers, HeritageClause, Identifier, idText, IfStatement, ImportClause, + ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, ImportSpecifier, ImportTypeNode, + IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, InterfaceDeclaration, IntersectionTypeNode, + isAccessExpression, isArray, isArrowFunction, isBinaryExpression, isBindingPattern, isBlock, isBundle, + isBundleFileTextLike, isDeclaration, isDeclarationFileName, isDecorator, isEmptyStatement, isExportAssignment, + isExportSpecifier, isExpression, isFunctionLike, isGeneratedIdentifier, isGeneratedPrivateIdentifier, isIdentifier, + isIncrementalCompilation, isInJsonFile, isInternalDeclaration, isJSDocLikeText, isJsonSourceFile, + isJsxClosingElement, isJsxOpeningElement, isKeyword, isLet, isLiteralExpression, isMemberName, isModifier, + isModuleDeclaration, isNodeDescendantOf, isNumericLiteral, isParenthesizedExpression, isPartiallyEmittedExpression, + isPinnedComment, isPrivateIdentifier, isPrologueDirective, isRecognizedTripleSlashComment, isSourceFile, + isSourceFileNotJson, isStringLiteral, isTemplateLiteralKind, isTokenKind, isTypeParameterDeclaration, + isUnparsedNode, isUnparsedPrepend, isUnparsedSource, isVarConst, isVariableStatement, JSDoc, JSDocAugmentsTag, + JSDocCallbackTag, JSDocComment, JSDocEnumTag, JSDocFunctionType, JSDocImplementsTag, JSDocNameReference, + JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, JSDocPropertyLikeTag, JSDocReturnTag, JSDocSeeTag, + JSDocSignature, JSDocTag, JSDocTemplateTag, JSDocThisTag, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeLiteral, + JSDocTypeTag, JSDocVariadicType, JsxAttribute, JsxAttributes, JsxClosingElement, JsxClosingFragment, JsxElement, + JsxEmit, JsxExpression, JsxFragment, JsxOpeningElement, JsxOpeningFragment, JsxSelfClosingElement, + JsxSpreadAttribute, JsxTagNameExpression, JsxText, LabeledStatement, last, lastOrUndefined, LateBoundDeclaration, + length, ListFormat, LiteralExpression, LiteralLikeNode, LiteralTypeNode, makeIdentifierFromModuleName, Map, + MappedTypeNode, maybeBind, memoize, MetaProperty, MethodDeclaration, MethodSignature, Modifier, ModifierLike, + ModuleBlock, ModuleDeclaration, ModuleKind, ModuleReference, NamedDeclaration, NamedExports, NamedImports, + NamedImportsOrExports, NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, + NewExpression, Node, NodeArray, NodeFlags, nodeIsSynthesized, noEmitNotification, noEmitSubstitution, + NonNullExpression, normalizePath, normalizeSlashes, notImplemented, NumericLiteral, ObjectBindingPattern, + ObjectLiteralExpression, OptionalTypeNode, outFile, OutputFile, ParameterDeclaration, ParenthesizedExpression, + ParenthesizedTypeNode, ParsedCommandLine, PartiallyEmittedExpression, Placeholder, positionIsSynthesized, + positionsAreOnSameLine, PostfixUnaryExpression, PrefixUnaryExpression, Printer, PrinterOptions, PrintHandlers, + PrivateIdentifier, ProgramBuildInfo, ProgramBundleEmitBuildInfo, ProjectReference, PropertyAccessExpression, + PropertyAssignment, PropertyDeclaration, PropertySignature, QualifiedName, rangeEndIsOnSameLineAsRangeStart, + rangeEndPositionsAreOnSameLine, rangeIsOnSingleLine, rangeStartPositionsAreOnSameLine, readJsonOrUndefined, + removeFileExtension, resolvePath, RestTypeNode, returnFalse, ReturnStatement, returnUndefined, SatisfiesExpression, + ScriptTarget, Set, setEachParent, setOriginalNode, setParent, setTextRange, setTextRangePosEnd, + setTextRangePosWidth, ShorthandPropertyAssignment, SignatureDeclaration, singleOrUndefined, + skipPartiallyEmittedExpressions, skipTrivia, SnippetElement, SnippetKind, some, SourceFile, + SourceFilePrologueDirective, SourceFilePrologueInfo, SourceMapEmitResult, SourceMapGenerator, SourceMapSource, + SpreadAssignment, SpreadElement, stableSort, Statement, stringContains, StringLiteral, supportedJSExtensionsFlat, + SwitchStatement, Symbol, SymbolFlags, SyntaxKind, SynthesizedComment, sys, TabStop, TaggedTemplateExpression, + TemplateExpression, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateSpan, TextRange, ThrowStatement, + tokenToString, tracing, TransformationResult, transformNodes, tryParseRawSourceMap, TryStatement, TupleTypeNode, + TypeAliasDeclaration, TypeAssertion, TypeLiteralNode, TypeNode, TypeOfExpression, TypeOperatorNode, + TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnionTypeNode, UnparsedNode, + UnparsedPrepend, UnparsedPrologue, UnparsedSource, UnparsedSyntheticReference, UnparsedTextLike, + VariableDeclaration, VariableDeclarationList, VariableStatement, VoidExpression, WhileStatement, WithStatement, + writeCommentRange, writeFile, WriteFileCallbackData, YieldExpression, +} from "./_namespaces/ts"; const brackets = createBracketsMap(); /*@internal*/ export function isBuildInfoFile(file: string) { - return ts.fileExtensionIs(file, ts.Extension.TsBuildInfo); + return fileExtensionIs(file, Extension.TsBuildInfo); } /*@internal*/ @@ -18,17 +98,17 @@ export function isBuildInfoFile(file: string) { * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit. */ export function forEachEmittedFile( - host: ts.EmitHost, action: (emitFileNames: ts.EmitFileNames, sourceFileOrBundle: ts.SourceFile | ts.Bundle | undefined) => T, - sourceFilesOrTargetSourceFile?: readonly ts.SourceFile[] | ts.SourceFile, + host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) => T, + sourceFilesOrTargetSourceFile?: readonly SourceFile[] | SourceFile, forceDtsEmit = false, onlyBuildInfo?: boolean, includeBuildInfo?: boolean) { - const sourceFiles = ts.isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : ts.getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); + const sourceFiles = isArray(sourceFilesOrTargetSourceFile) ? sourceFilesOrTargetSourceFile : getSourceFilesToEmit(host, sourceFilesOrTargetSourceFile, forceDtsEmit); const options = host.getCompilerOptions(); - if (ts.outFile(options)) { + if (outFile(options)) { const prepends = host.getPrependNodes(); if (sourceFiles.length || prepends.length) { - const bundle = ts.factory.createBundle(sourceFiles, prepends); + const bundle = factory.createBundle(sourceFiles, prepends); const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle); if (result) { return result; @@ -51,96 +131,96 @@ export function forEachEmittedFile( } } -export function getTsBuildInfoEmitOutputFilePath(options: ts.CompilerOptions) { +export function getTsBuildInfoEmitOutputFilePath(options: CompilerOptions) { const configFile = options.configFilePath; - if (!ts.isIncrementalCompilation(options)) return undefined; + if (!isIncrementalCompilation(options)) return undefined; if (options.tsBuildInfoFile) return options.tsBuildInfoFile; - const outPath = ts.outFile(options); + const outPath = outFile(options); let buildInfoExtensionLess: string; if (outPath) { - buildInfoExtensionLess = ts.removeFileExtension(outPath); + buildInfoExtensionLess = removeFileExtension(outPath); } else { if (!configFile) return undefined; - const configFileExtensionLess = ts.removeFileExtension(configFile); + const configFileExtensionLess = removeFileExtension(configFile); buildInfoExtensionLess = options.outDir ? options.rootDir ? - ts.resolvePath(options.outDir, ts.getRelativePathFromDirectory(options.rootDir, configFileExtensionLess, /*ignoreCase*/ true)) : - ts.combinePaths(options.outDir, ts.getBaseFileName(configFileExtensionLess)) : + resolvePath(options.outDir, getRelativePathFromDirectory(options.rootDir, configFileExtensionLess, /*ignoreCase*/ true)) : + combinePaths(options.outDir, getBaseFileName(configFileExtensionLess)) : configFileExtensionLess; } - return buildInfoExtensionLess + ts.Extension.TsBuildInfo; + return buildInfoExtensionLess + Extension.TsBuildInfo; } /*@internal*/ -export function getOutputPathsForBundle(options: ts.CompilerOptions, forceDtsPaths: boolean): ts.EmitFileNames { - const outPath = ts.outFile(options)!; +export function getOutputPathsForBundle(options: CompilerOptions, forceDtsPaths: boolean): EmitFileNames { + const outPath = outFile(options)!; const jsFilePath = options.emitDeclarationOnly ? undefined : outPath; const sourceMapFilePath = jsFilePath && getSourceMapFilePath(jsFilePath, options); - const declarationFilePath = (forceDtsPaths || ts.getEmitDeclarations(options)) ? ts.removeFileExtension(outPath) + ts.Extension.Dts : undefined; - const declarationMapPath = declarationFilePath && ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; + const declarationFilePath = (forceDtsPaths || getEmitDeclarations(options)) ? removeFileExtension(outPath) + Extension.Dts : undefined; + const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; const buildInfoPath = getTsBuildInfoEmitOutputFilePath(options); return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }; } /*@internal*/ -export function getOutputPathsFor(sourceFile: ts.SourceFile | ts.Bundle, host: ts.EmitHost, forceDtsPaths: boolean): ts.EmitFileNames { +export function getOutputPathsFor(sourceFile: SourceFile | Bundle, host: EmitHost, forceDtsPaths: boolean): EmitFileNames { const options = host.getCompilerOptions(); - if (sourceFile.kind === ts.SyntaxKind.Bundle) { + if (sourceFile.kind === SyntaxKind.Bundle) { return getOutputPathsForBundle(options, forceDtsPaths); } else { - const ownOutputFilePath = ts.getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile.fileName, options)); - const isJsonFile = ts.isJsonSourceFile(sourceFile); + const ownOutputFilePath = getOwnEmitOutputFilePath(sourceFile.fileName, host, getOutputExtension(sourceFile.fileName, options)); + const isJsonFile = isJsonSourceFile(sourceFile); // If json file emits to the same location skip writing it, if emitDeclarationOnly skip writing it const isJsonEmittedToSameLocation = isJsonFile && - ts.comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === ts.Comparison.EqualTo; + comparePaths(sourceFile.fileName, ownOutputFilePath, host.getCurrentDirectory(), !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; const jsFilePath = options.emitDeclarationOnly || isJsonEmittedToSameLocation ? undefined : ownOutputFilePath; - const sourceMapFilePath = !jsFilePath || ts.isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); - const declarationFilePath = (forceDtsPaths || (ts.getEmitDeclarations(options) && !isJsonFile)) ? ts.getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined; - const declarationMapPath = declarationFilePath && ts.getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; + const sourceMapFilePath = !jsFilePath || isJsonSourceFile(sourceFile) ? undefined : getSourceMapFilePath(jsFilePath, options); + const declarationFilePath = (forceDtsPaths || (getEmitDeclarations(options) && !isJsonFile)) ? getDeclarationEmitOutputFilePath(sourceFile.fileName, host) : undefined; + const declarationMapPath = declarationFilePath && getAreDeclarationMapsEnabled(options) ? declarationFilePath + ".map" : undefined; return { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath: undefined }; } } -function getSourceMapFilePath(jsFilePath: string, options: ts.CompilerOptions) { +function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) { return (options.sourceMap && !options.inlineSourceMap) ? jsFilePath + ".map" : undefined; } /* @internal */ -export function getOutputExtension(fileName: string, options: ts.CompilerOptions): ts.Extension { - return ts.fileExtensionIs(fileName, ts.Extension.Json) ? ts.Extension.Json : - options.jsx === ts.JsxEmit.Preserve && ts.fileExtensionIsOneOf(fileName, [ts.Extension.Jsx, ts.Extension.Tsx]) ? ts.Extension.Jsx : - ts.fileExtensionIsOneOf(fileName, [ts.Extension.Mts, ts.Extension.Mjs]) ? ts.Extension.Mjs : - ts.fileExtensionIsOneOf(fileName, [ts.Extension.Cts, ts.Extension.Cjs]) ? ts.Extension.Cjs : - ts.Extension.Js; +export function getOutputExtension(fileName: string, options: CompilerOptions): Extension { + return fileExtensionIs(fileName, Extension.Json) ? Extension.Json : + options.jsx === JsxEmit.Preserve && fileExtensionIsOneOf(fileName, [Extension.Jsx, Extension.Tsx]) ? Extension.Jsx : + fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Mjs]) ? Extension.Mjs : + fileExtensionIsOneOf(fileName, [Extension.Cts, Extension.Cjs]) ? Extension.Cjs : + Extension.Js; } -function getOutputPathWithoutChangingExt(inputFileName: string, configFile: ts.ParsedCommandLine, ignoreCase: boolean, outputDir: string | undefined, getCommonSourceDirectory?: () => string) { +function getOutputPathWithoutChangingExt(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, outputDir: string | undefined, getCommonSourceDirectory?: () => string) { return outputDir ? - ts.resolvePath( + resolvePath( outputDir, - ts.getRelativePathFromDirectory(getCommonSourceDirectory ? getCommonSourceDirectory() : getCommonSourceDirectoryOfConfig(configFile, ignoreCase), inputFileName, ignoreCase) + getRelativePathFromDirectory(getCommonSourceDirectory ? getCommonSourceDirectory() : getCommonSourceDirectoryOfConfig(configFile, ignoreCase), inputFileName, ignoreCase) ) : inputFileName; } /* @internal */ -export function getOutputDeclarationFileName(inputFileName: string, configFile: ts.ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { - return ts.changeExtension( +export function getOutputDeclarationFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { + return changeExtension( getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.declarationDir || configFile.options.outDir, getCommonSourceDirectory), - ts.getDeclarationEmitExtensionForPath(inputFileName) + getDeclarationEmitExtensionForPath(inputFileName) ); } -function getOutputJSFileName(inputFileName: string, configFile: ts.ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { +function getOutputJSFileName(inputFileName: string, configFile: ParsedCommandLine, ignoreCase: boolean, getCommonSourceDirectory?: () => string) { if (configFile.options.emitDeclarationOnly) return undefined; - const isJsonFile = ts.fileExtensionIs(inputFileName, ts.Extension.Json); - const outputFileName = ts.changeExtension( + const isJsonFile = fileExtensionIs(inputFileName, Extension.Json); + const outputFileName = changeExtension( getOutputPathWithoutChangingExt(inputFileName, configFile, ignoreCase, configFile.options.outDir, getCommonSourceDirectory), getOutputExtension(inputFileName, configFile.options) ); - return !isJsonFile || ts.comparePaths(inputFileName, outputFileName, ts.Debug.checkDefined(configFile.options.configFilePath), ignoreCase) !== ts.Comparison.EqualTo ? + return !isJsonFile || comparePaths(inputFileName, outputFileName, Debug.checkDefined(configFile.options.configFilePath), ignoreCase) !== Comparison.EqualTo ? outputFileName : undefined; } @@ -154,11 +234,11 @@ function createAddOutput() { } } function getOutputs(): readonly string[] { - return outputs || ts.emptyArray; + return outputs || emptyArray; } } -function getSingleOutputFileNames(configFile: ts.ParsedCommandLine, addOutput: ReturnType["addOutput"]) { +function getSingleOutputFileNames(configFile: ParsedCommandLine, addOutput: ReturnType["addOutput"]) { const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); addOutput(jsFilePath); addOutput(sourceMapFilePath); @@ -167,15 +247,15 @@ function getSingleOutputFileNames(configFile: ts.ParsedCommandLine, addOutput: R addOutput(buildInfoPath); } -function getOwnOutputFileNames(configFile: ts.ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType["addOutput"], getCommonSourceDirectory?: () => string) { - if (ts.isDeclarationFileName(inputFileName)) return; +function getOwnOutputFileNames(configFile: ParsedCommandLine, inputFileName: string, ignoreCase: boolean, addOutput: ReturnType["addOutput"], getCommonSourceDirectory?: () => string) { + if (isDeclarationFileName(inputFileName)) return; const js = getOutputJSFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory); addOutput(js); - if (ts.fileExtensionIs(inputFileName, ts.Extension.Json)) return; + if (fileExtensionIs(inputFileName, Extension.Json)) return; if (js && configFile.options.sourceMap) { addOutput(`${js}.map`); } - if (ts.getEmitDeclarations(configFile.options)) { + if (getEmitDeclarations(configFile.options)) { const dts = getOutputDeclarationFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory); addOutput(dts); if (configFile.options.declarationMap) { @@ -186,54 +266,54 @@ function getOwnOutputFileNames(configFile: ts.ParsedCommandLine, inputFileName: /*@internal*/ export function getCommonSourceDirectory( - options: ts.CompilerOptions, + options: CompilerOptions, emittedFiles: () => readonly string[], currentDirectory: string, - getCanonicalFileName: ts.GetCanonicalFileName, + getCanonicalFileName: GetCanonicalFileName, checkSourceFilesBelongToPath?: (commonSourceDirectory: string) => void ): string { let commonSourceDirectory; if (options.rootDir) { // If a rootDir is specified use it as the commonSourceDirectory - commonSourceDirectory = ts.getNormalizedAbsolutePath(options.rootDir, currentDirectory); + commonSourceDirectory = getNormalizedAbsolutePath(options.rootDir, currentDirectory); checkSourceFilesBelongToPath?.(options.rootDir); } else if (options.composite && options.configFilePath) { // Project compilations never infer their root from the input source paths - commonSourceDirectory = ts.getDirectoryPath(ts.normalizeSlashes(options.configFilePath)); + commonSourceDirectory = getDirectoryPath(normalizeSlashes(options.configFilePath)); checkSourceFilesBelongToPath?.(commonSourceDirectory); } else { - commonSourceDirectory = ts.computeCommonSourceDirectoryOfFilenames(emittedFiles(), currentDirectory, getCanonicalFileName); + commonSourceDirectory = computeCommonSourceDirectoryOfFilenames(emittedFiles(), currentDirectory, getCanonicalFileName); } - if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== ts.directorySeparator) { + if (commonSourceDirectory && commonSourceDirectory[commonSourceDirectory.length - 1] !== directorySeparator) { // Make sure directory path ends with directory separator so this string can directly // used to replace with "" to get the relative path of the source file and the relative path doesn't // start with / making it rooted path - commonSourceDirectory += ts.directorySeparator; + commonSourceDirectory += directorySeparator; } return commonSourceDirectory; } /*@internal*/ -export function getCommonSourceDirectoryOfConfig({ options, fileNames }: ts.ParsedCommandLine, ignoreCase: boolean): string { +export function getCommonSourceDirectoryOfConfig({ options, fileNames }: ParsedCommandLine, ignoreCase: boolean): string { return getCommonSourceDirectory( options, - () => ts.filter(fileNames, file => !(options.noEmitForJsFiles && ts.fileExtensionIsOneOf(file, ts.supportedJSExtensionsFlat)) && !ts.isDeclarationFileName(file)), - ts.getDirectoryPath(ts.normalizeSlashes(ts.Debug.checkDefined(options.configFilePath))), - ts.createGetCanonicalFileName(!ignoreCase) + () => filter(fileNames, file => !(options.noEmitForJsFiles && fileExtensionIsOneOf(file, supportedJSExtensionsFlat)) && !isDeclarationFileName(file)), + getDirectoryPath(normalizeSlashes(Debug.checkDefined(options.configFilePath))), + createGetCanonicalFileName(!ignoreCase) ); } /*@internal*/ -export function getAllProjectOutputs(configFile: ts.ParsedCommandLine, ignoreCase: boolean): readonly string[] { +export function getAllProjectOutputs(configFile: ParsedCommandLine, ignoreCase: boolean): readonly string[] { const { addOutput, getOutputs } = createAddOutput(); - if (ts.outFile(configFile.options)) { + if (outFile(configFile.options)) { getSingleOutputFileNames(configFile, addOutput); } else { - const getCommonSourceDirectory = ts.memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)); + const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)); for (const inputFileName of configFile.fileNames) { getOwnOutputFileNames(configFile, inputFileName, ignoreCase, addOutput, getCommonSourceDirectory); } @@ -242,11 +322,11 @@ export function getAllProjectOutputs(configFile: ts.ParsedCommandLine, ignoreCas return getOutputs(); } -export function getOutputFileNames(commandLine: ts.ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[] { - inputFileName = ts.normalizePath(inputFileName); - ts.Debug.assert(ts.contains(commandLine.fileNames, inputFileName), `Expected fileName to be present in command line`); +export function getOutputFileNames(commandLine: ParsedCommandLine, inputFileName: string, ignoreCase: boolean): readonly string[] { + inputFileName = normalizePath(inputFileName); + Debug.assert(contains(commandLine.fileNames, inputFileName), `Expected fileName to be present in command line`); const { addOutput, getOutputs } = createAddOutput(); - if (ts.outFile(commandLine.options)) { + if (outFile(commandLine.options)) { getSingleOutputFileNames(commandLine, addOutput); } else { @@ -256,38 +336,38 @@ export function getOutputFileNames(commandLine: ts.ParsedCommandLine, inputFileN } /*@internal*/ -export function getFirstProjectOutput(configFile: ts.ParsedCommandLine, ignoreCase: boolean): string { - if (ts.outFile(configFile.options)) { +export function getFirstProjectOutput(configFile: ParsedCommandLine, ignoreCase: boolean): string { + if (outFile(configFile.options)) { const { jsFilePath, declarationFilePath } = getOutputPathsForBundle(configFile.options, /*forceDtsPaths*/ false); - return ts.Debug.checkDefined(jsFilePath || declarationFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`); + return Debug.checkDefined(jsFilePath || declarationFilePath, `project ${configFile.options.configFilePath} expected to have at least one output`); } - const getCommonSourceDirectory = ts.memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)); + const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(configFile, ignoreCase)); for (const inputFileName of configFile.fileNames) { - if (ts.isDeclarationFileName(inputFileName)) continue; + if (isDeclarationFileName(inputFileName)) continue; const jsFilePath = getOutputJSFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory); if (jsFilePath) return jsFilePath; - if (ts.fileExtensionIs(inputFileName, ts.Extension.Json)) continue; - if (ts.getEmitDeclarations(configFile.options)) { + if (fileExtensionIs(inputFileName, Extension.Json)) continue; + if (getEmitDeclarations(configFile.options)) { return getOutputDeclarationFileName(inputFileName, configFile, ignoreCase, getCommonSourceDirectory); } } const buildInfoPath = getTsBuildInfoEmitOutputFilePath(configFile.options); if (buildInfoPath) return buildInfoPath; - return ts.Debug.fail(`project ${configFile.options.configFilePath} expected to have at least one output`); + return Debug.fail(`project ${configFile.options.configFilePath} expected to have at least one output`); } /*@internal*/ // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature -export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSourceFile: ts.SourceFile | undefined, { scriptTransformers, declarationTransformers }: ts.EmitTransformers, emitOnly?: boolean | ts.EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): ts.EmitResult { +export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile | undefined, { scriptTransformers, declarationTransformers }: EmitTransformers, emitOnly?: boolean | EmitOnly, onlyBuildInfo?: boolean, forceDtsEmit?: boolean): EmitResult { const compilerOptions = host.getCompilerOptions(); - const sourceMapDataList: ts.SourceMapEmitResult[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || ts.getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; + const sourceMapDataList: SourceMapEmitResult[] | undefined = (compilerOptions.sourceMap || compilerOptions.inlineSourceMap || getAreDeclarationMapsEnabled(compilerOptions)) ? [] : undefined; const emittedFilesList: string[] | undefined = compilerOptions.listEmittedFiles ? [] : undefined; - const emitterDiagnostics = ts.createDiagnosticCollection(); - const newLine = ts.getNewLineCharacter(compilerOptions, () => host.getNewLine()); - const writer = ts.createTextWriter(newLine); + const emitterDiagnostics = createDiagnosticCollection(); + const newLine = getNewLineCharacter(compilerOptions, () => host.getNewLine()); + const writer = createTextWriter(newLine); const { enter, exit } = ts.performance.createTimer("printTime", "beforePrint", "afterPrint"); - let bundleBuildInfo: ts.BundleBuildInfo | undefined; + let bundleBuildInfo: BundleBuildInfo | undefined; let emitSkipped = false; // Emit each output file @@ -295,7 +375,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo forEachEmittedFile( host, emitSourceFileOrBundle, - ts.getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit), + getSourceFilesToEmit(host, targetSourceFile, forceDtsEmit), forceDtsEmit, onlyBuildInfo, !targetSourceFile @@ -310,26 +390,26 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo sourceMaps: sourceMapDataList, }; - function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: ts.EmitFileNames, sourceFileOrBundle: ts.SourceFile | ts.Bundle | undefined) { + function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle | undefined) { let buildInfoDirectory: string | undefined; - if (buildInfoPath && sourceFileOrBundle && ts.isBundle(sourceFileOrBundle)) { - buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); + if (buildInfoPath && sourceFileOrBundle && isBundle(sourceFileOrBundle)) { + buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory())); bundleBuildInfo = { commonSourceDirectory: relativeToBuildInfo(host.getCommonSourceDirectory()), - sourceFiles: sourceFileOrBundle.sourceFiles.map(file => relativeToBuildInfo(ts.getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()))) + sourceFiles: sourceFileOrBundle.sourceFiles.map(file => relativeToBuildInfo(getNormalizedAbsolutePath(file.fileName, host.getCurrentDirectory()))) }; } - ts.tracing?.push(ts.tracing.Phase.Emit, "emitJsFileOrBundle", { jsFilePath }); + tracing?.push(tracing.Phase.Emit, "emitJsFileOrBundle", { jsFilePath }); emitJsFileOrBundle(sourceFileOrBundle, jsFilePath, sourceMapFilePath, relativeToBuildInfo); - ts.tracing?.pop(); + tracing?.pop(); - ts.tracing?.push(ts.tracing.Phase.Emit, "emitDeclarationFileOrBundle", { declarationFilePath }); + tracing?.push(tracing.Phase.Emit, "emitDeclarationFileOrBundle", { declarationFilePath }); emitDeclarationFileOrBundle(sourceFileOrBundle, declarationFilePath, declarationMapPath, relativeToBuildInfo); - ts.tracing?.pop(); + tracing?.pop(); - ts.tracing?.push(ts.tracing.Phase.Emit, "emitBuildInfo", { buildInfoPath }); + tracing?.push(tracing.Phase.Emit, "emitBuildInfo", { buildInfoPath }); emitBuildInfo(bundleBuildInfo, buildInfoPath); - ts.tracing?.pop(); + tracing?.pop(); if (!emitSkipped && emittedFilesList) { if (!emitOnly) { @@ -343,7 +423,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo emittedFilesList.push(buildInfoPath); } } - if (emitOnly !== ts.EmitOnly.Js) { + if (emitOnly !== EmitOnly.Js) { if (declarationFilePath) { emittedFilesList.push(declarationFilePath); } @@ -354,11 +434,11 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } function relativeToBuildInfo(path: string) { - return ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(buildInfoDirectory!, path, host.getCanonicalFileName)); + return ensurePathIsNonModuleName(getRelativePathFromDirectory(buildInfoDirectory!, path, host.getCanonicalFileName)); } } - function emitBuildInfo(bundle: ts.BundleBuildInfo | undefined, buildInfoPath: string | undefined) { + function emitBuildInfo(bundle: BundleBuildInfo | undefined, buildInfoPath: string | undefined) { // Write build information if applicable if (!buildInfoPath || targetSourceFile || emitSkipped) return; if (host.isEmitBlocked(buildInfoPath)) { @@ -367,11 +447,11 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } const buildInfo = host.getBuildInfo(bundle) || createBuildInfo(/*program*/ undefined, bundle); // Pass buildinfo as additional data to avoid having to reparse - ts.writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo }); + writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo }); } function emitJsFileOrBundle( - sourceFileOrBundle: ts.SourceFile | ts.Bundle | undefined, + sourceFileOrBundle: SourceFile | Bundle | undefined, jsFilePath: string | undefined, sourceMapFilePath: string | undefined, relativeToBuildInfo: (path: string) => string) { @@ -385,9 +465,9 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo return; } // Transform the source files - const transform = ts.transformNodes(resolver, host, ts.factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); + const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false); - const printerOptions: ts.PrinterOptions = { + const printerOptions: PrinterOptions = { removeComments: compilerOptions.removeComments, newLine: compilerOptions.newLine, noEmitHelpers: compilerOptions.noEmitHelpers, @@ -412,7 +492,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo substituteNode: transform.substituteNode, }); - ts.Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); + Debug.assert(transform.transformed.length === 1, "Should only see one output from the transform"); printSourceFileOrBundle(jsFilePath, sourceMapFilePath, transform, printer, compilerOptions); // Clean up emit nodes on parse tree @@ -421,32 +501,32 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } function emitDeclarationFileOrBundle( - sourceFileOrBundle: ts.SourceFile | ts.Bundle | undefined, + sourceFileOrBundle: SourceFile | Bundle | undefined, declarationFilePath: string | undefined, declarationMapPath: string | undefined, relativeToBuildInfo: (path: string) => string) { - if (!sourceFileOrBundle || emitOnly === ts.EmitOnly.Js) return; + if (!sourceFileOrBundle || emitOnly === EmitOnly.Js) return; if (!declarationFilePath) { if (emitOnly || compilerOptions.emitDeclarationOnly) emitSkipped = true; return; } - const sourceFiles = ts.isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; - const filesForEmit = forceDtsEmit ? sourceFiles : ts.filter(sourceFiles, ts.isSourceFileNotJson); + const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles; + const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson); // Setup and perform the transformation to retrieve declarations from the input files - const inputListOrBundle = ts.outFile(compilerOptions) ? [ts.factory.createBundle(filesForEmit, !ts.isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit; - if (emitOnly && !ts.getEmitDeclarations(compilerOptions)) { + const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit; + if (emitOnly && !getEmitDeclarations(compilerOptions)) { // Checker wont collect the linked aliases since thats only done when declaration is enabled. // Do that here when emitting only dts files filesForEmit.forEach(collectLinkedAliases); } - const declarationTransform = ts.transformNodes(resolver, host, ts.factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); - if (ts.length(declarationTransform.diagnostics)) { + const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false); + if (length(declarationTransform.diagnostics)) { for (const diagnostic of declarationTransform.diagnostics!) { emitterDiagnostics.add(diagnostic); } } - const printerOptions: ts.PrinterOptions = { + const printerOptions: PrinterOptions = { removeComments: compilerOptions.removeComments, newLine: compilerOptions.newLine, noEmitHelpers: true, @@ -473,7 +553,7 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo const declBlocked = (!!declarationTransform.diagnostics && !!declarationTransform.diagnostics.length) || !!host.isEmitBlocked(declarationFilePath) || !!compilerOptions.noEmit; emitSkipped = emitSkipped || declBlocked; if (!declBlocked || forceDtsEmit) { - ts.Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); + Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); printSourceFileOrBundle( declarationFilePath, declarationMapPath, @@ -492,31 +572,31 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo if (bundleBuildInfo) bundleBuildInfo.dts = declarationPrinter.bundleFileInfo; } - function collectLinkedAliases(node: ts.Node) { - if (ts.isExportAssignment(node)) { - if (node.expression.kind === ts.SyntaxKind.Identifier) { - resolver.collectLinkedAliases(node.expression as ts.Identifier, /*setVisibility*/ true); + function collectLinkedAliases(node: Node) { + if (isExportAssignment(node)) { + if (node.expression.kind === SyntaxKind.Identifier) { + resolver.collectLinkedAliases(node.expression as Identifier, /*setVisibility*/ true); } return; } - else if (ts.isExportSpecifier(node)) { + else if (isExportSpecifier(node)) { resolver.collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true); return; } - ts.forEachChild(node, collectLinkedAliases); + forEachChild(node, collectLinkedAliases); } - function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, transform: ts.TransformationResult, printer: ts.Printer, mapOptions: SourceMapOptions) { + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string | undefined, transform: TransformationResult, printer: Printer, mapOptions: SourceMapOptions) { const sourceFileOrBundle = transform.transformed[0]; - const bundle = sourceFileOrBundle.kind === ts.SyntaxKind.Bundle ? sourceFileOrBundle : undefined; - const sourceFile = sourceFileOrBundle.kind === ts.SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; + const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; + const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile!]; - let sourceMapGenerator: ts.SourceMapGenerator | undefined; + let sourceMapGenerator: SourceMapGenerator | undefined; if (shouldEmitSourceMaps(mapOptions, sourceFileOrBundle)) { - sourceMapGenerator = ts.createSourceMapGenerator( + sourceMapGenerator = createSourceMapGenerator( host, - ts.getBaseFileName(ts.normalizeSlashes(jsFilePath)), + getBaseFileName(normalizeSlashes(jsFilePath)), getSourceRoot(mapOptions), getSourceMapDirectory(mapOptions, jsFilePath, sourceFile), mapOptions); @@ -554,8 +634,8 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo // Write the source map if (sourceMapFilePath) { const sourceMap = sourceMapGenerator.toString(); - ts.writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap, /*writeByteOrderMark*/ false, sourceFiles); - if (printer.bundleFileInfo) printer.bundleFileInfo.mapHash = ts.computeSignature(sourceMap, ts.maybeBind(host, host.createHash)); + writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap, /*writeByteOrderMark*/ false, sourceFiles); + if (printer.bundleFileInfo) printer.bundleFileInfo.mapHash = computeSignature(sourceMap, maybeBind(host, host.createHash)); } } else { @@ -564,10 +644,10 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo // Write the output file const text = writer.getText(); - ts.writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos, diagnostics: transform.diagnostics }); + writeFile(host, emitterDiagnostics, jsFilePath, text, !!compilerOptions.emitBOM, sourceFiles, { sourceMapUrlPos, diagnostics: transform.diagnostics }); // We store the hash of the text written in the buildinfo to ensure that text of the referenced d.ts file is same as whats in the buildinfo // This is needed because incremental can be toggled between two runs and we might use stale file text to do text manipulation in prepend mode - if (printer.bundleFileInfo) printer.bundleFileInfo.hash = ts.computeSignature(text, ts.maybeBind(host, host.createHash)); + if (printer.bundleFileInfo) printer.bundleFileInfo.hash = computeSignature(text, maybeBind(host, host.createHash)); // Reset state writer.clear(); @@ -582,65 +662,65 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo extendedDiagnostics?: boolean; } - function shouldEmitSourceMaps(mapOptions: SourceMapOptions, sourceFileOrBundle: ts.SourceFile | ts.Bundle) { + function shouldEmitSourceMaps(mapOptions: SourceMapOptions, sourceFileOrBundle: SourceFile | Bundle) { return (mapOptions.sourceMap || mapOptions.inlineSourceMap) - && (sourceFileOrBundle.kind !== ts.SyntaxKind.SourceFile || !ts.fileExtensionIs(sourceFileOrBundle.fileName, ts.Extension.Json)); + && (sourceFileOrBundle.kind !== SyntaxKind.SourceFile || !fileExtensionIs(sourceFileOrBundle.fileName, Extension.Json)); } function getSourceRoot(mapOptions: SourceMapOptions) { // Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the // relative paths of the sources list in the sourcemap - const sourceRoot = ts.normalizeSlashes(mapOptions.sourceRoot || ""); - return sourceRoot ? ts.ensureTrailingDirectorySeparator(sourceRoot) : sourceRoot; + const sourceRoot = normalizeSlashes(mapOptions.sourceRoot || ""); + return sourceRoot ? ensureTrailingDirectorySeparator(sourceRoot) : sourceRoot; } - function getSourceMapDirectory(mapOptions: SourceMapOptions, filePath: string, sourceFile: ts.SourceFile | undefined) { + function getSourceMapDirectory(mapOptions: SourceMapOptions, filePath: string, sourceFile: SourceFile | undefined) { if (mapOptions.sourceRoot) return host.getCommonSourceDirectory(); if (mapOptions.mapRoot) { - let sourceMapDir = ts.normalizeSlashes(mapOptions.mapRoot); + let sourceMapDir = normalizeSlashes(mapOptions.mapRoot); if (sourceFile) { // For modules or multiple emit files the mapRoot will have directory structure like the sources // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFile.fileName, host, sourceMapDir)); + sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFile.fileName, host, sourceMapDir)); } - if (ts.getRootLength(sourceMapDir) === 0) { + if (getRootLength(sourceMapDir) === 0) { // The relative paths are relative to the common directory - sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); + sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir); } return sourceMapDir; } - return ts.getDirectoryPath(ts.normalizePath(filePath)); + return getDirectoryPath(normalizePath(filePath)); } - function getSourceMappingURL(mapOptions: SourceMapOptions, sourceMapGenerator: ts.SourceMapGenerator, filePath: string, sourceMapFilePath: string | undefined, sourceFile: ts.SourceFile | undefined) { + function getSourceMappingURL(mapOptions: SourceMapOptions, sourceMapGenerator: SourceMapGenerator, filePath: string, sourceMapFilePath: string | undefined, sourceFile: SourceFile | undefined) { if (mapOptions.inlineSourceMap) { // Encode the sourceMap into the sourceMap url const sourceMapText = sourceMapGenerator.toString(); - const base64SourceMapText = ts.base64encode(ts.sys, sourceMapText); + const base64SourceMapText = base64encode(sys, sourceMapText); return `data:application/json;base64,${base64SourceMapText}`; } - const sourceMapFile = ts.getBaseFileName(ts.normalizeSlashes(ts.Debug.checkDefined(sourceMapFilePath))); + const sourceMapFile = getBaseFileName(normalizeSlashes(Debug.checkDefined(sourceMapFilePath))); if (mapOptions.mapRoot) { - let sourceMapDir = ts.normalizeSlashes(mapOptions.mapRoot); + let sourceMapDir = normalizeSlashes(mapOptions.mapRoot); if (sourceFile) { // For modules or multiple emit files the mapRoot will have directory structure like the sources // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = ts.getDirectoryPath(ts.getSourceFilePathInNewDir(sourceFile.fileName, host, sourceMapDir)); + sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFile.fileName, host, sourceMapDir)); } - if (ts.getRootLength(sourceMapDir) === 0) { + if (getRootLength(sourceMapDir) === 0) { // The relative paths are relative to the common directory - sourceMapDir = ts.combinePaths(host.getCommonSourceDirectory(), sourceMapDir); + sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir); return encodeURI( - ts.getRelativePathToDirectoryOrUrl( - ts.getDirectoryPath(ts.normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath - ts.combinePaths(sourceMapDir, sourceMapFile), // this is where user expects to see sourceMap + getRelativePathToDirectoryOrUrl( + getDirectoryPath(normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath + combinePaths(sourceMapDir, sourceMapFile), // this is where user expects to see sourceMap host.getCurrentDirectory(), host.getCanonicalFileName, /*isAbsolutePathAnUrl*/ true)); } else { - return encodeURI(ts.combinePaths(sourceMapDir, sourceMapFile)); + return encodeURI(combinePaths(sourceMapDir, sourceMapFile)); } } return encodeURI(sourceMapFile); @@ -648,146 +728,146 @@ export function emitFiles(resolver: ts.EmitResolver, host: ts.EmitHost, targetSo } /*@internal*/ -export function createBuildInfo(program: ts.ProgramBuildInfo | undefined, bundle: ts.BundleBuildInfo | undefined): ts.BuildInfo { +export function createBuildInfo(program: ProgramBuildInfo | undefined, bundle: BundleBuildInfo | undefined): BuildInfo { const version = ts.version; // Extracted into a const so the form is stable between namespace and module return { bundle, program, version }; } /*@internal*/ -export function getBuildInfoText(buildInfo: ts.BuildInfo) { +export function getBuildInfoText(buildInfo: BuildInfo) { return JSON.stringify(buildInfo); } /*@internal*/ export function getBuildInfo(buildInfoFile: string, buildInfoText: string) { - return ts.readJsonOrUndefined(buildInfoFile, buildInfoText) as ts.BuildInfo | undefined; + return readJsonOrUndefined(buildInfoFile, buildInfoText) as BuildInfo | undefined; } /*@internal*/ -export const notImplementedResolver: ts.EmitResolver = { - hasGlobalName: ts.notImplemented, - getReferencedExportContainer: ts.notImplemented, - getReferencedImportDeclaration: ts.notImplemented, - getReferencedDeclarationWithCollidingName: ts.notImplemented, - isDeclarationWithCollidingName: ts.notImplemented, - isValueAliasDeclaration: ts.notImplemented, - isReferencedAliasDeclaration: ts.notImplemented, - isTopLevelValueImportEqualsWithEntityName: ts.notImplemented, - getNodeCheckFlags: ts.notImplemented, - isDeclarationVisible: ts.notImplemented, - isLateBound: (_node): _node is ts.LateBoundDeclaration => false, - collectLinkedAliases: ts.notImplemented, - isImplementationOfOverload: ts.notImplemented, - isRequiredInitializedParameter: ts.notImplemented, - isOptionalUninitializedParameterProperty: ts.notImplemented, - isExpandoFunctionDeclaration: ts.notImplemented, - getPropertiesOfContainerFunction: ts.notImplemented, - createTypeOfDeclaration: ts.notImplemented, - createReturnTypeOfSignatureDeclaration: ts.notImplemented, - createTypeOfExpression: ts.notImplemented, - createLiteralConstValue: ts.notImplemented, - isSymbolAccessible: ts.notImplemented, - isEntityNameVisible: ts.notImplemented, +export const notImplementedResolver: EmitResolver = { + hasGlobalName: notImplemented, + getReferencedExportContainer: notImplemented, + getReferencedImportDeclaration: notImplemented, + getReferencedDeclarationWithCollidingName: notImplemented, + isDeclarationWithCollidingName: notImplemented, + isValueAliasDeclaration: notImplemented, + isReferencedAliasDeclaration: notImplemented, + isTopLevelValueImportEqualsWithEntityName: notImplemented, + getNodeCheckFlags: notImplemented, + isDeclarationVisible: notImplemented, + isLateBound: (_node): _node is LateBoundDeclaration => false, + collectLinkedAliases: notImplemented, + isImplementationOfOverload: notImplemented, + isRequiredInitializedParameter: notImplemented, + isOptionalUninitializedParameterProperty: notImplemented, + isExpandoFunctionDeclaration: notImplemented, + getPropertiesOfContainerFunction: notImplemented, + createTypeOfDeclaration: notImplemented, + createReturnTypeOfSignatureDeclaration: notImplemented, + createTypeOfExpression: notImplemented, + createLiteralConstValue: notImplemented, + isSymbolAccessible: notImplemented, + isEntityNameVisible: notImplemented, // Returns the constant value this property access resolves to: notImplemented, or 'undefined' for a non-constant - getConstantValue: ts.notImplemented, - getReferencedValueDeclaration: ts.notImplemented, - getTypeReferenceSerializationKind: ts.notImplemented, - isOptionalParameter: ts.notImplemented, - moduleExportsSomeValue: ts.notImplemented, - isArgumentsLocalBinding: ts.notImplemented, - getExternalModuleFileFromDeclaration: ts.notImplemented, - getTypeReferenceDirectivesForEntityName: ts.notImplemented, - getTypeReferenceDirectivesForSymbol: ts.notImplemented, - isLiteralConstDeclaration: ts.notImplemented, - getJsxFactoryEntity: ts.notImplemented, - getJsxFragmentFactoryEntity: ts.notImplemented, - getAllAccessorDeclarations: ts.notImplemented, - getSymbolOfExternalModuleSpecifier: ts.notImplemented, - isBindingCapturedByNode: ts.notImplemented, - getDeclarationStatementsForSourceFile: ts.notImplemented, - isImportRequiredByAugmentation: ts.notImplemented, + getConstantValue: notImplemented, + getReferencedValueDeclaration: notImplemented, + getTypeReferenceSerializationKind: notImplemented, + isOptionalParameter: notImplemented, + moduleExportsSomeValue: notImplemented, + isArgumentsLocalBinding: notImplemented, + getExternalModuleFileFromDeclaration: notImplemented, + getTypeReferenceDirectivesForEntityName: notImplemented, + getTypeReferenceDirectivesForSymbol: notImplemented, + isLiteralConstDeclaration: notImplemented, + getJsxFactoryEntity: notImplemented, + getJsxFragmentFactoryEntity: notImplemented, + getAllAccessorDeclarations: notImplemented, + getSymbolOfExternalModuleSpecifier: notImplemented, + isBindingCapturedByNode: notImplemented, + getDeclarationStatementsForSourceFile: notImplemented, + isImportRequiredByAugmentation: notImplemented, }; /*@internal*/ /** File that isnt present resulting in error or output files */ -export type EmitUsingBuildInfoResult = string | readonly ts.OutputFile[]; +export type EmitUsingBuildInfoResult = string | readonly OutputFile[]; -function createSourceFilesFromBundleBuildInfo(bundle: ts.BundleBuildInfo, buildInfoDirectory: string, host: ts.CompilerHost): readonly ts.SourceFile[] { - const jsBundle = ts.Debug.checkDefined(bundle.js); - const prologueMap = jsBundle.sources?.prologues && ts.arrayToMap(jsBundle.sources.prologues, prologueInfo => prologueInfo.file); +function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: CompilerHost): readonly SourceFile[] { + const jsBundle = Debug.checkDefined(bundle.js); + const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => prologueInfo.file); return bundle.sourceFiles.map((fileName, index) => { const prologueInfo = prologueMap?.get(index); const statements = prologueInfo?.directives.map(directive => { - const literal = ts.setTextRange(ts.factory.createStringLiteral(directive.expression.text), directive.expression); - const statement = ts.setTextRange(ts.factory.createExpressionStatement(literal), directive); - ts.setParent(literal, statement); + const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression); + const statement = setTextRange(factory.createExpressionStatement(literal), directive); + setParent(literal, statement); return statement; }); - const eofToken = ts.factory.createToken(ts.SyntaxKind.EndOfFileToken); - const sourceFile = ts.factory.createSourceFile(statements ?? [], eofToken, ts.NodeFlags.None); - sourceFile.fileName = ts.getRelativePathFromDirectory( + const eofToken = factory.createToken(SyntaxKind.EndOfFileToken); + const sourceFile = factory.createSourceFile(statements ?? [], eofToken, NodeFlags.None); + sourceFile.fileName = getRelativePathFromDirectory( host.getCurrentDirectory(), - ts.getNormalizedAbsolutePath(fileName, buildInfoDirectory), + getNormalizedAbsolutePath(fileName, buildInfoDirectory), !host.useCaseSensitiveFileNames() ); sourceFile.text = prologueInfo?.text ?? ""; - ts.setTextRangePosWidth(sourceFile, 0, prologueInfo?.text.length ?? 0); - ts.setEachParent(sourceFile.statements, sourceFile); - ts.setTextRangePosWidth(eofToken, sourceFile.end, 0); - ts.setParent(eofToken, sourceFile); + setTextRangePosWidth(sourceFile, 0, prologueInfo?.text.length ?? 0); + setEachParent(sourceFile.statements, sourceFile); + setTextRangePosWidth(eofToken, sourceFile.end, 0); + setParent(eofToken, sourceFile); return sourceFile; }); } /*@internal*/ export function emitUsingBuildInfo( - config: ts.ParsedCommandLine, - host: ts.CompilerHost, - getCommandLine: (ref: ts.ProjectReference) => ts.ParsedCommandLine | undefined, - customTransformers?: ts.CustomTransformers + config: ParsedCommandLine, + host: CompilerHost, + getCommandLine: (ref: ProjectReference) => ParsedCommandLine | undefined, + customTransformers?: CustomTransformers ): EmitUsingBuildInfoResult { - ts.tracing?.push(ts.tracing.Phase.Emit, "emitUsingBuildInfo", {}, /*separateBeginAndEnd*/ true); + tracing?.push(tracing.Phase.Emit, "emitUsingBuildInfo", {}, /*separateBeginAndEnd*/ true); ts.performance.mark("beforeEmit"); const result = emitUsingBuildInfoWorker(config, host, getCommandLine, customTransformers); ts.performance.mark("afterEmit"); ts.performance.measure("Emit", "beforeEmit", "afterEmit"); - ts.tracing?.pop(); + tracing?.pop(); return result; } function emitUsingBuildInfoWorker( - config: ts.ParsedCommandLine, - host: ts.CompilerHost, - getCommandLine: (ref: ts.ProjectReference) => ts.ParsedCommandLine | undefined, - customTransformers?: ts.CustomTransformers + config: ParsedCommandLine, + host: CompilerHost, + getCommandLine: (ref: ProjectReference) => ParsedCommandLine | undefined, + customTransformers?: CustomTransformers ): EmitUsingBuildInfoResult { - const createHash = ts.maybeBind(host, host.createHash); + const createHash = maybeBind(host, host.createHash); const { buildInfoPath, jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath } = getOutputPathsForBundle(config.options, /*forceDtsPaths*/ false); // If host directly provides buildinfo we can get it directly. This allows host to cache the buildinfo const buildInfo = host.getBuildInfo!(buildInfoPath!, config.options.configFilePath); if (!buildInfo) return buildInfoPath!; if (!buildInfo.bundle || !buildInfo.bundle.js || (declarationFilePath && !buildInfo.bundle.dts)) return buildInfoPath!; - const jsFileText = host.readFile(ts.Debug.checkDefined(jsFilePath)); + const jsFileText = host.readFile(Debug.checkDefined(jsFilePath)); if (!jsFileText) return jsFilePath!; // If the jsFileText is not same has what it was created with, tsbuildinfo is stale so dont use it - if (ts.computeSignature(jsFileText, createHash) !== buildInfo.bundle.js.hash) return jsFilePath!; + if (computeSignature(jsFileText, createHash) !== buildInfo.bundle.js.hash) return jsFilePath!; const sourceMapText = sourceMapFilePath && host.readFile(sourceMapFilePath); // error if no source map or for now if inline sourcemap if ((sourceMapFilePath && !sourceMapText) || config.options.inlineSourceMap) return sourceMapFilePath || "inline sourcemap decoding"; - if (sourceMapFilePath && ts.computeSignature(sourceMapText!, createHash) !== buildInfo.bundle.js.mapHash) return sourceMapFilePath; + if (sourceMapFilePath && computeSignature(sourceMapText!, createHash) !== buildInfo.bundle.js.mapHash) return sourceMapFilePath; // read declaration text const declarationText = declarationFilePath && host.readFile(declarationFilePath); if (declarationFilePath && !declarationText) return declarationFilePath; - if (declarationFilePath && ts.computeSignature(declarationText!, createHash) !== buildInfo.bundle.dts!.hash) return declarationFilePath; + if (declarationFilePath && computeSignature(declarationText!, createHash) !== buildInfo.bundle.dts!.hash) return declarationFilePath; const declarationMapText = declarationMapPath && host.readFile(declarationMapPath); // error if no source map or for now if inline sourcemap if ((declarationMapPath && !declarationMapText) || config.options.inlineSourceMap) return declarationMapPath || "inline sourcemap decoding"; - if (declarationMapPath && ts.computeSignature(declarationMapText!, createHash) !== buildInfo.bundle.dts!.mapHash) return declarationMapPath; + if (declarationMapPath && computeSignature(declarationMapText!, createHash) !== buildInfo.bundle.dts!.mapHash) return declarationMapPath; - const buildInfoDirectory = ts.getDirectoryPath(ts.getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); - const ownPrependInput = ts.createInputFilesWithFileTexts( + const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath!, host.getCurrentDirectory())); + const ownPrependInput = createInputFilesWithFileTexts( jsFilePath, jsFileText, sourceMapFilePath, @@ -800,26 +880,26 @@ function emitUsingBuildInfoWorker( buildInfo, /*onlyOwnText*/ true ); - const outputFiles: ts.OutputFile[] = []; - const prependNodes = ts.createPrependNodes(config.projectReferences, getCommandLine, f => host.readFile(f), host); + const outputFiles: OutputFile[] = []; + const prependNodes = createPrependNodes(config.projectReferences, getCommandLine, f => host.readFile(f), host); const sourceFilesForJsEmit = createSourceFilesFromBundleBuildInfo(buildInfo.bundle, buildInfoDirectory, host); let changedDtsText: string | undefined; - let changedDtsData: ts.WriteFileCallbackData | undefined; - const emitHost: ts.EmitHost = { - getPrependNodes: ts.memoize(() => [...prependNodes, ownPrependInput]), + let changedDtsData: WriteFileCallbackData | undefined; + const emitHost: EmitHost = { + getPrependNodes: memoize(() => [...prependNodes, ownPrependInput]), getCanonicalFileName: host.getCanonicalFileName, - getCommonSourceDirectory: () => ts.getNormalizedAbsolutePath(buildInfo.bundle!.commonSourceDirectory, buildInfoDirectory), + getCommonSourceDirectory: () => getNormalizedAbsolutePath(buildInfo.bundle!.commonSourceDirectory, buildInfoDirectory), getCompilerOptions: () => config.options, getCurrentDirectory: () => host.getCurrentDirectory(), getNewLine: () => host.getNewLine(), - getSourceFile: ts.returnUndefined, - getSourceFileByPath: ts.returnUndefined, + getSourceFile: returnUndefined, + getSourceFileByPath: returnUndefined, getSourceFiles: () => sourceFilesForJsEmit, - getLibFileFromReference: ts.notImplemented, - isSourceFileFromExternalLibrary: ts.returnFalse, - getResolvedProjectReferenceToRedirect: ts.returnUndefined, - getProjectReferenceRedirect: ts.returnUndefined, - isSourceOfProjectReferenceRedirect: ts.returnFalse, + getLibFileFromReference: notImplemented, + isSourceFileFromExternalLibrary: returnFalse, + getResolvedProjectReferenceToRedirect: returnUndefined, + getProjectReferenceRedirect: returnUndefined, + isSourceOfProjectReferenceRedirect: returnFalse, writeFile: (name, text, writeByteOrderMark, _onError, _sourceFiles, data) => { switch (name) { case jsFilePath: @@ -839,11 +919,11 @@ function emitUsingBuildInfoWorker( if (declarationMapText === text) return; break; default: - ts.Debug.fail(`Unexpected path: ${name}`); + Debug.fail(`Unexpected path: ${name}`); } outputFiles.push({ name, text, writeByteOrderMark, data }); }, - isEmitBlocked: ts.returnFalse, + isEmitBlocked: returnFalse, readFile: f => host.readFile(f), fileExists: f => host.fileExists(f), useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(), @@ -851,7 +931,7 @@ function emitUsingBuildInfoWorker( const program = buildInfo.program; if (program && changedDtsText !== undefined && config.options.composite) { // Update the output signature - (program as ts.ProgramBundleEmitBuildInfo).outSignature = ts.computeSignature(changedDtsText, createHash, changedDtsData); + (program as ProgramBundleEmitBuildInfo).outSignature = computeSignature(changedDtsText, createHash, changedDtsData); } // Update sourceFileInfo const { js, dts, sourceFiles } = buildInfo.bundle!; @@ -862,16 +942,16 @@ function emitUsingBuildInfoWorker( bundle!.sourceFiles = sourceFiles; return createBuildInfo(program, bundle); }, - getSourceFileFromReference: ts.returnUndefined, - redirectTargetsMap: ts.createMultiMap(), - getFileIncludeReasons: ts.notImplemented, + getSourceFileFromReference: returnUndefined, + redirectTargetsMap: createMultiMap(), + getFileIncludeReasons: notImplemented, createHash, }; emitFiles( notImplementedResolver, emitHost, /*targetSourceFile*/ undefined, - ts.getTransformers(config.options, customTransformers) + getTransformers(config.options, customTransformers) ); return outputFiles; } @@ -884,12 +964,12 @@ const enum PipelinePhase { Emit, } -export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: ts.PrintHandlers = {}): ts.Printer { +export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer { const { hasGlobalName, - onEmitNode = ts.noEmitNotification, + onEmitNode = noEmitNotification, isEmitNotificationEnabled, - substituteNode = ts.noEmitSubstitution, + substituteNode = noEmitSubstitution, onBeforeEmitNode, onAfterEmitNode, onBeforeEmitNodeArray, @@ -899,41 +979,41 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } = handlers; const extendedDiagnostics = !!printerOptions.extendedDiagnostics; - const newLine = ts.getNewLineCharacter(printerOptions); - const moduleKind = ts.getEmitModuleKind(printerOptions); - const bundledHelpers = new ts.Map(); + const newLine = getNewLineCharacter(printerOptions); + const moduleKind = getEmitModuleKind(printerOptions); + const bundledHelpers = new Map(); - let currentSourceFile: ts.SourceFile | undefined; + let currentSourceFile: SourceFile | undefined; let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. - let generatedNames: ts.Set; // Set of names generated by the NameGenerator. - let formattedNameTempFlagsStack: (ts.ESMap | undefined)[]; - let formattedNameTempFlags: ts.ESMap | undefined; + let generatedNames: Set; // Set of names generated by the NameGenerator. + let formattedNameTempFlagsStack: (ESMap | undefined)[]; + let formattedNameTempFlags: ESMap | undefined; let privateNameTempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes. let privateNameTempFlags: TempFlags; // TempFlags for the current name generation scope. let tempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes. let tempFlags: TempFlags; // TempFlags for the current name generation scope. - let reservedNamesStack: ts.Set[]; // Stack of TempFlags reserved in enclosing name generation scopes. - let reservedNames: ts.Set; // TempFlags to reserve in nested name generation scopes. + let reservedNamesStack: Set[]; // Stack of TempFlags reserved in enclosing name generation scopes. + let reservedNames: Set; // TempFlags to reserve in nested name generation scopes. let preserveSourceNewlines = printerOptions.preserveSourceNewlines; // Can be overridden inside nodes with the `IgnoreSourceNewlines` emit flag. let nextListElementPos: number | undefined; // See comment in `getLeadingLineTerminatorCount`. - let writer: ts.EmitTextWriter; - let ownWriter: ts.EmitTextWriter; // Reusable `EmitTextWriter` for basic printing. + let writer: EmitTextWriter; + let ownWriter: EmitTextWriter; // Reusable `EmitTextWriter` for basic printing. let write = writeBase; let isOwnFileEmit: boolean; - const bundleFileInfo = printerOptions.writeBundleFileInfo ? { sections: [] } as ts.BundleFileInfo : undefined; - const relativeToBuildInfo = bundleFileInfo ? ts.Debug.checkDefined(printerOptions.relativeToBuildInfo) : undefined; + const bundleFileInfo = printerOptions.writeBundleFileInfo ? { sections: [] } as BundleFileInfo : undefined; + const relativeToBuildInfo = bundleFileInfo ? Debug.checkDefined(printerOptions.relativeToBuildInfo) : undefined; const recordInternalSection = printerOptions.recordInternalSection; let sourceFileTextPos = 0; - let sourceFileTextKind: ts.BundleFileTextLikeKind = ts.BundleFileSectionKind.Text; + let sourceFileTextKind: BundleFileTextLikeKind = BundleFileSectionKind.Text; // Source Maps let sourceMapsDisabled = true; - let sourceMapGenerator: ts.SourceMapGenerator | undefined; - let sourceMapSource: ts.SourceMapSource; + let sourceMapGenerator: SourceMapGenerator | undefined; + let sourceMapSource: SourceMapSource; let sourceMapSourceIndex = -1; - let mostRecentlyAddedSourceMapSource: ts.SourceMapSource; + let mostRecentlyAddedSourceMapSource: SourceMapSource; let mostRecentlyAddedSourceMapSourceIndex = -1; // Comments @@ -944,11 +1024,11 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number }[] | undefined; let hasWrittenComment = false; let commentsDisabled = !!printerOptions.removeComments; - let lastSubstitution: ts.Node | undefined; - let currentParenthesizerRule: ((node: ts.Node) => ts.Node) | undefined; + let lastSubstitution: Node | undefined; + let currentParenthesizerRule: ((node: Node) => Node) | undefined; const { enter: enterComment, exit: exitComment } = ts.performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment"); - const parenthesizer = ts.factory.parenthesizer; - const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector = { + const parenthesizer = factory.parenthesizer; + const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector = { select: index => index === 0 ? parenthesizer.parenthesizeLeadingTypeArgument : undefined }; const emitBinaryExpression = createEmitBinaryExpression(); @@ -969,43 +1049,43 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: bundleFileInfo }; - function printNode(hint: ts.EmitHint, node: ts.Node, sourceFile: ts.SourceFile): string { + function printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string { switch (hint) { - case ts.EmitHint.SourceFile: - ts.Debug.assert(ts.isSourceFile(node), "Expected a SourceFile node."); + case EmitHint.SourceFile: + Debug.assert(isSourceFile(node), "Expected a SourceFile node."); break; - case ts.EmitHint.IdentifierName: - ts.Debug.assert(ts.isIdentifier(node), "Expected an Identifier node."); + case EmitHint.IdentifierName: + Debug.assert(isIdentifier(node), "Expected an Identifier node."); break; - case ts.EmitHint.Expression: - ts.Debug.assert(ts.isExpression(node), "Expected an Expression node."); + case EmitHint.Expression: + Debug.assert(isExpression(node), "Expected an Expression node."); break; } switch (node.kind) { - case ts.SyntaxKind.SourceFile: return printFile(node as ts.SourceFile); - case ts.SyntaxKind.Bundle: return printBundle(node as ts.Bundle); - case ts.SyntaxKind.UnparsedSource: return printUnparsedSource(node as ts.UnparsedSource); + case SyntaxKind.SourceFile: return printFile(node as SourceFile); + case SyntaxKind.Bundle: return printBundle(node as Bundle); + case SyntaxKind.UnparsedSource: return printUnparsedSource(node as UnparsedSource); } writeNode(hint, node, sourceFile, beginPrint()); return endPrint(); } - function printList(format: ts.ListFormat, nodes: ts.NodeArray, sourceFile: ts.SourceFile) { + function printList(format: ListFormat, nodes: NodeArray, sourceFile: SourceFile) { writeList(format, nodes, sourceFile, beginPrint()); return endPrint(); } - function printBundle(bundle: ts.Bundle): string { + function printBundle(bundle: Bundle): string { writeBundle(bundle, beginPrint(), /*sourceMapEmitter*/ undefined); return endPrint(); } - function printFile(sourceFile: ts.SourceFile): string { + function printFile(sourceFile: SourceFile): string { writeFile(sourceFile, beginPrint(), /*sourceMapEmitter*/ undefined); return endPrint(); } - function printUnparsedSource(unparsed: ts.UnparsedSource): string { + function printUnparsedSource(unparsed: UnparsedSource): string { writeUnparsedSource(unparsed, beginPrint()); return endPrint(); } @@ -1013,9 +1093,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * If `sourceFile` is `undefined`, `node` must be a synthesized `TypeNode`. */ - function writeNode(hint: ts.EmitHint, node: ts.TypeNode, sourceFile: undefined, output: ts.EmitTextWriter): void; - function writeNode(hint: ts.EmitHint, node: ts.Node, sourceFile: ts.SourceFile, output: ts.EmitTextWriter): void; - function writeNode(hint: ts.EmitHint, node: ts.Node, sourceFile: ts.SourceFile | undefined, output: ts.EmitTextWriter) { + function writeNode(hint: EmitHint, node: TypeNode, sourceFile: undefined, output: EmitTextWriter): void; + function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, output: EmitTextWriter): void; + function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined, output: EmitTextWriter) { const previousWriter = writer; setWriter(output, /*_sourceMapGenerator*/ undefined); print(hint, node, sourceFile); @@ -1023,7 +1103,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writer = previousWriter; } - function writeList(format: ts.ListFormat, nodes: ts.NodeArray, sourceFile: ts.SourceFile | undefined, output: ts.EmitTextWriter) { + function writeList(format: ListFormat, nodes: NodeArray, sourceFile: SourceFile | undefined, output: EmitTextWriter) { const previousWriter = writer; setWriter(output, /*_sourceMapGenerator*/ undefined); if (sourceFile) { @@ -1038,8 +1118,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return writer.getTextPosWithWriteLine ? writer.getTextPosWithWriteLine() : writer.getTextPos(); } - function updateOrPushBundleFileTextLike(pos: number, end: number, kind: ts.BundleFileTextLikeKind) { - const last = ts.lastOrUndefined(bundleFileInfo!.sections); + function updateOrPushBundleFileTextLike(pos: number, end: number, kind: BundleFileTextLikeKind) { + const last = lastOrUndefined(bundleFileInfo!.sections); if (last && last.kind === kind) { last.end = end; } @@ -1048,17 +1128,17 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function recordBundleFileInternalSectionStart(node: ts.Node) { + function recordBundleFileInternalSectionStart(node: Node) { if (recordInternalSection && bundleFileInfo && currentSourceFile && - (ts.isDeclaration(node) || ts.isVariableStatement(node)) && - ts.isInternalDeclaration(node, currentSourceFile) && - sourceFileTextKind !== ts.BundleFileSectionKind.Internal) { + (isDeclaration(node) || isVariableStatement(node)) && + isInternalDeclaration(node, currentSourceFile) && + sourceFileTextKind !== BundleFileSectionKind.Internal) { const prevSourceFileTextKind = sourceFileTextKind; recordBundleFileTextLikeSection(writer.getTextPos()); sourceFileTextPos = getTextPosWithWriteLine(); - sourceFileTextKind = ts.BundleFileSectionKind.Internal; + sourceFileTextKind = BundleFileSectionKind.Internal; return prevSourceFileTextKind; } return undefined; @@ -1080,7 +1160,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return false; } - function writeBundle(bundle: ts.Bundle, output: ts.EmitTextWriter, sourceMapGenerator: ts.SourceMapGenerator | undefined) { + function writeBundle(bundle: Bundle, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) { isOwnFileEmit = false; const previousWriter = writer; setWriter(output, sourceMapGenerator); @@ -1094,19 +1174,19 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: const pos = writer.getTextPos(); const savedSections = bundleFileInfo && bundleFileInfo.sections; if (savedSections) bundleFileInfo.sections = []; - print(ts.EmitHint.Unspecified, prepend, /*sourceFile*/ undefined); + print(EmitHint.Unspecified, prepend, /*sourceFile*/ undefined); if (bundleFileInfo) { const newSections = bundleFileInfo.sections; bundleFileInfo.sections = savedSections!; if (prepend.oldFileOfCurrentEmit) bundleFileInfo.sections.push(...newSections); else { - newSections.forEach(section => ts.Debug.assert(ts.isBundleFileTextLike(section))); + newSections.forEach(section => Debug.assert(isBundleFileTextLike(section))); bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), - kind: ts.BundleFileSectionKind.Prepend, - data: relativeToBuildInfo!((prepend as ts.UnparsedSource).fileName), - texts: newSections as ts.BundleFileTextLike[] + kind: BundleFileSectionKind.Prepend, + data: relativeToBuildInfo!((prepend as UnparsedSource).fileName), + texts: newSections as BundleFileTextLike[] }); } } @@ -1114,7 +1194,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: sourceFileTextPos = getTextPosWithWriteLine(); for (const sourceFile of bundle.sourceFiles) { - print(ts.EmitHint.SourceFile, sourceFile, sourceFile); + print(EmitHint.SourceFile, sourceFile, sourceFile); } if (bundleFileInfo && bundle.sourceFiles.length) { const end = writer.getTextPos(); @@ -1139,27 +1219,27 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writer = previousWriter; } - function writeUnparsedSource(unparsed: ts.UnparsedSource, output: ts.EmitTextWriter) { + function writeUnparsedSource(unparsed: UnparsedSource, output: EmitTextWriter) { const previousWriter = writer; setWriter(output, /*_sourceMapGenerator*/ undefined); - print(ts.EmitHint.Unspecified, unparsed, /*sourceFile*/ undefined); + print(EmitHint.Unspecified, unparsed, /*sourceFile*/ undefined); reset(); writer = previousWriter; } - function writeFile(sourceFile: ts.SourceFile, output: ts.EmitTextWriter, sourceMapGenerator: ts.SourceMapGenerator | undefined) { + function writeFile(sourceFile: SourceFile, output: EmitTextWriter, sourceMapGenerator: SourceMapGenerator | undefined) { isOwnFileEmit = true; const previousWriter = writer; setWriter(output, sourceMapGenerator); emitShebangIfNeeded(sourceFile); emitPrologueDirectivesIfNeeded(sourceFile); - print(ts.EmitHint.SourceFile, sourceFile, sourceFile); + print(EmitHint.SourceFile, sourceFile, sourceFile); reset(); writer = previousWriter; } function beginPrint() { - return ownWriter || (ownWriter = ts.createTextWriter(newLine)); + return ownWriter || (ownWriter = createTextWriter(newLine)); } function endPrint() { @@ -1168,7 +1248,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return text; } - function print(hint: ts.EmitHint, node: ts.Node, sourceFile: ts.SourceFile | undefined) { + function print(hint: EmitHint, node: Node, sourceFile: SourceFile | undefined) { if (sourceFile) { setSourceFile(sourceFile); } @@ -1176,7 +1256,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: pipelineEmit(hint, node, /*parenthesizerRule*/ undefined); } - function setSourceFile(sourceFile: ts.SourceFile | undefined) { + function setSourceFile(sourceFile: SourceFile | undefined) { currentSourceFile = sourceFile; currentLineMap = undefined; detachedCommentsInfo = undefined; @@ -1185,9 +1265,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function setWriter(_writer: ts.EmitTextWriter | undefined, _sourceMapGenerator: ts.SourceMapGenerator | undefined) { + function setWriter(_writer: EmitTextWriter | undefined, _sourceMapGenerator: SourceMapGenerator | undefined) { if (_writer && printerOptions.omitTrailingSemicolon) { - _writer = ts.getTrailingSemicolonDeferringWriter(_writer); + _writer = getTrailingSemicolonDeferringWriter(_writer); } writer = _writer!; // TODO: GH#18217 @@ -1198,9 +1278,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function reset() { nodeIdToGeneratedName = []; autoGeneratedIdToGeneratedName = []; - generatedNames = new ts.Set(); + generatedNames = new Set(); formattedNameTempFlagsStack = []; - formattedNameTempFlags = new ts.Map(); + formattedNameTempFlags = new Map(); privateNameTempFlagsStack = []; privateNameTempFlags = TempFlags.Auto; tempFlagsStack = []; @@ -1213,38 +1293,38 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } function getCurrentLineMap() { - return currentLineMap || (currentLineMap = ts.getLineStarts(ts.Debug.checkDefined(currentSourceFile))); + return currentLineMap || (currentLineMap = getLineStarts(Debug.checkDefined(currentSourceFile))); } - function emit(node: ts.Node, parenthesizerRule?: (node: ts.Node) => ts.Node): void; - function emit(node: ts.Node | undefined, parenthesizerRule?: (node: ts.Node) => ts.Node): void; - function emit(node: ts.Node | undefined, parenthesizerRule?: (node: ts.Node) => ts.Node) { + function emit(node: Node, parenthesizerRule?: (node: Node) => Node): void; + function emit(node: Node | undefined, parenthesizerRule?: (node: Node) => Node): void; + function emit(node: Node | undefined, parenthesizerRule?: (node: Node) => Node) { if (node === undefined) return; const prevSourceFileTextKind = recordBundleFileInternalSectionStart(node); - pipelineEmit(ts.EmitHint.Unspecified, node, parenthesizerRule); + pipelineEmit(EmitHint.Unspecified, node, parenthesizerRule); recordBundleFileInternalSectionEnd(prevSourceFileTextKind); } - function emitIdentifierName(node: ts.Identifier): void; - function emitIdentifierName(node: ts.Identifier | undefined): void; - function emitIdentifierName(node: ts.Identifier | undefined) { + function emitIdentifierName(node: Identifier): void; + function emitIdentifierName(node: Identifier | undefined): void; + function emitIdentifierName(node: Identifier | undefined) { if (node === undefined) return; - pipelineEmit(ts.EmitHint.IdentifierName, node, /*parenthesizerRule*/ undefined); + pipelineEmit(EmitHint.IdentifierName, node, /*parenthesizerRule*/ undefined); } - function emitExpression(node: ts.Expression, parenthesizerRule?: (node: ts.Expression) => ts.Expression): void; - function emitExpression(node: ts.Expression | undefined, parenthesizerRule?: (node: ts.Expression) => ts.Expression): void; - function emitExpression(node: ts.Expression | undefined, parenthesizerRule?: (node: ts.Expression) => ts.Expression) { + function emitExpression(node: Expression, parenthesizerRule?: (node: Expression) => Expression): void; + function emitExpression(node: Expression | undefined, parenthesizerRule?: (node: Expression) => Expression): void; + function emitExpression(node: Expression | undefined, parenthesizerRule?: (node: Expression) => Expression) { if (node === undefined) return; - pipelineEmit(ts.EmitHint.Expression, node, parenthesizerRule); + pipelineEmit(EmitHint.Expression, node, parenthesizerRule); } - function emitJsxAttributeValue(node: ts.StringLiteral | ts.JsxExpression): void { - pipelineEmit(ts.isStringLiteral(node) ? ts.EmitHint.JsxAttributeValue : ts.EmitHint.Unspecified, node); + function emitJsxAttributeValue(node: StringLiteral | JsxExpression): void { + pipelineEmit(isStringLiteral(node) ? EmitHint.JsxAttributeValue : EmitHint.Unspecified, node); } - function beforeEmitNode(node: ts.Node) { - if (preserveSourceNewlines && (ts.getEmitFlags(node) & ts.EmitFlags.IgnoreSourceNewlines)) { + function beforeEmitNode(node: Node) { + if (preserveSourceNewlines && (getEmitFlags(node) & EmitFlags.IgnoreSourceNewlines)) { preserveSourceNewlines = false; } } @@ -1253,34 +1333,34 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: preserveSourceNewlines = savedPreserveSourceNewlines; } - function pipelineEmit(emitHint: ts.EmitHint, node: ts.Node, parenthesizerRule?: (node: ts.Node) => ts.Node) { + function pipelineEmit(emitHint: EmitHint, node: Node, parenthesizerRule?: (node: Node) => Node) { currentParenthesizerRule = parenthesizerRule; const pipelinePhase = getPipelinePhase(PipelinePhase.Notification, emitHint, node); pipelinePhase(emitHint, node); currentParenthesizerRule = undefined; } - function shouldEmitComments(node: ts.Node) { - return !commentsDisabled && !ts.isSourceFile(node); + function shouldEmitComments(node: Node) { + return !commentsDisabled && !isSourceFile(node); } - function shouldEmitSourceMaps(node: ts.Node) { + function shouldEmitSourceMaps(node: Node) { return !sourceMapsDisabled && - !ts.isSourceFile(node) && - !ts.isInJsonFile(node) && - !ts.isUnparsedSource(node) && - !ts.isUnparsedPrepend(node); + !isSourceFile(node) && + !isInJsonFile(node) && + !isUnparsedSource(node) && + !isUnparsedPrepend(node); } - function getPipelinePhase(phase: PipelinePhase, emitHint: ts.EmitHint, node: ts.Node) { + function getPipelinePhase(phase: PipelinePhase, emitHint: EmitHint, node: Node) { switch (phase) { case PipelinePhase.Notification: - if (onEmitNode !== ts.noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node))) { + if (onEmitNode !== noEmitNotification && (!isEmitNotificationEnabled || isEmitNotificationEnabled(node))) { return pipelineEmitWithNotification; } // falls through case PipelinePhase.Substitution: - if (substituteNode !== ts.noEmitSubstitution && (lastSubstitution = substituteNode(emitHint, node) || node) !== node) { + if (substituteNode !== noEmitSubstitution && (lastSubstitution = substituteNode(emitHint, node) || node) !== node) { if (currentParenthesizerRule) { lastSubstitution = currentParenthesizerRule(lastSubstitution); } @@ -1300,20 +1380,20 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: case PipelinePhase.Emit: return pipelineEmitWithHint; default: - return ts.Debug.assertNever(phase); + return Debug.assertNever(phase); } } - function getNextPipelinePhase(currentPhase: PipelinePhase, emitHint: ts.EmitHint, node: ts.Node) { + function getNextPipelinePhase(currentPhase: PipelinePhase, emitHint: EmitHint, node: Node) { return getPipelinePhase(currentPhase + 1, emitHint, node); } - function pipelineEmitWithNotification(hint: ts.EmitHint, node: ts.Node) { + function pipelineEmitWithNotification(hint: EmitHint, node: Node) { const pipelinePhase = getNextPipelinePhase(PipelinePhase.Notification, hint, node); onEmitNode(hint, node, pipelinePhase); } - function pipelineEmitWithHint(hint: ts.EmitHint, node: ts.Node): void { + function pipelineEmitWithHint(hint: EmitHint, node: Node): void { onBeforeEmitNode?.(node); if (preserveSourceNewlines) { const savedPreserveSourceNewlines = preserveSourceNewlines; @@ -1329,369 +1409,369 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: currentParenthesizerRule = undefined; } - function pipelineEmitWithHintWorker(hint: ts.EmitHint, node: ts.Node, allowSnippets = true): void { + function pipelineEmitWithHintWorker(hint: EmitHint, node: Node, allowSnippets = true): void { if (allowSnippets) { - const snippet = ts.getSnippetElement(node); + const snippet = getSnippetElement(node); if (snippet) { return emitSnippetNode(hint, node, snippet); } } - if (hint === ts.EmitHint.SourceFile) return emitSourceFile(ts.cast(node, ts.isSourceFile)); - if (hint === ts.EmitHint.IdentifierName) return emitIdentifier(ts.cast(node, ts.isIdentifier)); - if (hint === ts.EmitHint.JsxAttributeValue) return emitLiteral(ts.cast(node, ts.isStringLiteral), /*jsxAttributeEscape*/ true); - if (hint === ts.EmitHint.MappedTypeParameter) return emitMappedTypeParameter(ts.cast(node, ts.isTypeParameterDeclaration)); - if (hint === ts.EmitHint.EmbeddedStatement) { - ts.Debug.assertNode(node, ts.isEmptyStatement); + if (hint === EmitHint.SourceFile) return emitSourceFile(cast(node, isSourceFile)); + if (hint === EmitHint.IdentifierName) return emitIdentifier(cast(node, isIdentifier)); + if (hint === EmitHint.JsxAttributeValue) return emitLiteral(cast(node, isStringLiteral), /*jsxAttributeEscape*/ true); + if (hint === EmitHint.MappedTypeParameter) return emitMappedTypeParameter(cast(node, isTypeParameterDeclaration)); + if (hint === EmitHint.EmbeddedStatement) { + Debug.assertNode(node, isEmptyStatement); return emitEmptyStatement(/*isEmbeddedStatement*/ true); } - if (hint === ts.EmitHint.Unspecified) { + if (hint === EmitHint.Unspecified) { switch (node.kind) { // Pseudo-literals - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.TemplateMiddle: - case ts.SyntaxKind.TemplateTail: - return emitLiteral(node as ts.LiteralExpression, /*jsxAttributeEscape*/ false); + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + return emitLiteral(node as LiteralExpression, /*jsxAttributeEscape*/ false); // Identifiers - case ts.SyntaxKind.Identifier: - return emitIdentifier(node as ts.Identifier); + case SyntaxKind.Identifier: + return emitIdentifier(node as Identifier); // PrivateIdentifiers - case ts.SyntaxKind.PrivateIdentifier: - return emitPrivateIdentifier(node as ts.PrivateIdentifier); + case SyntaxKind.PrivateIdentifier: + return emitPrivateIdentifier(node as PrivateIdentifier); // Parse tree nodes // Names - case ts.SyntaxKind.QualifiedName: - return emitQualifiedName(node as ts.QualifiedName); - case ts.SyntaxKind.ComputedPropertyName: - return emitComputedPropertyName(node as ts.ComputedPropertyName); + case SyntaxKind.QualifiedName: + return emitQualifiedName(node as QualifiedName); + case SyntaxKind.ComputedPropertyName: + return emitComputedPropertyName(node as ComputedPropertyName); // Signature elements - case ts.SyntaxKind.TypeParameter: - return emitTypeParameter(node as ts.TypeParameterDeclaration); - case ts.SyntaxKind.Parameter: - return emitParameter(node as ts.ParameterDeclaration); - case ts.SyntaxKind.Decorator: - return emitDecorator(node as ts.Decorator); + case SyntaxKind.TypeParameter: + return emitTypeParameter(node as TypeParameterDeclaration); + case SyntaxKind.Parameter: + return emitParameter(node as ParameterDeclaration); + case SyntaxKind.Decorator: + return emitDecorator(node as Decorator); // Type members - case ts.SyntaxKind.PropertySignature: - return emitPropertySignature(node as ts.PropertySignature); - case ts.SyntaxKind.PropertyDeclaration: - return emitPropertyDeclaration(node as ts.PropertyDeclaration); - case ts.SyntaxKind.MethodSignature: - return emitMethodSignature(node as ts.MethodSignature); - case ts.SyntaxKind.MethodDeclaration: - return emitMethodDeclaration(node as ts.MethodDeclaration); - case ts.SyntaxKind.ClassStaticBlockDeclaration: - return emitClassStaticBlockDeclaration(node as ts.ClassStaticBlockDeclaration); - case ts.SyntaxKind.Constructor: - return emitConstructor(node as ts.ConstructorDeclaration); - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return emitAccessorDeclaration(node as ts.AccessorDeclaration); - case ts.SyntaxKind.CallSignature: - return emitCallSignature(node as ts.CallSignatureDeclaration); - case ts.SyntaxKind.ConstructSignature: - return emitConstructSignature(node as ts.ConstructSignatureDeclaration); - case ts.SyntaxKind.IndexSignature: - return emitIndexSignature(node as ts.IndexSignatureDeclaration); + case SyntaxKind.PropertySignature: + return emitPropertySignature(node as PropertySignature); + case SyntaxKind.PropertyDeclaration: + return emitPropertyDeclaration(node as PropertyDeclaration); + case SyntaxKind.MethodSignature: + return emitMethodSignature(node as MethodSignature); + case SyntaxKind.MethodDeclaration: + return emitMethodDeclaration(node as MethodDeclaration); + case SyntaxKind.ClassStaticBlockDeclaration: + return emitClassStaticBlockDeclaration(node as ClassStaticBlockDeclaration); + case SyntaxKind.Constructor: + return emitConstructor(node as ConstructorDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return emitAccessorDeclaration(node as AccessorDeclaration); + case SyntaxKind.CallSignature: + return emitCallSignature(node as CallSignatureDeclaration); + case SyntaxKind.ConstructSignature: + return emitConstructSignature(node as ConstructSignatureDeclaration); + case SyntaxKind.IndexSignature: + return emitIndexSignature(node as IndexSignatureDeclaration); // Types - case ts.SyntaxKind.TypePredicate: - return emitTypePredicate(node as ts.TypePredicateNode); - case ts.SyntaxKind.TypeReference: - return emitTypeReference(node as ts.TypeReferenceNode); - case ts.SyntaxKind.FunctionType: - return emitFunctionType(node as ts.FunctionTypeNode); - case ts.SyntaxKind.ConstructorType: - return emitConstructorType(node as ts.ConstructorTypeNode); - case ts.SyntaxKind.TypeQuery: - return emitTypeQuery(node as ts.TypeQueryNode); - case ts.SyntaxKind.TypeLiteral: - return emitTypeLiteral(node as ts.TypeLiteralNode); - case ts.SyntaxKind.ArrayType: - return emitArrayType(node as ts.ArrayTypeNode); - case ts.SyntaxKind.TupleType: - return emitTupleType(node as ts.TupleTypeNode); - case ts.SyntaxKind.OptionalType: - return emitOptionalType(node as ts.OptionalTypeNode); + case SyntaxKind.TypePredicate: + return emitTypePredicate(node as TypePredicateNode); + case SyntaxKind.TypeReference: + return emitTypeReference(node as TypeReferenceNode); + case SyntaxKind.FunctionType: + return emitFunctionType(node as FunctionTypeNode); + case SyntaxKind.ConstructorType: + return emitConstructorType(node as ConstructorTypeNode); + case SyntaxKind.TypeQuery: + return emitTypeQuery(node as TypeQueryNode); + case SyntaxKind.TypeLiteral: + return emitTypeLiteral(node as TypeLiteralNode); + case SyntaxKind.ArrayType: + return emitArrayType(node as ArrayTypeNode); + case SyntaxKind.TupleType: + return emitTupleType(node as TupleTypeNode); + case SyntaxKind.OptionalType: + return emitOptionalType(node as OptionalTypeNode); // SyntaxKind.RestType is handled below - case ts.SyntaxKind.UnionType: - return emitUnionType(node as ts.UnionTypeNode); - case ts.SyntaxKind.IntersectionType: - return emitIntersectionType(node as ts.IntersectionTypeNode); - case ts.SyntaxKind.ConditionalType: - return emitConditionalType(node as ts.ConditionalTypeNode); - case ts.SyntaxKind.InferType: - return emitInferType(node as ts.InferTypeNode); - case ts.SyntaxKind.ParenthesizedType: - return emitParenthesizedType(node as ts.ParenthesizedTypeNode); - case ts.SyntaxKind.ExpressionWithTypeArguments: - return emitExpressionWithTypeArguments(node as ts.ExpressionWithTypeArguments); - case ts.SyntaxKind.ThisType: + case SyntaxKind.UnionType: + return emitUnionType(node as UnionTypeNode); + case SyntaxKind.IntersectionType: + return emitIntersectionType(node as IntersectionTypeNode); + case SyntaxKind.ConditionalType: + return emitConditionalType(node as ConditionalTypeNode); + case SyntaxKind.InferType: + return emitInferType(node as InferTypeNode); + case SyntaxKind.ParenthesizedType: + return emitParenthesizedType(node as ParenthesizedTypeNode); + case SyntaxKind.ExpressionWithTypeArguments: + return emitExpressionWithTypeArguments(node as ExpressionWithTypeArguments); + case SyntaxKind.ThisType: return emitThisType(); - case ts.SyntaxKind.TypeOperator: - return emitTypeOperator(node as ts.TypeOperatorNode); - case ts.SyntaxKind.IndexedAccessType: - return emitIndexedAccessType(node as ts.IndexedAccessTypeNode); - case ts.SyntaxKind.MappedType: - return emitMappedType(node as ts.MappedTypeNode); - case ts.SyntaxKind.LiteralType: - return emitLiteralType(node as ts.LiteralTypeNode); - case ts.SyntaxKind.NamedTupleMember: - return emitNamedTupleMember(node as ts.NamedTupleMember); - case ts.SyntaxKind.TemplateLiteralType: - return emitTemplateType(node as ts.TemplateLiteralTypeNode); - case ts.SyntaxKind.TemplateLiteralTypeSpan: - return emitTemplateTypeSpan(node as ts.TemplateLiteralTypeSpan); - case ts.SyntaxKind.ImportType: - return emitImportTypeNode(node as ts.ImportTypeNode); + case SyntaxKind.TypeOperator: + return emitTypeOperator(node as TypeOperatorNode); + case SyntaxKind.IndexedAccessType: + return emitIndexedAccessType(node as IndexedAccessTypeNode); + case SyntaxKind.MappedType: + return emitMappedType(node as MappedTypeNode); + case SyntaxKind.LiteralType: + return emitLiteralType(node as LiteralTypeNode); + case SyntaxKind.NamedTupleMember: + return emitNamedTupleMember(node as NamedTupleMember); + case SyntaxKind.TemplateLiteralType: + return emitTemplateType(node as TemplateLiteralTypeNode); + case SyntaxKind.TemplateLiteralTypeSpan: + return emitTemplateTypeSpan(node as TemplateLiteralTypeSpan); + case SyntaxKind.ImportType: + return emitImportTypeNode(node as ImportTypeNode); // Binding patterns - case ts.SyntaxKind.ObjectBindingPattern: - return emitObjectBindingPattern(node as ts.ObjectBindingPattern); - case ts.SyntaxKind.ArrayBindingPattern: - return emitArrayBindingPattern(node as ts.ArrayBindingPattern); - case ts.SyntaxKind.BindingElement: - return emitBindingElement(node as ts.BindingElement); + case SyntaxKind.ObjectBindingPattern: + return emitObjectBindingPattern(node as ObjectBindingPattern); + case SyntaxKind.ArrayBindingPattern: + return emitArrayBindingPattern(node as ArrayBindingPattern); + case SyntaxKind.BindingElement: + return emitBindingElement(node as BindingElement); // Misc - case ts.SyntaxKind.TemplateSpan: - return emitTemplateSpan(node as ts.TemplateSpan); - case ts.SyntaxKind.SemicolonClassElement: + case SyntaxKind.TemplateSpan: + return emitTemplateSpan(node as TemplateSpan); + case SyntaxKind.SemicolonClassElement: return emitSemicolonClassElement(); // Statements - case ts.SyntaxKind.Block: - return emitBlock(node as ts.Block); - case ts.SyntaxKind.VariableStatement: - return emitVariableStatement(node as ts.VariableStatement); - case ts.SyntaxKind.EmptyStatement: + case SyntaxKind.Block: + return emitBlock(node as Block); + case SyntaxKind.VariableStatement: + return emitVariableStatement(node as VariableStatement); + case SyntaxKind.EmptyStatement: return emitEmptyStatement(/*isEmbeddedStatement*/ false); - case ts.SyntaxKind.ExpressionStatement: - return emitExpressionStatement(node as ts.ExpressionStatement); - case ts.SyntaxKind.IfStatement: - return emitIfStatement(node as ts.IfStatement); - case ts.SyntaxKind.DoStatement: - return emitDoStatement(node as ts.DoStatement); - case ts.SyntaxKind.WhileStatement: - return emitWhileStatement(node as ts.WhileStatement); - case ts.SyntaxKind.ForStatement: - return emitForStatement(node as ts.ForStatement); - case ts.SyntaxKind.ForInStatement: - return emitForInStatement(node as ts.ForInStatement); - case ts.SyntaxKind.ForOfStatement: - return emitForOfStatement(node as ts.ForOfStatement); - case ts.SyntaxKind.ContinueStatement: - return emitContinueStatement(node as ts.ContinueStatement); - case ts.SyntaxKind.BreakStatement: - return emitBreakStatement(node as ts.BreakStatement); - case ts.SyntaxKind.ReturnStatement: - return emitReturnStatement(node as ts.ReturnStatement); - case ts.SyntaxKind.WithStatement: - return emitWithStatement(node as ts.WithStatement); - case ts.SyntaxKind.SwitchStatement: - return emitSwitchStatement(node as ts.SwitchStatement); - case ts.SyntaxKind.LabeledStatement: - return emitLabeledStatement(node as ts.LabeledStatement); - case ts.SyntaxKind.ThrowStatement: - return emitThrowStatement(node as ts.ThrowStatement); - case ts.SyntaxKind.TryStatement: - return emitTryStatement(node as ts.TryStatement); - case ts.SyntaxKind.DebuggerStatement: - return emitDebuggerStatement(node as ts.DebuggerStatement); + case SyntaxKind.ExpressionStatement: + return emitExpressionStatement(node as ExpressionStatement); + case SyntaxKind.IfStatement: + return emitIfStatement(node as IfStatement); + case SyntaxKind.DoStatement: + return emitDoStatement(node as DoStatement); + case SyntaxKind.WhileStatement: + return emitWhileStatement(node as WhileStatement); + case SyntaxKind.ForStatement: + return emitForStatement(node as ForStatement); + case SyntaxKind.ForInStatement: + return emitForInStatement(node as ForInStatement); + case SyntaxKind.ForOfStatement: + return emitForOfStatement(node as ForOfStatement); + case SyntaxKind.ContinueStatement: + return emitContinueStatement(node as ContinueStatement); + case SyntaxKind.BreakStatement: + return emitBreakStatement(node as BreakStatement); + case SyntaxKind.ReturnStatement: + return emitReturnStatement(node as ReturnStatement); + case SyntaxKind.WithStatement: + return emitWithStatement(node as WithStatement); + case SyntaxKind.SwitchStatement: + return emitSwitchStatement(node as SwitchStatement); + case SyntaxKind.LabeledStatement: + return emitLabeledStatement(node as LabeledStatement); + case SyntaxKind.ThrowStatement: + return emitThrowStatement(node as ThrowStatement); + case SyntaxKind.TryStatement: + return emitTryStatement(node as TryStatement); + case SyntaxKind.DebuggerStatement: + return emitDebuggerStatement(node as DebuggerStatement); // Declarations - case ts.SyntaxKind.VariableDeclaration: - return emitVariableDeclaration(node as ts.VariableDeclaration); - case ts.SyntaxKind.VariableDeclarationList: - return emitVariableDeclarationList(node as ts.VariableDeclarationList); - case ts.SyntaxKind.FunctionDeclaration: - return emitFunctionDeclaration(node as ts.FunctionDeclaration); - case ts.SyntaxKind.ClassDeclaration: - return emitClassDeclaration(node as ts.ClassDeclaration); - case ts.SyntaxKind.InterfaceDeclaration: - return emitInterfaceDeclaration(node as ts.InterfaceDeclaration); - case ts.SyntaxKind.TypeAliasDeclaration: - return emitTypeAliasDeclaration(node as ts.TypeAliasDeclaration); - case ts.SyntaxKind.EnumDeclaration: - return emitEnumDeclaration(node as ts.EnumDeclaration); - case ts.SyntaxKind.ModuleDeclaration: - return emitModuleDeclaration(node as ts.ModuleDeclaration); - case ts.SyntaxKind.ModuleBlock: - return emitModuleBlock(node as ts.ModuleBlock); - case ts.SyntaxKind.CaseBlock: - return emitCaseBlock(node as ts.CaseBlock); - case ts.SyntaxKind.NamespaceExportDeclaration: - return emitNamespaceExportDeclaration(node as ts.NamespaceExportDeclaration); - case ts.SyntaxKind.ImportEqualsDeclaration: - return emitImportEqualsDeclaration(node as ts.ImportEqualsDeclaration); - case ts.SyntaxKind.ImportDeclaration: - return emitImportDeclaration(node as ts.ImportDeclaration); - case ts.SyntaxKind.ImportClause: - return emitImportClause(node as ts.ImportClause); - case ts.SyntaxKind.NamespaceImport: - return emitNamespaceImport(node as ts.NamespaceImport); - case ts.SyntaxKind.NamespaceExport: - return emitNamespaceExport(node as ts.NamespaceExport); - case ts.SyntaxKind.NamedImports: - return emitNamedImports(node as ts.NamedImports); - case ts.SyntaxKind.ImportSpecifier: - return emitImportSpecifier(node as ts.ImportSpecifier); - case ts.SyntaxKind.ExportAssignment: - return emitExportAssignment(node as ts.ExportAssignment); - case ts.SyntaxKind.ExportDeclaration: - return emitExportDeclaration(node as ts.ExportDeclaration); - case ts.SyntaxKind.NamedExports: - return emitNamedExports(node as ts.NamedExports); - case ts.SyntaxKind.ExportSpecifier: - return emitExportSpecifier(node as ts.ExportSpecifier); - case ts.SyntaxKind.AssertClause: - return emitAssertClause(node as ts.AssertClause); - case ts.SyntaxKind.AssertEntry: - return emitAssertEntry(node as ts.AssertEntry); - case ts.SyntaxKind.MissingDeclaration: + case SyntaxKind.VariableDeclaration: + return emitVariableDeclaration(node as VariableDeclaration); + case SyntaxKind.VariableDeclarationList: + return emitVariableDeclarationList(node as VariableDeclarationList); + case SyntaxKind.FunctionDeclaration: + return emitFunctionDeclaration(node as FunctionDeclaration); + case SyntaxKind.ClassDeclaration: + return emitClassDeclaration(node as ClassDeclaration); + case SyntaxKind.InterfaceDeclaration: + return emitInterfaceDeclaration(node as InterfaceDeclaration); + case SyntaxKind.TypeAliasDeclaration: + return emitTypeAliasDeclaration(node as TypeAliasDeclaration); + case SyntaxKind.EnumDeclaration: + return emitEnumDeclaration(node as EnumDeclaration); + case SyntaxKind.ModuleDeclaration: + return emitModuleDeclaration(node as ModuleDeclaration); + case SyntaxKind.ModuleBlock: + return emitModuleBlock(node as ModuleBlock); + case SyntaxKind.CaseBlock: + return emitCaseBlock(node as CaseBlock); + case SyntaxKind.NamespaceExportDeclaration: + return emitNamespaceExportDeclaration(node as NamespaceExportDeclaration); + case SyntaxKind.ImportEqualsDeclaration: + return emitImportEqualsDeclaration(node as ImportEqualsDeclaration); + case SyntaxKind.ImportDeclaration: + return emitImportDeclaration(node as ImportDeclaration); + case SyntaxKind.ImportClause: + return emitImportClause(node as ImportClause); + case SyntaxKind.NamespaceImport: + return emitNamespaceImport(node as NamespaceImport); + case SyntaxKind.NamespaceExport: + return emitNamespaceExport(node as NamespaceExport); + case SyntaxKind.NamedImports: + return emitNamedImports(node as NamedImports); + case SyntaxKind.ImportSpecifier: + return emitImportSpecifier(node as ImportSpecifier); + case SyntaxKind.ExportAssignment: + return emitExportAssignment(node as ExportAssignment); + case SyntaxKind.ExportDeclaration: + return emitExportDeclaration(node as ExportDeclaration); + case SyntaxKind.NamedExports: + return emitNamedExports(node as NamedExports); + case SyntaxKind.ExportSpecifier: + return emitExportSpecifier(node as ExportSpecifier); + case SyntaxKind.AssertClause: + return emitAssertClause(node as AssertClause); + case SyntaxKind.AssertEntry: + return emitAssertEntry(node as AssertEntry); + case SyntaxKind.MissingDeclaration: return; // Module references - case ts.SyntaxKind.ExternalModuleReference: - return emitExternalModuleReference(node as ts.ExternalModuleReference); + case SyntaxKind.ExternalModuleReference: + return emitExternalModuleReference(node as ExternalModuleReference); // JSX (non-expression) - case ts.SyntaxKind.JsxText: - return emitJsxText(node as ts.JsxText); - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxOpeningFragment: - return emitJsxOpeningElementOrFragment(node as ts.JsxOpeningElement); - case ts.SyntaxKind.JsxClosingElement: - case ts.SyntaxKind.JsxClosingFragment: - return emitJsxClosingElementOrFragment(node as ts.JsxClosingElement); - case ts.SyntaxKind.JsxAttribute: - return emitJsxAttribute(node as ts.JsxAttribute); - case ts.SyntaxKind.JsxAttributes: - return emitJsxAttributes(node as ts.JsxAttributes); - case ts.SyntaxKind.JsxSpreadAttribute: - return emitJsxSpreadAttribute(node as ts.JsxSpreadAttribute); - case ts.SyntaxKind.JsxExpression: - return emitJsxExpression(node as ts.JsxExpression); + case SyntaxKind.JsxText: + return emitJsxText(node as JsxText); + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxOpeningFragment: + return emitJsxOpeningElementOrFragment(node as JsxOpeningElement); + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxClosingFragment: + return emitJsxClosingElementOrFragment(node as JsxClosingElement); + case SyntaxKind.JsxAttribute: + return emitJsxAttribute(node as JsxAttribute); + case SyntaxKind.JsxAttributes: + return emitJsxAttributes(node as JsxAttributes); + case SyntaxKind.JsxSpreadAttribute: + return emitJsxSpreadAttribute(node as JsxSpreadAttribute); + case SyntaxKind.JsxExpression: + return emitJsxExpression(node as JsxExpression); // Clauses - case ts.SyntaxKind.CaseClause: - return emitCaseClause(node as ts.CaseClause); - case ts.SyntaxKind.DefaultClause: - return emitDefaultClause(node as ts.DefaultClause); - case ts.SyntaxKind.HeritageClause: - return emitHeritageClause(node as ts.HeritageClause); - case ts.SyntaxKind.CatchClause: - return emitCatchClause(node as ts.CatchClause); + case SyntaxKind.CaseClause: + return emitCaseClause(node as CaseClause); + case SyntaxKind.DefaultClause: + return emitDefaultClause(node as DefaultClause); + case SyntaxKind.HeritageClause: + return emitHeritageClause(node as HeritageClause); + case SyntaxKind.CatchClause: + return emitCatchClause(node as CatchClause); // Property assignments - case ts.SyntaxKind.PropertyAssignment: - return emitPropertyAssignment(node as ts.PropertyAssignment); - case ts.SyntaxKind.ShorthandPropertyAssignment: - return emitShorthandPropertyAssignment(node as ts.ShorthandPropertyAssignment); - case ts.SyntaxKind.SpreadAssignment: - return emitSpreadAssignment(node as ts.SpreadAssignment); + case SyntaxKind.PropertyAssignment: + return emitPropertyAssignment(node as PropertyAssignment); + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignment(node as ShorthandPropertyAssignment); + case SyntaxKind.SpreadAssignment: + return emitSpreadAssignment(node as SpreadAssignment); // Enum - case ts.SyntaxKind.EnumMember: - return emitEnumMember(node as ts.EnumMember); + case SyntaxKind.EnumMember: + return emitEnumMember(node as EnumMember); // Unparsed - case ts.SyntaxKind.UnparsedPrologue: - return writeUnparsedNode(node as ts.UnparsedNode); - case ts.SyntaxKind.UnparsedSource: - case ts.SyntaxKind.UnparsedPrepend: - return emitUnparsedSourceOrPrepend(node as ts.UnparsedSource); - case ts.SyntaxKind.UnparsedText: - case ts.SyntaxKind.UnparsedInternalText: - return emitUnparsedTextLike(node as ts.UnparsedTextLike); - case ts.SyntaxKind.UnparsedSyntheticReference: - return emitUnparsedSyntheticReference(node as ts.UnparsedSyntheticReference); + case SyntaxKind.UnparsedPrologue: + return writeUnparsedNode(node as UnparsedNode); + case SyntaxKind.UnparsedSource: + case SyntaxKind.UnparsedPrepend: + return emitUnparsedSourceOrPrepend(node as UnparsedSource); + case SyntaxKind.UnparsedText: + case SyntaxKind.UnparsedInternalText: + return emitUnparsedTextLike(node as UnparsedTextLike); + case SyntaxKind.UnparsedSyntheticReference: + return emitUnparsedSyntheticReference(node as UnparsedSyntheticReference); // Top-level nodes - case ts.SyntaxKind.SourceFile: - return emitSourceFile(node as ts.SourceFile); - case ts.SyntaxKind.Bundle: - return ts.Debug.fail("Bundles should be printed using printBundle"); + case SyntaxKind.SourceFile: + return emitSourceFile(node as SourceFile); + case SyntaxKind.Bundle: + return Debug.fail("Bundles should be printed using printBundle"); // SyntaxKind.UnparsedSource (handled above) - case ts.SyntaxKind.InputFiles: - return ts.Debug.fail("InputFiles should not be printed"); + case SyntaxKind.InputFiles: + return Debug.fail("InputFiles should not be printed"); // JSDoc nodes (only used in codefixes currently) - case ts.SyntaxKind.JSDocTypeExpression: - return emitJSDocTypeExpression(node as ts.JSDocTypeExpression); - case ts.SyntaxKind.JSDocNameReference: - return emitJSDocNameReference(node as ts.JSDocNameReference); - case ts.SyntaxKind.JSDocAllType: + case SyntaxKind.JSDocTypeExpression: + return emitJSDocTypeExpression(node as JSDocTypeExpression); + case SyntaxKind.JSDocNameReference: + return emitJSDocNameReference(node as JSDocNameReference); + case SyntaxKind.JSDocAllType: return writePunctuation("*"); - case ts.SyntaxKind.JSDocUnknownType: + case SyntaxKind.JSDocUnknownType: return writePunctuation("?"); - case ts.SyntaxKind.JSDocNullableType: - return emitJSDocNullableType(node as ts.JSDocNullableType); - case ts.SyntaxKind.JSDocNonNullableType: - return emitJSDocNonNullableType(node as ts.JSDocNonNullableType); - case ts.SyntaxKind.JSDocOptionalType: - return emitJSDocOptionalType(node as ts.JSDocOptionalType); - case ts.SyntaxKind.JSDocFunctionType: - return emitJSDocFunctionType(node as ts.JSDocFunctionType); - case ts.SyntaxKind.RestType: - case ts.SyntaxKind.JSDocVariadicType: - return emitRestOrJSDocVariadicType(node as ts.RestTypeNode | ts.JSDocVariadicType); - case ts.SyntaxKind.JSDocNamepathType: + case SyntaxKind.JSDocNullableType: + return emitJSDocNullableType(node as JSDocNullableType); + case SyntaxKind.JSDocNonNullableType: + return emitJSDocNonNullableType(node as JSDocNonNullableType); + case SyntaxKind.JSDocOptionalType: + return emitJSDocOptionalType(node as JSDocOptionalType); + case SyntaxKind.JSDocFunctionType: + return emitJSDocFunctionType(node as JSDocFunctionType); + case SyntaxKind.RestType: + case SyntaxKind.JSDocVariadicType: + return emitRestOrJSDocVariadicType(node as RestTypeNode | JSDocVariadicType); + case SyntaxKind.JSDocNamepathType: return; - case ts.SyntaxKind.JSDoc: - return emitJSDoc(node as ts.JSDoc); - case ts.SyntaxKind.JSDocTypeLiteral: - return emitJSDocTypeLiteral(node as ts.JSDocTypeLiteral); - case ts.SyntaxKind.JSDocSignature: - return emitJSDocSignature(node as ts.JSDocSignature); - case ts.SyntaxKind.JSDocTag: - case ts.SyntaxKind.JSDocClassTag: - case ts.SyntaxKind.JSDocOverrideTag: - return emitJSDocSimpleTag(node as ts.JSDocTag); - case ts.SyntaxKind.JSDocAugmentsTag: - case ts.SyntaxKind.JSDocImplementsTag: - return emitJSDocHeritageTag(node as ts.JSDocImplementsTag | ts.JSDocAugmentsTag); - case ts.SyntaxKind.JSDocAuthorTag: - case ts.SyntaxKind.JSDocDeprecatedTag: + case SyntaxKind.JSDoc: + return emitJSDoc(node as JSDoc); + case SyntaxKind.JSDocTypeLiteral: + return emitJSDocTypeLiteral(node as JSDocTypeLiteral); + case SyntaxKind.JSDocSignature: + return emitJSDocSignature(node as JSDocSignature); + case SyntaxKind.JSDocTag: + case SyntaxKind.JSDocClassTag: + case SyntaxKind.JSDocOverrideTag: + return emitJSDocSimpleTag(node as JSDocTag); + case SyntaxKind.JSDocAugmentsTag: + case SyntaxKind.JSDocImplementsTag: + return emitJSDocHeritageTag(node as JSDocImplementsTag | JSDocAugmentsTag); + case SyntaxKind.JSDocAuthorTag: + case SyntaxKind.JSDocDeprecatedTag: return; // SyntaxKind.JSDocClassTag (see JSDocTag, above) - case ts.SyntaxKind.JSDocPublicTag: - case ts.SyntaxKind.JSDocPrivateTag: - case ts.SyntaxKind.JSDocProtectedTag: - case ts.SyntaxKind.JSDocReadonlyTag: + case SyntaxKind.JSDocPublicTag: + case SyntaxKind.JSDocPrivateTag: + case SyntaxKind.JSDocProtectedTag: + case SyntaxKind.JSDocReadonlyTag: return; - case ts.SyntaxKind.JSDocCallbackTag: - return emitJSDocCallbackTag(node as ts.JSDocCallbackTag); + case SyntaxKind.JSDocCallbackTag: + return emitJSDocCallbackTag(node as JSDocCallbackTag); // SyntaxKind.JSDocEnumTag (see below) - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocPropertyTag: - return emitJSDocPropertyLikeTag(node as ts.JSDocPropertyLikeTag); - case ts.SyntaxKind.JSDocEnumTag: - case ts.SyntaxKind.JSDocReturnTag: - case ts.SyntaxKind.JSDocThisTag: - case ts.SyntaxKind.JSDocTypeTag: - return emitJSDocSimpleTypedTag(node as ts.JSDocTypeTag); - case ts.SyntaxKind.JSDocTemplateTag: - return emitJSDocTemplateTag(node as ts.JSDocTemplateTag); - case ts.SyntaxKind.JSDocTypedefTag: - return emitJSDocTypedefTag(node as ts.JSDocTypedefTag); - case ts.SyntaxKind.JSDocSeeTag: - return emitJSDocSeeTag(node as ts.JSDocSeeTag); + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + return emitJSDocPropertyLikeTag(node as JSDocPropertyLikeTag); + case SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocReturnTag: + case SyntaxKind.JSDocThisTag: + case SyntaxKind.JSDocTypeTag: + return emitJSDocSimpleTypedTag(node as JSDocTypeTag); + case SyntaxKind.JSDocTemplateTag: + return emitJSDocTemplateTag(node as JSDocTemplateTag); + case SyntaxKind.JSDocTypedefTag: + return emitJSDocTypedefTag(node as JSDocTypedefTag); + case SyntaxKind.JSDocSeeTag: + return emitJSDocSeeTag(node as JSDocSeeTag); // SyntaxKind.JSDocPropertyTag (see JSDocParameterTag, above) // Transformation nodes - case ts.SyntaxKind.NotEmittedStatement: - case ts.SyntaxKind.EndOfDeclarationMarker: - case ts.SyntaxKind.MergeDeclarationMarker: + case SyntaxKind.NotEmittedStatement: + case SyntaxKind.EndOfDeclarationMarker: + case SyntaxKind.MergeDeclarationMarker: return; } - if (ts.isExpression(node)) { - hint = ts.EmitHint.Expression; - if (substituteNode !== ts.noEmitSubstitution) { + if (isExpression(node)) { + hint = EmitHint.Expression; + if (substituteNode !== noEmitSubstitution) { const substitute = substituteNode(hint, node) || node; if (substitute !== node) { node = substitute; @@ -1702,118 +1782,118 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } } - if (hint === ts.EmitHint.Expression) { + if (hint === EmitHint.Expression) { switch (node.kind) { // Literals - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - return emitNumericOrBigIntLiteral(node as ts.NumericLiteral | ts.BigIntLiteral); + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + return emitNumericOrBigIntLiteral(node as NumericLiteral | BigIntLiteral); - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.RegularExpressionLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - return emitLiteral(node as ts.LiteralExpression, /*jsxAttributeEscape*/ false); + case SyntaxKind.StringLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return emitLiteral(node as LiteralExpression, /*jsxAttributeEscape*/ false); // Identifiers - case ts.SyntaxKind.Identifier: - return emitIdentifier(node as ts.Identifier); - case ts.SyntaxKind.PrivateIdentifier: - return emitPrivateIdentifier(node as ts.PrivateIdentifier); + case SyntaxKind.Identifier: + return emitIdentifier(node as Identifier); + case SyntaxKind.PrivateIdentifier: + return emitPrivateIdentifier(node as PrivateIdentifier); // Expressions - case ts.SyntaxKind.ArrayLiteralExpression: - return emitArrayLiteralExpression(node as ts.ArrayLiteralExpression); - case ts.SyntaxKind.ObjectLiteralExpression: - return emitObjectLiteralExpression(node as ts.ObjectLiteralExpression); - case ts.SyntaxKind.PropertyAccessExpression: - return emitPropertyAccessExpression(node as ts.PropertyAccessExpression); - case ts.SyntaxKind.ElementAccessExpression: - return emitElementAccessExpression(node as ts.ElementAccessExpression); - case ts.SyntaxKind.CallExpression: - return emitCallExpression(node as ts.CallExpression); - case ts.SyntaxKind.NewExpression: - return emitNewExpression(node as ts.NewExpression); - case ts.SyntaxKind.TaggedTemplateExpression: - return emitTaggedTemplateExpression(node as ts.TaggedTemplateExpression); - case ts.SyntaxKind.TypeAssertionExpression: - return emitTypeAssertionExpression(node as ts.TypeAssertion); - case ts.SyntaxKind.ParenthesizedExpression: - return emitParenthesizedExpression(node as ts.ParenthesizedExpression); - case ts.SyntaxKind.FunctionExpression: - return emitFunctionExpression(node as ts.FunctionExpression); - case ts.SyntaxKind.ArrowFunction: - return emitArrowFunction(node as ts.ArrowFunction); - case ts.SyntaxKind.DeleteExpression: - return emitDeleteExpression(node as ts.DeleteExpression); - case ts.SyntaxKind.TypeOfExpression: - return emitTypeOfExpression(node as ts.TypeOfExpression); - case ts.SyntaxKind.VoidExpression: - return emitVoidExpression(node as ts.VoidExpression); - case ts.SyntaxKind.AwaitExpression: - return emitAwaitExpression(node as ts.AwaitExpression); - case ts.SyntaxKind.PrefixUnaryExpression: - return emitPrefixUnaryExpression(node as ts.PrefixUnaryExpression); - case ts.SyntaxKind.PostfixUnaryExpression: - return emitPostfixUnaryExpression(node as ts.PostfixUnaryExpression); - case ts.SyntaxKind.BinaryExpression: - return emitBinaryExpression(node as ts.BinaryExpression); - case ts.SyntaxKind.ConditionalExpression: - return emitConditionalExpression(node as ts.ConditionalExpression); - case ts.SyntaxKind.TemplateExpression: - return emitTemplateExpression(node as ts.TemplateExpression); - case ts.SyntaxKind.YieldExpression: - return emitYieldExpression(node as ts.YieldExpression); - case ts.SyntaxKind.SpreadElement: - return emitSpreadElement(node as ts.SpreadElement); - case ts.SyntaxKind.ClassExpression: - return emitClassExpression(node as ts.ClassExpression); - case ts.SyntaxKind.OmittedExpression: + case SyntaxKind.ArrayLiteralExpression: + return emitArrayLiteralExpression(node as ArrayLiteralExpression); + case SyntaxKind.ObjectLiteralExpression: + return emitObjectLiteralExpression(node as ObjectLiteralExpression); + case SyntaxKind.PropertyAccessExpression: + return emitPropertyAccessExpression(node as PropertyAccessExpression); + case SyntaxKind.ElementAccessExpression: + return emitElementAccessExpression(node as ElementAccessExpression); + case SyntaxKind.CallExpression: + return emitCallExpression(node as CallExpression); + case SyntaxKind.NewExpression: + return emitNewExpression(node as NewExpression); + case SyntaxKind.TaggedTemplateExpression: + return emitTaggedTemplateExpression(node as TaggedTemplateExpression); + case SyntaxKind.TypeAssertionExpression: + return emitTypeAssertionExpression(node as TypeAssertion); + case SyntaxKind.ParenthesizedExpression: + return emitParenthesizedExpression(node as ParenthesizedExpression); + case SyntaxKind.FunctionExpression: + return emitFunctionExpression(node as FunctionExpression); + case SyntaxKind.ArrowFunction: + return emitArrowFunction(node as ArrowFunction); + case SyntaxKind.DeleteExpression: + return emitDeleteExpression(node as DeleteExpression); + case SyntaxKind.TypeOfExpression: + return emitTypeOfExpression(node as TypeOfExpression); + case SyntaxKind.VoidExpression: + return emitVoidExpression(node as VoidExpression); + case SyntaxKind.AwaitExpression: + return emitAwaitExpression(node as AwaitExpression); + case SyntaxKind.PrefixUnaryExpression: + return emitPrefixUnaryExpression(node as PrefixUnaryExpression); + case SyntaxKind.PostfixUnaryExpression: + return emitPostfixUnaryExpression(node as PostfixUnaryExpression); + case SyntaxKind.BinaryExpression: + return emitBinaryExpression(node as BinaryExpression); + case SyntaxKind.ConditionalExpression: + return emitConditionalExpression(node as ConditionalExpression); + case SyntaxKind.TemplateExpression: + return emitTemplateExpression(node as TemplateExpression); + case SyntaxKind.YieldExpression: + return emitYieldExpression(node as YieldExpression); + case SyntaxKind.SpreadElement: + return emitSpreadElement(node as SpreadElement); + case SyntaxKind.ClassExpression: + return emitClassExpression(node as ClassExpression); + case SyntaxKind.OmittedExpression: return; - case ts.SyntaxKind.AsExpression: - return emitAsExpression(node as ts.AsExpression); - case ts.SyntaxKind.NonNullExpression: - return emitNonNullExpression(node as ts.NonNullExpression); - case ts.SyntaxKind.ExpressionWithTypeArguments: - return emitExpressionWithTypeArguments(node as ts.ExpressionWithTypeArguments); - case ts.SyntaxKind.SatisfiesExpression: - return emitSatisfiesExpression(node as ts.SatisfiesExpression); - case ts.SyntaxKind.MetaProperty: - return emitMetaProperty(node as ts.MetaProperty); - case ts.SyntaxKind.SyntheticExpression: - return ts.Debug.fail("SyntheticExpression should never be printed."); + case SyntaxKind.AsExpression: + return emitAsExpression(node as AsExpression); + case SyntaxKind.NonNullExpression: + return emitNonNullExpression(node as NonNullExpression); + case SyntaxKind.ExpressionWithTypeArguments: + return emitExpressionWithTypeArguments(node as ExpressionWithTypeArguments); + case SyntaxKind.SatisfiesExpression: + return emitSatisfiesExpression(node as SatisfiesExpression); + case SyntaxKind.MetaProperty: + return emitMetaProperty(node as MetaProperty); + case SyntaxKind.SyntheticExpression: + return Debug.fail("SyntheticExpression should never be printed."); // JSX - case ts.SyntaxKind.JsxElement: - return emitJsxElement(node as ts.JsxElement); - case ts.SyntaxKind.JsxSelfClosingElement: - return emitJsxSelfClosingElement(node as ts.JsxSelfClosingElement); - case ts.SyntaxKind.JsxFragment: - return emitJsxFragment(node as ts.JsxFragment); + case SyntaxKind.JsxElement: + return emitJsxElement(node as JsxElement); + case SyntaxKind.JsxSelfClosingElement: + return emitJsxSelfClosingElement(node as JsxSelfClosingElement); + case SyntaxKind.JsxFragment: + return emitJsxFragment(node as JsxFragment); // Synthesized list - case ts.SyntaxKind.SyntaxList: - return ts.Debug.fail("SyntaxList should not be printed"); + case SyntaxKind.SyntaxList: + return Debug.fail("SyntaxList should not be printed"); // Transformation nodes - case ts.SyntaxKind.NotEmittedStatement: + case SyntaxKind.NotEmittedStatement: return; - case ts.SyntaxKind.PartiallyEmittedExpression: - return emitPartiallyEmittedExpression(node as ts.PartiallyEmittedExpression); - case ts.SyntaxKind.CommaListExpression: - return emitCommaList(node as ts.CommaListExpression); - case ts.SyntaxKind.MergeDeclarationMarker: - case ts.SyntaxKind.EndOfDeclarationMarker: + case SyntaxKind.PartiallyEmittedExpression: + return emitPartiallyEmittedExpression(node as PartiallyEmittedExpression); + case SyntaxKind.CommaListExpression: + return emitCommaList(node as CommaListExpression); + case SyntaxKind.MergeDeclarationMarker: + case SyntaxKind.EndOfDeclarationMarker: return; - case ts.SyntaxKind.SyntheticReferenceExpression: - return ts.Debug.fail("SyntheticReferenceExpression should not be printed"); + case SyntaxKind.SyntheticReferenceExpression: + return Debug.fail("SyntheticReferenceExpression should not be printed"); } } - if (ts.isKeyword(node.kind)) return writeTokenNode(node, writeKeyword); - if (ts.isTokenKind(node.kind)) return writeTokenNode(node, writePunctuation); - ts.Debug.fail(`Unhandled SyntaxKind: ${ts.Debug.formatSyntaxKind(node.kind)}.`); + if (isKeyword(node.kind)) return writeTokenNode(node, writeKeyword); + if (isTokenKind(node.kind)) return writeTokenNode(node, writePunctuation); + Debug.fail(`Unhandled SyntaxKind: ${Debug.formatSyntaxKind(node.kind)}.`); } - function emitMappedTypeParameter(node: ts.TypeParameterDeclaration): void { + function emitMappedTypeParameter(node: TypeParameterDeclaration): void { emit(node.name); writeSpace(); writeKeyword("in"); @@ -1821,22 +1901,22 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emit(node.constraint); } - function pipelineEmitWithSubstitution(hint: ts.EmitHint, node: ts.Node) { + function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) { const pipelinePhase = getNextPipelinePhase(PipelinePhase.Substitution, hint, node); - ts.Debug.assertIsDefined(lastSubstitution); + Debug.assertIsDefined(lastSubstitution); node = lastSubstitution; lastSubstitution = undefined; pipelinePhase(hint, node); } - function getHelpersFromBundledSourceFiles(bundle: ts.Bundle): string[] | undefined { + function getHelpersFromBundledSourceFiles(bundle: Bundle): string[] | undefined { let result: string[] | undefined; - if (moduleKind === ts.ModuleKind.None || printerOptions.noEmitHelpers) { + if (moduleKind === ModuleKind.None || printerOptions.noEmitHelpers) { return undefined; } - const bundledHelpers = new ts.Map(); + const bundledHelpers = new Map(); for (const sourceFile of bundle.sourceFiles) { - const shouldSkip = ts.getExternalHelpersModuleName(sourceFile) !== undefined; + const shouldSkip = getExternalHelpersModuleName(sourceFile) !== undefined; const helpers = getSortedEmitHelpers(sourceFile); if (!helpers) continue; for (const helper of helpers) { @@ -1850,20 +1930,20 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return result; } - function emitHelpers(node: ts.Node) { + function emitHelpers(node: Node) { let helpersEmitted = false; - const bundle = node.kind === ts.SyntaxKind.Bundle ? node as ts.Bundle : undefined; - if (bundle && moduleKind === ts.ModuleKind.None) { + const bundle = node.kind === SyntaxKind.Bundle ? node as Bundle : undefined; + if (bundle && moduleKind === ModuleKind.None) { return; } const numPrepends = bundle ? bundle.prepends.length : 0; const numNodes = bundle ? bundle.sourceFiles.length + numPrepends : 1; for (let i = 0; i < numNodes; i++) { const currentNode = bundle ? i < numPrepends ? bundle.prepends[i] : bundle.sourceFiles[i - numPrepends] : node; - const sourceFile = ts.isSourceFile(currentNode) ? currentNode : ts.isUnparsedSource(currentNode) ? undefined : currentSourceFile; - const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && ts.hasRecordedExternalHelpers(sourceFile)); - const shouldBundle = (ts.isSourceFile(currentNode) || ts.isUnparsedSource(currentNode)) && !isOwnFileEmit; - const helpers = ts.isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode); + const sourceFile = isSourceFile(currentNode) ? currentNode : isUnparsedSource(currentNode) ? undefined : currentSourceFile; + const shouldSkip = printerOptions.noEmitHelpers || (!!sourceFile && hasRecordedExternalHelpers(sourceFile)); + const shouldBundle = (isSourceFile(currentNode) || isUnparsedSource(currentNode)) && !isOwnFileEmit; + const helpers = isUnparsedSource(currentNode) ? currentNode.helpers : getSortedEmitHelpers(currentNode); if (helpers) { for (const helper of helpers) { if (!helper.scoped) { @@ -1893,7 +1973,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: else { writeLines(helper.text(makeFileLevelOptimisticUniqueName)); } - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.EmitHelpers, data: helper.name }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.EmitHelpers, data: helper.name }); helpersEmitted = true; } } @@ -1902,9 +1982,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return helpersEmitted; } - function getSortedEmitHelpers(node: ts.Node) { - const helpers = ts.getEmitHelpers(node); - return helpers && ts.stableSort(helpers, ts.compareEmitHelpers); + function getSortedEmitHelpers(node: Node) { + const helpers = getEmitHelpers(node); + return helpers && stableSort(helpers, compareEmitHelpers); } // @@ -1913,7 +1993,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // SyntaxKind.NumericLiteral // SyntaxKind.BigIntLiteral - function emitNumericOrBigIntLiteral(node: ts.NumericLiteral | ts.BigIntLiteral) { + function emitNumericOrBigIntLiteral(node: NumericLiteral | BigIntLiteral) { emitLiteral(node, /*jsxAttributeEscape*/ false); } @@ -1923,10 +2003,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // SyntaxKind.TemplateHead // SyntaxKind.TemplateMiddle // SyntaxKind.TemplateTail - function emitLiteral(node: ts.LiteralLikeNode, jsxAttributeEscape: boolean) { + function emitLiteral(node: LiteralLikeNode, jsxAttributeEscape: boolean) { const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape, jsxAttributeEscape); if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) - && (node.kind === ts.SyntaxKind.StringLiteral || ts.isTemplateLiteralKind(node.kind))) { + && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { writeLiteral(text); } else { @@ -1937,7 +2017,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // SyntaxKind.UnparsedSource // SyntaxKind.UnparsedPrepend - function emitUnparsedSourceOrPrepend(unparsed: ts.UnparsedSource | ts.UnparsedPrepend) { + function emitUnparsedSourceOrPrepend(unparsed: UnparsedSource | UnparsedPrepend) { for (const text of unparsed.texts) { writeLine(); emit(text); @@ -1948,32 +2028,32 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // SyntaxKind.UnparsedText // SyntaxKind.UnparsedInternal // SyntaxKind.UnparsedSyntheticReference - function writeUnparsedNode(unparsed: ts.UnparsedNode) { + function writeUnparsedNode(unparsed: UnparsedNode) { writer.rawWrite(unparsed.parent.text.substring(unparsed.pos, unparsed.end)); } // SyntaxKind.UnparsedText // SyntaxKind.UnparsedInternal - function emitUnparsedTextLike(unparsed: ts.UnparsedTextLike) { + function emitUnparsedTextLike(unparsed: UnparsedTextLike) { const pos = getTextPosWithWriteLine(); writeUnparsedNode(unparsed); if (bundleFileInfo) { updateOrPushBundleFileTextLike( pos, writer.getTextPos(), - unparsed.kind === ts.SyntaxKind.UnparsedText ? - ts.BundleFileSectionKind.Text : - ts.BundleFileSectionKind.Internal + unparsed.kind === SyntaxKind.UnparsedText ? + BundleFileSectionKind.Text : + BundleFileSectionKind.Internal ); } } // SyntaxKind.UnparsedSyntheticReference - function emitUnparsedSyntheticReference(unparsed: ts.UnparsedSyntheticReference) { + function emitUnparsedSyntheticReference(unparsed: UnparsedSyntheticReference) { const pos = getTextPosWithWriteLine(); writeUnparsedNode(unparsed); if (bundleFileInfo) { - const section = ts.clone(unparsed.section); + const section = clone(unparsed.section); section.pos = pos; section.end = writer.getTextPos(); bundleFileInfo.sections.push(section); @@ -1984,29 +2064,29 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Snippet Elements // - function emitSnippetNode(hint: ts.EmitHint, node: ts.Node, snippet: ts.SnippetElement) { + function emitSnippetNode(hint: EmitHint, node: Node, snippet: SnippetElement) { switch (snippet.kind) { - case ts.SnippetKind.Placeholder: + case SnippetKind.Placeholder: emitPlaceholder(hint, node, snippet); break; - case ts.SnippetKind.TabStop: + case SnippetKind.TabStop: emitTabStop(hint, node, snippet); break; } } - function emitPlaceholder(hint: ts.EmitHint, node: ts.Node, snippet: ts.Placeholder) { + function emitPlaceholder(hint: EmitHint, node: Node, snippet: Placeholder) { nonEscapingWrite(`\$\{${snippet.order}:`); // `${2:` pipelineEmitWithHintWorker(hint, node, /*allowSnippets*/ false); // `...` nonEscapingWrite(`\}`); // `}` // `${2:...}` } - function emitTabStop(hint: ts.EmitHint, node: ts.Node, snippet: ts.TabStop) { + function emitTabStop(hint: EmitHint, node: Node, snippet: TabStop) { // A tab stop should only be attached to an empty node, i.e. a node that doesn't emit any text. - ts.Debug.assert(node.kind === ts.SyntaxKind.EmptyStatement, - `A tab stop cannot be attached to a node of kind ${ts.Debug.formatSyntaxKind(node.kind)}.`); - ts.Debug.assert(hint !== ts.EmitHint.EmbeddedStatement, + Debug.assert(node.kind === SyntaxKind.EmptyStatement, + `A tab stop cannot be attached to a node of kind ${Debug.formatSyntaxKind(node.kind)}.`); + Debug.assert(hint !== EmitHint.EmbeddedStatement, `A tab stop cannot be attached to an embedded statement.`); nonEscapingWrite(`\$${snippet.order}`); } @@ -2015,30 +2095,30 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Identifiers // - function emitIdentifier(node: ts.Identifier) { + function emitIdentifier(node: Identifier) { const writeText = node.symbol ? writeSymbol : write; writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); - emitList(node, node.typeArguments, ts.ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } // // Names // - function emitPrivateIdentifier(node: ts.PrivateIdentifier) { + function emitPrivateIdentifier(node: PrivateIdentifier) { const writeText = node.symbol ? writeSymbol : write; writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); } - function emitQualifiedName(node: ts.QualifiedName) { + function emitQualifiedName(node: QualifiedName) { emitEntityName(node.left); writePunctuation("."); emit(node.right); } - function emitEntityName(node: ts.EntityName) { - if (node.kind === ts.SyntaxKind.Identifier) { + function emitEntityName(node: EntityName) { + if (node.kind === SyntaxKind.Identifier) { emitExpression(node); } else { @@ -2046,7 +2126,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitComputedPropertyName(node: ts.ComputedPropertyName) { + function emitComputedPropertyName(node: ComputedPropertyName) { writePunctuation("["); emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfComputedPropertyName); writePunctuation("]"); @@ -2056,7 +2136,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Signature elements // - function emitTypeParameter(node: ts.TypeParameterDeclaration) { + function emitTypeParameter(node: TypeParameterDeclaration) { emitModifiers(node, node.modifiers); emit(node.name); if (node.constraint) { @@ -2073,12 +2153,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitParameter(node: ts.ParameterDeclaration) { + function emitParameter(node: ParameterDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers); emit(node.dotDotDotToken); emitNodeWithWriter(node.name, writeParameter); emit(node.questionToken); - if (node.parent && node.parent.kind === ts.SyntaxKind.JSDocFunctionType && !node.name) { + if (node.parent && node.parent.kind === SyntaxKind.JSDocFunctionType && !node.name) { emit(node.type); } else { @@ -2088,7 +2168,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitInitializer(node.initializer, node.type ? node.type.end : node.questionToken ? node.questionToken.end : node.name ? node.name.end : node.modifiers ? node.modifiers.end : node.pos, node, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitDecorator(decorator: ts.Decorator) { + function emitDecorator(decorator: Decorator) { writePunctuation("@"); emitExpression(decorator.expression, parenthesizer.parenthesizeLeftSideOfAccess); } @@ -2097,7 +2177,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Type members // - function emitPropertySignature(node: ts.PropertySignature) { + function emitPropertySignature(node: PropertySignature) { emitModifiers(node, node.modifiers); emitNodeWithWriter(node.name, writeProperty); emit(node.questionToken); @@ -2105,7 +2185,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitPropertyDeclaration(node: ts.PropertyDeclaration) { + function emitPropertyDeclaration(node: PropertyDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers); emit(node.name); emit(node.questionToken); @@ -2115,7 +2195,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitMethodSignature(node: ts.MethodSignature) { + function emitMethodSignature(node: MethodSignature) { pushNameGenerationScope(node); emitModifiers(node, node.modifiers); emit(node.name); @@ -2127,7 +2207,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitMethodDeclaration(node: ts.MethodDeclaration) { + function emitMethodDeclaration(node: MethodDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers); emit(node.asteriskToken); emit(node.name); @@ -2135,26 +2215,26 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitSignatureAndBody(node, emitSignatureHead); } - function emitClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function emitClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { writeKeyword("static"); emitBlockFunctionBody(node.body); } - function emitConstructor(node: ts.ConstructorDeclaration) { + function emitConstructor(node: ConstructorDeclaration) { emitModifiers(node, node.modifiers); writeKeyword("constructor"); emitSignatureAndBody(node, emitSignatureHead); } - function emitAccessorDeclaration(node: ts.AccessorDeclaration) { + function emitAccessorDeclaration(node: AccessorDeclaration) { emitDecoratorsAndModifiers(node, node.modifiers); - writeKeyword(node.kind === ts.SyntaxKind.GetAccessor ? "get" : "set"); + writeKeyword(node.kind === SyntaxKind.GetAccessor ? "get" : "set"); writeSpace(); emit(node.name); emitSignatureAndBody(node, emitSignatureHead); } - function emitCallSignature(node: ts.CallSignatureDeclaration) { + function emitCallSignature(node: CallSignatureDeclaration) { pushNameGenerationScope(node); emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); @@ -2163,7 +2243,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitConstructSignature(node: ts.ConstructSignatureDeclaration) { + function emitConstructSignature(node: ConstructSignatureDeclaration) { pushNameGenerationScope(node); writeKeyword("new"); writeSpace(); @@ -2174,14 +2254,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitIndexSignature(node: ts.IndexSignatureDeclaration) { + function emitIndexSignature(node: IndexSignatureDeclaration) { emitModifiers(node, node.modifiers); emitParametersForIndexSignature(node, node.parameters); emitTypeAnnotation(node.type); writeTrailingSemicolon(); } - function emitTemplateTypeSpan(node: ts.TemplateLiteralTypeSpan) { + function emitTemplateTypeSpan(node: TemplateLiteralTypeSpan) { emit(node.type); emit(node.literal); } @@ -2194,7 +2274,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Types // - function emitTypePredicate(node: ts.TypePredicateNode) { + function emitTypePredicate(node: TypePredicateNode) { if (node.assertsModifier) { emit(node.assertsModifier); writeSpace(); @@ -2208,12 +2288,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitTypeReference(node: ts.TypeReferenceNode) { + function emitTypeReference(node: TypeReferenceNode) { emit(node.typeName); emitTypeArguments(node, node.typeArguments); } - function emitFunctionType(node: ts.FunctionTypeNode) { + function emitFunctionType(node: FunctionTypeNode) { pushNameGenerationScope(node); emitTypeParameters(node, node.typeParameters); emitParametersForArrow(node, node.parameters); @@ -2224,7 +2304,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitJSDocFunctionType(node: ts.JSDocFunctionType) { + function emitJSDocFunctionType(node: JSDocFunctionType) { writeKeyword("function"); emitParameters(node, node.parameters); writePunctuation(":"); @@ -2232,22 +2312,22 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } - function emitJSDocNullableType(node: ts.JSDocNullableType) { + function emitJSDocNullableType(node: JSDocNullableType) { writePunctuation("?"); emit(node.type); } - function emitJSDocNonNullableType(node: ts.JSDocNonNullableType) { + function emitJSDocNonNullableType(node: JSDocNonNullableType) { writePunctuation("!"); emit(node.type); } - function emitJSDocOptionalType(node: ts.JSDocOptionalType) { + function emitJSDocOptionalType(node: JSDocOptionalType) { emit(node.type); writePunctuation("="); } - function emitConstructorType(node: ts.ConstructorTypeNode) { + function emitConstructorType(node: ConstructorTypeNode) { pushNameGenerationScope(node); emitModifiers(node, node.modifiers); writeKeyword("new"); @@ -2261,61 +2341,61 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: popNameGenerationScope(node); } - function emitTypeQuery(node: ts.TypeQueryNode) { + function emitTypeQuery(node: TypeQueryNode) { writeKeyword("typeof"); writeSpace(); emit(node.exprName); emitTypeArguments(node, node.typeArguments); } - function emitTypeLiteral(node: ts.TypeLiteralNode) { + function emitTypeLiteral(node: TypeLiteralNode) { writePunctuation("{"); - const flags = ts.getEmitFlags(node) & ts.EmitFlags.SingleLine ? ts.ListFormat.SingleLineTypeLiteralMembers : ts.ListFormat.MultiLineTypeLiteralMembers; - emitList(node, node.members, flags | ts.ListFormat.NoSpaceIfEmpty); + const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTypeLiteralMembers : ListFormat.MultiLineTypeLiteralMembers; + emitList(node, node.members, flags | ListFormat.NoSpaceIfEmpty); writePunctuation("}"); } - function emitArrayType(node: ts.ArrayTypeNode) { + function emitArrayType(node: ArrayTypeNode) { emit(node.elementType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType); writePunctuation("["); writePunctuation("]"); } - function emitRestOrJSDocVariadicType(node: ts.RestTypeNode | ts.JSDocVariadicType) { + function emitRestOrJSDocVariadicType(node: RestTypeNode | JSDocVariadicType) { writePunctuation("..."); emit(node.type); } - function emitTupleType(node: ts.TupleTypeNode) { - emitTokenWithComment(ts.SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node); - const flags = ts.getEmitFlags(node) & ts.EmitFlags.SingleLine ? ts.ListFormat.SingleLineTupleTypeElements : ts.ListFormat.MultiLineTupleTypeElements; - emitList(node, node.elements, flags | ts.ListFormat.NoSpaceIfEmpty, parenthesizer.parenthesizeElementTypeOfTupleType); - emitTokenWithComment(ts.SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node); + function emitTupleType(node: TupleTypeNode) { + emitTokenWithComment(SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node); + const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements : ListFormat.MultiLineTupleTypeElements; + emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty, parenthesizer.parenthesizeElementTypeOfTupleType); + emitTokenWithComment(SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node); } - function emitNamedTupleMember(node: ts.NamedTupleMember) { + function emitNamedTupleMember(node: NamedTupleMember) { emit(node.dotDotDotToken); emit(node.name); emit(node.questionToken); - emitTokenWithComment(ts.SyntaxKind.ColonToken, node.name.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.ColonToken, node.name.end, writePunctuation, node); writeSpace(); emit(node.type); } - function emitOptionalType(node: ts.OptionalTypeNode) { + function emitOptionalType(node: OptionalTypeNode) { emit(node.type, parenthesizer.parenthesizeTypeOfOptionalType); writePunctuation("?"); } - function emitUnionType(node: ts.UnionTypeNode) { - emitList(node, node.types, ts.ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfUnionType); + function emitUnionType(node: UnionTypeNode) { + emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfUnionType); } - function emitIntersectionType(node: ts.IntersectionTypeNode) { - emitList(node, node.types, ts.ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfIntersectionType); + function emitIntersectionType(node: IntersectionTypeNode) { + emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfIntersectionType); } - function emitConditionalType(node: ts.ConditionalTypeNode) { + function emitConditionalType(node: ConditionalTypeNode) { emit(node.checkType, parenthesizer.parenthesizeCheckTypeOfConditionalType); writeSpace(); writeKeyword("extends"); @@ -2331,13 +2411,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emit(node.falseType); } - function emitInferType(node: ts.InferTypeNode) { + function emitInferType(node: InferTypeNode) { writeKeyword("infer"); writeSpace(); emit(node.typeParameter); } - function emitParenthesizedType(node: ts.ParenthesizedTypeNode) { + function emitParenthesizedType(node: ParenthesizedTypeNode) { writePunctuation("("); emit(node.type); writePunctuation(")"); @@ -2347,27 +2427,27 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeKeyword("this"); } - function emitTypeOperator(node: ts.TypeOperatorNode) { + function emitTypeOperator(node: TypeOperatorNode) { writeTokenText(node.operator, writeKeyword); writeSpace(); - const parenthesizerRule = node.operator === ts.SyntaxKind.ReadonlyKeyword ? + const parenthesizerRule = node.operator === SyntaxKind.ReadonlyKeyword ? parenthesizer.parenthesizeOperandOfReadonlyTypeOperator : parenthesizer.parenthesizeOperandOfTypeOperator; emit(node.type, parenthesizerRule); } - function emitIndexedAccessType(node: ts.IndexedAccessTypeNode) { + function emitIndexedAccessType(node: IndexedAccessTypeNode) { emit(node.objectType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType); writePunctuation("["); emit(node.indexType); writePunctuation("]"); } - function emitMappedType(node: ts.MappedTypeNode) { - const emitFlags = ts.getEmitFlags(node); + function emitMappedType(node: MappedTypeNode) { + const emitFlags = getEmitFlags(node); writePunctuation("{"); - if (emitFlags & ts.EmitFlags.SingleLine) { + if (emitFlags & EmitFlags.SingleLine) { writeSpace(); } else { @@ -2376,14 +2456,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } if (node.readonlyToken) { emit(node.readonlyToken); - if (node.readonlyToken.kind !== ts.SyntaxKind.ReadonlyKeyword) { + if (node.readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { writeKeyword("readonly"); } writeSpace(); } writePunctuation("["); - pipelineEmit(ts.EmitHint.MappedTypeParameter, node.typeParameter); + pipelineEmit(EmitHint.MappedTypeParameter, node.typeParameter); if (node.nameType) { writeSpace(); writeKeyword("as"); @@ -2394,7 +2474,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writePunctuation("]"); if (node.questionToken) { emit(node.questionToken); - if (node.questionToken.kind !== ts.SyntaxKind.QuestionToken) { + if (node.questionToken.kind !== SyntaxKind.QuestionToken) { writePunctuation("?"); } } @@ -2402,27 +2482,27 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeSpace(); emit(node.type); writeTrailingSemicolon(); - if (emitFlags & ts.EmitFlags.SingleLine) { + if (emitFlags & EmitFlags.SingleLine) { writeSpace(); } else { writeLine(); decreaseIndent(); } - emitList(node, node.members, ts.ListFormat.PreserveLines); + emitList(node, node.members, ListFormat.PreserveLines); writePunctuation("}"); } - function emitLiteralType(node: ts.LiteralTypeNode) { + function emitLiteralType(node: LiteralTypeNode) { emitExpression(node.literal); } - function emitTemplateType(node: ts.TemplateLiteralTypeNode) { + function emitTemplateType(node: TemplateLiteralTypeNode) { emit(node.head); - emitList(node, node.templateSpans, ts.ListFormat.TemplateExpressionSpans); + emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); } - function emitImportTypeNode(node: ts.ImportTypeNode) { + function emitImportTypeNode(node: ImportTypeNode) { if (node.isTypeOf) { writeKeyword("typeof"); writeSpace(); @@ -2439,7 +2519,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writePunctuation(":"); writeSpace(); const elements = node.assertions.assertClause.elements; - emitList(node.assertions.assertClause, elements, ts.ListFormat.ImportClauseEntries); + emitList(node.assertions.assertClause, elements, ListFormat.ImportClauseEntries); writeSpace(); writePunctuation("}"); } @@ -2455,19 +2535,19 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Binding patterns // - function emitObjectBindingPattern(node: ts.ObjectBindingPattern) { + function emitObjectBindingPattern(node: ObjectBindingPattern) { writePunctuation("{"); - emitList(node, node.elements, ts.ListFormat.ObjectBindingPatternElements); + emitList(node, node.elements, ListFormat.ObjectBindingPatternElements); writePunctuation("}"); } - function emitArrayBindingPattern(node: ts.ArrayBindingPattern) { + function emitArrayBindingPattern(node: ArrayBindingPattern) { writePunctuation("["); - emitList(node, node.elements, ts.ListFormat.ArrayBindingPatternElements); + emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); writePunctuation("]"); } - function emitBindingElement(node: ts.BindingElement) { + function emitBindingElement(node: BindingElement) { emit(node.dotDotDotToken); if (node.propertyName) { emit(node.propertyName); @@ -2482,39 +2562,39 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Expressions // - function emitArrayLiteralExpression(node: ts.ArrayLiteralExpression) { + function emitArrayLiteralExpression(node: ArrayLiteralExpression) { const elements = node.elements; - const preferNewLine = node.multiLine ? ts.ListFormat.PreferNewLine : ts.ListFormat.None; - emitExpressionList(node, elements, ts.ListFormat.ArrayLiteralExpressionElements | preferNewLine, parenthesizer.parenthesizeExpressionForDisallowedComma); + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitObjectLiteralExpression(node: ts.ObjectLiteralExpression) { - ts.forEach(node.properties, generateMemberNames); + function emitObjectLiteralExpression(node: ObjectLiteralExpression) { + forEach(node.properties, generateMemberNames); - const indentedFlag = ts.getEmitFlags(node) & ts.EmitFlags.Indented; + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } - const preferNewLine = node.multiLine ? ts.ListFormat.PreferNewLine : ts.ListFormat.None; - const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ts.ScriptTarget.ES5 && !ts.isJsonSourceFile(currentSourceFile) ? ts.ListFormat.AllowTrailingComma : ts.ListFormat.None; - emitList(node, node.properties, ts.ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + const allowTrailingComma = currentSourceFile && currentSourceFile.languageVersion >= ScriptTarget.ES5 && !isJsonSourceFile(currentSourceFile) ? ListFormat.AllowTrailingComma : ListFormat.None; + emitList(node, node.properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); if (indentedFlag) { decreaseIndent(); } } - function emitPropertyAccessExpression(node: ts.PropertyAccessExpression) { + function emitPropertyAccessExpression(node: PropertyAccessExpression) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); - const token = node.questionDotToken || ts.setTextRangePosEnd(ts.factory.createToken(ts.SyntaxKind.DotToken) as ts.DotToken, node.expression.end, node.name.pos); + const token = node.questionDotToken || setTextRangePosEnd(factory.createToken(SyntaxKind.DotToken) as DotToken, node.expression.end, node.name.pos); const linesBeforeDot = getLinesBetweenNodes(node, node.expression, token); const linesAfterDot = getLinesBetweenNodes(node, token, node.name); writeLinesAndIndent(linesBeforeDot, /*writeSpaceIfNotIndenting*/ false); const shouldEmitDotDot = - token.kind !== ts.SyntaxKind.QuestionDotToken && + token.kind !== SyntaxKind.QuestionDotToken && mayNeedDotDotForPropertyAccess(node.expression) && !writer.hasTrailingComment() && !writer.hasTrailingWhitespace(); @@ -2536,34 +2616,34 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // 1..toString is a valid property access, emit a dot after the literal // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal - function mayNeedDotDotForPropertyAccess(expression: ts.Expression) { - expression = ts.skipPartiallyEmittedExpressions(expression); - if (ts.isNumericLiteral(expression)) { + function mayNeedDotDotForPropertyAccess(expression: Expression) { + expression = skipPartiallyEmittedExpressions(expression); + if (isNumericLiteral(expression)) { // check if numeric literal is a decimal literal that was originally written with a dot - const text = getLiteralTextOfNode(expression as ts.LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false); + const text = getLiteralTextOfNode(expression as LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false); // If he number will be printed verbatim and it doesn't already contain a dot, add one // if the expression doesn't have any comments that will be emitted. - return !expression.numericLiteralFlags && !ts.stringContains(text, ts.tokenToString(ts.SyntaxKind.DotToken)!); + return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!); } - else if (ts.isAccessExpression(expression)) { + else if (isAccessExpression(expression)) { // check if constant enum value is integer - const constantValue = ts.getConstantValue(expression); + const constantValue = getConstantValue(expression); // isFinite handles cases when constantValue is undefined return typeof constantValue === "number" && isFinite(constantValue) && Math.floor(constantValue) === constantValue; } } - function emitElementAccessExpression(node: ts.ElementAccessExpression) { + function emitElementAccessExpression(node: ElementAccessExpression) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); emit(node.questionDotToken); - emitTokenWithComment(ts.SyntaxKind.OpenBracketToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenBracketToken, node.expression.end, writePunctuation, node); emitExpression(node.argumentExpression); - emitTokenWithComment(ts.SyntaxKind.CloseBracketToken, node.argumentExpression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseBracketToken, node.argumentExpression.end, writePunctuation, node); } - function emitCallExpression(node: ts.CallExpression) { - const indirectCall = ts.getEmitFlags(node) & ts.EmitFlags.IndirectCall; + function emitCallExpression(node: CallExpression) { + const indirectCall = getEmitFlags(node) & EmitFlags.IndirectCall; if (indirectCall) { writePunctuation("("); writeLiteral("0"); @@ -2576,19 +2656,19 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } emit(node.questionDotToken); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ts.ListFormat.CallExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitNewExpression(node: ts.NewExpression) { - emitTokenWithComment(ts.SyntaxKind.NewKeyword, node.pos, writeKeyword, node); + function emitNewExpression(node: NewExpression) { + emitTokenWithComment(SyntaxKind.NewKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfNew); emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ts.ListFormat.NewExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); + emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitTaggedTemplateExpression(node: ts.TaggedTemplateExpression) { - const indirectCall = ts.getEmitFlags(node) & ts.EmitFlags.IndirectCall; + function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { + const indirectCall = getEmitFlags(node) & EmitFlags.IndirectCall; if (indirectCall) { writePunctuation("("); writeLiteral("0"); @@ -2604,33 +2684,33 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitExpression(node.template); } - function emitTypeAssertionExpression(node: ts.TypeAssertion) { + function emitTypeAssertionExpression(node: TypeAssertion) { writePunctuation("<"); emit(node.type); writePunctuation(">"); emitExpression(node.expression, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function emitParenthesizedExpression(node: ts.ParenthesizedExpression) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.OpenParenToken, node.pos, writePunctuation, node); + function emitParenthesizedExpression(node: ParenthesizedExpression) { + const openParenPos = emitTokenWithComment(SyntaxKind.OpenParenToken, node.pos, writePunctuation, node); const indented = writeLineSeparatorsAndIndentBefore(node.expression, node); emitExpression(node.expression, /*parenthesizerRules*/ undefined); writeLineSeparatorsAfter(node.expression, node); decreaseIndentIf(indented); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression ? node.expression.end : openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression ? node.expression.end : openParenPos, writePunctuation, node); } - function emitFunctionExpression(node: ts.FunctionExpression) { + function emitFunctionExpression(node: FunctionExpression) { generateNameIfNeeded(node.name); emitFunctionDeclarationOrExpression(node); } - function emitArrowFunction(node: ts.ArrowFunction) { + function emitArrowFunction(node: ArrowFunction) { emitModifiers(node, node.modifiers); emitSignatureAndBody(node, emitArrowFunctionHead); } - function emitArrowFunctionHead(node: ts.ArrowFunction) { + function emitArrowFunctionHead(node: ArrowFunction) { emitTypeParameters(node, node.typeParameters); emitParametersForArrow(node, node.parameters); emitTypeAnnotation(node.type); @@ -2638,31 +2718,31 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emit(node.equalsGreaterThanToken); } - function emitDeleteExpression(node: ts.DeleteExpression) { - emitTokenWithComment(ts.SyntaxKind.DeleteKeyword, node.pos, writeKeyword, node); + function emitDeleteExpression(node: DeleteExpression) { + emitTokenWithComment(SyntaxKind.DeleteKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function emitTypeOfExpression(node: ts.TypeOfExpression) { - emitTokenWithComment(ts.SyntaxKind.TypeOfKeyword, node.pos, writeKeyword, node); + function emitTypeOfExpression(node: TypeOfExpression) { + emitTokenWithComment(SyntaxKind.TypeOfKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function emitVoidExpression(node: ts.VoidExpression) { - emitTokenWithComment(ts.SyntaxKind.VoidKeyword, node.pos, writeKeyword, node); + function emitVoidExpression(node: VoidExpression) { + emitTokenWithComment(SyntaxKind.VoidKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function emitAwaitExpression(node: ts.AwaitExpression) { - emitTokenWithComment(ts.SyntaxKind.AwaitKeyword, node.pos, writeKeyword, node); + function emitAwaitExpression(node: AwaitExpression) { + emitTokenWithComment(SyntaxKind.AwaitKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function emitPrefixUnaryExpression(node: ts.PrefixUnaryExpression) { + function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { writeTokenText(node.operator, writeOperator); if (shouldEmitWhitespaceBeforeOperand(node)) { writeSpace(); @@ -2670,7 +2750,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitExpression(node.operand, parenthesizer.parenthesizeOperandOfPrefixUnary); } - function shouldEmitWhitespaceBeforeOperand(node: ts.PrefixUnaryExpression) { + function shouldEmitWhitespaceBeforeOperand(node: PrefixUnaryExpression) { // In some cases, we need to emit a space between the operator and the operand. One obvious case // is when the operator is an identifier, like delete or typeof. We also need to do this for plus // and minus expressions in certain cases. Specifically, consider the following two cases (parens @@ -2684,12 +2764,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // expression a prefix increment whose operand is a plus expression - (++(+x)) // The same is true of minus of course. const operand = node.operand; - return operand.kind === ts.SyntaxKind.PrefixUnaryExpression - && ((node.operator === ts.SyntaxKind.PlusToken && ((operand as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.PlusToken || (operand as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.PlusPlusToken)) - || (node.operator === ts.SyntaxKind.MinusToken && ((operand as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.MinusToken || (operand as ts.PrefixUnaryExpression).operator === ts.SyntaxKind.MinusMinusToken))); + return operand.kind === SyntaxKind.PrefixUnaryExpression + && ((node.operator === SyntaxKind.PlusToken && ((operand as PrefixUnaryExpression).operator === SyntaxKind.PlusToken || (operand as PrefixUnaryExpression).operator === SyntaxKind.PlusPlusToken)) + || (node.operator === SyntaxKind.MinusToken && ((operand as PrefixUnaryExpression).operator === SyntaxKind.MinusToken || (operand as PrefixUnaryExpression).operator === SyntaxKind.MinusMinusToken))); } - function emitPostfixUnaryExpression(node: ts.PostfixUnaryExpression) { + function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { emitExpression(node.operand, parenthesizer.parenthesizeOperandOfPostfixUnary); writeTokenText(node.operator, writeOperator); } @@ -2705,9 +2785,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: shouldEmitSourceMapsStack: boolean[]; } - return ts.createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, /*foldState*/ undefined); + return createBinaryExpressionTrampoline(onEnter, onLeft, onOperator, onRight, onExit, /*foldState*/ undefined); - function onEnter(node: ts.BinaryExpression, state: WorkArea | undefined) { + function onEnter(node: BinaryExpression, state: WorkArea | undefined) { if (state) { state.stackIndex++; state.preserveSourceNewlinesStack[state.stackIndex] = preserveSourceNewlines; @@ -2735,26 +2815,26 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return state; } - function onLeft(next: ts.Expression, _workArea: WorkArea, parent: ts.BinaryExpression) { + function onLeft(next: Expression, _workArea: WorkArea, parent: BinaryExpression) { return maybeEmitExpression(next, parent, "left"); } - function onOperator(operatorToken: ts.BinaryOperatorToken, _state: WorkArea, node: ts.BinaryExpression) { - const isCommaOperator = operatorToken.kind !== ts.SyntaxKind.CommaToken; + function onOperator(operatorToken: BinaryOperatorToken, _state: WorkArea, node: BinaryExpression) { + const isCommaOperator = operatorToken.kind !== SyntaxKind.CommaToken; const linesBeforeOperator = getLinesBetweenNodes(node, node.left, operatorToken); const linesAfterOperator = getLinesBetweenNodes(node, operatorToken, node.right); writeLinesAndIndent(linesBeforeOperator, isCommaOperator); emitLeadingCommentsOfPosition(operatorToken.pos); - writeTokenNode(operatorToken, operatorToken.kind === ts.SyntaxKind.InKeyword ? writeKeyword : writeOperator); + writeTokenNode(operatorToken, operatorToken.kind === SyntaxKind.InKeyword ? writeKeyword : writeOperator); emitTrailingCommentsOfPosition(operatorToken.end, /*prefixSpace*/ true); // Binary operators should have a space before the comment starts writeLinesAndIndent(linesAfterOperator, /*writeSpaceIfNotIndenting*/ true); } - function onRight(next: ts.Expression, _workArea: WorkArea, parent: ts.BinaryExpression) { + function onRight(next: Expression, _workArea: WorkArea, parent: BinaryExpression) { return maybeEmitExpression(next, parent, "right"); } - function onExit(node: ts.BinaryExpression, state: WorkArea) { + function onExit(node: BinaryExpression, state: WorkArea) { const linesBeforeOperator = getLinesBetweenNodes(node, node.left, node.operatorToken); const linesAfterOperator = getLinesBetweenNodes(node, node.operatorToken, node.right); decreaseIndentIf(linesBeforeOperator, linesAfterOperator); @@ -2773,33 +2853,33 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function maybeEmitExpression(next: ts.Expression, parent: ts.BinaryExpression, side: "left" | "right") { + function maybeEmitExpression(next: Expression, parent: BinaryExpression, side: "left" | "right") { const parenthesizerRule = side === "left" ? parenthesizer.getParenthesizeLeftSideOfBinaryForOperator(parent.operatorToken.kind) : parenthesizer.getParenthesizeRightSideOfBinaryForOperator(parent.operatorToken.kind); - let pipelinePhase = getPipelinePhase(PipelinePhase.Notification, ts.EmitHint.Expression, next); + let pipelinePhase = getPipelinePhase(PipelinePhase.Notification, EmitHint.Expression, next); if (pipelinePhase === pipelineEmitWithSubstitution) { - ts.Debug.assertIsDefined(lastSubstitution); - next = parenthesizerRule(ts.cast(lastSubstitution, ts.isExpression)); - pipelinePhase = getNextPipelinePhase(PipelinePhase.Substitution, ts.EmitHint.Expression, next); + Debug.assertIsDefined(lastSubstitution); + next = parenthesizerRule(cast(lastSubstitution, isExpression)); + pipelinePhase = getNextPipelinePhase(PipelinePhase.Substitution, EmitHint.Expression, next); lastSubstitution = undefined; } if (pipelinePhase === pipelineEmitWithComments || pipelinePhase === pipelineEmitWithSourceMaps || pipelinePhase === pipelineEmitWithHint) { - if (ts.isBinaryExpression(next)) { + if (isBinaryExpression(next)) { return next; } } currentParenthesizerRule = parenthesizerRule; - pipelinePhase(ts.EmitHint.Expression, next); + pipelinePhase(EmitHint.Expression, next); } } - function emitConditionalExpression(node: ts.ConditionalExpression) { + function emitConditionalExpression(node: ConditionalExpression) { const linesBeforeQuestion = getLinesBetweenNodes(node, node.condition, node.questionToken); const linesAfterQuestion = getLinesBetweenNodes(node, node.questionToken, node.whenTrue); const linesBeforeColon = getLinesBetweenNodes(node, node.whenTrue, node.colonToken); @@ -2819,33 +2899,33 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: decreaseIndentIf(linesBeforeColon, linesAfterColon); } - function emitTemplateExpression(node: ts.TemplateExpression) { + function emitTemplateExpression(node: TemplateExpression) { emit(node.head); - emitList(node, node.templateSpans, ts.ListFormat.TemplateExpressionSpans); + emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); } - function emitYieldExpression(node: ts.YieldExpression) { - emitTokenWithComment(ts.SyntaxKind.YieldKeyword, node.pos, writeKeyword, node); + function emitYieldExpression(node: YieldExpression) { + emitTokenWithComment(SyntaxKind.YieldKeyword, node.pos, writeKeyword, node); emit(node.asteriskToken); emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsiAndDisallowedComma); } - function emitSpreadElement(node: ts.SpreadElement) { - emitTokenWithComment(ts.SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node); + function emitSpreadElement(node: SpreadElement) { + emitTokenWithComment(SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node); emitExpression(node.expression, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitClassExpression(node: ts.ClassExpression) { + function emitClassExpression(node: ClassExpression) { generateNameIfNeeded(node.name); emitClassDeclarationOrExpression(node); } - function emitExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments) { + function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); emitTypeArguments(node, node.typeArguments); } - function emitAsExpression(node: ts.AsExpression) { + function emitAsExpression(node: AsExpression) { emitExpression(node.expression, /*parenthesizerRules*/ undefined); if (node.type) { writeSpace(); @@ -2855,12 +2935,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitNonNullExpression(node: ts.NonNullExpression) { + function emitNonNullExpression(node: NonNullExpression) { emitExpression(node.expression, parenthesizer.parenthesizeLeftSideOfAccess); writeOperator("!"); } - function emitSatisfiesExpression(node: ts.SatisfiesExpression) { + function emitSatisfiesExpression(node: SatisfiesExpression) { emitExpression(node.expression, /*parenthesizerRules*/ undefined); if (node.type) { writeSpace(); @@ -2870,7 +2950,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitMetaProperty(node: ts.MetaProperty) { + function emitMetaProperty(node: MetaProperty) { writeToken(node.keywordToken, node.pos, writePunctuation); writePunctuation("."); emit(node.name); @@ -2880,7 +2960,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Misc // - function emitTemplateSpan(node: ts.TemplateSpan) { + function emitTemplateSpan(node: TemplateSpan) { emitExpression(node.expression); emit(node.literal); } @@ -2889,18 +2969,18 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Statements // - function emitBlock(node: ts.Block) { + function emitBlock(node: Block) { emitBlockStatements(node, /*forceSingleLine*/ !node.multiLine && isEmptyBlock(node)); } - function emitBlockStatements(node: ts.BlockLike, forceSingleLine: boolean) { - emitTokenWithComment(ts.SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node); - const format = forceSingleLine || ts.getEmitFlags(node) & ts.EmitFlags.SingleLine ? ts.ListFormat.SingleLineBlockStatements : ts.ListFormat.MultiLineBlockStatements; + function emitBlockStatements(node: BlockLike, forceSingleLine: boolean) { + emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, /*contextNode*/ node); + const format = forceSingleLine || getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineBlockStatements : ListFormat.MultiLineBlockStatements; emitList(node, node.statements, format); - emitTokenWithComment(ts.SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & ts.ListFormat.MultiLine)); + emitTokenWithComment(SyntaxKind.CloseBraceToken, node.statements.end, writePunctuation, /*contextNode*/ node, /*indentLeading*/ !!(format & ListFormat.MultiLine)); } - function emitVariableStatement(node: ts.VariableStatement) { + function emitVariableStatement(node: VariableStatement) { emitModifiers(node, node.modifiers); emit(node.declarationList); writeTrailingSemicolon(); @@ -2917,26 +2997,26 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitExpressionStatement(node: ts.ExpressionStatement) { + function emitExpressionStatement(node: ExpressionStatement) { emitExpression(node.expression, parenthesizer.parenthesizeExpressionOfExpressionStatement); // Emit semicolon in non json files // or if json file that created synthesized expression(eg.define expression statement when --out and amd code generation) - if (!currentSourceFile || !ts.isJsonSourceFile(currentSourceFile) || ts.nodeIsSynthesized(node.expression)) { + if (!currentSourceFile || !isJsonSourceFile(currentSourceFile) || nodeIsSynthesized(node.expression)) { writeTrailingSemicolon(); } } - function emitIfStatement(node: ts.IfStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.IfKeyword, node.pos, writeKeyword, node); + function emitIfStatement(node: IfStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.IfKeyword, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.thenStatement); if (node.elseStatement) { writeLineOrSpace(node, node.thenStatement, node.elseStatement); - emitTokenWithComment(ts.SyntaxKind.ElseKeyword, node.thenStatement.end, writeKeyword, node); - if (node.elseStatement.kind === ts.SyntaxKind.IfStatement) { + emitTokenWithComment(SyntaxKind.ElseKeyword, node.thenStatement.end, writeKeyword, node); + if (node.elseStatement.kind === SyntaxKind.IfStatement) { writeSpace(); emit(node.elseStatement); } @@ -2946,18 +3026,18 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitWhileClause(node: ts.WhileStatement | ts.DoStatement, startPos: number) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.WhileKeyword, startPos, writeKeyword, node); + function emitWhileClause(node: WhileStatement | DoStatement, startPos: number) { + const openParenPos = emitTokenWithComment(SyntaxKind.WhileKeyword, startPos, writeKeyword, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); } - function emitDoStatement(node: ts.DoStatement) { - emitTokenWithComment(ts.SyntaxKind.DoKeyword, node.pos, writeKeyword, node); + function emitDoStatement(node: DoStatement) { + emitTokenWithComment(SyntaxKind.DoKeyword, node.pos, writeKeyword, node); emitEmbeddedStatement(node, node.statement); - if (ts.isBlock(node.statement) && !preserveSourceNewlines) { + if (isBlock(node.statement) && !preserveSourceNewlines) { writeSpace(); } else { @@ -2968,54 +3048,54 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitWhileStatement(node: ts.WhileStatement) { + function emitWhileStatement(node: WhileStatement) { emitWhileClause(node, node.pos); emitEmbeddedStatement(node, node.statement); } - function emitForStatement(node: ts.ForStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.ForKeyword, node.pos, writeKeyword, node); + function emitForStatement(node: ForStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node); writeSpace(); - let pos = emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node); + let pos = emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, /*contextNode*/ node); emitForBinding(node.initializer); - pos = emitTokenWithComment(ts.SyntaxKind.SemicolonToken, node.initializer ? node.initializer.end : pos, writePunctuation, node); + pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.initializer ? node.initializer.end : pos, writePunctuation, node); emitExpressionWithLeadingSpace(node.condition); - pos = emitTokenWithComment(ts.SyntaxKind.SemicolonToken, node.condition ? node.condition.end : pos, writePunctuation, node); + pos = emitTokenWithComment(SyntaxKind.SemicolonToken, node.condition ? node.condition.end : pos, writePunctuation, node); emitExpressionWithLeadingSpace(node.incrementor); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.incrementor ? node.incrementor.end : pos, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } - function emitForInStatement(node: ts.ForInStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.ForKeyword, node.pos, writeKeyword, node); + function emitForInStatement(node: ForInStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.InKeyword, node.initializer.end, writeKeyword, node); + emitTokenWithComment(SyntaxKind.InKeyword, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } - function emitForOfStatement(node: ts.ForOfStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.ForKeyword, node.pos, writeKeyword, node); + function emitForOfStatement(node: ForOfStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.ForKeyword, node.pos, writeKeyword, node); writeSpace(); emitWithTrailingSpace(node.awaitModifier); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitForBinding(node.initializer); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OfKeyword, node.initializer.end, writeKeyword, node); + emitTokenWithComment(SyntaxKind.OfKeyword, node.initializer.end, writeKeyword, node); writeSpace(); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } - function emitForBinding(node: ts.VariableDeclarationList | ts.Expression | undefined) { + function emitForBinding(node: VariableDeclarationList | Expression | undefined) { if (node !== undefined) { - if (node.kind === ts.SyntaxKind.VariableDeclarationList) { + if (node.kind === SyntaxKind.VariableDeclarationList) { emit(node); } else { @@ -3024,27 +3104,27 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitContinueStatement(node: ts.ContinueStatement) { - emitTokenWithComment(ts.SyntaxKind.ContinueKeyword, node.pos, writeKeyword, node); + function emitContinueStatement(node: ContinueStatement) { + emitTokenWithComment(SyntaxKind.ContinueKeyword, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeTrailingSemicolon(); } - function emitBreakStatement(node: ts.BreakStatement) { - emitTokenWithComment(ts.SyntaxKind.BreakKeyword, node.pos, writeKeyword, node); + function emitBreakStatement(node: BreakStatement) { + emitTokenWithComment(SyntaxKind.BreakKeyword, node.pos, writeKeyword, node); emitWithLeadingSpace(node.label); writeTrailingSemicolon(); } - function emitTokenWithComment(token: ts.SyntaxKind, pos: number, writer: (s: string) => void, contextNode: ts.Node, indentLeading?: boolean) { - const node = ts.getParseTreeNode(contextNode); + function emitTokenWithComment(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode: Node, indentLeading?: boolean) { + const node = getParseTreeNode(contextNode); const isSimilarNode = node && node.kind === contextNode.kind; const startPos = pos; if (isSimilarNode && currentSourceFile) { - pos = ts.skipTrivia(currentSourceFile.text, pos); + pos = skipTrivia(currentSourceFile.text, pos); } if (isSimilarNode && contextNode.pos !== startPos) { - const needsIndent = indentLeading && currentSourceFile && !ts.positionsAreOnSameLine(startPos, pos, currentSourceFile); + const needsIndent = indentLeading && currentSourceFile && !positionsAreOnSameLine(startPos, pos, currentSourceFile); if (needsIndent) { increaseIndent(); } @@ -3055,23 +3135,23 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } pos = writeTokenText(token, writer, pos); if (isSimilarNode && contextNode.end !== pos) { - const isJsxExprContext = contextNode.kind === ts.SyntaxKind.JsxExpression; + const isJsxExprContext = contextNode.kind === SyntaxKind.JsxExpression; emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ !isJsxExprContext, /*forceNoNewline*/ isJsxExprContext); } return pos; } - function commentWillEmitNewLine(node: ts.CommentRange) { - return node.kind === ts.SyntaxKind.SingleLineCommentTrivia || !!node.hasTrailingNewLine; + function commentWillEmitNewLine(node: CommentRange) { + return node.kind === SyntaxKind.SingleLineCommentTrivia || !!node.hasTrailingNewLine; } - function willEmitLeadingNewLine(node: ts.Expression): boolean { + function willEmitLeadingNewLine(node: Expression): boolean { if (!currentSourceFile) return false; - if (ts.some(ts.getLeadingCommentRanges(currentSourceFile.text, node.pos), commentWillEmitNewLine)) return true; - if (ts.some(ts.getSyntheticLeadingComments(node), commentWillEmitNewLine)) return true; - if (ts.isPartiallyEmittedExpression(node)) { + if (some(getLeadingCommentRanges(currentSourceFile.text, node.pos), commentWillEmitNewLine)) return true; + if (some(getSyntheticLeadingComments(node), commentWillEmitNewLine)) return true; + if (isPartiallyEmittedExpression(node)) { if (node.pos !== node.expression.pos) { - if (ts.some(ts.getTrailingCommentRanges(currentSourceFile.text, node.expression.pos), commentWillEmitNewLine)) return true; + if (some(getTrailingCommentRanges(currentSourceFile.text, node.expression.pos), commentWillEmitNewLine)) return true; } return willEmitLeadingNewLine(node.expression); } @@ -3082,65 +3162,65 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * Wraps an expression in parens if we would emit a leading comment that would introduce a line separator * between the node and its parent. */ - function parenthesizeExpressionForNoAsi(node: ts.Expression) { - if (!commentsDisabled && ts.isPartiallyEmittedExpression(node) && willEmitLeadingNewLine(node)) { - const parseNode = ts.getParseTreeNode(node); - if (parseNode && ts.isParenthesizedExpression(parseNode)) { + function parenthesizeExpressionForNoAsi(node: Expression) { + if (!commentsDisabled && isPartiallyEmittedExpression(node) && willEmitLeadingNewLine(node)) { + const parseNode = getParseTreeNode(node); + if (parseNode && isParenthesizedExpression(parseNode)) { // If the original node was a parenthesized expression, restore it to preserve comment and source map emit - const parens = ts.factory.createParenthesizedExpression(node.expression); - ts.setOriginalNode(parens, node); - ts.setTextRange(parens, parseNode); + const parens = factory.createParenthesizedExpression(node.expression); + setOriginalNode(parens, node); + setTextRange(parens, parseNode); return parens; } - return ts.factory.createParenthesizedExpression(node); + return factory.createParenthesizedExpression(node); } return node; } - function parenthesizeExpressionForNoAsiAndDisallowedComma(node: ts.Expression) { + function parenthesizeExpressionForNoAsiAndDisallowedComma(node: Expression) { return parenthesizeExpressionForNoAsi(parenthesizer.parenthesizeExpressionForDisallowedComma(node)); } - function emitReturnStatement(node: ts.ReturnStatement) { - emitTokenWithComment(ts.SyntaxKind.ReturnKeyword, node.pos, writeKeyword, /*contextNode*/ node); + function emitReturnStatement(node: ReturnStatement) { + emitTokenWithComment(SyntaxKind.ReturnKeyword, node.pos, writeKeyword, /*contextNode*/ node); emitExpressionWithLeadingSpace(node.expression && parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsi); writeTrailingSemicolon(); } - function emitWithStatement(node: ts.WithStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.WithKeyword, node.pos, writeKeyword, node); + function emitWithStatement(node: WithStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.WithKeyword, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); emitEmbeddedStatement(node, node.statement); } - function emitSwitchStatement(node: ts.SwitchStatement) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.SwitchKeyword, node.pos, writeKeyword, node); + function emitSwitchStatement(node: SwitchStatement) { + const openParenPos = emitTokenWithComment(SyntaxKind.SwitchKeyword, node.pos, writeKeyword, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.expression.end, writePunctuation, node); writeSpace(); emit(node.caseBlock); } - function emitLabeledStatement(node: ts.LabeledStatement) { + function emitLabeledStatement(node: LabeledStatement) { emit(node.label); - emitTokenWithComment(ts.SyntaxKind.ColonToken, node.label.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.ColonToken, node.label.end, writePunctuation, node); writeSpace(); emit(node.statement); } - function emitThrowStatement(node: ts.ThrowStatement) { - emitTokenWithComment(ts.SyntaxKind.ThrowKeyword, node.pos, writeKeyword, node); + function emitThrowStatement(node: ThrowStatement) { + emitTokenWithComment(SyntaxKind.ThrowKeyword, node.pos, writeKeyword, node); emitExpressionWithLeadingSpace(parenthesizeExpressionForNoAsi(node.expression), parenthesizeExpressionForNoAsi); writeTrailingSemicolon(); } - function emitTryStatement(node: ts.TryStatement) { - emitTokenWithComment(ts.SyntaxKind.TryKeyword, node.pos, writeKeyword, node); + function emitTryStatement(node: TryStatement) { + emitTokenWithComment(SyntaxKind.TryKeyword, node.pos, writeKeyword, node); writeSpace(); emit(node.tryBlock); if (node.catchClause) { @@ -3149,14 +3229,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } if (node.finallyBlock) { writeLineOrSpace(node, node.catchClause || node.tryBlock, node.finallyBlock); - emitTokenWithComment(ts.SyntaxKind.FinallyKeyword, (node.catchClause || node.tryBlock).end, writeKeyword, node); + emitTokenWithComment(SyntaxKind.FinallyKeyword, (node.catchClause || node.tryBlock).end, writeKeyword, node); writeSpace(); emit(node.finallyBlock); } } - function emitDebuggerStatement(node: ts.DebuggerStatement) { - writeToken(ts.SyntaxKind.DebuggerKeyword, node.pos, writeKeyword); + function emitDebuggerStatement(node: DebuggerStatement) { + writeToken(SyntaxKind.DebuggerKeyword, node.pos, writeKeyword); writeTrailingSemicolon(); } @@ -3164,24 +3244,24 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Declarations // - function emitVariableDeclaration(node: ts.VariableDeclaration) { + function emitVariableDeclaration(node: VariableDeclaration) { emit(node.name); emit(node.exclamationToken); emitTypeAnnotation(node.type); emitInitializer(node.initializer, node.type?.end ?? node.name.emitNode?.typeNode?.end ?? node.name.end, node, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitVariableDeclarationList(node: ts.VariableDeclarationList) { - writeKeyword(ts.isLet(node) ? "let" : ts.isVarConst(node) ? "const" : "var"); + function emitVariableDeclarationList(node: VariableDeclarationList) { + writeKeyword(isLet(node) ? "let" : isVarConst(node) ? "const" : "var"); writeSpace(); - emitList(node, node.declarations, ts.ListFormat.VariableDeclarationList); + emitList(node, node.declarations, ListFormat.VariableDeclarationList); } - function emitFunctionDeclaration(node: ts.FunctionDeclaration) { + function emitFunctionDeclaration(node: FunctionDeclaration) { emitFunctionDeclarationOrExpression(node); } - function emitFunctionDeclarationOrExpression(node: ts.FunctionDeclaration | ts.FunctionExpression) { + function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { emitModifiers(node, node.modifiers); writeKeyword("function"); emit(node.asteriskToken); @@ -3190,17 +3270,17 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitSignatureAndBody(node, emitSignatureHead); } - function emitSignatureAndBody(node: ts.FunctionLikeDeclaration, emitSignatureHead: (node: ts.SignatureDeclaration) => void) { + function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) { const body = node.body; if (body) { - if (ts.isBlock(body)) { - const indentedFlag = ts.getEmitFlags(node) & ts.EmitFlags.Indented; + if (isBlock(body)) { + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } pushNameGenerationScope(node); - ts.forEach(node.parameters, generateNames); + forEach(node.parameters, generateNames); generateNames(node.body); emitSignatureHead(node); @@ -3224,13 +3304,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } - function emitSignatureHead(node: ts.FunctionDeclaration | ts.FunctionExpression | ts.MethodDeclaration | ts.AccessorDeclaration | ts.ConstructorDeclaration) { + function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { emitTypeParameters(node, node.typeParameters); emitParameters(node, node.parameters); emitTypeAnnotation(node.type); } - function shouldEmitBlockFunctionBodyOnSingleLine(body: ts.Block) { + function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { // We must emit a function body as a single-line body in the following case: // * The body has NodeEmitFlags.SingleLine specified. @@ -3239,7 +3319,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // * A non-synthesized body's start and end position are on different lines. // * Any statement in the body starts on a new line. - if (ts.getEmitFlags(body) & ts.EmitFlags.SingleLine) { + if (getEmitFlags(body) & EmitFlags.SingleLine) { return true; } @@ -3247,18 +3327,18 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return false; } - if (!ts.nodeIsSynthesized(body) && currentSourceFile && !ts.rangeIsOnSingleLine(body, currentSourceFile)) { + if (!nodeIsSynthesized(body) && currentSourceFile && !rangeIsOnSingleLine(body, currentSourceFile)) { return false; } - if (getLeadingLineTerminatorCount(body, ts.firstOrUndefined(body.statements), ts.ListFormat.PreserveLines) - || getClosingLineTerminatorCount(body, ts.lastOrUndefined(body.statements), ts.ListFormat.PreserveLines, body.statements)) { + if (getLeadingLineTerminatorCount(body, firstOrUndefined(body.statements), ListFormat.PreserveLines) + || getClosingLineTerminatorCount(body, lastOrUndefined(body.statements), ListFormat.PreserveLines, body.statements)) { return false; } - let previousStatement: ts.Statement | undefined; + let previousStatement: Statement | undefined; for (const statement of body.statements) { - if (getSeparatingLineTerminatorCount(previousStatement, statement, ts.ListFormat.PreserveLines) > 0) { + if (getSeparatingLineTerminatorCount(previousStatement, statement, ListFormat.PreserveLines) > 0) { return false; } @@ -3268,7 +3348,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return true; } - function emitBlockFunctionBody(body: ts.Block) { + function emitBlockFunctionBody(body: Block) { onBeforeEmitNode?.(body); writeSpace(); writePunctuation("{"); @@ -3281,35 +3361,35 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitBodyWithDetachedComments(body, body.statements, emitBlockFunctionBody); decreaseIndent(); - writeToken(ts.SyntaxKind.CloseBraceToken, body.statements.end, writePunctuation, body); + writeToken(SyntaxKind.CloseBraceToken, body.statements.end, writePunctuation, body); onAfterEmitNode?.(body); } - function emitBlockFunctionBodyOnSingleLine(body: ts.Block) { + function emitBlockFunctionBodyOnSingleLine(body: Block) { emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); } - function emitBlockFunctionBodyWorker(body: ts.Block, emitBlockFunctionBodyOnSingleLine?: boolean) { + function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) { // Emit all the prologue directives (like "use strict"). const statementOffset = emitPrologueDirectives(body.statements); const pos = writer.getTextPos(); emitHelpers(body); if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { decreaseIndent(); - emitList(body, body.statements, ts.ListFormat.SingleLineFunctionBodyStatements); + emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements); increaseIndent(); } else { - emitList(body, body.statements, ts.ListFormat.MultiLineFunctionBodyStatements, /*parenthesizerRule*/ undefined, statementOffset); + emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, /*parenthesizerRule*/ undefined, statementOffset); } } - function emitClassDeclaration(node: ts.ClassDeclaration) { + function emitClassDeclaration(node: ClassDeclaration) { emitClassDeclarationOrExpression(node); } - function emitClassDeclarationOrExpression(node: ts.ClassDeclaration | ts.ClassExpression) { - ts.forEach(node.members, generateMemberNames); + function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { + forEach(node.members, generateMemberNames); emitDecoratorsAndModifiers(node, node.modifiers); writeKeyword("class"); @@ -3318,17 +3398,17 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitIdentifierName(node.name); } - const indentedFlag = ts.getEmitFlags(node) & ts.EmitFlags.Indented; + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; if (indentedFlag) { increaseIndent(); } emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ts.ListFormat.ClassHeritageClauses); + emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); writeSpace(); writePunctuation("{"); - emitList(node, node.members, ts.ListFormat.ClassMembers); + emitList(node, node.members, ListFormat.ClassMembers); writePunctuation("}"); if (indentedFlag) { @@ -3336,20 +3416,20 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitInterfaceDeclaration(node: ts.InterfaceDeclaration) { + function emitInterfaceDeclaration(node: InterfaceDeclaration) { emitModifiers(node, node.modifiers); writeKeyword("interface"); writeSpace(); emit(node.name); emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ts.ListFormat.HeritageClauses); + emitList(node, node.heritageClauses, ListFormat.HeritageClauses); writeSpace(); writePunctuation("{"); - emitList(node, node.members, ts.ListFormat.InterfaceMembers); + emitList(node, node.members, ListFormat.InterfaceMembers); writePunctuation("}"); } - function emitTypeAliasDeclaration(node: ts.TypeAliasDeclaration) { + function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { emitModifiers(node, node.modifiers); writeKeyword("type"); writeSpace(); @@ -3362,7 +3442,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitEnumDeclaration(node: ts.EnumDeclaration) { + function emitEnumDeclaration(node: EnumDeclaration) { emitModifiers(node, node.modifiers); writeKeyword("enum"); writeSpace(); @@ -3370,21 +3450,21 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeSpace(); writePunctuation("{"); - emitList(node, node.members, ts.ListFormat.EnumMembers); + emitList(node, node.members, ListFormat.EnumMembers); writePunctuation("}"); } - function emitModuleDeclaration(node: ts.ModuleDeclaration) { + function emitModuleDeclaration(node: ModuleDeclaration) { emitModifiers(node, node.modifiers); - if (~node.flags & ts.NodeFlags.GlobalAugmentation) { - writeKeyword(node.flags & ts.NodeFlags.Namespace ? "namespace" : "module"); + if (~node.flags & NodeFlags.GlobalAugmentation) { + writeKeyword(node.flags & NodeFlags.Namespace ? "namespace" : "module"); writeSpace(); } emit(node.name); let body = node.body; if (!body) return writeTrailingSemicolon(); - while (body && ts.isModuleDeclaration(body)) { + while (body && isModuleDeclaration(body)) { writePunctuation("."); emit(body.name); body = body.body; @@ -3394,37 +3474,37 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emit(body); } - function emitModuleBlock(node: ts.ModuleBlock) { + function emitModuleBlock(node: ModuleBlock) { pushNameGenerationScope(node); - ts.forEach(node.statements, generateNames); + forEach(node.statements, generateNames); emitBlockStatements(node, /*forceSingleLine*/ isEmptyBlock(node)); popNameGenerationScope(node); } - function emitCaseBlock(node: ts.CaseBlock) { - emitTokenWithComment(ts.SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node); - emitList(node, node.clauses, ts.ListFormat.CaseBlockClauses); - emitTokenWithComment(ts.SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation, node, /*indentLeading*/ true); + function emitCaseBlock(node: CaseBlock) { + emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node); + emitList(node, node.clauses, ListFormat.CaseBlockClauses); + emitTokenWithComment(SyntaxKind.CloseBraceToken, node.clauses.end, writePunctuation, node, /*indentLeading*/ true); } - function emitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration) { + function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { emitModifiers(node, node.modifiers); - emitTokenWithComment(ts.SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); if (node.isTypeOnly) { - emitTokenWithComment(ts.SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); writeSpace(); } emit(node.name); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.EqualsToken, node.name.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.EqualsToken, node.name.end, writePunctuation, node); writeSpace(); emitModuleReference(node.moduleReference); writeTrailingSemicolon(); } - function emitModuleReference(node: ts.ModuleReference) { - if (node.kind === ts.SyntaxKind.Identifier) { + function emitModuleReference(node: ModuleReference) { + if (node.kind === SyntaxKind.Identifier) { emitExpression(node); } else { @@ -3432,14 +3512,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitImportDeclaration(node: ts.ImportDeclaration) { + function emitImportDeclaration(node: ImportDeclaration) { emitModifiers(node, node.modifiers); - emitTokenWithComment(ts.SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.ImportKeyword, node.modifiers ? node.modifiers.end : node.pos, writeKeyword, node); writeSpace(); if (node.importClause) { emit(node.importClause); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.FromKeyword, node.importClause.end, writeKeyword, node); + emitTokenWithComment(SyntaxKind.FromKeyword, node.importClause.end, writeKeyword, node); writeSpace(); } emitExpression(node.moduleSpecifier); @@ -3449,69 +3529,69 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitImportClause(node: ts.ImportClause) { + function emitImportClause(node: ImportClause) { if (node.isTypeOnly) { - emitTokenWithComment(ts.SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.TypeKeyword, node.pos, writeKeyword, node); writeSpace(); } emit(node.name); if (node.name && node.namedBindings) { - emitTokenWithComment(ts.SyntaxKind.CommaToken, node.name.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CommaToken, node.name.end, writePunctuation, node); writeSpace(); } emit(node.namedBindings); } - function emitNamespaceImport(node: ts.NamespaceImport) { - const asPos = emitTokenWithComment(ts.SyntaxKind.AsteriskToken, node.pos, writePunctuation, node); + function emitNamespaceImport(node: NamespaceImport) { + const asPos = emitTokenWithComment(SyntaxKind.AsteriskToken, node.pos, writePunctuation, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.AsKeyword, asPos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.AsKeyword, asPos, writeKeyword, node); writeSpace(); emit(node.name); } - function emitNamedImports(node: ts.NamedImports) { + function emitNamedImports(node: NamedImports) { emitNamedImportsOrExports(node); } - function emitImportSpecifier(node: ts.ImportSpecifier) { + function emitImportSpecifier(node: ImportSpecifier) { emitImportOrExportSpecifier(node); } - function emitExportAssignment(node: ts.ExportAssignment) { - const nextPos = emitTokenWithComment(ts.SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); + function emitExportAssignment(node: ExportAssignment) { + const nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); writeSpace(); if (node.isExportEquals) { - emitTokenWithComment(ts.SyntaxKind.EqualsToken, nextPos, writeOperator, node); + emitTokenWithComment(SyntaxKind.EqualsToken, nextPos, writeOperator, node); } else { - emitTokenWithComment(ts.SyntaxKind.DefaultKeyword, nextPos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.DefaultKeyword, nextPos, writeKeyword, node); } writeSpace(); emitExpression(node.expression, node.isExportEquals ? - parenthesizer.getParenthesizeRightSideOfBinaryForOperator(ts.SyntaxKind.EqualsToken) : + parenthesizer.getParenthesizeRightSideOfBinaryForOperator(SyntaxKind.EqualsToken) : parenthesizer.parenthesizeExpressionOfExportDefault); writeTrailingSemicolon(); } - function emitExportDeclaration(node: ts.ExportDeclaration) { + function emitExportDeclaration(node: ExportDeclaration) { emitModifiers(node, node.modifiers); - let nextPos = emitTokenWithComment(ts.SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); + let nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); writeSpace(); if (node.isTypeOnly) { - nextPos = emitTokenWithComment(ts.SyntaxKind.TypeKeyword, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(SyntaxKind.TypeKeyword, nextPos, writeKeyword, node); writeSpace(); } if (node.exportClause) { emit(node.exportClause); } else { - nextPos = emitTokenWithComment(ts.SyntaxKind.AsteriskToken, nextPos, writePunctuation, node); + nextPos = emitTokenWithComment(SyntaxKind.AsteriskToken, nextPos, writePunctuation, node); } if (node.moduleSpecifier) { writeSpace(); const fromPos = node.exportClause ? node.exportClause.end : nextPos; - emitTokenWithComment(ts.SyntaxKind.FromKeyword, fromPos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.FromKeyword, fromPos, writeKeyword, node); writeSpace(); emitExpression(node.moduleSpecifier); } @@ -3521,61 +3601,61 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeTrailingSemicolon(); } - function emitAssertClause(node: ts.AssertClause) { - emitTokenWithComment(ts.SyntaxKind.AssertKeyword, node.pos, writeKeyword, node); + function emitAssertClause(node: AssertClause) { + emitTokenWithComment(SyntaxKind.AssertKeyword, node.pos, writeKeyword, node); writeSpace(); const elements = node.elements; - emitList(node, elements, ts.ListFormat.ImportClauseEntries); + emitList(node, elements, ListFormat.ImportClauseEntries); } - function emitAssertEntry(node: ts.AssertEntry) { + function emitAssertEntry(node: AssertEntry) { emit(node.name); writePunctuation(":"); writeSpace(); const value = node.value; /** @see {emitPropertyAssignment} */ - if ((ts.getEmitFlags(value) & ts.EmitFlags.NoLeadingComments) === 0) { - const commentRange = ts.getCommentRange(value); + if ((getEmitFlags(value) & EmitFlags.NoLeadingComments) === 0) { + const commentRange = getCommentRange(value); emitTrailingCommentsOfPosition(commentRange.pos); } emit(value); } - function emitNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration) { - let nextPos = emitTokenWithComment(ts.SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); + function emitNamespaceExportDeclaration(node: NamespaceExportDeclaration) { + let nextPos = emitTokenWithComment(SyntaxKind.ExportKeyword, node.pos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(ts.SyntaxKind.AsKeyword, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(SyntaxKind.AsKeyword, nextPos, writeKeyword, node); writeSpace(); - nextPos = emitTokenWithComment(ts.SyntaxKind.NamespaceKeyword, nextPos, writeKeyword, node); + nextPos = emitTokenWithComment(SyntaxKind.NamespaceKeyword, nextPos, writeKeyword, node); writeSpace(); emit(node.name); writeTrailingSemicolon(); } - function emitNamespaceExport(node: ts.NamespaceExport) { - const asPos = emitTokenWithComment(ts.SyntaxKind.AsteriskToken, node.pos, writePunctuation, node); + function emitNamespaceExport(node: NamespaceExport) { + const asPos = emitTokenWithComment(SyntaxKind.AsteriskToken, node.pos, writePunctuation, node); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.AsKeyword, asPos, writeKeyword, node); + emitTokenWithComment(SyntaxKind.AsKeyword, asPos, writeKeyword, node); writeSpace(); emit(node.name); } - function emitNamedExports(node: ts.NamedExports) { + function emitNamedExports(node: NamedExports) { emitNamedImportsOrExports(node); } - function emitExportSpecifier(node: ts.ExportSpecifier) { + function emitExportSpecifier(node: ExportSpecifier) { emitImportOrExportSpecifier(node); } - function emitNamedImportsOrExports(node: ts.NamedImportsOrExports) { + function emitNamedImportsOrExports(node: NamedImportsOrExports) { writePunctuation("{"); - emitList(node, node.elements, ts.ListFormat.NamedImportsOrExportsElements); + emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); writePunctuation("}"); } - function emitImportOrExportSpecifier(node: ts.ImportOrExportSpecifier) { + function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { if (node.isTypeOnly) { writeKeyword("type"); writeSpace(); @@ -3583,7 +3663,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: if (node.propertyName) { emit(node.propertyName); writeSpace(); - emitTokenWithComment(ts.SyntaxKind.AsKeyword, node.propertyName.end, writeKeyword, node); + emitTokenWithComment(SyntaxKind.AsKeyword, node.propertyName.end, writeKeyword, node); writeSpace(); } @@ -3594,7 +3674,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Module references // - function emitExternalModuleReference(node: ts.ExternalModuleReference) { + function emitExternalModuleReference(node: ExternalModuleReference) { writeKeyword("require"); writePunctuation("("); emitExpression(node.expression); @@ -3605,13 +3685,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // JSX // - function emitJsxElement(node: ts.JsxElement) { + function emitJsxElement(node: JsxElement) { emit(node.openingElement); - emitList(node, node.children, ts.ListFormat.JsxElementOrFragmentChildren); + emitList(node, node.children, ListFormat.JsxElementOrFragmentChildren); emit(node.closingElement); } - function emitJsxSelfClosingElement(node: ts.JsxSelfClosingElement) { + function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { writePunctuation("<"); emitJsxTagName(node.tagName); emitTypeArguments(node, node.typeArguments); @@ -3620,16 +3700,16 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writePunctuation("/>"); } - function emitJsxFragment(node: ts.JsxFragment) { + function emitJsxFragment(node: JsxFragment) { emit(node.openingFragment); - emitList(node, node.children, ts.ListFormat.JsxElementOrFragmentChildren); + emitList(node, node.children, ListFormat.JsxElementOrFragmentChildren); emit(node.closingFragment); } - function emitJsxOpeningElementOrFragment(node: ts.JsxOpeningElement | ts.JsxOpeningFragment) { + function emitJsxOpeningElementOrFragment(node: JsxOpeningElement | JsxOpeningFragment) { writePunctuation("<"); - if (ts.isJsxOpeningElement(node)) { + if (isJsxOpeningElement(node)) { const indented = writeLineSeparatorsAndIndentBefore(node.tagName, node); emitJsxTagName(node.tagName); emitTypeArguments(node, node.typeArguments); @@ -3644,28 +3724,28 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writePunctuation(">"); } - function emitJsxText(node: ts.JsxText) { + function emitJsxText(node: JsxText) { writer.writeLiteral(node.text); } - function emitJsxClosingElementOrFragment(node: ts.JsxClosingElement | ts.JsxClosingFragment) { + function emitJsxClosingElementOrFragment(node: JsxClosingElement | JsxClosingFragment) { writePunctuation(""); } - function emitJsxAttributes(node: ts.JsxAttributes) { - emitList(node, node.properties, ts.ListFormat.JsxElementAttributes); + function emitJsxAttributes(node: JsxAttributes) { + emitList(node, node.properties, ListFormat.JsxElementAttributes); } - function emitJsxAttribute(node: ts.JsxAttribute) { + function emitJsxAttribute(node: JsxAttribute) { emit(node.name); emitNodeWithPrefix("=", writePunctuation, node.initializer, emitJsxAttributeValue); } - function emitJsxSpreadAttribute(node: ts.JsxSpreadAttribute) { + function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { writePunctuation("{..."); emitExpression(node.expression); writePunctuation("}"); @@ -3673,13 +3753,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function hasTrailingCommentsAtPosition(pos: number) { let result = false; - ts.forEachTrailingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true); + forEachTrailingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true); return result; } function hasLeadingCommentsAtPosition(pos: number) { let result = false; - ts.forEachLeadingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true); + forEachLeadingCommentRange(currentSourceFile?.text || "", pos + 1, () => result = true); return result; } @@ -3687,24 +3767,24 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return hasTrailingCommentsAtPosition(pos) || hasLeadingCommentsAtPosition(pos); } - function emitJsxExpression(node: ts.JsxExpression) { - if (node.expression || (!commentsDisabled && !ts.nodeIsSynthesized(node) && hasCommentsAtPosition(node.pos))) { // preserve empty expressions if they contain comments! - const isMultiline = currentSourceFile && !ts.nodeIsSynthesized(node) && ts.getLineAndCharacterOfPosition(currentSourceFile, node.pos).line !== ts.getLineAndCharacterOfPosition(currentSourceFile, node.end).line; + function emitJsxExpression(node: JsxExpression) { + if (node.expression || (!commentsDisabled && !nodeIsSynthesized(node) && hasCommentsAtPosition(node.pos))) { // preserve empty expressions if they contain comments! + const isMultiline = currentSourceFile && !nodeIsSynthesized(node) && getLineAndCharacterOfPosition(currentSourceFile, node.pos).line !== getLineAndCharacterOfPosition(currentSourceFile, node.end).line; if (isMultiline) { writer.increaseIndent(); } - const end = emitTokenWithComment(ts.SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node); + const end = emitTokenWithComment(SyntaxKind.OpenBraceToken, node.pos, writePunctuation, node); emit(node.dotDotDotToken); emitExpression(node.expression); - emitTokenWithComment(ts.SyntaxKind.CloseBraceToken, node.expression?.end || end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseBraceToken, node.expression?.end || end, writePunctuation, node); if (isMultiline) { writer.decreaseIndent(); } } } - function emitJsxTagName(node: ts.JsxTagNameExpression) { - if (node.kind === ts.SyntaxKind.Identifier) { + function emitJsxTagName(node: JsxTagNameExpression) { + if (node.kind === SyntaxKind.Identifier) { emitExpression(node); } else { @@ -3716,56 +3796,56 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Clauses // - function emitCaseClause(node: ts.CaseClause) { - emitTokenWithComment(ts.SyntaxKind.CaseKeyword, node.pos, writeKeyword, node); + function emitCaseClause(node: CaseClause) { + emitTokenWithComment(SyntaxKind.CaseKeyword, node.pos, writeKeyword, node); writeSpace(); emitExpression(node.expression, parenthesizer.parenthesizeExpressionForDisallowedComma); emitCaseOrDefaultClauseRest(node, node.statements, node.expression.end); } - function emitDefaultClause(node: ts.DefaultClause) { - const pos = emitTokenWithComment(ts.SyntaxKind.DefaultKeyword, node.pos, writeKeyword, node); + function emitDefaultClause(node: DefaultClause) { + const pos = emitTokenWithComment(SyntaxKind.DefaultKeyword, node.pos, writeKeyword, node); emitCaseOrDefaultClauseRest(node, node.statements, pos); } - function emitCaseOrDefaultClauseRest(parentNode: ts.Node, statements: ts.NodeArray, colonPos: number) { + function emitCaseOrDefaultClauseRest(parentNode: Node, statements: NodeArray, colonPos: number) { const emitAsSingleStatement = statements.length === 1 && ( // treat synthesized nodes as located on the same line for emit purposes !currentSourceFile || - ts.nodeIsSynthesized(parentNode) || - ts.nodeIsSynthesized(statements[0]) || - ts.rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) + nodeIsSynthesized(parentNode) || + nodeIsSynthesized(statements[0]) || + rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) ); - let format = ts.ListFormat.CaseOrDefaultClauseStatements; + let format = ListFormat.CaseOrDefaultClauseStatements; if (emitAsSingleStatement) { - writeToken(ts.SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode); + writeToken(SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode); writeSpace(); - format &= ~(ts.ListFormat.MultiLine | ts.ListFormat.Indented); + format &= ~(ListFormat.MultiLine | ListFormat.Indented); } else { - emitTokenWithComment(ts.SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode); + emitTokenWithComment(SyntaxKind.ColonToken, colonPos, writePunctuation, parentNode); } emitList(parentNode, statements, format); } - function emitHeritageClause(node: ts.HeritageClause) { + function emitHeritageClause(node: HeritageClause) { writeSpace(); writeTokenText(node.token, writeKeyword); writeSpace(); - emitList(node, node.types, ts.ListFormat.HeritageClauseTypes); + emitList(node, node.types, ListFormat.HeritageClauseTypes); } - function emitCatchClause(node: ts.CatchClause) { - const openParenPos = emitTokenWithComment(ts.SyntaxKind.CatchKeyword, node.pos, writeKeyword, node); + function emitCatchClause(node: CatchClause) { + const openParenPos = emitTokenWithComment(SyntaxKind.CatchKeyword, node.pos, writeKeyword, node); writeSpace(); if (node.variableDeclaration) { - emitTokenWithComment(ts.SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.OpenParenToken, openParenPos, writePunctuation, node); emit(node.variableDeclaration); - emitTokenWithComment(ts.SyntaxKind.CloseParenToken, node.variableDeclaration.end, writePunctuation, node); + emitTokenWithComment(SyntaxKind.CloseParenToken, node.variableDeclaration.end, writePunctuation, node); writeSpace(); } emit(node.block); @@ -3775,7 +3855,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Property assignments // - function emitPropertyAssignment(node: ts.PropertyAssignment) { + function emitPropertyAssignment(node: PropertyAssignment) { emit(node.name); writePunctuation(":"); writeSpace(); @@ -3787,14 +3867,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // "comment1" is not considered to be leading comment for node.initializer // but rather a trailing comment on the previous node. const initializer = node.initializer; - if ((ts.getEmitFlags(initializer) & ts.EmitFlags.NoLeadingComments) === 0) { - const commentRange = ts.getCommentRange(initializer); + if ((getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { + const commentRange = getCommentRange(initializer); emitTrailingCommentsOfPosition(commentRange.pos); } emitExpression(initializer, parenthesizer.parenthesizeExpressionForDisallowedComma); } - function emitShorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment) { + function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { emit(node.name); if (node.objectAssignmentInitializer) { writeSpace(); @@ -3804,9 +3884,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitSpreadAssignment(node: ts.SpreadAssignment) { + function emitSpreadAssignment(node: SpreadAssignment) { if (node.expression) { - emitTokenWithComment(ts.SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node); + emitTokenWithComment(SyntaxKind.DotDotDotToken, node.pos, writePunctuation, node); emitExpression(node.expression, parenthesizer.parenthesizeExpressionForDisallowedComma); } } @@ -3815,7 +3895,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Enum // - function emitEnumMember(node: ts.EnumMember) { + function emitEnumMember(node: EnumMember) { emit(node.name); emitInitializer(node.initializer, node.name.end, node, parenthesizer.parenthesizeExpressionForDisallowedComma); } @@ -3823,10 +3903,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // // JSDoc // - function emitJSDoc(node: ts.JSDoc) { + function emitJSDoc(node: JSDoc) { write("/**"); if (node.comment) { - const text = ts.getTextOfJSDocComment(node.comment); + const text = getTextOfJSDocComment(node.comment); if (text) { const lines = text.split(/\r\n?|\n/g); for (const line of lines) { @@ -3839,38 +3919,38 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } if (node.tags) { - if (node.tags.length === 1 && node.tags[0].kind === ts.SyntaxKind.JSDocTypeTag && !node.comment) { + if (node.tags.length === 1 && node.tags[0].kind === SyntaxKind.JSDocTypeTag && !node.comment) { writeSpace(); emit(node.tags[0]); } else { - emitList(node, node.tags, ts.ListFormat.JSDocComment); + emitList(node, node.tags, ListFormat.JSDocComment); } } writeSpace(); write("*/"); } - function emitJSDocSimpleTypedTag(tag: ts.JSDocTypeTag | ts.JSDocThisTag | ts.JSDocEnumTag | ts.JSDocReturnTag) { + function emitJSDocSimpleTypedTag(tag: JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocReturnTag) { emitJSDocTagName(tag.tagName); emitJSDocTypeExpression(tag.typeExpression); emitJSDocComment(tag.comment); } - function emitJSDocSeeTag(tag: ts.JSDocSeeTag) { + function emitJSDocSeeTag(tag: JSDocSeeTag) { emitJSDocTagName(tag.tagName); emit(tag.name); emitJSDocComment(tag.comment); } - function emitJSDocNameReference(node: ts.JSDocNameReference) { + function emitJSDocNameReference(node: JSDocNameReference) { writeSpace(); writePunctuation("{"); emit(node.name); writePunctuation("}"); } - function emitJSDocHeritageTag(tag: ts.JSDocImplementsTag | ts.JSDocAugmentsTag) { + function emitJSDocHeritageTag(tag: JSDocImplementsTag | JSDocAugmentsTag) { emitJSDocTagName(tag.tagName); writeSpace(); writePunctuation("{"); @@ -3879,18 +3959,18 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitJSDocComment(tag.comment); } - function emitJSDocTemplateTag(tag: ts.JSDocTemplateTag) { + function emitJSDocTemplateTag(tag: JSDocTemplateTag) { emitJSDocTagName(tag.tagName); emitJSDocTypeExpression(tag.constraint); writeSpace(); - emitList(tag, tag.typeParameters, ts.ListFormat.CommaListElements); + emitList(tag, tag.typeParameters, ListFormat.CommaListElements); emitJSDocComment(tag.comment); } - function emitJSDocTypedefTag(tag: ts.JSDocTypedefTag) { + function emitJSDocTypedefTag(tag: JSDocTypedefTag) { emitJSDocTagName(tag.tagName); if (tag.typeExpression) { - if (tag.typeExpression.kind === ts.SyntaxKind.JSDocTypeExpression) { + if (tag.typeExpression.kind === SyntaxKind.JSDocTypeExpression) { emitJSDocTypeExpression(tag.typeExpression); } else { @@ -3909,12 +3989,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emit(tag.fullName); } emitJSDocComment(tag.comment); - if (tag.typeExpression && tag.typeExpression.kind === ts.SyntaxKind.JSDocTypeLiteral) { + if (tag.typeExpression && tag.typeExpression.kind === SyntaxKind.JSDocTypeLiteral) { emitJSDocTypeLiteral(tag.typeExpression); } } - function emitJSDocCallbackTag(tag: ts.JSDocCallbackTag) { + function emitJSDocCallbackTag(tag: JSDocCallbackTag) { emitJSDocTagName(tag.tagName); if (tag.name) { writeSpace(); @@ -3924,21 +4004,21 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitJSDocSignature(tag.typeExpression); } - function emitJSDocSimpleTag(tag: ts.JSDocTag) { + function emitJSDocSimpleTag(tag: JSDocTag) { emitJSDocTagName(tag.tagName); emitJSDocComment(tag.comment); } - function emitJSDocTypeLiteral(lit: ts.JSDocTypeLiteral) { - emitList(lit, ts.factory.createNodeArray(lit.jsDocPropertyTags), ts.ListFormat.JSDocComment); + function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) { + emitList(lit, factory.createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment); } - function emitJSDocSignature(sig: ts.JSDocSignature) { + function emitJSDocSignature(sig: JSDocSignature) { if (sig.typeParameters) { - emitList(sig, ts.factory.createNodeArray(sig.typeParameters), ts.ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.typeParameters), ListFormat.JSDocComment); } if (sig.parameters) { - emitList(sig, ts.factory.createNodeArray(sig.parameters), ts.ListFormat.JSDocComment); + emitList(sig, factory.createNodeArray(sig.parameters), ListFormat.JSDocComment); } if (sig.type) { writeLine(); @@ -3949,7 +4029,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitJSDocPropertyLikeTag(param: ts.JSDocPropertyLikeTag) { + function emitJSDocPropertyLikeTag(param: JSDocPropertyLikeTag) { emitJSDocTagName(param.tagName); emitJSDocTypeExpression(param.typeExpression); writeSpace(); @@ -3963,20 +4043,20 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitJSDocComment(param.comment); } - function emitJSDocTagName(tagName: ts.Identifier) { + function emitJSDocTagName(tagName: Identifier) { writePunctuation("@"); emit(tagName); } - function emitJSDocComment(comment: string | ts.NodeArray | undefined) { - const text = ts.getTextOfJSDocComment(comment); + function emitJSDocComment(comment: string | NodeArray | undefined) { + const text = getTextOfJSDocComment(comment); if (text) { writeSpace(); write(text); } } - function emitJSDocTypeExpression(typeExpression: ts.JSDocTypeExpression | undefined) { + function emitJSDocTypeExpression(typeExpression: JSDocTypeExpression | undefined) { if (typeExpression) { writeSpace(); writePunctuation("{"); @@ -3989,14 +4069,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Top-level nodes // - function emitSourceFile(node: ts.SourceFile) { + function emitSourceFile(node: SourceFile) { writeLine(); const statements = node.statements; // Emit detached comment if there are no prologue directives or if the first node is synthesized. // The synthesized node will have no leading comment so some comments may be missed. const shouldEmitDetachedComment = statements.length === 0 || - !ts.isPrologueDirective(statements[0]) || - ts.nodeIsSynthesized(statements[0]); + !isPrologueDirective(statements[0]) || + nodeIsSynthesized(statements[0]); if (shouldEmitDetachedComment) { emitBodyWithDetachedComments(node, statements, emitSourceFileWorker); return; @@ -4004,10 +4084,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitSourceFileWorker(node); } - function emitSyntheticTripleSlashReferencesIfNeeded(node: ts.Bundle) { + function emitSyntheticTripleSlashReferencesIfNeeded(node: Bundle) { emitTripleSlashDirectives(!!node.hasNoDefaultLib, node.syntheticFileReferences || [], node.syntheticTypeReferences || [], node.syntheticLibReferences || []); for (const prepend of node.prepends) { - if (ts.isUnparsedSource(prepend) && prepend.syntheticReferences) { + if (isUnparsedSource(prepend) && prepend.syntheticReferences) { for (const ref of prepend.syntheticReferences) { emit(ref); writeLine(); @@ -4016,15 +4096,15 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitTripleSlashDirectivesIfNeeded(node: ts.SourceFile) { + function emitTripleSlashDirectivesIfNeeded(node: SourceFile) { if (node.isDeclarationFile) emitTripleSlashDirectives(node.hasNoDefaultLib, node.referencedFiles, node.typeReferenceDirectives, node.libReferenceDirectives); } - function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: readonly ts.FileReference[], types: readonly ts.FileReference[], libs: readonly ts.FileReference[]) { + function emitTripleSlashDirectives(hasNoDefaultLib: boolean, files: readonly FileReference[], types: readonly FileReference[], libs: readonly FileReference[]) { if (hasNoDefaultLib) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.NoDefaultLib }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.NoDefaultLib }); writeLine(); } if (currentSourceFile && currentSourceFile.moduleName) { @@ -4045,63 +4125,63 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: for (const directive of files) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.Reference, data: directive.fileName }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Reference, data: directive.fileName }); writeLine(); } for (const directive of types) { const pos = writer.getTextPos(); const resolutionMode = directive.resolutionMode && directive.resolutionMode !== currentSourceFile?.impliedNodeFormat - ? `resolution-mode="${directive.resolutionMode === ts.ModuleKind.ESNext ? "import" : "require"}"` + ? `resolution-mode="${directive.resolutionMode === ModuleKind.ESNext ? "import" : "require"}"` : ""; writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: !directive.resolutionMode ? ts.BundleFileSectionKind.Type : directive.resolutionMode === ts.ModuleKind.ESNext ? ts.BundleFileSectionKind.TypeResolutionModeImport : ts.BundleFileSectionKind.TypeResolutionModeRequire, data: directive.fileName }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: !directive.resolutionMode ? BundleFileSectionKind.Type : directive.resolutionMode === ModuleKind.ESNext ? BundleFileSectionKind.TypeResolutionModeImport : BundleFileSectionKind.TypeResolutionModeRequire, data: directive.fileName }); writeLine(); } for (const directive of libs) { const pos = writer.getTextPos(); writeComment(`/// `); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.Lib, data: directive.fileName }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Lib, data: directive.fileName }); writeLine(); } } - function emitSourceFileWorker(node: ts.SourceFile) { + function emitSourceFileWorker(node: SourceFile) { const statements = node.statements; pushNameGenerationScope(node); - ts.forEach(node.statements, generateNames); + forEach(node.statements, generateNames); emitHelpers(node); - const index = ts.findIndex(statements, statement => !ts.isPrologueDirective(statement)); + const index = findIndex(statements, statement => !isPrologueDirective(statement)); emitTripleSlashDirectivesIfNeeded(node); - emitList(node, statements, ts.ListFormat.MultiLine, /*parenthesizerRule*/ undefined, index === -1 ? statements.length : index); + emitList(node, statements, ListFormat.MultiLine, /*parenthesizerRule*/ undefined, index === -1 ? statements.length : index); popNameGenerationScope(node); } // Transformation nodes - function emitPartiallyEmittedExpression(node: ts.PartiallyEmittedExpression) { - const emitFlags = ts.getEmitFlags(node); - if (!(emitFlags & ts.EmitFlags.NoLeadingComments) && node.pos !== node.expression.pos) { + function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) { + const emitFlags = getEmitFlags(node); + if (!(emitFlags & EmitFlags.NoLeadingComments) && node.pos !== node.expression.pos) { emitTrailingCommentsOfPosition(node.expression.pos); } emitExpression(node.expression); - if (!(emitFlags & ts.EmitFlags.NoTrailingComments) && node.end !== node.expression.end) { + if (!(emitFlags & EmitFlags.NoTrailingComments) && node.end !== node.expression.end) { emitLeadingCommentsOfPosition(node.expression.end); } } - function emitCommaList(node: ts.CommaListExpression) { - emitExpressionList(node, node.elements, ts.ListFormat.CommaListElements, /*parenthesizerRule*/ undefined); + function emitCommaList(node: CommaListExpression) { + emitExpressionList(node, node.elements, ListFormat.CommaListElements, /*parenthesizerRule*/ undefined); } /** * Emits any prologue directives at the start of a Statement list, returning the * number of prologue directives written to the output. */ - function emitPrologueDirectives(statements: readonly ts.Node[], sourceFile?: ts.SourceFile, seenPrologueDirectives?: ts.Set, recordBundleFileSection?: true): number { + function emitPrologueDirectives(statements: readonly Node[], sourceFile?: SourceFile, seenPrologueDirectives?: Set, recordBundleFileSection?: true): number { let needsToSetSourceFile = !!sourceFile; for (let i = 0; i < statements.length; i++) { const statement = statements[i]; - if (ts.isPrologueDirective(statement)) { + if (isPrologueDirective(statement)) { const shouldEmitPrologueDirective = seenPrologueDirectives ? !seenPrologueDirectives.has(statement.expression.text) : true; if (shouldEmitPrologueDirective) { if (needsToSetSourceFile) { @@ -4111,7 +4191,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeLine(); const pos = writer.getTextPos(); emit(statement); - if (recordBundleFileSection && bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.Prologue, data: statement.expression.text }); + if (recordBundleFileSection && bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, data: statement.expression.text }); if (seenPrologueDirectives) { seenPrologueDirectives.add(statement.expression.text); } @@ -4126,13 +4206,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return statements.length; } - function emitUnparsedPrologues(prologues: readonly ts.UnparsedPrologue[], seenPrologueDirectives: ts.Set) { + function emitUnparsedPrologues(prologues: readonly UnparsedPrologue[], seenPrologueDirectives: Set) { for (const prologue of prologues) { if (!seenPrologueDirectives.has(prologue.data)) { writeLine(); const pos = writer.getTextPos(); emit(prologue); - if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: ts.BundleFileSectionKind.Prologue, data: prologue.data }); + if (bundleFileInfo) bundleFileInfo.sections.push({ pos, end: writer.getTextPos(), kind: BundleFileSectionKind.Prologue, data: prologue.data }); if (seenPrologueDirectives) { seenPrologueDirectives.add(prologue.data); } @@ -4140,14 +4220,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: ts.Bundle | ts.SourceFile) { - if (ts.isSourceFile(sourceFileOrBundle)) { + function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) { + if (isSourceFile(sourceFileOrBundle)) { emitPrologueDirectives(sourceFileOrBundle.statements, sourceFileOrBundle); } else { - const seenPrologueDirectives = new ts.Set(); + const seenPrologueDirectives = new Set(); for (const prepend of sourceFileOrBundle.prepends) { - emitUnparsedPrologues((prepend as ts.UnparsedSource).prologues, seenPrologueDirectives); + emitUnparsedPrologues((prepend as UnparsedSource).prologues, seenPrologueDirectives); } for (const sourceFile of sourceFileOrBundle.sourceFiles) { emitPrologueDirectives(sourceFile.statements, sourceFile, seenPrologueDirectives, /*recordBundleFileSection*/ true); @@ -4156,15 +4236,15 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function getPrologueDirectivesFromBundledSourceFiles(bundle: ts.Bundle): ts.SourceFilePrologueInfo[] | undefined { - const seenPrologueDirectives = new ts.Set(); - let prologues: ts.SourceFilePrologueInfo[] | undefined; + function getPrologueDirectivesFromBundledSourceFiles(bundle: Bundle): SourceFilePrologueInfo[] | undefined { + const seenPrologueDirectives = new Set(); + let prologues: SourceFilePrologueInfo[] | undefined; for (let index = 0; index < bundle.sourceFiles.length; index++) { const sourceFile = bundle.sourceFiles[index]; - let directives: ts.SourceFilePrologueDirective[] | undefined; + let directives: SourceFilePrologueDirective[] | undefined; let end = 0; for (const statement of sourceFile.statements) { - if (!ts.isPrologueDirective(statement)) break; + if (!isPrologueDirective(statement)) break; if (seenPrologueDirectives.has(statement.expression.text)) continue; seenPrologueDirectives.add(statement.expression.text); (directives || (directives = [])).push({ @@ -4183,9 +4263,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return prologues; } - function emitShebangIfNeeded(sourceFileOrBundle: ts.Bundle | ts.SourceFile | ts.UnparsedSource) { - if (ts.isSourceFile(sourceFileOrBundle) || ts.isUnparsedSource(sourceFileOrBundle)) { - const shebang = ts.getShebang(sourceFileOrBundle.text); + function emitShebangIfNeeded(sourceFileOrBundle: Bundle | SourceFile | UnparsedSource) { + if (isSourceFile(sourceFileOrBundle) || isUnparsedSource(sourceFileOrBundle)) { + const shebang = getShebang(sourceFileOrBundle.text); if (shebang) { writeComment(shebang); writeLine(); @@ -4194,7 +4274,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } else { for (const prepend of sourceFileOrBundle.prepends) { - ts.Debug.assertNode(prepend, ts.isUnparsedSource); + Debug.assertNode(prepend, isUnparsedSource); if (emitShebangIfNeeded(prepend)) { return true; } @@ -4212,7 +4292,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Helpers // - function emitNodeWithWriter(node: ts.Node | undefined, writer: typeof write) { + function emitNodeWithWriter(node: Node | undefined, writer: typeof write) { if (!node) return; const savedWrite = write; write = writer; @@ -4220,16 +4300,16 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: write = savedWrite; } - function emitDecoratorsAndModifiers(node: ts.Node, modifiers: ts.NodeArray | undefined) { + function emitDecoratorsAndModifiers(node: Node, modifiers: NodeArray | undefined) { if (modifiers?.length) { - if (ts.every(modifiers, ts.isModifier)) { + if (every(modifiers, isModifier)) { // if all modifier-likes are `Modifier`, simply emit the array as modifiers. - return emitModifiers(node, modifiers as ts.NodeArray); + return emitModifiers(node, modifiers as NodeArray); } - if (ts.every(modifiers, ts.isDecorator)) { + if (every(modifiers, isDecorator)) { // if all modifier-likes are `Decorator`, simply emit the array as decorators. - return emitDecorators(node, modifiers as ts.NodeArray); + return emitDecorators(node, modifiers as NodeArray); } onBeforeEmitNodeArray?.(modifiers); @@ -4242,7 +4322,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: while (start < modifiers.length) { while (pos < modifiers.length) { const modifier = modifiers[pos]; - mode = ts.isDecorator(modifier) ? "decorators" : "modifiers"; + mode = isDecorator(modifier) ? "decorators" : "modifiers"; if (lastMode === undefined) { lastMode = mode; } @@ -4253,14 +4333,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: pos++; } - const textRange: ts.TextRange = { pos: -1, end: -1 }; + const textRange: TextRange = { pos: -1, end: -1 }; if (start === 0) textRange.pos = modifiers.pos; if (pos === modifiers.length - 1) textRange.end = modifiers.end; emitNodeListItems( emit, node, modifiers, - lastMode === "modifiers" ? ts.ListFormat.Modifiers : ts.ListFormat.Decorators, + lastMode === "modifiers" ? ListFormat.Modifiers : ListFormat.Decorators, /*parenthesizerRule*/ undefined, start, pos - start, @@ -4275,11 +4355,11 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitModifiers(node: ts.Node, modifiers: ts.NodeArray | undefined): void { - emitList(node, modifiers, ts.ListFormat.Modifiers); + function emitModifiers(node: Node, modifiers: NodeArray | undefined): void { + emitList(node, modifiers, ListFormat.Modifiers); } - function emitTypeAnnotation(node: ts.TypeNode | undefined) { + function emitTypeAnnotation(node: TypeNode | undefined) { if (node) { writePunctuation(":"); writeSpace(); @@ -4287,53 +4367,53 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitInitializer(node: ts.Expression | undefined, equalCommentStartPos: number, container: ts.Node, parenthesizerRule?: (node: ts.Expression) => ts.Expression) { + function emitInitializer(node: Expression | undefined, equalCommentStartPos: number, container: Node, parenthesizerRule?: (node: Expression) => Expression) { if (node) { writeSpace(); - emitTokenWithComment(ts.SyntaxKind.EqualsToken, equalCommentStartPos, writeOperator, container); + emitTokenWithComment(SyntaxKind.EqualsToken, equalCommentStartPos, writeOperator, container); writeSpace(); emitExpression(node, parenthesizerRule); } } - function emitNodeWithPrefix(prefix: string, prefixWriter: (s: string) => void, node: T | undefined, emit: (node: T) => void) { + function emitNodeWithPrefix(prefix: string, prefixWriter: (s: string) => void, node: T | undefined, emit: (node: T) => void) { if (node) { prefixWriter(prefix); emit(node); } } - function emitWithLeadingSpace(node: ts.Node | undefined) { + function emitWithLeadingSpace(node: Node | undefined) { if (node) { writeSpace(); emit(node); } } - function emitExpressionWithLeadingSpace(node: ts.Expression | undefined, parenthesizerRule?: (node: ts.Expression) => ts.Expression) { + function emitExpressionWithLeadingSpace(node: Expression | undefined, parenthesizerRule?: (node: Expression) => Expression) { if (node) { writeSpace(); emitExpression(node, parenthesizerRule); } } - function emitWithTrailingSpace(node: ts.Node | undefined) { + function emitWithTrailingSpace(node: Node | undefined) { if (node) { emit(node); writeSpace(); } } - function emitEmbeddedStatement(parent: ts.Node, node: ts.Statement) { - if (ts.isBlock(node) || ts.getEmitFlags(parent) & ts.EmitFlags.SingleLine) { + function emitEmbeddedStatement(parent: Node, node: Statement) { + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { writeSpace(); emit(node); } else { writeLine(); increaseIndent(); - if (ts.isEmptyStatement(node)) { - pipelineEmit(ts.EmitHint.EmbeddedStatement, node); + if (isEmptyStatement(node)) { + pipelineEmit(EmitHint.EmbeddedStatement, node); } else { emit(node); @@ -4342,99 +4422,99 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitDecorators(parentNode: ts.Node, decorators: ts.NodeArray | undefined): void { - emitList(parentNode, decorators, ts.ListFormat.Decorators); + function emitDecorators(parentNode: Node, decorators: NodeArray | undefined): void { + emitList(parentNode, decorators, ListFormat.Decorators); } - function emitTypeArguments(parentNode: ts.Node, typeArguments: ts.NodeArray | undefined) { - emitList(parentNode, typeArguments, ts.ListFormat.TypeArguments, typeArgumentParenthesizerRuleSelector); + function emitTypeArguments(parentNode: Node, typeArguments: NodeArray | undefined) { + emitList(parentNode, typeArguments, ListFormat.TypeArguments, typeArgumentParenthesizerRuleSelector); } - function emitTypeParameters(parentNode: ts.SignatureDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.ClassDeclaration | ts.ClassExpression, typeParameters: ts.NodeArray | undefined) { - if (ts.isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures + function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray | undefined) { + if (isFunctionLike(parentNode) && parentNode.typeArguments) { // Quick info uses type arguments in place of type parameters on instantiated signatures return emitTypeArguments(parentNode, parentNode.typeArguments); } - emitList(parentNode, typeParameters, ts.ListFormat.TypeParameters); + emitList(parentNode, typeParameters, ListFormat.TypeParameters); } - function emitParameters(parentNode: ts.Node, parameters: ts.NodeArray) { - emitList(parentNode, parameters, ts.ListFormat.Parameters); + function emitParameters(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.Parameters); } - function canEmitSimpleArrowHead(parentNode: ts.FunctionTypeNode | ts.ArrowFunction, parameters: ts.NodeArray) { - const parameter = ts.singleOrUndefined(parameters); + function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { + const parameter = singleOrUndefined(parameters); return parameter && parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter - && ts.isArrowFunction(parentNode) // only arrow functions may have simple arrow head + && isArrowFunction(parentNode) // only arrow functions may have simple arrow head && !parentNode.type // arrow function may not have return type annotation - && !ts.some(parentNode.modifiers) // parent may not have decorators or modifiers - && !ts.some(parentNode.typeParameters) // parent may not have type parameters - && !ts.some(parameter.modifiers) // parameter may not have decorators or modifiers + && !some(parentNode.modifiers) // parent may not have decorators or modifiers + && !some(parentNode.typeParameters) // parent may not have type parameters + && !some(parameter.modifiers) // parameter may not have decorators or modifiers && !parameter.dotDotDotToken // parameter may not be rest && !parameter.questionToken // parameter may not be optional && !parameter.type // parameter may not have a type annotation && !parameter.initializer // parameter may not have an initializer - && ts.isIdentifier(parameter.name); // parameter name must be identifier + && isIdentifier(parameter.name); // parameter name must be identifier } - function emitParametersForArrow(parentNode: ts.FunctionTypeNode | ts.ArrowFunction, parameters: ts.NodeArray) { + function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray) { if (canEmitSimpleArrowHead(parentNode, parameters)) { - emitList(parentNode, parameters, ts.ListFormat.Parameters & ~ts.ListFormat.Parenthesis); + emitList(parentNode, parameters, ListFormat.Parameters & ~ListFormat.Parenthesis); } else { emitParameters(parentNode, parameters); } } - function emitParametersForIndexSignature(parentNode: ts.Node, parameters: ts.NodeArray) { - emitList(parentNode, parameters, ts.ListFormat.IndexSignatureParameters); + function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); } - function writeDelimiter(format: ts.ListFormat) { - switch (format & ts.ListFormat.DelimitersMask) { - case ts.ListFormat.None: + function writeDelimiter(format: ListFormat) { + switch (format & ListFormat.DelimitersMask) { + case ListFormat.None: break; - case ts.ListFormat.CommaDelimited: + case ListFormat.CommaDelimited: writePunctuation(","); break; - case ts.ListFormat.BarDelimited: + case ListFormat.BarDelimited: writeSpace(); writePunctuation("|"); break; - case ts.ListFormat.AsteriskDelimited: + case ListFormat.AsteriskDelimited: writeSpace(); writePunctuation("*"); writeSpace(); break; - case ts.ListFormat.AmpersandDelimited: + case ListFormat.AmpersandDelimited: writeSpace(); writePunctuation("&"); break; } } - function emitList(parentNode: ts.Node | undefined, children: ts.NodeArray | undefined, format: ts.ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { + function emitList(parentNode: Node | undefined, children: NodeArray | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { emitNodeList(emit, parentNode, children, format, parenthesizerRule, start, count); } - function emitExpressionList(parentNode: ts.Node | undefined, children: ts.NodeArray | undefined, format: ts.ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { + function emitExpressionList(parentNode: Node | undefined, children: NodeArray | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector, start?: number, count?: number) { emitNodeList(emitExpression, parentNode, children, format, parenthesizerRule, start, count); } - function emitNodeList(emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parentNode: ts.Node | undefined, children: ts.NodeArray | undefined, format: ts.ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start = 0, count = children ? children.length - start : 0) { + function emitNodeList(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: NodeArray | undefined, format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start = 0, count = children ? children.length - start : 0) { const isUndefined = children === undefined; - if (isUndefined && format & ts.ListFormat.OptionalIfUndefined) { + if (isUndefined && format & ListFormat.OptionalIfUndefined) { return; } const isEmpty = children === undefined || start >= children.length || count === 0; - if (isEmpty && format & ts.ListFormat.OptionalIfEmpty) { + if (isEmpty && format & ListFormat.OptionalIfEmpty) { onBeforeEmitNodeArray?.(children); onAfterEmitNodeArray?.(children); return; } - if (format & ts.ListFormat.BracketsMask) { + if (format & ListFormat.BracketsMask) { writePunctuation(getOpeningBracket(format)); if (isEmpty && children) { emitTrailingCommentsOfPosition(children.pos, /*prefixSpace*/ true); // Emit comments within empty bracketed lists @@ -4445,10 +4525,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: if (isEmpty) { // Write a line terminator if the parent node was multi-line - if (format & ts.ListFormat.MultiLine && !(preserveSourceNewlines && (!parentNode || currentSourceFile && ts.rangeIsOnSingleLine(parentNode, currentSourceFile)))) { + if (format & ListFormat.MultiLine && !(preserveSourceNewlines && (!parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile)))) { writeLine(); } - else if (format & ts.ListFormat.SpaceBetweenBraces && !(format & ts.ListFormat.NoSpaceIfEmpty)) { + else if (format & ListFormat.SpaceBetweenBraces && !(format & ListFormat.NoSpaceIfEmpty)) { writeSpace(); } } @@ -4458,7 +4538,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: onAfterEmitNodeArray?.(children); - if (format & ts.ListFormat.BracketsMask) { + if (format & ListFormat.BracketsMask) { if (isEmpty && children) { emitLeadingCommentsOfPosition(children.end); // Emit leading comments within empty lists } @@ -4471,9 +4551,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * * NOTE: You probably don't want to call this directly and should be using `emitList` or `emitExpressionList` instead. */ - function emitNodeListItems(emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parentNode: ts.Node | undefined, children: readonly ts.Node[], format: ts.ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start: number, count: number, hasTrailingComma: boolean, childrenTextRange: ts.TextRange | undefined) { + function emitNodeListItems(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: readonly Node[], format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector | undefined, start: number, count: number, hasTrailingComma: boolean, childrenTextRange: TextRange | undefined) { // Write the opening line terminator or leading whitespace. - const mayEmitInterveningComments = (format & ts.ListFormat.NoInterveningComments) === 0; + const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; let shouldEmitInterveningComments = mayEmitInterveningComments; const leadingLineTerminatorCount = getLeadingLineTerminatorCount(parentNode, children[start], format); @@ -4481,26 +4561,26 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeLine(leadingLineTerminatorCount); shouldEmitInterveningComments = false; } - else if (format & ts.ListFormat.SpaceBetweenBraces) { + else if (format & ListFormat.SpaceBetweenBraces) { writeSpace(); } // Increase the indent, if requested. - if (format & ts.ListFormat.Indented) { + if (format & ListFormat.Indented) { increaseIndent(); } const emitListItem = getEmitListItem(emit, parenthesizerRule); // Emit each child. - let previousSibling: ts.Node | undefined; + let previousSibling: Node | undefined; let previousSourceFileTextKind: ReturnType; let shouldDecreaseIndentAfterEmit = false; for (let i = 0; i < count; i++) { const child = children[start + i]; // Write the delimiter if this is not the first node. - if (format & ts.ListFormat.AsteriskDelimited) { + if (format & ListFormat.AsteriskDelimited) { // always write JSDoc in the format "\n *" writeLine(); writeDelimiter(format); @@ -4512,7 +4592,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // a // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline // , - if (format & ts.ListFormat.DelimitersMask && previousSibling.end !== (parentNode ? parentNode.end : -1)) { + if (format & ListFormat.DelimitersMask && previousSibling.end !== (parentNode ? parentNode.end : -1)) { emitLeadingCommentsOfPosition(previousSibling.end); } writeDelimiter(format); @@ -4523,7 +4603,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: if (separatingLineTerminatorCount > 0) { // If a synthesized node in a single-line list starts on a new // line, we should increase the indent. - if ((format & (ts.ListFormat.LinesMask | ts.ListFormat.Indented)) === ts.ListFormat.SingleLine) { + if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { increaseIndent(); shouldDecreaseIndentAfterEmit = true; } @@ -4531,7 +4611,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writeLine(separatingLineTerminatorCount); shouldEmitInterveningComments = false; } - else if (previousSibling && format & ts.ListFormat.SpaceBetweenSiblings) { + else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { writeSpace(); } } @@ -4539,7 +4619,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Emit this child. previousSourceFileTextKind = recordBundleFileInternalSectionStart(child); if (shouldEmitInterveningComments) { - const commentRange = ts.getCommentRange(child); + const commentRange = getCommentRange(child); emitTrailingCommentsOfPosition(commentRange.pos); } else { @@ -4558,12 +4638,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } // Write a trailing comma, if requested. - const emitFlags = previousSibling ? ts.getEmitFlags(previousSibling) : 0; - const skipTrailingComments = commentsDisabled || !!(emitFlags & ts.EmitFlags.NoTrailingComments); - const emitTrailingComma = hasTrailingComma && (format & ts.ListFormat.AllowTrailingComma) && (format & ts.ListFormat.CommaDelimited); + const emitFlags = previousSibling ? getEmitFlags(previousSibling) : 0; + const skipTrailingComments = commentsDisabled || !!(emitFlags & EmitFlags.NoTrailingComments); + const emitTrailingComma = hasTrailingComma && (format & ListFormat.AllowTrailingComma) && (format & ListFormat.CommaDelimited); if (emitTrailingComma) { if (previousSibling && !skipTrailingComments) { - emitTokenWithComment(ts.SyntaxKind.CommaToken, previousSibling.end, writePunctuation, previousSibling); + emitTokenWithComment(SyntaxKind.CommaToken, previousSibling.end, writePunctuation, previousSibling); } else { writePunctuation(","); @@ -4576,12 +4656,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // 2 // /* end of element 2 */ // ]; - if (previousSibling && (parentNode ? parentNode.end : -1) !== previousSibling.end && (format & ts.ListFormat.DelimitersMask) && !skipTrailingComments) { + if (previousSibling && (parentNode ? parentNode.end : -1) !== previousSibling.end && (format & ListFormat.DelimitersMask) && !skipTrailingComments) { emitLeadingCommentsOfPosition(emitTrailingComma && childrenTextRange?.end ? childrenTextRange.end : previousSibling.end); } // Decrease the indent, if requested. - if (format & ts.ListFormat.Indented) { + if (format & ListFormat.Indented) { decreaseIndent(); } @@ -4592,7 +4672,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: if (closingLineTerminatorCount) { writeLine(closingLineTerminatorCount); } - else if (format & (ts.ListFormat.SpaceAfterList | ts.ListFormat.SpaceBetweenBraces)) { + else if (format & (ListFormat.SpaceAfterList | ListFormat.SpaceBetweenBraces)) { writeSpace(); } } @@ -4611,7 +4691,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writer.write(s); } - function writeSymbol(s: string, sym: ts.Symbol) { + function writeSymbol(s: string, sym: Symbol) { writer.writeSymbol(s, sym); } @@ -4671,32 +4751,32 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: writer.decreaseIndent(); } - function writeToken(token: ts.SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: ts.Node) { + function writeToken(token: SyntaxKind, pos: number, writer: (s: string) => void, contextNode?: Node) { return !sourceMapsDisabled ? emitTokenWithSourceMap(contextNode, token, writer, pos, writeTokenText) : writeTokenText(token, writer, pos); } - function writeTokenNode(node: ts.Node, writer: (s: string) => void) { + function writeTokenNode(node: Node, writer: (s: string) => void) { if (onBeforeEmitToken) { onBeforeEmitToken(node); } - writer(ts.tokenToString(node.kind)!); + writer(tokenToString(node.kind)!); if (onAfterEmitToken) { onAfterEmitToken(node); } } - function writeTokenText(token: ts.SyntaxKind, writer: (s: string) => void): void; - function writeTokenText(token: ts.SyntaxKind, writer: (s: string) => void, pos: number): number; - function writeTokenText(token: ts.SyntaxKind, writer: (s: string) => void, pos?: number): number { - const tokenString = ts.tokenToString(token)!; + function writeTokenText(token: SyntaxKind, writer: (s: string) => void): void; + function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos: number): number; + function writeTokenText(token: SyntaxKind, writer: (s: string) => void, pos?: number): number { + const tokenString = tokenToString(token)!; writer(tokenString); return pos! < 0 ? pos! : pos! + tokenString.length; } - function writeLineOrSpace(parentNode: ts.Node, prevChildNode: ts.Node, nextChildNode: ts.Node) { - if (ts.getEmitFlags(parentNode) & ts.EmitFlags.SingleLine) { + function writeLineOrSpace(parentNode: Node, prevChildNode: Node, nextChildNode: Node) { + if (getEmitFlags(parentNode) & EmitFlags.SingleLine) { writeSpace(); } else if (preserveSourceNewlines) { @@ -4715,7 +4795,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function writeLines(text: string): void { const lines = text.split(/\r\n?|\n/g); - const indentation = ts.guessIndentation(lines); + const indentation = guessIndentation(lines); for (const lineText of lines) { const line = indentation ? lineText.slice(indentation) : lineText; if (line.length) { @@ -4748,14 +4828,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function getLeadingLineTerminatorCount(parentNode: ts.Node | undefined, firstChild: ts.Node | undefined, format: ts.ListFormat): number { - if (format & ts.ListFormat.PreserveLines || preserveSourceNewlines) { - if (format & ts.ListFormat.PreferNewLine) { + function getLeadingLineTerminatorCount(parentNode: Node | undefined, firstChild: Node | undefined, format: ListFormat): number { + if (format & ListFormat.PreserveLines || preserveSourceNewlines) { + if (format & ListFormat.PreferNewLine) { return 1; } if (firstChild === undefined) { - return !parentNode || currentSourceFile && ts.rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1; + return !parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1; } if (firstChild.pos === nextListElementPos) { // If this child starts at the beginning of a list item in a parent list, its leading @@ -4775,45 +4855,45 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // leading newline to start the modifiers. return 0; } - if (firstChild.kind === ts.SyntaxKind.JsxText) { + if (firstChild.kind === SyntaxKind.JsxText) { // JsxText will be written with its leading whitespace, so don't add more manually. return 0; } if (currentSourceFile && parentNode && - !ts.positionIsSynthesized(parentNode.pos) && - !ts.nodeIsSynthesized(firstChild) && - (!firstChild.parent || ts.getOriginalNode(firstChild.parent) === ts.getOriginalNode(parentNode)) + !positionIsSynthesized(parentNode.pos) && + !nodeIsSynthesized(firstChild) && + (!firstChild.parent || getOriginalNode(firstChild.parent) === getOriginalNode(parentNode)) ) { if (preserveSourceNewlines) { return getEffectiveLines( - includeComments => ts.getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter( + includeComments => getLinesBetweenPositionAndPrecedingNonWhitespaceCharacter( firstChild.pos, parentNode.pos, currentSourceFile!, includeComments)); } - return ts.rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile) ? 0 : 1; + return rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile) ? 0 : 1; } if (synthesizedNodeStartsOnNewLine(firstChild, format)) { return 1; } } - return format & ts.ListFormat.MultiLine ? 1 : 0; + return format & ListFormat.MultiLine ? 1 : 0; } - function getSeparatingLineTerminatorCount(previousNode: ts.Node | undefined, nextNode: ts.Node, format: ts.ListFormat): number { - if (format & ts.ListFormat.PreserveLines || preserveSourceNewlines) { + function getSeparatingLineTerminatorCount(previousNode: Node | undefined, nextNode: Node, format: ListFormat): number { + if (format & ListFormat.PreserveLines || preserveSourceNewlines) { if (previousNode === undefined || nextNode === undefined) { return 0; } - if (nextNode.kind === ts.SyntaxKind.JsxText) { + if (nextNode.kind === SyntaxKind.JsxText) { // JsxText will be written with its leading whitespace, so don't add more manually. return 0; } - else if (currentSourceFile && !ts.nodeIsSynthesized(previousNode) && !ts.nodeIsSynthesized(nextNode)) { + else if (currentSourceFile && !nodeIsSynthesized(previousNode) && !nodeIsSynthesized(nextNode)) { if (preserveSourceNewlines && siblingNodePositionsAreComparable(previousNode, nextNode)) { return getEffectiveLines( - includeComments => ts.getLinesBetweenRangeEndAndRangeStart( + includeComments => getLinesBetweenRangeEndAndRangeStart( previousNode, nextNode, currentSourceFile!, @@ -4825,48 +4905,48 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // expensive than checking with `preserveSourceNewlines` as above, but the goal is not to preserve the // effective source lines between two sibling nodes. else if (!preserveSourceNewlines && originalNodesHaveSameParent(previousNode, nextNode)) { - return ts.rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile) ? 0 : 1; + return rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile) ? 0 : 1; } // If the two nodes are not comparable, add a line terminator based on the format that can indicate // whether new lines are preferred or not. - return format & ts.ListFormat.PreferNewLine ? 1 : 0; + return format & ListFormat.PreferNewLine ? 1 : 0; } else if (synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format)) { return 1; } } - else if (ts.getStartsOnNewLine(nextNode)) { + else if (getStartsOnNewLine(nextNode)) { return 1; } - return format & ts.ListFormat.MultiLine ? 1 : 0; + return format & ListFormat.MultiLine ? 1 : 0; } - function getClosingLineTerminatorCount(parentNode: ts.Node | undefined, lastChild: ts.Node | undefined, format: ts.ListFormat, childrenTextRange: ts.TextRange | undefined): number { - if (format & ts.ListFormat.PreserveLines || preserveSourceNewlines) { - if (format & ts.ListFormat.PreferNewLine) { + function getClosingLineTerminatorCount(parentNode: Node | undefined, lastChild: Node | undefined, format: ListFormat, childrenTextRange: TextRange | undefined): number { + if (format & ListFormat.PreserveLines || preserveSourceNewlines) { + if (format & ListFormat.PreferNewLine) { return 1; } if (lastChild === undefined) { - return !parentNode || currentSourceFile && ts.rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1; + return !parentNode || currentSourceFile && rangeIsOnSingleLine(parentNode, currentSourceFile) ? 0 : 1; } - if (currentSourceFile && parentNode && !ts.positionIsSynthesized(parentNode.pos) && !ts.nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode)) { + if (currentSourceFile && parentNode && !positionIsSynthesized(parentNode.pos) && !nodeIsSynthesized(lastChild) && (!lastChild.parent || lastChild.parent === parentNode)) { if (preserveSourceNewlines) { - const end = childrenTextRange && !ts.positionIsSynthesized(childrenTextRange.end) ? childrenTextRange.end : lastChild.end; + const end = childrenTextRange && !positionIsSynthesized(childrenTextRange.end) ? childrenTextRange.end : lastChild.end; return getEffectiveLines( - includeComments => ts.getLinesBetweenPositionAndNextNonWhitespaceCharacter( + includeComments => getLinesBetweenPositionAndNextNonWhitespaceCharacter( end, parentNode.end, currentSourceFile!, includeComments)); } - return ts.rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile) ? 0 : 1; + return rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile) ? 0 : 1; } if (synthesizedNodeStartsOnNewLine(lastChild, format)) { return 1; } } - if (format & ts.ListFormat.MultiLine && !(format & ts.ListFormat.NoTrailingNewLine)) { + if (format & ListFormat.MultiLine && !(format & ListFormat.NoTrailingNewLine)) { return 1; } return 0; @@ -4875,7 +4955,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function getEffectiveLines(getLineDifference: (includeComments: boolean) => number) { // If 'preserveSourceNewlines' is disabled, we should never call this function // because it could be more expensive than alternative approximations. - ts.Debug.assert(!!preserveSourceNewlines); + Debug.assert(!!preserveSourceNewlines); // We start by measuring the line difference from a position to its adjacent comments, // so that this is counted as a one-line difference, not two: // @@ -4896,36 +4976,36 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return lines; } - function writeLineSeparatorsAndIndentBefore(node: ts.Node, parent: ts.Node): boolean { - const leadingNewlines = preserveSourceNewlines && getLeadingLineTerminatorCount(parent, node, ts.ListFormat.None); + function writeLineSeparatorsAndIndentBefore(node: Node, parent: Node): boolean { + const leadingNewlines = preserveSourceNewlines && getLeadingLineTerminatorCount(parent, node, ListFormat.None); if (leadingNewlines) { writeLinesAndIndent(leadingNewlines, /*writeSpaceIfNotIndenting*/ false); } return !!leadingNewlines; } - function writeLineSeparatorsAfter(node: ts.Node, parent: ts.Node) { - const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(parent, node, ts.ListFormat.None, /*childrenTextRange*/ undefined); + function writeLineSeparatorsAfter(node: Node, parent: Node) { + const trailingNewlines = preserveSourceNewlines && getClosingLineTerminatorCount(parent, node, ListFormat.None, /*childrenTextRange*/ undefined); if (trailingNewlines) { writeLine(trailingNewlines); } } - function synthesizedNodeStartsOnNewLine(node: ts.Node, format: ts.ListFormat) { - if (ts.nodeIsSynthesized(node)) { - const startsOnNewLine = ts.getStartsOnNewLine(node); + function synthesizedNodeStartsOnNewLine(node: Node, format: ListFormat) { + if (nodeIsSynthesized(node)) { + const startsOnNewLine = getStartsOnNewLine(node); if (startsOnNewLine === undefined) { - return (format & ts.ListFormat.PreferNewLine) !== 0; + return (format & ListFormat.PreferNewLine) !== 0; } return startsOnNewLine; } - return (format & ts.ListFormat.PreferNewLine) !== 0; + return (format & ListFormat.PreferNewLine) !== 0; } - function getLinesBetweenNodes(parent: ts.Node, node1: ts.Node, node2: ts.Node): number { - if (ts.getEmitFlags(parent) & ts.EmitFlags.NoIndentation) { + function getLinesBetweenNodes(parent: Node, node1: Node, node2: Node): number { + if (getEmitFlags(parent) & EmitFlags.NoIndentation) { return 0; } @@ -4934,88 +5014,88 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: node2 = skipSynthesizedParentheses(node2); // Always use a newline for synthesized code if the synthesizer desires it. - if (ts.getStartsOnNewLine(node2)) { + if (getStartsOnNewLine(node2)) { return 1; } - if (currentSourceFile && !ts.nodeIsSynthesized(parent) && !ts.nodeIsSynthesized(node1) && !ts.nodeIsSynthesized(node2)) { + if (currentSourceFile && !nodeIsSynthesized(parent) && !nodeIsSynthesized(node1) && !nodeIsSynthesized(node2)) { if (preserveSourceNewlines) { return getEffectiveLines( - includeComments => ts.getLinesBetweenRangeEndAndRangeStart( + includeComments => getLinesBetweenRangeEndAndRangeStart( node1, node2, currentSourceFile!, includeComments)); } - return ts.rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile) ? 0 : 1; + return rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile) ? 0 : 1; } return 0; } - function isEmptyBlock(block: ts.BlockLike) { + function isEmptyBlock(block: BlockLike) { return block.statements.length === 0 - && (!currentSourceFile || ts.rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile)); + && (!currentSourceFile || rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile)); } - function skipSynthesizedParentheses(node: ts.Node) { - while (node.kind === ts.SyntaxKind.ParenthesizedExpression && ts.nodeIsSynthesized(node)) { - node = (node as ts.ParenthesizedExpression).expression; + function skipSynthesizedParentheses(node: Node) { + while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) { + node = (node as ParenthesizedExpression).expression; } return node; } - function getTextOfNode(node: ts.Identifier | ts.PrivateIdentifier | ts.LiteralExpression, includeTrivia?: boolean): string { - if (ts.isGeneratedIdentifier(node) || ts.isGeneratedPrivateIdentifier(node)) { + function getTextOfNode(node: Identifier | PrivateIdentifier | LiteralExpression, includeTrivia?: boolean): string { + if (isGeneratedIdentifier(node) || isGeneratedPrivateIdentifier(node)) { return generateName(node); } - if (ts.isStringLiteral(node) && node.textSourceNode) { + if (isStringLiteral(node) && node.textSourceNode) { return getTextOfNode(node.textSourceNode, includeTrivia); } const sourceFile = currentSourceFile; // const needed for control flow - const canUseSourceFile = !!sourceFile && !!node.parent && !ts.nodeIsSynthesized(node); - if (ts.isMemberName(node)) { - if (!canUseSourceFile || ts.getSourceFileOfNode(node) !== ts.getOriginalNode(sourceFile)) { - return ts.idText(node); + const canUseSourceFile = !!sourceFile && !!node.parent && !nodeIsSynthesized(node); + if (isMemberName(node)) { + if (!canUseSourceFile || getSourceFileOfNode(node) !== getOriginalNode(sourceFile)) { + return idText(node); } } else { - ts.Debug.assertNode(node, ts.isLiteralExpression); // not strictly necessary + Debug.assertNode(node, isLiteralExpression); // not strictly necessary if (!canUseSourceFile) { return node.text; } } - return ts.getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia); + return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia); } - function getLiteralTextOfNode(node: ts.LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string { - if (node.kind === ts.SyntaxKind.StringLiteral && (node as ts.StringLiteral).textSourceNode) { - const textSourceNode = (node as ts.StringLiteral).textSourceNode!; - if (ts.isIdentifier(textSourceNode) || ts.isPrivateIdentifier(textSourceNode) || ts.isNumericLiteral(textSourceNode)) { - const text = ts.isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode); - return jsxAttributeEscape ? `"${ts.escapeJsxAttributeString(text)}"` : - neverAsciiEscape || (ts.getEmitFlags(node) & ts.EmitFlags.NoAsciiEscaping) ? `"${ts.escapeString(text)}"` : - `"${ts.escapeNonAsciiString(text)}"`; + function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string { + if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) { + const textSourceNode = (node as StringLiteral).textSourceNode!; + if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode)) { + const text = isNumericLiteral(textSourceNode) ? textSourceNode.text : getTextOfNode(textSourceNode); + return jsxAttributeEscape ? `"${escapeJsxAttributeString(text)}"` : + neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? `"${escapeString(text)}"` : + `"${escapeNonAsciiString(text)}"`; } else { return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape); } } - const flags = (neverAsciiEscape ? ts.GetLiteralTextFlags.NeverAsciiEscape : 0) - | (jsxAttributeEscape ? ts.GetLiteralTextFlags.JsxAttributeEscape : 0) - | (printerOptions.terminateUnterminatedLiterals ? ts.GetLiteralTextFlags.TerminateUnterminatedLiterals : 0) - | (printerOptions.target && printerOptions.target === ts.ScriptTarget.ESNext ? ts.GetLiteralTextFlags.AllowNumericSeparator : 0); + const flags = (neverAsciiEscape ? GetLiteralTextFlags.NeverAsciiEscape : 0) + | (jsxAttributeEscape ? GetLiteralTextFlags.JsxAttributeEscape : 0) + | (printerOptions.terminateUnterminatedLiterals ? GetLiteralTextFlags.TerminateUnterminatedLiterals : 0) + | (printerOptions.target && printerOptions.target === ScriptTarget.ESNext ? GetLiteralTextFlags.AllowNumericSeparator : 0); - return ts.getLiteralText(node, currentSourceFile, flags); + return getLiteralText(node, currentSourceFile, flags); } /** * Push a new name generation scope. */ - function pushNameGenerationScope(node: ts.Node | undefined) { - if (node && ts.getEmitFlags(node) & ts.EmitFlags.ReuseTempVariableScope) { + function pushNameGenerationScope(node: Node | undefined) { + if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { return; } tempFlagsStack.push(tempFlags); @@ -5030,8 +5110,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Pop the current name generation scope. */ - function popNameGenerationScope(node: ts.Node | undefined) { - if (node && ts.getEmitFlags(node) & ts.EmitFlags.ReuseTempVariableScope) { + function popNameGenerationScope(node: Node | undefined) { + if (node && getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { return; } tempFlags = tempFlagsStack.pop()!; @@ -5041,118 +5121,118 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } function reserveNameInNestedScopes(name: string) { - if (!reservedNames || reservedNames === ts.lastOrUndefined(reservedNamesStack)) { - reservedNames = new ts.Set(); + if (!reservedNames || reservedNames === lastOrUndefined(reservedNamesStack)) { + reservedNames = new Set(); } reservedNames.add(name); } - function generateNames(node: ts.Node | undefined) { + function generateNames(node: Node | undefined) { if (!node) return; switch (node.kind) { - case ts.SyntaxKind.Block: - ts.forEach((node as ts.Block).statements, generateNames); + case SyntaxKind.Block: + forEach((node as Block).statements, generateNames); break; - case ts.SyntaxKind.LabeledStatement: - case ts.SyntaxKind.WithStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WhileStatement: - generateNames((node as ts.LabeledStatement | ts.WithStatement | ts.DoStatement | ts.WhileStatement).statement); + case SyntaxKind.LabeledStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + generateNames((node as LabeledStatement | WithStatement | DoStatement | WhileStatement).statement); break; - case ts.SyntaxKind.IfStatement: - generateNames((node as ts.IfStatement).thenStatement); - generateNames((node as ts.IfStatement).elseStatement); + case SyntaxKind.IfStatement: + generateNames((node as IfStatement).thenStatement); + generateNames((node as IfStatement).elseStatement); break; - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForInStatement: - generateNames((node as ts.ForStatement | ts.ForInOrOfStatement).initializer); - generateNames((node as ts.ForStatement | ts.ForInOrOfStatement).statement); + case SyntaxKind.ForStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForInStatement: + generateNames((node as ForStatement | ForInOrOfStatement).initializer); + generateNames((node as ForStatement | ForInOrOfStatement).statement); break; - case ts.SyntaxKind.SwitchStatement: - generateNames((node as ts.SwitchStatement).caseBlock); + case SyntaxKind.SwitchStatement: + generateNames((node as SwitchStatement).caseBlock); break; - case ts.SyntaxKind.CaseBlock: - ts.forEach((node as ts.CaseBlock).clauses, generateNames); + case SyntaxKind.CaseBlock: + forEach((node as CaseBlock).clauses, generateNames); break; - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: - ts.forEach((node as ts.CaseOrDefaultClause).statements, generateNames); + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + forEach((node as CaseOrDefaultClause).statements, generateNames); break; - case ts.SyntaxKind.TryStatement: - generateNames((node as ts.TryStatement).tryBlock); - generateNames((node as ts.TryStatement).catchClause); - generateNames((node as ts.TryStatement).finallyBlock); + case SyntaxKind.TryStatement: + generateNames((node as TryStatement).tryBlock); + generateNames((node as TryStatement).catchClause); + generateNames((node as TryStatement).finallyBlock); break; - case ts.SyntaxKind.CatchClause: - generateNames((node as ts.CatchClause).variableDeclaration); - generateNames((node as ts.CatchClause).block); + case SyntaxKind.CatchClause: + generateNames((node as CatchClause).variableDeclaration); + generateNames((node as CatchClause).block); break; - case ts.SyntaxKind.VariableStatement: - generateNames((node as ts.VariableStatement).declarationList); + case SyntaxKind.VariableStatement: + generateNames((node as VariableStatement).declarationList); break; - case ts.SyntaxKind.VariableDeclarationList: - ts.forEach((node as ts.VariableDeclarationList).declarations, generateNames); + case SyntaxKind.VariableDeclarationList: + forEach((node as VariableDeclarationList).declarations, generateNames); break; - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.ClassDeclaration: - generateNameIfNeeded((node as ts.NamedDeclaration).name); + case SyntaxKind.VariableDeclaration: + case SyntaxKind.Parameter: + case SyntaxKind.BindingElement: + case SyntaxKind.ClassDeclaration: + generateNameIfNeeded((node as NamedDeclaration).name); break; - case ts.SyntaxKind.FunctionDeclaration: - generateNameIfNeeded((node as ts.FunctionDeclaration).name); - if (ts.getEmitFlags(node) & ts.EmitFlags.ReuseTempVariableScope) { - ts.forEach((node as ts.FunctionDeclaration).parameters, generateNames); - generateNames((node as ts.FunctionDeclaration).body); + case SyntaxKind.FunctionDeclaration: + generateNameIfNeeded((node as FunctionDeclaration).name); + if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { + forEach((node as FunctionDeclaration).parameters, generateNames); + generateNames((node as FunctionDeclaration).body); } break; - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - ts.forEach((node as ts.BindingPattern).elements, generateNames); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + forEach((node as BindingPattern).elements, generateNames); break; - case ts.SyntaxKind.ImportDeclaration: - generateNames((node as ts.ImportDeclaration).importClause); + case SyntaxKind.ImportDeclaration: + generateNames((node as ImportDeclaration).importClause); break; - case ts.SyntaxKind.ImportClause: - generateNameIfNeeded((node as ts.ImportClause).name); - generateNames((node as ts.ImportClause).namedBindings); + case SyntaxKind.ImportClause: + generateNameIfNeeded((node as ImportClause).name); + generateNames((node as ImportClause).namedBindings); break; - case ts.SyntaxKind.NamespaceImport: - generateNameIfNeeded((node as ts.NamespaceImport).name); + case SyntaxKind.NamespaceImport: + generateNameIfNeeded((node as NamespaceImport).name); break; - case ts.SyntaxKind.NamespaceExport: - generateNameIfNeeded((node as ts.NamespaceExport).name); + case SyntaxKind.NamespaceExport: + generateNameIfNeeded((node as NamespaceExport).name); break; - case ts.SyntaxKind.NamedImports: - ts.forEach((node as ts.NamedImports).elements, generateNames); + case SyntaxKind.NamedImports: + forEach((node as NamedImports).elements, generateNames); break; - case ts.SyntaxKind.ImportSpecifier: - generateNameIfNeeded((node as ts.ImportSpecifier).propertyName || (node as ts.ImportSpecifier).name); + case SyntaxKind.ImportSpecifier: + generateNameIfNeeded((node as ImportSpecifier).propertyName || (node as ImportSpecifier).name); break; } } - function generateMemberNames(node: ts.Node | undefined) { + function generateMemberNames(node: Node | undefined) { if (!node) return; switch (node.kind) { - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - generateNameIfNeeded((node as ts.NamedDeclaration).name); + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + generateNameIfNeeded((node as NamedDeclaration).name); break; } } - function generateNameIfNeeded(name: ts.DeclarationName | undefined) { + function generateNameIfNeeded(name: DeclarationName | undefined) { if (name) { - if (ts.isGeneratedIdentifier(name) || ts.isGeneratedPrivateIdentifier(name)) { + if (isGeneratedIdentifier(name) || isGeneratedPrivateIdentifier(name)) { generateName(name); } - else if (ts.isBindingPattern(name)) { + else if (isBindingPattern(name)) { generateNames(name); } } @@ -5161,11 +5241,11 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generate the text for a generated identifier. */ - function generateName(name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) { - if ((name.autoGenerateFlags & ts.GeneratedIdentifierFlags.KindMask) === ts.GeneratedIdentifierFlags.Node) { + function generateName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { + if ((name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) { // Node names generate unique names based on their original node // and are cached based on that node's id. - return generateNameCached(ts.getNodeForGeneratedName(name), ts.isPrivateIdentifier(name), name.autoGenerateFlags, name.autoGeneratePrefix, name.autoGenerateSuffix); + return generateNameCached(getNodeForGeneratedName(name), isPrivateIdentifier(name), name.autoGenerateFlags, name.autoGeneratePrefix, name.autoGenerateSuffix); } else { // Auto, Loop, and Unique names are cached based on their unique @@ -5175,9 +5255,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function generateNameCached(node: ts.Node, privateName: boolean, flags?: ts.GeneratedIdentifierFlags, prefix?: string | ts.GeneratedNamePart, suffix?: string) { - const nodeId = ts.getNodeId(node); - return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, privateName, flags ?? ts.GeneratedIdentifierFlags.None, ts.formatGeneratedNamePart(prefix, generateName), ts.formatGeneratedNamePart(suffix))); + function generateNameCached(node: Node, privateName: boolean, flags?: GeneratedIdentifierFlags, prefix?: string | GeneratedNamePart, suffix?: string) { + const nodeId = getNodeId(node); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = generateNameForNode(node, privateName, flags ?? GeneratedIdentifierFlags.None, formatGeneratedNamePart(prefix, generateName), formatGeneratedNamePart(suffix))); } /** @@ -5200,12 +5280,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Returns a value indicating whether a name is unique within a container. */ - function isUniqueLocalName(name: string, container: ts.Node): boolean { - for (let node = container; ts.isNodeDescendantOf(node, container); node = node.nextContainer!) { + function isUniqueLocalName(name: string, container: Node): boolean { + for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer!) { if (node.locals) { - const local = node.locals.get(ts.escapeLeadingUnderscores(name)); + const local = node.locals.get(escapeLeadingUnderscores(name)); // We conservatively include alias symbols to cover cases where they're emitted as locals - if (local && local.flags & (ts.SymbolFlags.Value | ts.SymbolFlags.ExportValue | ts.SymbolFlags.Alias)) { + if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { return false; } } @@ -5233,7 +5313,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: privateNameTempFlags = flags; break; default: - formattedNameTempFlags ??= new ts.Map(); + formattedNameTempFlags ??= new Map(); formattedNameTempFlags.set(formattedNameKey, flags); break; } @@ -5245,17 +5325,17 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. */ function makeTempVariableName(flags: TempFlags, reservedInNestedScopes: boolean, privateName: boolean, prefix: string, suffix: string): string { - if (prefix.length > 0 && prefix.charCodeAt(0) === ts.CharacterCodes.hash) { + if (prefix.length > 0 && prefix.charCodeAt(0) === CharacterCodes.hash) { prefix = prefix.slice(1); } // Generate a key to use to acquire a TempFlags counter based on the fixed portions of the generated name. - const key = ts.formatGeneratedName(privateName, prefix, "", suffix); + const key = formatGeneratedName(privateName, prefix, "", suffix); let tempFlags = getTempFlags(key); if (flags && !(tempFlags & flags)) { const name = flags === TempFlags._i ? "_i" : "_n"; - const fullName = ts.formatGeneratedName(privateName, prefix, name, suffix); + const fullName = formatGeneratedName(privateName, prefix, name, suffix); if (isUniqueName(fullName)) { tempFlags |= flags; if (reservedInNestedScopes) { @@ -5272,9 +5352,9 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Skip over 'i' and 'n' if (count !== 8 && count !== 13) { const name = count < 26 - ? "_" + String.fromCharCode(ts.CharacterCodes.a + count) + ? "_" + String.fromCharCode(CharacterCodes.a + count) : "_" + (count - 26); - const fullName = ts.formatGeneratedName(privateName, prefix, name, suffix); + const fullName = formatGeneratedName(privateName, prefix, name, suffix); if (isUniqueName(fullName)) { if (reservedInNestedScopes) { reserveNameInNestedScopes(fullName); @@ -5294,14 +5374,14 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * If `optimistic` is set, the first instance will use 'baseName' verbatim instead of 'baseName_1' */ function makeUniqueName(baseName: string, checkFn: (name: string) => boolean = isUniqueName, optimistic: boolean, scoped: boolean, privateName: boolean, prefix: string, suffix: string): string { - if (baseName.length > 0 && baseName.charCodeAt(0) === ts.CharacterCodes.hash) { + if (baseName.length > 0 && baseName.charCodeAt(0) === CharacterCodes.hash) { baseName = baseName.slice(1); } - if (prefix.length > 0 && prefix.charCodeAt(0) === ts.CharacterCodes.hash) { + if (prefix.length > 0 && prefix.charCodeAt(0) === CharacterCodes.hash) { prefix = prefix.slice(1); } if (optimistic) { - const fullName = ts.formatGeneratedName(privateName, prefix, baseName, suffix); + const fullName = formatGeneratedName(privateName, prefix, baseName, suffix); if (checkFn(fullName)) { if (scoped) { reserveNameInNestedScopes(fullName); @@ -5313,12 +5393,12 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } // Find the first unique 'name_n', where n is a positive number - if (baseName.charCodeAt(baseName.length - 1) !== ts.CharacterCodes._) { + if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { baseName += "_"; } let i = 1; while (true) { - const fullName = ts.formatGeneratedName(privateName, prefix, baseName + i, suffix); + const fullName = formatGeneratedName(privateName, prefix, baseName + i, suffix); if (checkFn(fullName)) { if (scoped) { reserveNameInNestedScopes(fullName); @@ -5339,7 +5419,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique name for a ModuleDeclaration or EnumDeclaration. */ - function generateNameForModuleOrEnum(node: ts.ModuleDeclaration | ts.EnumDeclaration) { + function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { const name = getTextOfNode(node.name); // Use module/enum name itself if it is unique, otherwise make a unique variation return isUniqueLocalName(name, node) ? name : makeUniqueName(name, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); @@ -5348,10 +5428,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique name for an ImportDeclaration or ExportDeclaration. */ - function generateNameForImportOrExportDeclaration(node: ts.ImportDeclaration | ts.ExportDeclaration) { - const expr = ts.getExternalModuleName(node)!; // TODO: GH#18217 - const baseName = ts.isStringLiteral(expr) ? - ts.makeIdentifierFromModuleName(expr.text) : "module"; + function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { + const expr = getExternalModuleName(node)!; // TODO: GH#18217 + const baseName = isStringLiteral(expr) ? + makeIdentifierFromModuleName(expr.text) : "module"; return makeUniqueName(baseName, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); } @@ -5369,8 +5449,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: return makeUniqueName("class", isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); } - function generateNameForMethodOrAccessor(node: ts.MethodDeclaration | ts.AccessorDeclaration, privateName: boolean, prefix: string, suffix: string) { - if (ts.isIdentifier(node.name)) { + function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, privateName: boolean, prefix: string, suffix: string) { + if (isIdentifier(node.name)) { return generateNameCached(node.name, privateName); } return makeTempVariableName(TempFlags.Auto, /*reservedInNestedScopes*/ false, privateName, prefix, suffix); @@ -5379,40 +5459,40 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique name from a node. */ - function generateNameForNode(node: ts.Node, privateName: boolean, flags: ts.GeneratedIdentifierFlags, prefix: string, suffix: string): string { + function generateNameForNode(node: Node, privateName: boolean, flags: GeneratedIdentifierFlags, prefix: string, suffix: string): string { switch (node.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PrivateIdentifier: + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: return makeUniqueName( - getTextOfNode(node as ts.Identifier), + getTextOfNode(node as Identifier), isUniqueName, - !!(flags & ts.GeneratedIdentifierFlags.Optimistic), - !!(flags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes), + !!(flags & GeneratedIdentifierFlags.Optimistic), + !!(flags & GeneratedIdentifierFlags.ReservedInNestedScopes), privateName, prefix, suffix ); - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - ts.Debug.assert(!prefix && !suffix && !privateName); - return generateNameForModuleOrEnum(node as ts.ModuleDeclaration | ts.EnumDeclaration); - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - ts.Debug.assert(!prefix && !suffix && !privateName); - return generateNameForImportOrExportDeclaration(node as ts.ImportDeclaration | ts.ExportDeclaration); - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ExportAssignment: - ts.Debug.assert(!prefix && !suffix && !privateName); + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + Debug.assert(!prefix && !suffix && !privateName); + return generateNameForModuleOrEnum(node as ModuleDeclaration | EnumDeclaration); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + Debug.assert(!prefix && !suffix && !privateName); + return generateNameForImportOrExportDeclaration(node as ImportDeclaration | ExportDeclaration); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ExportAssignment: + Debug.assert(!prefix && !suffix && !privateName); return generateNameForExportDefault(); - case ts.SyntaxKind.ClassExpression: - ts.Debug.assert(!prefix && !suffix && !privateName); + case SyntaxKind.ClassExpression: + Debug.assert(!prefix && !suffix && !privateName); return generateNameForClassExpression(); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node as ts.MethodDeclaration | ts.AccessorDeclaration, privateName, prefix, suffix); - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return generateNameForMethodOrAccessor(node as MethodDeclaration | AccessorDeclaration, privateName, prefix, suffix); + case SyntaxKind.ComputedPropertyName: return makeTempVariableName(TempFlags.Auto, /*reserveInNestedScopes*/ true, privateName, prefix, suffix); default: return makeTempVariableName(TempFlags.Auto, /*reserveInNestedScopes*/ false, privateName, prefix, suffix); @@ -5422,33 +5502,33 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Generates a unique identifier for a node. */ - function makeName(name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) { - const prefix = ts.formatGeneratedNamePart(name.autoGeneratePrefix, generateName); - const suffix = ts.formatGeneratedNamePart (name.autoGenerateSuffix); - switch (name.autoGenerateFlags & ts.GeneratedIdentifierFlags.KindMask) { - case ts.GeneratedIdentifierFlags.Auto: - return makeTempVariableName(TempFlags.Auto, !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes), ts.isPrivateIdentifier(name), prefix, suffix); - case ts.GeneratedIdentifierFlags.Loop: - ts.Debug.assertNode(name, ts.isIdentifier); - return makeTempVariableName(TempFlags._i, !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes), /*privateName*/ false, prefix, suffix); - case ts.GeneratedIdentifierFlags.Unique: + function makeName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { + const prefix = formatGeneratedNamePart(name.autoGeneratePrefix, generateName); + const suffix = formatGeneratedNamePart (name.autoGenerateSuffix); + switch (name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask) { + case GeneratedIdentifierFlags.Auto: + return makeTempVariableName(TempFlags.Auto, !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), prefix, suffix); + case GeneratedIdentifierFlags.Loop: + Debug.assertNode(name, isIdentifier); + return makeTempVariableName(TempFlags._i, !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes), /*privateName*/ false, prefix, suffix); + case GeneratedIdentifierFlags.Unique: return makeUniqueName( - ts.idText(name), - (name.autoGenerateFlags & ts.GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName, - !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.Optimistic), - !!(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.ReservedInNestedScopes), - ts.isPrivateIdentifier(name), + idText(name), + (name.autoGenerateFlags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName, + !!(name.autoGenerateFlags & GeneratedIdentifierFlags.Optimistic), + !!(name.autoGenerateFlags & GeneratedIdentifierFlags.ReservedInNestedScopes), + isPrivateIdentifier(name), prefix, suffix ); } - return ts.Debug.fail(`Unsupported GeneratedIdentifierKind: ${ts.Debug.formatEnum(name.autoGenerateFlags & ts.GeneratedIdentifierFlags.KindMask, (ts as any).GeneratedIdentifierFlags, /*isFlags*/ true)}.`); + return Debug.fail(`Unsupported GeneratedIdentifierKind: ${Debug.formatEnum(name.autoGenerateFlags & GeneratedIdentifierFlags.KindMask, (ts as any).GeneratedIdentifierFlags, /*isFlags*/ true)}.`); } // Comments - function pipelineEmitWithComments(hint: ts.EmitHint, node: ts.Node) { + function pipelineEmitWithComments(hint: EmitHint, node: Node) { const pipelinePhase = getNextPipelinePhase(PipelinePhase.Comments, hint, node); const savedContainerPos = containerPos; const savedContainerEnd = containerEnd; @@ -5458,73 +5538,73 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: emitCommentsAfterNode(node, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); } - function emitCommentsBeforeNode(node: ts.Node) { - const emitFlags = ts.getEmitFlags(node); - const commentRange = ts.getCommentRange(node); + function emitCommentsBeforeNode(node: Node) { + const emitFlags = getEmitFlags(node); + const commentRange = getCommentRange(node); // Emit leading comments emitLeadingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end); - if (emitFlags & ts.EmitFlags.NoNestedComments) { + if (emitFlags & EmitFlags.NoNestedComments) { commentsDisabled = true; } } - function emitCommentsAfterNode(node: ts.Node, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { - const emitFlags = ts.getEmitFlags(node); - const commentRange = ts.getCommentRange(node); + function emitCommentsAfterNode(node: Node, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { + const emitFlags = getEmitFlags(node); + const commentRange = getCommentRange(node); // Emit trailing comments - if (emitFlags & ts.EmitFlags.NoNestedComments) { + if (emitFlags & EmitFlags.NoNestedComments) { commentsDisabled = false; } emitTrailingCommentsOfNode(node, emitFlags, commentRange.pos, commentRange.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); - const typeNode = ts.getTypeNode(node); + const typeNode = getTypeNode(node); if (typeNode) { emitTrailingCommentsOfNode(node, emitFlags, typeNode.pos, typeNode.end, savedContainerPos, savedContainerEnd, savedDeclarationListContainerEnd); } } - function emitLeadingCommentsOfNode(node: ts.Node, emitFlags: ts.EmitFlags, pos: number, end: number) { + function emitLeadingCommentsOfNode(node: Node, emitFlags: EmitFlags, pos: number, end: number) { enterComment(); hasWrittenComment = false; // We have to explicitly check that the node is JsxText because if the compilerOptions.jsx is "preserve" we will not do any transformation. // It is expensive to walk entire tree just to set one kind of node to have no comments. - const skipLeadingComments = pos < 0 || (emitFlags & ts.EmitFlags.NoLeadingComments) !== 0 || node.kind === ts.SyntaxKind.JsxText; - const skipTrailingComments = end < 0 || (emitFlags & ts.EmitFlags.NoTrailingComments) !== 0 || node.kind === ts.SyntaxKind.JsxText; + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0 || node.kind === SyntaxKind.JsxText; + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText; // Save current container state on the stack. if ((pos > 0 || end > 0) && pos !== end) { // Emit leading comments if the position is not synthesized and the node // has not opted out from emitting leading comments. if (!skipLeadingComments) { - emitLeadingComments(pos, /*isEmittedNode*/ node.kind !== ts.SyntaxKind.NotEmittedStatement); + emitLeadingComments(pos, /*isEmittedNode*/ node.kind !== SyntaxKind.NotEmittedStatement); } - if (!skipLeadingComments || (pos >= 0 && (emitFlags & ts.EmitFlags.NoLeadingComments) !== 0)) { + if (!skipLeadingComments || (pos >= 0 && (emitFlags & EmitFlags.NoLeadingComments) !== 0)) { // Advance the container position if comments get emitted or if they've been disabled explicitly using NoLeadingComments. containerPos = pos; } - if (!skipTrailingComments || (end >= 0 && (emitFlags & ts.EmitFlags.NoTrailingComments) !== 0)) { + if (!skipTrailingComments || (end >= 0 && (emitFlags & EmitFlags.NoTrailingComments) !== 0)) { // As above. containerEnd = end; // To avoid invalid comment emit in a down-level binding pattern, we // keep track of the last declaration list container's end - if (node.kind === ts.SyntaxKind.VariableDeclarationList) { + if (node.kind === SyntaxKind.VariableDeclarationList) { declarationListContainerEnd = end; } } } - ts.forEach(ts.getSyntheticLeadingComments(node), emitLeadingSynthesizedComment); + forEach(getSyntheticLeadingComments(node), emitLeadingSynthesizedComment); exitComment(); } - function emitTrailingCommentsOfNode(node: ts.Node, emitFlags: ts.EmitFlags, pos: number, end: number, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { + function emitTrailingCommentsOfNode(node: Node, emitFlags: EmitFlags, pos: number, end: number, savedContainerPos: number, savedContainerEnd: number, savedDeclarationListContainerEnd: number) { enterComment(); - const skipTrailingComments = end < 0 || (emitFlags & ts.EmitFlags.NoTrailingComments) !== 0 || node.kind === ts.SyntaxKind.JsxText; - ts.forEach(ts.getSyntheticTrailingComments(node), emitTrailingSynthesizedComment); + const skipTrailingComments = end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0 || node.kind === SyntaxKind.JsxText; + forEach(getSyntheticTrailingComments(node), emitTrailingSynthesizedComment); if ((pos > 0 || end > 0) && pos !== end) { // Restore previous container state. containerPos = savedContainerPos; @@ -5533,19 +5613,19 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: // Emit trailing comments if the position is not synthesized and the node // has not opted out from emitting leading comments and is an emitted node. - if (!skipTrailingComments && node.kind !== ts.SyntaxKind.NotEmittedStatement) { + if (!skipTrailingComments && node.kind !== SyntaxKind.NotEmittedStatement) { emitTrailingComments(end); } } exitComment(); } - function emitLeadingSynthesizedComment(comment: ts.SynthesizedComment) { - if (comment.hasLeadingNewline || comment.kind === ts.SyntaxKind.SingleLineCommentTrivia) { + function emitLeadingSynthesizedComment(comment: SynthesizedComment) { + if (comment.hasLeadingNewline || comment.kind === SyntaxKind.SingleLineCommentTrivia) { writer.writeLine(); } writeSynthesizedComment(comment); - if (comment.hasTrailingNewLine || comment.kind === ts.SyntaxKind.SingleLineCommentTrivia) { + if (comment.hasTrailingNewLine || comment.kind === SyntaxKind.SingleLineCommentTrivia) { writer.writeLine(); } else { @@ -5553,7 +5633,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitTrailingSynthesizedComment(comment: ts.SynthesizedComment) { + function emitTrailingSynthesizedComment(comment: SynthesizedComment) { if (!writer.isAtStartOfLine()) { writer.writeSpace(" "); } @@ -5563,30 +5643,30 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function writeSynthesizedComment(comment: ts.SynthesizedComment) { + function writeSynthesizedComment(comment: SynthesizedComment) { const text = formatSynthesizedComment(comment); - const lineMap = comment.kind === ts.SyntaxKind.MultiLineCommentTrivia ? ts.computeLineStarts(text) : undefined; - ts.writeCommentRange(text, lineMap!, writer, 0, text.length, newLine); + const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined; + writeCommentRange(text, lineMap!, writer, 0, text.length, newLine); } - function formatSynthesizedComment(comment: ts.SynthesizedComment) { - return comment.kind === ts.SyntaxKind.MultiLineCommentTrivia + function formatSynthesizedComment(comment: SynthesizedComment) { + return comment.kind === SyntaxKind.MultiLineCommentTrivia ? `/*${comment.text}*/` : `//${comment.text}`; } - function emitBodyWithDetachedComments(node: ts.Node, detachedRange: ts.TextRange, emitCallback: (node: ts.Node) => void) { + function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) { enterComment(); const { pos, end } = detachedRange; - const emitFlags = ts.getEmitFlags(node); - const skipLeadingComments = pos < 0 || (emitFlags & ts.EmitFlags.NoLeadingComments) !== 0; - const skipTrailingComments = commentsDisabled || end < 0 || (emitFlags & ts.EmitFlags.NoTrailingComments) !== 0; + const emitFlags = getEmitFlags(node); + const skipLeadingComments = pos < 0 || (emitFlags & EmitFlags.NoLeadingComments) !== 0; + const skipTrailingComments = commentsDisabled || end < 0 || (emitFlags & EmitFlags.NoTrailingComments) !== 0; if (!skipLeadingComments) { emitDetachedCommentsAndUpdateCommentsInfo(detachedRange); } exitComment(); - if (emitFlags & ts.EmitFlags.NoNestedComments && !commentsDisabled) { + if (emitFlags & EmitFlags.NoNestedComments && !commentsDisabled) { commentsDisabled = true; emitCallback(node); commentsDisabled = false; @@ -5606,26 +5686,26 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } - function originalNodesHaveSameParent(nodeA: ts.Node, nodeB: ts.Node) { - nodeA = ts.getOriginalNode(nodeA); + function originalNodesHaveSameParent(nodeA: Node, nodeB: Node) { + nodeA = getOriginalNode(nodeA); // For performance, do not call `getOriginalNode` for `nodeB` if `nodeA` doesn't even // have a parent node. - return nodeA.parent && nodeA.parent === ts.getOriginalNode(nodeB).parent; + return nodeA.parent && nodeA.parent === getOriginalNode(nodeB).parent; } - function siblingNodePositionsAreComparable(previousNode: ts.Node, nextNode: ts.Node) { + function siblingNodePositionsAreComparable(previousNode: Node, nextNode: Node) { if (nextNode.pos < previousNode.end) { return false; } - previousNode = ts.getOriginalNode(previousNode); - nextNode = ts.getOriginalNode(nextNode); + previousNode = getOriginalNode(previousNode); + nextNode = getOriginalNode(nextNode); const parent = previousNode.parent; if (!parent || parent !== nextNode.parent) { return false; } - const parentNodeArray = ts.getContainingNodeArray(previousNode); + const parentNodeArray = getContainingNodeArray(previousNode); const prevNodeIndex = parentNodeArray?.indexOf(previousNode); return prevNodeIndex !== undefined && prevNodeIndex > -1 && parentNodeArray!.indexOf(nextNode) === prevNodeIndex + 1; } @@ -5654,13 +5734,13 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { if (isTripleSlashComment(commentPos, commentEnd)) { emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); } } - function emitNonTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitNonTripleSlashLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { if (!isTripleSlashComment(commentPos, commentEnd)) { emitLeadingComment(commentPos, commentEnd, kind, hasTrailingNewLine, rangePos); } @@ -5668,27 +5748,27 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: function shouldWriteComment(text: string, pos: number) { if (printerOptions.onlyPrintJsDocStyle) { - return (ts.isJSDocLikeText(text, pos) || ts.isPinnedComment(text, pos)); + return (isJSDocLikeText(text, pos) || isPinnedComment(text, pos)); } return true; } - function emitLeadingComment(commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { + function emitLeadingComment(commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; if (!hasWrittenComment) { - ts.emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos); + emitNewLineBeforeLeadingCommentOfPosition(getCurrentLineMap(), writer, rangePos, commentPos); hasWrittenComment = true; } // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space emitPos(commentPos); - ts.writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { writer.writeLine(); } - else if (kind === ts.SyntaxKind.MultiLineCommentTrivia) { + else if (kind === SyntaxKind.MultiLineCommentTrivia) { writer.writeSpace(" "); } } @@ -5705,7 +5785,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: forEachTrailingCommentToEmit(pos, emitTrailingComment); } - function emitTrailingComment(commentPos: number, commentEnd: number, _kind: ts.SyntaxKind, hasTrailingNewLine: boolean) { + function emitTrailingComment(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; // trailing comments are emitted at space/*trailing comment1 */space/*trailing comment2*/ if (!writer.isAtStartOfLine()) { @@ -5713,7 +5793,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } emitPos(commentPos); - ts.writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { @@ -5730,25 +5810,25 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: exitComment(); } - function emitTrailingCommentOfPositionNoNewline(commentPos: number, commentEnd: number, kind: ts.SyntaxKind) { + function emitTrailingCommentOfPositionNoNewline(commentPos: number, commentEnd: number, kind: SyntaxKind) { if (!currentSourceFile) return; // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space emitPos(commentPos); - ts.writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); - if (kind === ts.SyntaxKind.SingleLineCommentTrivia) { + if (kind === SyntaxKind.SingleLineCommentTrivia) { writer.writeLine(); // still write a newline for single-line comments, so closing tokens aren't written on the same line } } - function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: ts.SyntaxKind, hasTrailingNewLine: boolean) { + function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { if(!currentSourceFile) return; // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space emitPos(commentPos); - ts.writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); + writeCommentRange(currentSourceFile.text, getCurrentLineMap(), writer, commentPos, commentEnd, newLine); emitPos(commentEnd); if (hasTrailingNewLine) { @@ -5759,33 +5839,33 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + function forEachLeadingCommentToEmit(pos: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { // Emit the leading comments only if the container's pos doesn't match because the container should take care of emitting these comments if (currentSourceFile && (containerPos === -1 || pos !== containerPos)) { if (hasDetachedComments(pos)) { forEachLeadingCommentWithoutDetachedComments(cb); } else { - ts.forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos); + forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos); } } } - function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean) => void) { + function forEachTrailingCommentToEmit(end: number, cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean) => void) { // Emit the trailing comments only if the container's end doesn't match because the container should take care of emitting these comments if (currentSourceFile && (containerEnd === -1 || (end !== containerEnd && end !== declarationListContainerEnd))) { - ts.forEachTrailingCommentRange(currentSourceFile.text, end, cb); + forEachTrailingCommentRange(currentSourceFile.text, end, cb); } } function hasDetachedComments(pos: number) { - return detachedCommentsInfo !== undefined && ts.last(detachedCommentsInfo).nodePos === pos; + return detachedCommentsInfo !== undefined && last(detachedCommentsInfo).nodePos === pos; } - function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: ts.SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { + function forEachLeadingCommentWithoutDetachedComments(cb: (commentPos: number, commentEnd: number, kind: SyntaxKind, hasTrailingNewLine: boolean, rangePos: number) => void) { if (!currentSourceFile) return; // get the leading comments from detachedPos - const pos = ts.last(detachedCommentsInfo!).detachedCommentEndPos; + const pos = last(detachedCommentsInfo!).detachedCommentEndPos; if (detachedCommentsInfo!.length - 1) { detachedCommentsInfo!.pop(); } @@ -5793,11 +5873,11 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: detachedCommentsInfo = undefined; } - ts.forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos); + forEachLeadingCommentRange(currentSourceFile.text, pos, cb, /*state*/ pos); } - function emitDetachedCommentsAndUpdateCommentsInfo(range: ts.TextRange) { - const currentDetachedCommentInfo = currentSourceFile && ts.emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled); + function emitDetachedCommentsAndUpdateCommentsInfo(range: TextRange) { + const currentDetachedCommentInfo = currentSourceFile && emitDetachedComments(currentSourceFile.text, getCurrentLineMap(), writer, emitComment, range, newLine, commentsDisabled); if (currentDetachedCommentInfo) { if (detachedCommentsInfo) { detachedCommentsInfo.push(currentDetachedCommentInfo); @@ -5808,10 +5888,10 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } } - function emitComment(text: string, lineMap: number[], writer: ts.EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { + function emitComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { if (!currentSourceFile || !shouldWriteComment(currentSourceFile.text, commentPos)) return; emitPos(commentPos); - ts.writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); + writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); emitPos(commentEnd); } @@ -5821,32 +5901,32 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * @return true if the comment is a triple-slash comment else false */ function isTripleSlashComment(commentPos: number, commentEnd: number) { - return !!currentSourceFile && ts.isRecognizedTripleSlashComment(currentSourceFile.text, commentPos, commentEnd); + return !!currentSourceFile && isRecognizedTripleSlashComment(currentSourceFile.text, commentPos, commentEnd); } // Source Maps - function getParsedSourceMap(node: ts.UnparsedSource) { + function getParsedSourceMap(node: UnparsedSource) { if (node.parsedSourceMap === undefined && node.sourceMapText !== undefined) { - node.parsedSourceMap = ts.tryParseRawSourceMap(node.sourceMapText) || false; + node.parsedSourceMap = tryParseRawSourceMap(node.sourceMapText) || false; } return node.parsedSourceMap || undefined; } - function pipelineEmitWithSourceMaps(hint: ts.EmitHint, node: ts.Node) { + function pipelineEmitWithSourceMaps(hint: EmitHint, node: Node) { const pipelinePhase = getNextPipelinePhase(PipelinePhase.SourceMaps, hint, node); emitSourceMapsBeforeNode(node); pipelinePhase(hint, node); emitSourceMapsAfterNode(node); } - function emitSourceMapsBeforeNode(node: ts.Node) { - const emitFlags = ts.getEmitFlags(node); - const sourceMapRange = ts.getSourceMapRange(node); + function emitSourceMapsBeforeNode(node: Node) { + const emitFlags = getEmitFlags(node); + const sourceMapRange = getSourceMapRange(node); // Emit leading sourcemap - if (ts.isUnparsedNode(node)) { - ts.Debug.assertIsDefined(node.parent, "UnparsedNodes must have parent pointers"); + if (isUnparsedNode(node)) { + Debug.assertIsDefined(node.parent, "UnparsedNodes must have parent pointers"); const parsed = getParsedSourceMap(node.parent); if (parsed && sourceMapGenerator) { sourceMapGenerator.appendSourceMap( @@ -5861,28 +5941,28 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: } else { const source = sourceMapRange.source || sourceMapSource; - if (node.kind !== ts.SyntaxKind.NotEmittedStatement - && (emitFlags & ts.EmitFlags.NoLeadingSourceMap) === 0 + if (node.kind !== SyntaxKind.NotEmittedStatement + && (emitFlags & EmitFlags.NoLeadingSourceMap) === 0 && sourceMapRange.pos >= 0) { emitSourcePos(sourceMapRange.source || sourceMapSource, skipSourceTrivia(source, sourceMapRange.pos)); } - if (emitFlags & ts.EmitFlags.NoNestedSourceMaps) { + if (emitFlags & EmitFlags.NoNestedSourceMaps) { sourceMapsDisabled = true; } } } - function emitSourceMapsAfterNode(node: ts.Node) { - const emitFlags = ts.getEmitFlags(node); - const sourceMapRange = ts.getSourceMapRange(node); + function emitSourceMapsAfterNode(node: Node) { + const emitFlags = getEmitFlags(node); + const sourceMapRange = getSourceMapRange(node); // Emit trailing sourcemap - if (!ts.isUnparsedNode(node)) { - if (emitFlags & ts.EmitFlags.NoNestedSourceMaps) { + if (!isUnparsedNode(node)) { + if (emitFlags & EmitFlags.NoNestedSourceMaps) { sourceMapsDisabled = false; } - if (node.kind !== ts.SyntaxKind.NotEmittedStatement - && (emitFlags & ts.EmitFlags.NoTrailingSourceMap) === 0 + if (node.kind !== SyntaxKind.NotEmittedStatement + && (emitFlags & EmitFlags.NoTrailingSourceMap) === 0 && sourceMapRange.end >= 0) { emitSourcePos(sourceMapRange.source || sourceMapSource, sourceMapRange.end); } @@ -5892,8 +5972,8 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /** * Skips trivia such as comments and white-space that can be optionally overridden by the source-map source */ - function skipSourceTrivia(source: ts.SourceMapSource, pos: number): number { - return source.skipTrivia ? source.skipTrivia(pos) : ts.skipTrivia(source.text, pos); + function skipSourceTrivia(source: SourceMapSource, pos: number): number { + return source.skipTrivia ? source.skipTrivia(pos) : skipTrivia(source.text, pos); } /** @@ -5905,11 +5985,11 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * @param pos The position. */ function emitPos(pos: number) { - if (sourceMapsDisabled || ts.positionIsSynthesized(pos) || isJsonSourceMapSource(sourceMapSource)) { + if (sourceMapsDisabled || positionIsSynthesized(pos) || isJsonSourceMapSource(sourceMapSource)) { return; } - const { line: sourceLine, character: sourceCharacter } = ts.getLineAndCharacterOfPosition(sourceMapSource, pos); + const { line: sourceLine, character: sourceCharacter } = getLineAndCharacterOfPosition(sourceMapSource, pos); sourceMapGenerator!.addMapping( writer.getLine(), writer.getColumn(), @@ -5919,7 +5999,7 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: /*nameIndex*/ undefined); } - function emitSourcePos(source: ts.SourceMapSource, pos: number) { + function emitSourcePos(source: SourceMapSource, pos: number) { if (source !== sourceMapSource) { const savedSourceMapSource = sourceMapSource; const savedSourceMapSourceIndex = sourceMapSourceIndex; @@ -5940,32 +6020,32 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: * @param tokenStartPos The start pos of the token. * @param emitCallback The callback used to emit the token. */ - function emitTokenWithSourceMap(node: ts.Node | undefined, token: ts.SyntaxKind, writer: (s: string) => void, tokenPos: number, emitCallback: (token: ts.SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number) { - if (sourceMapsDisabled || node && ts.isInJsonFile(node)) { + function emitTokenWithSourceMap(node: Node | undefined, token: SyntaxKind, writer: (s: string) => void, tokenPos: number, emitCallback: (token: SyntaxKind, writer: (s: string) => void, tokenStartPos: number) => number) { + if (sourceMapsDisabled || node && isInJsonFile(node)) { return emitCallback(token, writer, tokenPos); } const emitNode = node && node.emitNode; - const emitFlags = emitNode && emitNode.flags || ts.EmitFlags.None; + const emitFlags = emitNode && emitNode.flags || EmitFlags.None; const range = emitNode && emitNode.tokenSourceMapRanges && emitNode.tokenSourceMapRanges[token]; const source = range && range.source || sourceMapSource; tokenPos = skipSourceTrivia(source, range ? range.pos : tokenPos); - if ((emitFlags & ts.EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags & EmitFlags.NoTokenLeadingSourceMaps) === 0 && tokenPos >= 0) { emitSourcePos(source, tokenPos); } tokenPos = emitCallback(token, writer, tokenPos); if (range) tokenPos = range.end; - if ((emitFlags & ts.EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { + if ((emitFlags & EmitFlags.NoTokenTrailingSourceMaps) === 0 && tokenPos >= 0) { emitSourcePos(source, tokenPos); } return tokenPos; } - function setSourceMapSource(source: ts.SourceMapSource) { + function setSourceMapSource(source: SourceMapSource) { if (sourceMapsDisabled) { return; } @@ -5992,31 +6072,31 @@ export function createPrinter(printerOptions: ts.PrinterOptions = {}, handlers: mostRecentlyAddedSourceMapSourceIndex = sourceMapSourceIndex; } - function resetSourceMapSource(source: ts.SourceMapSource, sourceIndex: number) { + function resetSourceMapSource(source: SourceMapSource, sourceIndex: number) { sourceMapSource = source; sourceMapSourceIndex = sourceIndex; } - function isJsonSourceMapSource(sourceFile: ts.SourceMapSource) { - return ts.fileExtensionIs(sourceFile.fileName, ts.Extension.Json); + function isJsonSourceMapSource(sourceFile: SourceMapSource) { + return fileExtensionIs(sourceFile.fileName, Extension.Json); } } function createBracketsMap() { const brackets: string[][] = []; - brackets[ts.ListFormat.Braces] = ["{", "}"]; - brackets[ts.ListFormat.Parenthesis] = ["(", ")"]; - brackets[ts.ListFormat.AngleBrackets] = ["<", ">"]; - brackets[ts.ListFormat.SquareBrackets] = ["[", "]"]; + brackets[ListFormat.Braces] = ["{", "}"]; + brackets[ListFormat.Parenthesis] = ["(", ")"]; + brackets[ListFormat.AngleBrackets] = ["<", ">"]; + brackets[ListFormat.SquareBrackets] = ["[", "]"]; return brackets; } -function getOpeningBracket(format: ts.ListFormat) { - return brackets[format & ts.ListFormat.BracketsMask][0]; +function getOpeningBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][0]; } -function getClosingBracket(format: ts.ListFormat) { - return brackets[format & ts.ListFormat.BracketsMask][1]; +function getClosingBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][1]; } // Flags enum to track count of temp variables and a few dedicated names @@ -6026,27 +6106,27 @@ const enum TempFlags { _i = 0x10000000, // Use/preference flag for '_i' } -interface OrdinalParentheizerRuleSelector { +interface OrdinalParentheizerRuleSelector { select(index: number): ((node: T) => T) | undefined; } -type ParenthesizerRule = (node: T) => T; +type ParenthesizerRule = (node: T) => T; -type ParenthesizerRuleOrSelector = OrdinalParentheizerRuleSelector | ParenthesizerRule; +type ParenthesizerRuleOrSelector = OrdinalParentheizerRuleSelector | ParenthesizerRule; -function emitListItemNoParenthesizer(node: ts.Node, emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, _parenthesizerRule: ParenthesizerRuleOrSelector | undefined, _index: number) { +function emitListItemNoParenthesizer(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, _parenthesizerRule: ParenthesizerRuleOrSelector | undefined, _index: number) { emit(node); } -function emitListItemWithParenthesizerRuleSelector(node: ts.Node, emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parenthesizerRuleSelector: OrdinalParentheizerRuleSelector, index: number) { +function emitListItemWithParenthesizerRuleSelector(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRuleSelector: OrdinalParentheizerRuleSelector, index: number) { emit(node, parenthesizerRuleSelector.select(index)); } -function emitListItemWithParenthesizerRule(node: ts.Node, emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parenthesizerRule: ParenthesizerRule | undefined, _index: number) { +function emitListItemWithParenthesizerRule(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: ParenthesizerRule | undefined, _index: number) { emit(node, parenthesizerRule); } -function getEmitListItem | undefined>(emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parenthesizerRule: R): (node: ts.Node, emit: (node: ts.Node, parenthesizerRule?: ((node: ts.Node) => ts.Node) | undefined) => void, parenthesizerRule: R, index: number) => void { +function getEmitListItem | undefined>(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R): (node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R, index: number) => void { return emit.length === 1 ? emitListItemNoParenthesizer : typeof parenthesizerRule === "object" ? emitListItemWithParenthesizerRuleSelector : emitListItemWithParenthesizerRule; diff --git a/src/compiler/factory/baseNodeFactory.ts b/src/compiler/factory/baseNodeFactory.ts index 5f7c3dd44c8a9..782cee7ea73b0 100644 --- a/src/compiler/factory/baseNodeFactory.ts +++ b/src/compiler/factory/baseNodeFactory.ts @@ -1,4 +1,4 @@ -import * as ts from "../_namespaces/ts"; +import { Node, objectAllocator, SyntaxKind } from "../_namespaces/ts"; /** * A `BaseNodeFactory` is an abstraction over an `ObjectAllocator` that handles caching `Node` constructors @@ -6,11 +6,11 @@ import * as ts from "../_namespaces/ts"; */ /* @internal */ export interface BaseNodeFactory { - createBaseSourceFileNode(kind: ts.SyntaxKind): ts.Node; - createBaseIdentifierNode(kind: ts.SyntaxKind): ts.Node; - createBasePrivateIdentifierNode(kind: ts.SyntaxKind): ts.Node; - createBaseTokenNode(kind: ts.SyntaxKind): ts.Node; - createBaseNode(kind: ts.SyntaxKind): ts.Node; + createBaseSourceFileNode(kind: SyntaxKind): Node; + createBaseIdentifierNode(kind: SyntaxKind): Node; + createBasePrivateIdentifierNode(kind: SyntaxKind): Node; + createBaseTokenNode(kind: SyntaxKind): Node; + createBaseNode(kind: SyntaxKind): Node; } /** @internal */ @@ -18,11 +18,11 @@ export interface BaseNodeFactory { * Creates a `BaseNodeFactory` which can be used to create `Node` instances from the constructors provided by the object allocator. */ export function createBaseNodeFactory(): BaseNodeFactory { - let NodeConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; - let TokenConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; - let IdentifierConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; - let PrivateIdentifierConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; - let SourceFileConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; + let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; return { createBaseSourceFileNode, @@ -32,23 +32,23 @@ export function createBaseNodeFactory(): BaseNodeFactory { createBaseNode }; - function createBaseSourceFileNode(kind: ts.SyntaxKind): ts.Node { - return new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + function createBaseSourceFileNode(kind: SyntaxKind): Node { + return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1); } - function createBaseIdentifierNode(kind: ts.SyntaxKind): ts.Node { - return new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + function createBaseIdentifierNode(kind: SyntaxKind): Node { + return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); } - function createBasePrivateIdentifierNode(kind: ts.SyntaxKind): ts.Node { - return new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = ts.objectAllocator.getPrivateIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + function createBasePrivateIdentifierNode(kind: SyntaxKind): Node { + return new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1); } - function createBaseTokenNode(kind: ts.SyntaxKind): ts.Node { - return new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + function createBaseTokenNode(kind: SyntaxKind): Node { + return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1); } - function createBaseNode(kind: ts.SyntaxKind): ts.Node { - return new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1); + function createBaseNode(kind: SyntaxKind): Node { + return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1); } } diff --git a/src/compiler/factory/emitHelpers.ts b/src/compiler/factory/emitHelpers.ts index b54c0209a99c9..6b05b1c72a7e6 100644 --- a/src/compiler/factory/emitHelpers.ts +++ b/src/compiler/factory/emitHelpers.ts @@ -1,48 +1,55 @@ -import * as ts from "../_namespaces/ts"; +import { + __String, ArrayLiteralExpression, arrayToMap, BindingOrAssignmentElement, Block, compareValues, Comparison, + createExpressionFromEntityName, Debug, EmitFlags, EmitHelper, EmitHelperUniqueNameCallback, EmitNode, EntityName, + Expression, FunctionExpression, GeneratedIdentifierFlags, getEmitFlags, getEmitScriptTarget, + getPropertyNameOfBindingOrAssignmentElement, Identifier, isCallExpression, isComputedPropertyName, isIdentifier, + memoize, PrivateIdentifierKind, ReadonlyESMap, ScriptTarget, setEmitFlags, setTextRange, SyntaxKind, TextRange, + TransformationContext, UnscopedEmitHelper, +} from "../_namespaces/ts"; /** @internal */ export interface EmitHelperFactory { - getUnscopedHelperName(name: string): ts.Identifier; + getUnscopedHelperName(name: string): Identifier; // TypeScript Helpers - createDecorateHelper(decoratorExpressions: readonly ts.Expression[], target: ts.Expression, memberName?: ts.Expression, descriptor?: ts.Expression): ts.Expression; - createMetadataHelper(metadataKey: string, metadataValue: ts.Expression): ts.Expression; - createParamHelper(expression: ts.Expression, parameterOffset: number): ts.Expression; + createDecorateHelper(decoratorExpressions: readonly Expression[], target: Expression, memberName?: Expression, descriptor?: Expression): Expression; + createMetadataHelper(metadataKey: string, metadataValue: Expression): Expression; + createParamHelper(expression: Expression, parameterOffset: number): Expression; // ES2018 Helpers - createAssignHelper(attributesSegments: readonly ts.Expression[]): ts.Expression; - createAwaitHelper(expression: ts.Expression): ts.Expression; - createAsyncGeneratorHelper(generatorFunc: ts.FunctionExpression, hasLexicalThis: boolean): ts.Expression; - createAsyncDelegatorHelper(expression: ts.Expression): ts.Expression; - createAsyncValuesHelper(expression: ts.Expression): ts.Expression; + createAssignHelper(attributesSegments: readonly Expression[]): Expression; + createAwaitHelper(expression: Expression): Expression; + createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean): Expression; + createAsyncDelegatorHelper(expression: Expression): Expression; + createAsyncValuesHelper(expression: Expression): Expression; // ES2018 Destructuring Helpers - createRestHelper(value: ts.Expression, elements: readonly ts.BindingOrAssignmentElement[], computedTempVariables: readonly ts.Expression[] | undefined, location: ts.TextRange): ts.Expression; + createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression; // ES2017 Helpers - createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: ts.EntityName | ts.Expression | undefined, body: ts.Block): ts.Expression; + createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block): Expression; // ES2015 Helpers - createExtendsHelper(name: ts.Identifier): ts.Expression; - createTemplateObjectHelper(cooked: ts.ArrayLiteralExpression, raw: ts.ArrayLiteralExpression): ts.Expression; - createSpreadArrayHelper(to: ts.Expression, from: ts.Expression, packFrom: boolean): ts.Expression; + createExtendsHelper(name: Identifier): Expression; + createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression): Expression; + createSpreadArrayHelper(to: Expression, from: Expression, packFrom: boolean): Expression; // ES2015 Destructuring Helpers - createValuesHelper(expression: ts.Expression): ts.Expression; - createReadHelper(iteratorRecord: ts.Expression, count: number | undefined): ts.Expression; + createValuesHelper(expression: Expression): Expression; + createReadHelper(iteratorRecord: Expression, count: number | undefined): Expression; // ES2015 Generator Helpers - createGeneratorHelper(body: ts.FunctionExpression): ts.Expression; + createGeneratorHelper(body: FunctionExpression): Expression; // ES Module Helpers - createCreateBindingHelper(module: ts.Expression, inputName: ts.Expression, outputName: ts.Expression | undefined): ts.Expression; - createImportStarHelper(expression: ts.Expression): ts.Expression; - createImportStarCallbackHelper(): ts.Expression; - createImportDefaultHelper(expression: ts.Expression): ts.Expression; - createExportStarHelper(moduleExpression: ts.Expression, exportsExpression?: ts.Expression): ts.Expression; + createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined): Expression; + createImportStarHelper(expression: Expression): Expression; + createImportStarCallbackHelper(): Expression; + createImportDefaultHelper(expression: Expression): Expression; + createExportStarHelper(moduleExpression: Expression, exportsExpression?: Expression): Expression; // Class Fields Helpers - createClassPrivateFieldGetHelper(receiver: ts.Expression, state: ts.Identifier, kind: ts.PrivateIdentifierKind, f: ts.Identifier | undefined): ts.Expression; - createClassPrivateFieldSetHelper(receiver: ts.Expression, state: ts.Identifier, value: ts.Expression, kind: ts.PrivateIdentifierKind, f: ts.Identifier | undefined): ts.Expression; - createClassPrivateFieldInHelper(state: ts.Identifier, receiver: ts.Expression): ts.Expression; + createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression; + createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined): Expression; + createClassPrivateFieldInHelper(state: Identifier, receiver: Expression): Expression; } /** @internal */ -export function createEmitHelperFactory(context: ts.TransformationContext): EmitHelperFactory { +export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory { const factory = context.factory; - const immutableTrue = ts.memoize(() => ts.setEmitFlags(factory.createTrue(), ts.EmitFlags.Immutable)); - const immutableFalse = ts.memoize(() => ts.setEmitFlags(factory.createFalse(), ts.EmitFlags.Immutable)); + const immutableTrue = memoize(() => setEmitFlags(factory.createTrue(), EmitFlags.Immutable)); + const immutableFalse = memoize(() => setEmitFlags(factory.createFalse(), EmitFlags.Immutable)); return { getUnscopedHelperName, @@ -85,15 +92,15 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit * Gets an identifier for the name of an *unscoped* emit helper. */ function getUnscopedHelperName(name: string) { - return ts.setEmitFlags(factory.createIdentifier(name), ts.EmitFlags.HelperName | ts.EmitFlags.AdviseOnEmitNode); + return setEmitFlags(factory.createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode); } // TypeScript Helpers - function createDecorateHelper(decoratorExpressions: ts.Expression[], target: ts.Expression, memberName?: ts.Expression, descriptor?: ts.Expression) { + function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) { context.requestEmitHelper(decorateHelper); - const argumentsArray: ts.Expression[] = []; + const argumentsArray: Expression[] = []; argumentsArray.push(factory.createArrayLiteralExpression(decoratorExpressions, /*multiLine*/ true)); argumentsArray.push(target); if (memberName) { @@ -110,7 +117,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createMetadataHelper(metadataKey: string, metadataValue: ts.Expression) { + function createMetadataHelper(metadataKey: string, metadataValue: Expression) { context.requestEmitHelper(metadataHelper); return factory.createCallExpression( getUnscopedHelperName("__metadata"), @@ -122,9 +129,9 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createParamHelper(expression: ts.Expression, parameterOffset: number, location?: ts.TextRange) { + function createParamHelper(expression: Expression, parameterOffset: number, location?: TextRange) { context.requestEmitHelper(paramHelper); - return ts.setTextRange( + return setTextRange( factory.createCallExpression( getUnscopedHelperName("__param"), /*typeArguments*/ undefined, @@ -139,8 +146,8 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES2018 Helpers - function createAssignHelper(attributesSegments: ts.Expression[]) { - if (ts.getEmitScriptTarget(context.getCompilerOptions()) >= ts.ScriptTarget.ES2015) { + function createAssignHelper(attributesSegments: Expression[]) { + if (getEmitScriptTarget(context.getCompilerOptions()) >= ScriptTarget.ES2015) { return factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, attributesSegments); @@ -153,17 +160,17 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createAwaitHelper(expression: ts.Expression) { + function createAwaitHelper(expression: Expression) { context.requestEmitHelper(awaitHelper); return factory.createCallExpression(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]); } - function createAsyncGeneratorHelper(generatorFunc: ts.FunctionExpression, hasLexicalThis: boolean) { + function createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncGeneratorHelper); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as ts.EmitNode)).flags |= ts.EmitFlags.AsyncFunctionBody | ts.EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return factory.createCallExpression( getUnscopedHelperName("__asyncGenerator"), @@ -176,7 +183,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createAsyncDelegatorHelper(expression: ts.Expression) { + function createAsyncDelegatorHelper(expression: Expression) { context.requestEmitHelper(awaitHelper); context.requestEmitHelper(asyncDelegator); return factory.createCallExpression( @@ -186,7 +193,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createAsyncValuesHelper(expression: ts.Expression) { + function createAsyncValuesHelper(expression: Expression) { context.requestEmitHelper(asyncValues); return factory.createCallExpression( getUnscopedHelperName("__asyncValues"), @@ -200,15 +207,15 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit /** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement * `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);` */ - function createRestHelper(value: ts.Expression, elements: readonly ts.BindingOrAssignmentElement[], computedTempVariables: readonly ts.Expression[] | undefined, location: ts.TextRange): ts.Expression { + function createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression { context.requestEmitHelper(restHelper); - const propertyNames: ts.Expression[] = []; + const propertyNames: Expression[] = []; let computedTempVariableOffset = 0; for (let i = 0; i < elements.length - 1; i++) { - const propertyName = ts.getPropertyNameOfBindingOrAssignmentElement(elements[i]); + const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]); if (propertyName) { - if (ts.isComputedPropertyName(propertyName)) { - ts.Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided."); + if (isComputedPropertyName(propertyName)) { + Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided."); const temp = computedTempVariables[computedTempVariableOffset]; computedTempVariableOffset++; // typeof _tmp === "symbol" ? _tmp : _tmp + "" @@ -232,7 +239,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit /*typeArguments*/ undefined, [ value, - ts.setTextRange( + setTextRange( factory.createArrayLiteralExpression(propertyNames), location )] @@ -241,12 +248,12 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES2017 Helpers - function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: ts.EntityName | ts.Expression | undefined, body: ts.Block) { + function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) { context.requestEmitHelper(awaiterHelper); const generatorFunc = factory.createFunctionExpression( /*modifiers*/ undefined, - factory.createToken(ts.SyntaxKind.AsteriskToken), + factory.createToken(SyntaxKind.AsteriskToken), /*name*/ undefined, /*typeParameters*/ undefined, /*parameters*/ [], @@ -255,7 +262,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); // Mark this node as originally an async function - (generatorFunc.emitNode || (generatorFunc.emitNode = {} as ts.EmitNode)).flags |= ts.EmitFlags.AsyncFunctionBody | ts.EmitFlags.ReuseTempVariableScope; + (generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope; return factory.createCallExpression( getUnscopedHelperName("__awaiter"), @@ -263,7 +270,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit [ hasLexicalThis ? factory.createThis() : factory.createVoidZero(), hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZero(), - promiseConstructor ? ts.createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(), + promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(), generatorFunc ] ); @@ -271,16 +278,16 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES2015 Helpers - function createExtendsHelper(name: ts.Identifier) { + function createExtendsHelper(name: Identifier) { context.requestEmitHelper(extendsHelper); return factory.createCallExpression( getUnscopedHelperName("__extends"), /*typeArguments*/ undefined, - [name, factory.createUniqueName("_super", ts.GeneratedIdentifierFlags.Optimistic | ts.GeneratedIdentifierFlags.FileLevel)] + [name, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)] ); } - function createTemplateObjectHelper(cooked: ts.ArrayLiteralExpression, raw: ts.ArrayLiteralExpression) { + function createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) { context.requestEmitHelper(templateObjectHelper); return factory.createCallExpression( getUnscopedHelperName("__makeTemplateObject"), @@ -289,7 +296,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createSpreadArrayHelper(to: ts.Expression, from: ts.Expression, packFrom: boolean) { + function createSpreadArrayHelper(to: Expression, from: Expression, packFrom: boolean) { context.requestEmitHelper(spreadArrayHelper); return factory.createCallExpression( getUnscopedHelperName("__spreadArray"), @@ -300,7 +307,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES2015 Destructuring Helpers - function createValuesHelper(expression: ts.Expression) { + function createValuesHelper(expression: Expression) { context.requestEmitHelper(valuesHelper); return factory.createCallExpression( getUnscopedHelperName("__values"), @@ -309,7 +316,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createReadHelper(iteratorRecord: ts.Expression, count: number | undefined) { + function createReadHelper(iteratorRecord: Expression, count: number | undefined) { context.requestEmitHelper(readHelper); return factory.createCallExpression( getUnscopedHelperName("__read"), @@ -322,7 +329,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES2015 Generator Helpers - function createGeneratorHelper(body: ts.FunctionExpression) { + function createGeneratorHelper(body: FunctionExpression) { context.requestEmitHelper(generatorHelper); return factory.createCallExpression( getUnscopedHelperName("__generator"), @@ -332,7 +339,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // ES Module Helpers - function createCreateBindingHelper(module: ts.Expression, inputName: ts.Expression, outputName: ts.Expression | undefined) { + function createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined) { context.requestEmitHelper(createBindingHelper); return factory.createCallExpression( getUnscopedHelperName("__createBinding"), @@ -340,7 +347,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit [factory.createIdentifier("exports"), module, inputName, ...(outputName ? [outputName] : [])]); } - function createImportStarHelper(expression: ts.Expression) { + function createImportStarHelper(expression: Expression) { context.requestEmitHelper(importStarHelper); return factory.createCallExpression( getUnscopedHelperName("__importStar"), @@ -354,7 +361,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit return getUnscopedHelperName("__importStar"); } - function createImportDefaultHelper(expression: ts.Expression) { + function createImportDefaultHelper(expression: Expression) { context.requestEmitHelper(importDefaultHelper); return factory.createCallExpression( getUnscopedHelperName("__importDefault"), @@ -363,7 +370,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit ); } - function createExportStarHelper(moduleExpression: ts.Expression, exportsExpression: ts.Expression = factory.createIdentifier("exports")) { + function createExportStarHelper(moduleExpression: Expression, exportsExpression: Expression = factory.createIdentifier("exports")) { context.requestEmitHelper(exportStarHelper); context.requestEmitHelper(createBindingHelper); return factory.createCallExpression( @@ -375,7 +382,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit // Class Fields Helpers - function createClassPrivateFieldGetHelper(receiver: ts.Expression, state: ts.Identifier, kind: ts.PrivateIdentifierKind, f: ts.Identifier | undefined) { + function createClassPrivateFieldGetHelper(receiver: Expression, state: Identifier, kind: PrivateIdentifierKind, f: Identifier | undefined) { context.requestEmitHelper(classPrivateFieldGetHelper); let args; if (!f) { @@ -387,7 +394,7 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldGet"), /*typeArguments*/ undefined, args); } - function createClassPrivateFieldSetHelper(receiver: ts.Expression, state: ts.Identifier, value: ts.Expression, kind: ts.PrivateIdentifierKind, f: ts.Identifier | undefined) { + function createClassPrivateFieldSetHelper(receiver: Expression, state: Identifier, value: Expression, kind: PrivateIdentifierKind, f: Identifier | undefined) { context.requestEmitHelper(classPrivateFieldSetHelper); let args; if (!f) { @@ -399,19 +406,19 @@ export function createEmitHelperFactory(context: ts.TransformationContext): Emit return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldSet"), /*typeArguments*/ undefined, args); } - function createClassPrivateFieldInHelper(state: ts.Identifier, receiver: ts.Expression) { + function createClassPrivateFieldInHelper(state: Identifier, receiver: Expression) { context.requestEmitHelper(classPrivateFieldInHelper); return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldIn"), /* typeArguments*/ undefined, [state, receiver]); } } /* @internal */ -export function compareEmitHelpers(x: ts.EmitHelper, y: ts.EmitHelper) { - if (x === y) return ts.Comparison.EqualTo; - if (x.priority === y.priority) return ts.Comparison.EqualTo; - if (x.priority === undefined) return ts.Comparison.GreaterThan; - if (y.priority === undefined) return ts.Comparison.LessThan; - return ts.compareValues(x.priority, y.priority); +export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { + if (x === y) return Comparison.EqualTo; + if (x.priority === y.priority) return Comparison.EqualTo; + if (x.priority === undefined) return Comparison.GreaterThan; + if (y.priority === undefined) return Comparison.LessThan; + return compareValues(x.priority, y.priority); } /** @internal */ @@ -420,7 +427,7 @@ export function compareEmitHelpers(x: ts.EmitHelper, y: ts.EmitHelper) { * @param args Names which need to be made file-level unique */ export function helperString(input: TemplateStringsArray, ...args: string[]) { - return (uniqueName: ts.EmitHelperUniqueNameCallback) => { + return (uniqueName: EmitHelperUniqueNameCallback) => { let result = ""; for (let i = 0; i < args.length; i++) { result += input[i]; @@ -434,7 +441,7 @@ export function helperString(input: TemplateStringsArray, ...args: string[]) { // TypeScript Helpers /** @internal */ -export const decorateHelper: ts.UnscopedEmitHelper = { +export const decorateHelper: UnscopedEmitHelper = { name: "typescript:decorate", importName: "__decorate", scoped: false, @@ -449,7 +456,7 @@ export const decorateHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const metadataHelper: ts.UnscopedEmitHelper = { +export const metadataHelper: UnscopedEmitHelper = { name: "typescript:metadata", importName: "__metadata", scoped: false, @@ -461,7 +468,7 @@ export const metadataHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const paramHelper: ts.UnscopedEmitHelper = { +export const paramHelper: UnscopedEmitHelper = { name: "typescript:param", importName: "__param", scoped: false, @@ -475,7 +482,7 @@ export const paramHelper: ts.UnscopedEmitHelper = { // ES2018 Helpers /** @internal */ -export const assignHelper: ts.UnscopedEmitHelper = { +export const assignHelper: UnscopedEmitHelper = { name: "typescript:assign", importName: "__assign", scoped: false, @@ -495,7 +502,7 @@ export const assignHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const awaitHelper: ts.UnscopedEmitHelper = { +export const awaitHelper: UnscopedEmitHelper = { name: "typescript:await", importName: "__await", scoped: false, @@ -504,7 +511,7 @@ export const awaitHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const asyncGeneratorHelper: ts.UnscopedEmitHelper = { +export const asyncGeneratorHelper: UnscopedEmitHelper = { name: "typescript:asyncGenerator", importName: "__asyncGenerator", scoped: false, @@ -524,7 +531,7 @@ export const asyncGeneratorHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const asyncDelegator: ts.UnscopedEmitHelper = { +export const asyncDelegator: UnscopedEmitHelper = { name: "typescript:asyncDelegator", importName: "__asyncDelegator", scoped: false, @@ -538,7 +545,7 @@ export const asyncDelegator: ts.UnscopedEmitHelper = { }; /** @internal */ -export const asyncValues: ts.UnscopedEmitHelper = { +export const asyncValues: UnscopedEmitHelper = { name: "typescript:asyncValues", importName: "__asyncValues", scoped: false, @@ -555,7 +562,7 @@ export const asyncValues: ts.UnscopedEmitHelper = { // ES2018 Destructuring Helpers /** @internal */ -export const restHelper: ts.UnscopedEmitHelper = { +export const restHelper: UnscopedEmitHelper = { name: "typescript:rest", importName: "__rest", scoped: false, @@ -576,7 +583,7 @@ export const restHelper: ts.UnscopedEmitHelper = { // ES2017 Helpers /** @internal */ -export const awaiterHelper: ts.UnscopedEmitHelper = { +export const awaiterHelper: UnscopedEmitHelper = { name: "typescript:awaiter", importName: "__awaiter", scoped: false, @@ -596,7 +603,7 @@ export const awaiterHelper: ts.UnscopedEmitHelper = { // ES2015 Helpers /** @internal */ -export const extendsHelper: ts.UnscopedEmitHelper = { +export const extendsHelper: UnscopedEmitHelper = { name: "typescript:extends", importName: "__extends", scoped: false, @@ -621,7 +628,7 @@ export const extendsHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const templateObjectHelper: ts.UnscopedEmitHelper = { +export const templateObjectHelper: UnscopedEmitHelper = { name: "typescript:makeTemplateObject", importName: "__makeTemplateObject", scoped: false, @@ -634,7 +641,7 @@ export const templateObjectHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const readHelper: ts.UnscopedEmitHelper = { +export const readHelper: UnscopedEmitHelper = { name: "typescript:read", importName: "__read", scoped: false, @@ -658,7 +665,7 @@ export const readHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const spreadArrayHelper: ts.UnscopedEmitHelper = { +export const spreadArrayHelper: UnscopedEmitHelper = { name: "typescript:spreadArray", importName: "__spreadArray", scoped: false, @@ -677,7 +684,7 @@ export const spreadArrayHelper: ts.UnscopedEmitHelper = { // ES2015 Destructuring Helpers /** @internal */ -export const valuesHelper: ts.UnscopedEmitHelper = { +export const valuesHelper: UnscopedEmitHelper = { name: "typescript:values", importName: "__values", scoped: false, @@ -759,7 +766,7 @@ export const valuesHelper: ts.UnscopedEmitHelper = { // // For examples of how these are used, see the comments in ./transformers/generators.ts /** @internal */ -export const generatorHelper: ts.UnscopedEmitHelper = { +export const generatorHelper: UnscopedEmitHelper = { name: "typescript:generator", importName: "__generator", scoped: false, @@ -797,7 +804,7 @@ export const generatorHelper: ts.UnscopedEmitHelper = { // ES Module Helpers /** @internal */ -export const createBindingHelper: ts.UnscopedEmitHelper = { +export const createBindingHelper: UnscopedEmitHelper = { name: "typescript:commonjscreatebinding", importName: "__createBinding", scoped: false, @@ -817,7 +824,7 @@ export const createBindingHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const setModuleDefaultHelper: ts.UnscopedEmitHelper = { +export const setModuleDefaultHelper: UnscopedEmitHelper = { name: "typescript:commonjscreatevalue", importName: "__setModuleDefault", scoped: false, @@ -832,7 +839,7 @@ export const setModuleDefaultHelper: ts.UnscopedEmitHelper = { // emit helper for `import * as Name from "foo"` /** @internal */ -export const importStarHelper: ts.UnscopedEmitHelper = { +export const importStarHelper: UnscopedEmitHelper = { name: "typescript:commonjsimportstar", importName: "__importStar", scoped: false, @@ -850,7 +857,7 @@ export const importStarHelper: ts.UnscopedEmitHelper = { // emit helper for `import Name from "foo"` /** @internal */ -export const importDefaultHelper: ts.UnscopedEmitHelper = { +export const importDefaultHelper: UnscopedEmitHelper = { name: "typescript:commonjsimportdefault", importName: "__importDefault", scoped: false, @@ -861,7 +868,7 @@ export const importDefaultHelper: ts.UnscopedEmitHelper = { }; /** @internal */ -export const exportStarHelper: ts.UnscopedEmitHelper = { +export const exportStarHelper: UnscopedEmitHelper = { name: "typescript:export-star", importName: "__exportStar", scoped: false, @@ -922,7 +929,7 @@ export const exportStarHelper: ts.UnscopedEmitHelper = { * Reading from a private static method (TS 4.3+): * __classPrivateFieldGet(, , "m", ) */ -export const classPrivateFieldGetHelper: ts.UnscopedEmitHelper = { +export const classPrivateFieldGetHelper: UnscopedEmitHelper = { name: "typescript:classPrivateFieldGet", importName: "__classPrivateFieldGet", scoped: false, @@ -986,7 +993,7 @@ export const classPrivateFieldGetHelper: ts.UnscopedEmitHelper = { * __classPrivateFieldSet(, , , "m", ) * NOTE: This always results in a runtime error. */ -export const classPrivateFieldSetHelper: ts.UnscopedEmitHelper = { +export const classPrivateFieldSetHelper: UnscopedEmitHelper = { name: "typescript:classPrivateFieldSet", importName: "__classPrivateFieldSet", scoped: false, @@ -1012,7 +1019,7 @@ export const classPrivateFieldSetHelper: ts.UnscopedEmitHelper = { * This helper is used to transform `#field in expression` to * `__classPrivateFieldIn(, expression)` */ -export const classPrivateFieldInHelper: ts.UnscopedEmitHelper = { +export const classPrivateFieldInHelper: UnscopedEmitHelper = { name: "typescript:classPrivateFieldIn", importName: "__classPrivateFieldIn", scoped: false, @@ -1023,11 +1030,11 @@ export const classPrivateFieldInHelper: ts.UnscopedEmitHelper = { };` }; -let allUnscopedEmitHelpers: ts.ReadonlyESMap | undefined; +let allUnscopedEmitHelpers: ReadonlyESMap | undefined; /** @internal */ export function getAllUnscopedEmitHelpers() { - return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = ts.arrayToMap([ + return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([ decorateHelper, metadataHelper, paramHelper, @@ -1056,7 +1063,7 @@ export function getAllUnscopedEmitHelpers() { } /** @internal */ -export const asyncSuperHelper: ts.EmitHelper = { +export const asyncSuperHelper: EmitHelper = { name: "typescript:async-super", scoped: true, text: helperString` @@ -1064,7 +1071,7 @@ export const asyncSuperHelper: ts.EmitHelper = { }; /** @internal */ -export const advancedAsyncSuperHelper: ts.EmitHelper = { +export const advancedAsyncSuperHelper: EmitHelper = { name: "typescript:advanced-async-super", scoped: true, text: helperString` @@ -1075,9 +1082,9 @@ export const advancedAsyncSuperHelper: ts.EmitHelper = { }; /** @internal */ -export function isCallToHelper(firstSegment: ts.Expression, helperName: ts.__String): boolean { - return ts.isCallExpression(firstSegment) - && ts.isIdentifier(firstSegment.expression) - && (ts.getEmitFlags(firstSegment.expression) & ts.EmitFlags.HelperName) !== 0 +export function isCallToHelper(firstSegment: Expression, helperName: __String): boolean { + return isCallExpression(firstSegment) + && isIdentifier(firstSegment.expression) + && (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName) !== 0 && firstSegment.expression.escapedText === helperName; } diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts index 2d34aa065be8f..44717059b4ada 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -1,28 +1,32 @@ -import * as ts from "../_namespaces/ts"; +import { + AccessExpression, append, appendIfUnique, Debug, EmitFlags, EmitHelper, EmitNode, getParseTreeNode, + getSourceFileOfNode, isParseTreeNode, Node, orderedRemoveItem, SnippetElement, some, SourceFile, SourceMapRange, + SyntaxKind, SynthesizedComment, TextRange, TypeNode, +} from "../_namespaces/ts"; /** * Associates a node with the current transformation, initializing * various transient transformation properties. * @internal */ -export function getOrCreateEmitNode(node: ts.Node): ts.EmitNode { +export function getOrCreateEmitNode(node: Node): EmitNode { if (!node.emitNode) { - if (ts.isParseTreeNode(node)) { + if (isParseTreeNode(node)) { // To avoid holding onto transformation artifacts, we keep track of any // parse tree node we are annotating. This allows us to clean them up after // all transformations have completed. - if (node.kind === ts.SyntaxKind.SourceFile) { - return node.emitNode = { annotatedNodes: [node] } as ts.EmitNode; + if (node.kind === SyntaxKind.SourceFile) { + return node.emitNode = { annotatedNodes: [node] } as EmitNode; } - const sourceFile = ts.getSourceFileOfNode(ts.getParseTreeNode(ts.getSourceFileOfNode(node))) ?? ts.Debug.fail("Could not determine parsed source file."); + const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) ?? Debug.fail("Could not determine parsed source file."); getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node); } - node.emitNode = {} as ts.EmitNode; + node.emitNode = {} as EmitNode; } else { - ts.Debug.assert(!(node.emitNode.flags & ts.EmitFlags.Immutable), "Invalid attempt to mutate an immutable node."); + Debug.assert(!(node.emitNode.flags & EmitFlags.Immutable), "Invalid attempt to mutate an immutable node."); } return node.emitNode; } @@ -31,14 +35,14 @@ export function getOrCreateEmitNode(node: ts.Node): ts.EmitNode { * Clears any `EmitNode` entries from parse-tree nodes. * @param sourceFile A source file. */ -export function disposeEmitNodes(sourceFile: ts.SourceFile | undefined) { +export function disposeEmitNodes(sourceFile: SourceFile | undefined) { // During transformation we may need to annotate a parse tree node with transient // transformation properties. As parse tree nodes live longer than transformation // nodes, we need to make sure we reclaim any memory allocated for custom ranges // from these nodes to ensure we do not hold onto entire subtrees just for position // information. We also need to reset these nodes to a pre-transformation state // for incremental parsing scenarios so that we do not impact later emit. - const annotatedNodes = ts.getSourceFileOfNode(ts.getParseTreeNode(sourceFile))?.emitNode?.annotatedNodes; + const annotatedNodes = getSourceFileOfNode(getParseTreeNode(sourceFile))?.emitNode?.annotatedNodes; if (annotatedNodes) { for (const node of annotatedNodes) { node.emitNode = undefined; @@ -50,9 +54,9 @@ export function disposeEmitNodes(sourceFile: ts.SourceFile | undefined) { * Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments. * @internal */ -export function removeAllComments(node: T): T { +export function removeAllComments(node: T): T { const emitNode = getOrCreateEmitNode(node); - emitNode.flags |= ts.EmitFlags.NoComments; + emitNode.flags |= EmitFlags.NoComments; emitNode.leadingComments = undefined; emitNode.trailingComments = undefined; return node; @@ -61,7 +65,7 @@ export function removeAllComments(node: T): T { /** * Sets flags that control emit behavior of a node. */ -export function setEmitFlags(node: T, emitFlags: ts.EmitFlags) { +export function setEmitFlags(node: T, emitFlags: EmitFlags) { getOrCreateEmitNode(node).flags = emitFlags; return node; } @@ -70,7 +74,7 @@ export function setEmitFlags(node: T, emitFlags: ts.EmitFlags * Sets flags that control emit behavior of a node. */ /* @internal */ -export function addEmitFlags(node: T, emitFlags: ts.EmitFlags) { +export function addEmitFlags(node: T, emitFlags: EmitFlags) { const emitNode = getOrCreateEmitNode(node); emitNode.flags = emitNode.flags | emitFlags; return node; @@ -79,14 +83,14 @@ export function addEmitFlags(node: T, emitFlags: ts.EmitFlags /** * Gets a custom text range to use when emitting source maps. */ -export function getSourceMapRange(node: ts.Node): ts.SourceMapRange { +export function getSourceMapRange(node: Node): SourceMapRange { return node.emitNode?.sourceMapRange ?? node; } /** * Sets a custom text range to use when emitting source maps. */ -export function setSourceMapRange(node: T, range: ts.SourceMapRange | undefined) { +export function setSourceMapRange(node: T, range: SourceMapRange | undefined) { getOrCreateEmitNode(node).sourceMapRange = range; return node; } @@ -94,14 +98,14 @@ export function setSourceMapRange(node: T, range: ts.SourceMa /** * Gets the TextRange to use for source maps for a token of a node. */ -export function getTokenSourceMapRange(node: ts.Node, token: ts.SyntaxKind): ts.SourceMapRange | undefined { +export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined { return node.emitNode?.tokenSourceMapRanges?.[token]; } /** * Sets the TextRange to use for source maps for a token of a node. */ -export function setTokenSourceMapRange(node: T, token: ts.SyntaxKind, range: ts.SourceMapRange | undefined) { +export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: SourceMapRange | undefined) { const emitNode = getOrCreateEmitNode(node); const tokenSourceMapRanges = emitNode.tokenSourceMapRanges ?? (emitNode.tokenSourceMapRanges = []); tokenSourceMapRanges[token] = range; @@ -112,7 +116,7 @@ export function setTokenSourceMapRange(node: T, token: ts.Syn * Gets a custom text range to use when emitting comments. */ /*@internal*/ -export function getStartsOnNewLine(node: ts.Node) { +export function getStartsOnNewLine(node: Node) { return node.emitNode?.startsOnNewLine; } @@ -120,7 +124,7 @@ export function getStartsOnNewLine(node: ts.Node) { * Sets a custom text range to use when emitting comments. */ /*@internal*/ -export function setStartsOnNewLine(node: T, newLine: boolean) { +export function setStartsOnNewLine(node: T, newLine: boolean) { getOrCreateEmitNode(node).startsOnNewLine = newLine; return node; } @@ -128,45 +132,45 @@ export function setStartsOnNewLine(node: T, newLine: boolean) /** * Gets a custom text range to use when emitting comments. */ -export function getCommentRange(node: ts.Node): ts.TextRange { +export function getCommentRange(node: Node): TextRange { return node.emitNode?.commentRange ?? node; } /** * Sets a custom text range to use when emitting comments. */ -export function setCommentRange(node: T, range: ts.TextRange) { +export function setCommentRange(node: T, range: TextRange) { getOrCreateEmitNode(node).commentRange = range; return node; } -export function getSyntheticLeadingComments(node: ts.Node): ts.SynthesizedComment[] | undefined { +export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined { return node.emitNode?.leadingComments; } -export function setSyntheticLeadingComments(node: T, comments: ts.SynthesizedComment[] | undefined) { +export function setSyntheticLeadingComments(node: T, comments: SynthesizedComment[] | undefined) { getOrCreateEmitNode(node).leadingComments = comments; return node; } -export function addSyntheticLeadingComment(node: T, kind: ts.SyntaxKind.SingleLineCommentTrivia | ts.SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticLeadingComments(node, ts.append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); +export function addSyntheticLeadingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); } -export function getSyntheticTrailingComments(node: ts.Node): ts.SynthesizedComment[] | undefined { +export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined { return node.emitNode?.trailingComments; } -export function setSyntheticTrailingComments(node: T, comments: ts.SynthesizedComment[] | undefined) { +export function setSyntheticTrailingComments(node: T, comments: SynthesizedComment[] | undefined) { getOrCreateEmitNode(node).trailingComments = comments; return node; } -export function addSyntheticTrailingComment(node: T, kind: ts.SyntaxKind.SingleLineCommentTrivia | ts.SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { - return setSyntheticTrailingComments(node, ts.append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); +export function addSyntheticTrailingComment(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) { + return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text })); } -export function moveSyntheticComments(node: T, original: ts.Node): T { +export function moveSyntheticComments(node: T, original: Node): T { setSyntheticLeadingComments(node, getSyntheticLeadingComments(original)); setSyntheticTrailingComments(node, getSyntheticTrailingComments(original)); const emit = getOrCreateEmitNode(original); @@ -178,14 +182,14 @@ export function moveSyntheticComments(node: T, original: ts.N /** * Gets the constant value to emit for an expression representing an enum. */ -export function getConstantValue(node: ts.AccessExpression): string | number | undefined { +export function getConstantValue(node: AccessExpression): string | number | undefined { return node.emitNode?.constantValue; } /** * Sets the constant value to emit for an expression. */ -export function setConstantValue(node: ts.AccessExpression, value: string | number): ts.AccessExpression { +export function setConstantValue(node: AccessExpression, value: string | number): AccessExpression { const emitNode = getOrCreateEmitNode(node); emitNode.constantValue = value; return node; @@ -194,20 +198,20 @@ export function setConstantValue(node: ts.AccessExpression, value: string | numb /** * Adds an EmitHelper to a node. */ -export function addEmitHelper(node: T, helper: ts.EmitHelper): T { +export function addEmitHelper(node: T, helper: EmitHelper): T { const emitNode = getOrCreateEmitNode(node); - emitNode.helpers = ts.append(emitNode.helpers, helper); + emitNode.helpers = append(emitNode.helpers, helper); return node; } /** * Add EmitHelpers to a node. */ -export function addEmitHelpers(node: T, helpers: ts.EmitHelper[] | undefined): T { - if (ts.some(helpers)) { +export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { + if (some(helpers)) { const emitNode = getOrCreateEmitNode(node); for (const helper of helpers) { - emitNode.helpers = ts.appendIfUnique(emitNode.helpers, helper); + emitNode.helpers = appendIfUnique(emitNode.helpers, helper); } } return node; @@ -216,10 +220,10 @@ export function addEmitHelpers(node: T, helpers: ts.EmitHelpe /** * Removes an EmitHelper from a node. */ -export function removeEmitHelper(node: ts.Node, helper: ts.EmitHelper): boolean { +export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { const helpers = node.emitNode?.helpers; if (helpers) { - return ts.orderedRemoveItem(helpers, helper); + return orderedRemoveItem(helpers, helper); } return false; } @@ -227,17 +231,17 @@ export function removeEmitHelper(node: ts.Node, helper: ts.EmitHelper): boolean /** * Gets the EmitHelpers of a node. */ -export function getEmitHelpers(node: ts.Node): ts.EmitHelper[] | undefined { +export function getEmitHelpers(node: Node): EmitHelper[] | undefined { return node.emitNode?.helpers; } /** * Moves matching emit helpers from a source node to a target node. */ -export function moveEmitHelpers(source: ts.Node, target: ts.Node, predicate: (helper: ts.EmitHelper) => boolean) { +export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { const sourceEmitNode = source.emitNode; const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; - if (!ts.some(sourceEmitHelpers)) return; + if (!some(sourceEmitHelpers)) return; const targetEmitNode = getOrCreateEmitNode(target); let helpersRemoved = 0; @@ -245,7 +249,7 @@ export function moveEmitHelpers(source: ts.Node, target: ts.Node, predicate: (he const helper = sourceEmitHelpers[i]; if (predicate(helper)) { helpersRemoved++; - targetEmitNode.helpers = ts.appendIfUnique(targetEmitNode.helpers, helper); + targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper); } else if (helpersRemoved > 0) { sourceEmitHelpers[i - helpersRemoved] = helper; @@ -261,7 +265,7 @@ export function moveEmitHelpers(source: ts.Node, target: ts.Node, predicate: (he * Gets the SnippetElement of a node. */ /* @internal */ -export function getSnippetElement(node: ts.Node): ts.SnippetElement | undefined { +export function getSnippetElement(node: Node): SnippetElement | undefined { return node.emitNode?.snippetElement; } @@ -269,26 +273,26 @@ export function getSnippetElement(node: ts.Node): ts.SnippetElement | undefined * Sets the SnippetElement of a node. */ /* @internal */ -export function setSnippetElement(node: T, snippet: ts.SnippetElement): T { +export function setSnippetElement(node: T, snippet: SnippetElement): T { const emitNode = getOrCreateEmitNode(node); emitNode.snippetElement = snippet; return node; } /* @internal */ -export function ignoreSourceNewlines(node: T): T { - getOrCreateEmitNode(node).flags |= ts.EmitFlags.IgnoreSourceNewlines; +export function ignoreSourceNewlines(node: T): T { + getOrCreateEmitNode(node).flags |= EmitFlags.IgnoreSourceNewlines; return node; } /* @internal */ -export function setTypeNode(node: T, type: ts.TypeNode): T { +export function setTypeNode(node: T, type: TypeNode): T { const emitNode = getOrCreateEmitNode(node); emitNode.typeNode = type; return node; } /* @internal */ -export function getTypeNode(node: T): ts.TypeNode | undefined { +export function getTypeNode(node: T): TypeNode | undefined { return node.emitNode?.typeNode; } diff --git a/src/compiler/factory/nodeConverters.ts b/src/compiler/factory/nodeConverters.ts index 3fa27aedbbd01..3efb85e75e3f1 100644 --- a/src/compiler/factory/nodeConverters.ts +++ b/src/compiler/factory/nodeConverters.ts @@ -1,7 +1,14 @@ -import * as ts from "../_namespaces/ts"; +import { + ArrayBindingOrAssignmentElement, ArrayBindingOrAssignmentPattern, AssignmentPattern, + BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, Block, cast, ConciseBody, Debug, Expression, + FunctionDeclaration, getStartsOnNewLine, isArrayBindingPattern, isArrayLiteralExpression, isBindingElement, + isBindingPattern, isBlock, isExpression, isIdentifier, isObjectBindingPattern, isObjectLiteralElementLike, + isObjectLiteralExpression, map, NodeConverters, NodeFactory, notImplemented, ObjectBindingOrAssignmentElement, + ObjectBindingOrAssignmentPattern, setOriginalNode, setStartsOnNewLine, setTextRange, SyntaxKind, +} from "../_namespaces/ts"; /** @internal */ -export function createNodeConverters(factory: ts.NodeFactory): ts.NodeConverters { +export function createNodeConverters(factory: NodeFactory): NodeConverters { return { convertToFunctionBlock, convertToFunctionExpression, @@ -13,17 +20,17 @@ export function createNodeConverters(factory: ts.NodeFactory): ts.NodeConverters convertToAssignmentElementTarget, }; - function convertToFunctionBlock(node: ts.ConciseBody, multiLine?: boolean): ts.Block { - if (ts.isBlock(node)) return node; + function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block { + if (isBlock(node)) return node; const returnStatement = factory.createReturnStatement(node); - ts.setTextRange(returnStatement, node); + setTextRange(returnStatement, node); const body = factory.createBlock([returnStatement], multiLine); - ts.setTextRange(body, node); + setTextRange(body, node); return body; } - function convertToFunctionExpression(node: ts.FunctionDeclaration) { - if (!node.body) return ts.Debug.fail(`Cannot convert a FunctionDeclaration without a body`); + function convertToFunctionExpression(node: FunctionDeclaration) { + if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`); const updated = factory.createFunctionExpression( node.modifiers, node.asteriskToken, @@ -33,24 +40,24 @@ export function createNodeConverters(factory: ts.NodeFactory): ts.NodeConverters node.type, node.body ); - ts.setOriginalNode(updated, node); - ts.setTextRange(updated, node); - if (ts.getStartsOnNewLine(node)) { - ts.setStartsOnNewLine(updated, /*newLine*/ true); + setOriginalNode(updated, node); + setTextRange(updated, node); + if (getStartsOnNewLine(node)) { + setStartsOnNewLine(updated, /*newLine*/ true); } return updated; } - function convertToArrayAssignmentElement(element: ts.ArrayBindingOrAssignmentElement) { - if (ts.isBindingElement(element)) { + function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) { + if (isBindingElement(element)) { if (element.dotDotDotToken) { - ts.Debug.assertNode(element.name, ts.isIdentifier); - return ts.setOriginalNode(ts.setTextRange(factory.createSpreadElement(element.name), element), element); + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpreadElement(element.name), element), element); } const expression = convertToAssignmentElementTarget(element.name); return element.initializer - ? ts.setOriginalNode( - ts.setTextRange( + ? setOriginalNode( + setTextRange( factory.createAssignment(expression, element.initializer), element ), @@ -58,81 +65,81 @@ export function createNodeConverters(factory: ts.NodeFactory): ts.NodeConverters ) : expression; } - return ts.cast(element, ts.isExpression); + return cast(element, isExpression); } - function convertToObjectAssignmentElement(element: ts.ObjectBindingOrAssignmentElement) { - if (ts.isBindingElement(element)) { + function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) { + if (isBindingElement(element)) { if (element.dotDotDotToken) { - ts.Debug.assertNode(element.name, ts.isIdentifier); - return ts.setOriginalNode(ts.setTextRange(factory.createSpreadAssignment(element.name), element), element); + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element); } if (element.propertyName) { const expression = convertToAssignmentElementTarget(element.name); - return ts.setOriginalNode(ts.setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); + return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element); } - ts.Debug.assertNode(element.name, ts.isIdentifier); - return ts.setOriginalNode(ts.setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); + Debug.assertNode(element.name, isIdentifier); + return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element); } - return ts.cast(element, ts.isObjectLiteralElementLike); + return cast(element, isObjectLiteralElementLike); } - function convertToAssignmentPattern(node: ts.BindingOrAssignmentPattern): ts.AssignmentPattern { + function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern { switch (node.kind) { - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: return convertToArrayAssignmentPattern(node); - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ObjectLiteralExpression: return convertToObjectAssignmentPattern(node); } } - function convertToObjectAssignmentPattern(node: ts.ObjectBindingOrAssignmentPattern) { - if (ts.isObjectBindingPattern(node)) { - return ts.setOriginalNode( - ts.setTextRange( - factory.createObjectLiteralExpression(ts.map(node.elements, convertToObjectAssignmentElement)), + function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { + if (isObjectBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createObjectLiteralExpression(map(node.elements, convertToObjectAssignmentElement)), node ), node ); } - return ts.cast(node, ts.isObjectLiteralExpression); + return cast(node, isObjectLiteralExpression); } - function convertToArrayAssignmentPattern(node: ts.ArrayBindingOrAssignmentPattern) { - if (ts.isArrayBindingPattern(node)) { - return ts.setOriginalNode( - ts.setTextRange( - factory.createArrayLiteralExpression(ts.map(node.elements, convertToArrayAssignmentElement)), + function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { + if (isArrayBindingPattern(node)) { + return setOriginalNode( + setTextRange( + factory.createArrayLiteralExpression(map(node.elements, convertToArrayAssignmentElement)), node ), node ); } - return ts.cast(node, ts.isArrayLiteralExpression); + return cast(node, isArrayLiteralExpression); } - function convertToAssignmentElementTarget(node: ts.BindingOrAssignmentElementTarget): ts.Expression { - if (ts.isBindingPattern(node)) { + function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression { + if (isBindingPattern(node)) { return convertToAssignmentPattern(node); } - return ts.cast(node, ts.isExpression); + return cast(node, isExpression); } } /** @internal */ -export const nullNodeConverters: ts.NodeConverters = { - convertToFunctionBlock: ts.notImplemented, - convertToFunctionExpression: ts.notImplemented, - convertToArrayAssignmentElement: ts.notImplemented, - convertToObjectAssignmentElement: ts.notImplemented, - convertToAssignmentPattern: ts.notImplemented, - convertToObjectAssignmentPattern: ts.notImplemented, - convertToArrayAssignmentPattern: ts.notImplemented, - convertToAssignmentElementTarget: ts.notImplemented, +export const nullNodeConverters: NodeConverters = { + convertToFunctionBlock: notImplemented, + convertToFunctionExpression: notImplemented, + convertToArrayAssignmentElement: notImplemented, + convertToObjectAssignmentElement: notImplemented, + convertToAssignmentPattern: notImplemented, + convertToObjectAssignmentPattern: notImplemented, + convertToArrayAssignmentPattern: notImplemented, + convertToAssignmentElementTarget: notImplemented, }; \ No newline at end of file diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 2350c5f68abbc..e02cc3d22839b 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1,4 +1,84 @@ -import * as ts from "../_namespaces/ts"; +import { + addRange, append, appendIfUnique, ArrayBindingElement, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, + ArrowFunction, AsExpression, AssertClause, AssertEntry, AssertionKey, AssertsKeyword, AssignmentPattern, + AsteriskToken, AwaitExpression, AwaitKeyword, BaseNodeFactory, BigIntLiteral, BinaryExpression, BinaryOperator, + BinaryOperatorToken, BindingElement, BindingName, BindingPattern, Block, BooleanLiteral, BreakStatement, BuildInfo, + Bundle, BundleFileHasNoDefaultLib, BundleFileInfo, BundleFileReference, BundleFileSectionKind, CallBinding, + CallChain, CallExpression, CallSignatureDeclaration, canHaveModifiers, CaseBlock, CaseClause, CaseOrDefaultClause, + cast, CatchClause, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, + ClassStaticBlockDeclaration, ColonToken, CommaListExpression, CompilerHost, CompilerOptions, ComputedPropertyName, + ConciseBody, ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, + ConstructSignatureDeclaration, ContinueStatement, createBaseNodeFactory, createNodeConverters, + createParenthesizerRules, createScanner, Debug, DebuggerStatement, Declaration, DeclarationName, Decorator, + DefaultClause, DeleteExpression, DoStatement, DotDotDotToken, ElementAccessChain, ElementAccessExpression, + EmitFlags, EmitNode, emptyArray, EmptyStatement, EndOfDeclarationMarker, EndOfFileToken, EntityName, + EnumDeclaration, EnumMember, EqualsGreaterThanToken, escapeLeadingUnderscores, every, ExclamationToken, + ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, ExpressionStatement, ExpressionWithTypeArguments, + ExternalModuleReference, FalseLiteral, FileReference, findUseStrictPrologue, forEach, ForInitializer, + ForInStatement, formatGeneratedName, ForOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, FunctionTypeNode, GeneratedIdentifier, GeneratedIdentifierFlags, GeneratedNamePart, + GetAccessorDeclaration, getAllUnscopedEmitHelpers, getBuildInfo, getCommentRange, + getElementsOfBindingOrAssignmentPattern, getEmitFlags, getJSDocTypeAliasName, getLineAndCharacterOfPosition, + getNameOfDeclaration, getNodeId, getSourceMapRange, getSyntheticLeadingComments, getSyntheticTrailingComments, + getTargetOfBindingOrAssignmentElement, getTextOfIdentifierOrLiteral, hasInvalidEscape, HasModifiers, hasProperty, + hasStaticModifier, hasSyntacticModifier, HeritageClause, Identifier, idText, IfStatement, ImportClause, + ImportDeclaration, ImportEqualsDeclaration, ImportSpecifier, ImportTypeAssertionContainer, ImportTypeNode, + IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, InputFiles, InterfaceDeclaration, + IntersectionTypeNode, isArray, isArrayLiteralExpression, isArrowFunction, isAssignmentPattern, isBinaryExpression, + isCallChain, isClassDeclaration, isClassExpression, isCommaListExpression, isCommaToken, isComputedPropertyName, + isConstructorDeclaration, isConstructorTypeNode, isCustomPrologue, isElementAccessChain, isElementAccessExpression, + isEnumDeclaration, isExclamationToken, isExportAssignment, isExportDeclaration, isExternalModuleReference, + isFunctionDeclaration, isFunctionExpression, isGeneratedIdentifier, isGetAccessorDeclaration, isHoistedFunction, + isHoistedVariableStatement, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isImportKeyword, + isIndexSignatureDeclaration, isInterfaceDeclaration, isLabeledStatement, isLocalName, + isLogicalOrCoalescingAssignmentOperator, isMemberName, isMethodDeclaration, isMethodSignature, isModuleDeclaration, + isNamedDeclaration, isNodeArray, isNodeKind, isNonNullChain, isNotEmittedStatement, isObjectLiteralExpression, + isOmittedExpression, isOuterExpression, isParameter, isParenthesizedExpression, isParseTreeNode, + isPrivateIdentifier, isPrologueDirective, isPropertyAccessChain, isPropertyAccessExpression, isPropertyDeclaration, + isPropertyName, isPropertySignature, isQuestionToken, isSetAccessorDeclaration, isSourceFile, isStatement, + isStatementOrBlock, isString, isStringLiteral, isSuperKeyword, isSuperProperty, isThisIdentifier, + isTypeAliasDeclaration, isTypeParameterDeclaration, isVariableDeclaration, isVariableStatement, JSDoc, JSDocAllType, + JSDocAugmentsTag, JSDocAuthorTag, JSDocCallbackTag, JSDocClassTag, JSDocComment, JSDocDeprecatedTag, JSDocEnumTag, + JSDocFunctionType, JSDocImplementsTag, JSDocLink, JSDocLinkCode, JSDocLinkPlain, JSDocMemberName, JSDocNamepathType, + JSDocNameReference, JSDocNamespaceDeclaration, JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, JSDocPropertyLikeTag, JSDocPropertyTag, JSDocProtectedTag, + JSDocPublicTag, JSDocReadonlyTag, JSDocReturnTag, JSDocSeeTag, JSDocSignature, JSDocTag, JSDocTemplateTag, + JSDocText, JSDocThisTag, JSDocType, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeLiteral, JSDocTypeTag, + JSDocUnknownTag, JSDocUnknownType, JSDocVariadicType, JsxAttribute, JsxAttributeLike, JsxAttributes, + JsxAttributeValue, JsxChild, JsxClosingElement, JsxClosingFragment, JsxElement, JsxExpression, JsxFragment, + JsxOpeningElement, JsxOpeningFragment, JsxSelfClosingElement, JsxSpreadAttribute, JsxTagNameExpression, JsxText, + KeywordSyntaxKind, KeywordToken, KeywordTypeNode, KeywordTypeSyntaxKind, LabeledStatement, LanguageVariant, + lastOrUndefined, LeftHandSideExpression, LiteralToken, LiteralTypeNode, map, Map, MappedTypeNode, MemberName, + memoize, memoizeOne, MergeDeclarationMarker, MetaProperty, MethodDeclaration, MethodSignature, MinusToken, + MissingDeclaration, Modifier, ModifierFlags, ModifierLike, modifiersToFlags, ModifierSyntaxKind, ModifierToken, + ModuleBlock, ModuleBody, ModuleDeclaration, ModuleKind, ModuleName, ModuleReference, Mutable, MutableNodeArray, + NamedDeclaration, NamedExportBindings, NamedExports, NamedImportBindings, NamedImports, NamedTupleMember, + NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, Node, NodeArray, NodeFactory, + NodeFlags, nodeIsSynthesized, NonNullChain, NonNullExpression, NoSubstitutionTemplateLiteral, NotEmittedStatement, + NullLiteral, nullNodeConverters, nullParenthesizerRules, NumericLiteral, objectAllocator, ObjectBindingPattern, + ObjectLiteralElementLike, ObjectLiteralExpression, OmittedExpression, OptionalTypeNode, OuterExpression, + OuterExpressionKinds, ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, parseNodeFactory, + PartiallyEmittedExpression, PlusToken, PostfixUnaryExpression, PostfixUnaryOperator, PrefixUnaryExpression, + PrefixUnaryOperator, PrimaryExpression, PrivateIdentifier, PrologueDirective, PropertyAccessChain, + PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, PropertyDescriptorAttributes, PropertyName, + PropertyNameLiteral, PropertySignature, PseudoBigInt, pseudoBigIntToString, PunctuationSyntaxKind, PunctuationToken, + Push, QualifiedName, QuestionDotToken, QuestionToken, ReadonlyKeyword, reduceLeft, RegularExpressionLiteral, + RestTypeNode, ReturnStatement, returnTrue, sameFlatMap, SatisfiesExpression, Scanner, ScriptTarget, + SemicolonClassElement, SetAccessorDeclaration, setEachParent, setEmitFlags, setParent, setTextRange, + setTextRangePosEnd, setTextRangePosWidth, ShorthandPropertyAssignment, SignatureDeclarationBase, singleOrUndefined, + skipOuterExpressions, skipParentheses, some, SourceFile, SourceMapSource, SpreadAssignment, SpreadElement, + startOnNewLine, startsWith, Statement, StringLiteral, StringLiteralLike, stringToToken, SuperExpression, + SwitchStatement, SyntaxKind, SyntaxList, SyntheticExpression, SyntheticReferenceExpression, + TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteral, TemplateLiteralLikeNode, + TemplateLiteralToken, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateMiddle, TemplateSpan, TemplateTail, + TextRange, ThisExpression, ThisTypeNode, ThrowStatement, Token, TokenFlags, TransformFlags, TrueLiteral, + TryStatement, TupleTypeNode, Type, TypeAliasDeclaration, TypeAssertion, TypeElement, TypeLiteralNode, TypeNode, + TypeOfExpression, TypeOfTag, TypeOperatorNode, TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, + TypeReferenceNode, UnionOrIntersectionTypeNode, UnionTypeNode, UnparsedNode, UnparsedPrepend, UnparsedPrologue, + UnparsedSource, UnparsedSourceText, UnparsedSyntheticReference, UnparsedTextLike, UnscopedEmitHelper, + VariableDeclaration, VariableDeclarationList, VariableStatement, visitNode, VisitResult, VoidExpression, + WhileStatement, WithStatement, YieldExpression, +} from "../_namespaces/ts"; let nextAutoGenerateId = 0; @@ -15,10 +95,10 @@ export const enum NodeFactoryFlags { NoOriginalNode = 1 << 3, } -const nodeFactoryPatchers: ((factory: ts.NodeFactory) => void)[] = []; +const nodeFactoryPatchers: ((factory: NodeFactory) => void)[] = []; /* @internal */ -export function addNodeFactoryPatcher(fn: (factory: ts.NodeFactory) => void) { +export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) { nodeFactoryPatchers.push(fn); } @@ -28,28 +108,28 @@ export function addNodeFactoryPatcher(fn: (factory: ts.NodeFactory) => void) { * @param baseFactory A `BaseNodeFactory` used to create the base `Node` objects. */ /* @internal */ -export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseNodeFactory): ts.NodeFactory { +export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory { const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal; // Lazily load the parenthesizer, node converters, and some factory methods until they are used. - const parenthesizerRules = ts.memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? ts.nullParenthesizerRules : ts.createParenthesizerRules(factory)); - const converters = ts.memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? ts.nullNodeConverters : ts.createNodeConverters(factory)); + const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory)); + const converters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory)); // lazy initializaton of common operator factories - const getBinaryCreateFunction = ts.memoizeOne((operator: ts.BinaryOperator) => (left: ts.Expression, right: ts.Expression) => createBinaryExpression(left, operator, right)); - const getPrefixUnaryCreateFunction = ts.memoizeOne((operator: ts.PrefixUnaryOperator) => (operand: ts.Expression) => createPrefixUnaryExpression(operator, operand)); - const getPostfixUnaryCreateFunction = ts.memoizeOne((operator: ts.PostfixUnaryOperator) => (operand: ts.Expression) => createPostfixUnaryExpression(operand, operator)); - const getJSDocPrimaryTypeCreateFunction = ts.memoizeOne((kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind)); - const getJSDocUnaryTypeCreateFunction = ts.memoizeOne((kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker(kind, type)); - const getJSDocUnaryTypeUpdateFunction = ts.memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker(kind, node, type)); - const getJSDocPrePostfixUnaryTypeCreateFunction = ts.memoizeOne((kind: T["kind"]) => (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker(kind, type, postfix)); - const getJSDocPrePostfixUnaryTypeUpdateFunction = ts.memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker(kind, node, type)); - const getJSDocSimpleTagCreateFunction = ts.memoizeOne((kind: T["kind"]) => (tagName: ts.Identifier | undefined, comment?: ts.NodeArray) => createJSDocSimpleTagWorker(kind, tagName, comment)); - const getJSDocSimpleTagUpdateFunction = ts.memoizeOne((kind: T["kind"]) => (node: T, tagName: ts.Identifier | undefined, comment?: ts.NodeArray) => updateJSDocSimpleTagWorker(kind, node, tagName, comment)); - const getJSDocTypeLikeTagCreateFunction = ts.memoizeOne((kind: T["kind"]) => (tagName: ts.Identifier | undefined, typeExpression?: ts.JSDocTypeExpression, comment?: ts.NodeArray) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment)); - const getJSDocTypeLikeTagUpdateFunction = ts.memoizeOne((kind: T["kind"]) => (node: T, tagName: ts.Identifier | undefined, typeExpression?: ts.JSDocTypeExpression, comment?: ts.NodeArray) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment)); - - const factory: ts.NodeFactory = { + const getBinaryCreateFunction = memoizeOne((operator: BinaryOperator) => (left: Expression, right: Expression) => createBinaryExpression(left, operator, right)); + const getPrefixUnaryCreateFunction = memoizeOne((operator: PrefixUnaryOperator) => (operand: Expression) => createPrefixUnaryExpression(operator, operand)); + const getPostfixUnaryCreateFunction = memoizeOne((operator: PostfixUnaryOperator) => (operand: Expression) => createPostfixUnaryExpression(operand, operator)); + const getJSDocPrimaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind)); + const getJSDocUnaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker(kind, type)); + const getJSDocUnaryTypeUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker(kind, node, type)); + const getJSDocPrePostfixUnaryTypeCreateFunction = memoizeOne((kind: T["kind"]) => (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker(kind, type, postfix)); + const getJSDocPrePostfixUnaryTypeUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker(kind, node, type)); + const getJSDocSimpleTagCreateFunction = memoizeOne((kind: T["kind"]) => (tagName: Identifier | undefined, comment?: NodeArray) => createJSDocSimpleTagWorker(kind, tagName, comment)); + const getJSDocSimpleTagUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, tagName: Identifier | undefined, comment?: NodeArray) => updateJSDocSimpleTagWorker(kind, node, tagName, comment)); + const getJSDocTypeLikeTagCreateFunction = memoizeOne((kind: T["kind"]) => (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment)); + const getJSDocTypeLikeTagUpdateFunction = memoizeOne((kind: T["kind"]) => (node: T, tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment)); + + const factory: NodeFactory = { get parenthesizer() { return parenthesizerRules(); }, get converters() { return converters(); }, baseFactory, @@ -169,11 +249,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN createObjectLiteralExpression, updateObjectLiteralExpression, createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression: ts.Expression, name: string | ts.MemberName) => ts.setEmitFlags(createPropertyAccessExpression(expression, name), ts.EmitFlags.NoIndentation) : + (expression: Expression, name: string | MemberName) => setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) : createPropertyAccessExpression, updatePropertyAccessExpression, createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ? - (expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, name: string | ts.MemberName) => ts.setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), ts.EmitFlags.NoIndentation) : + (expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | MemberName) => setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) : createPropertyAccessChain, updatePropertyAccessChain, createElementAccessExpression, @@ -331,18 +411,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN createExternalModuleReference, updateExternalModuleReference, // lazily load factory members for JSDoc types with similar structure - get createJSDocAllType() { return getJSDocPrimaryTypeCreateFunction(ts.SyntaxKind.JSDocAllType); }, - get createJSDocUnknownType() { return getJSDocPrimaryTypeCreateFunction(ts.SyntaxKind.JSDocUnknownType); }, - get createJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction(ts.SyntaxKind.JSDocNonNullableType); }, - get updateJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction(ts.SyntaxKind.JSDocNonNullableType); }, - get createJSDocNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction(ts.SyntaxKind.JSDocNullableType); }, - get updateJSDocNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction(ts.SyntaxKind.JSDocNullableType); }, - get createJSDocOptionalType() { return getJSDocUnaryTypeCreateFunction(ts.SyntaxKind.JSDocOptionalType); }, - get updateJSDocOptionalType() { return getJSDocUnaryTypeUpdateFunction(ts.SyntaxKind.JSDocOptionalType); }, - get createJSDocVariadicType() { return getJSDocUnaryTypeCreateFunction(ts.SyntaxKind.JSDocVariadicType); }, - get updateJSDocVariadicType() { return getJSDocUnaryTypeUpdateFunction(ts.SyntaxKind.JSDocVariadicType); }, - get createJSDocNamepathType() { return getJSDocUnaryTypeCreateFunction(ts.SyntaxKind.JSDocNamepathType); }, - get updateJSDocNamepathType() { return getJSDocUnaryTypeUpdateFunction(ts.SyntaxKind.JSDocNamepathType); }, + get createJSDocAllType() { return getJSDocPrimaryTypeCreateFunction(SyntaxKind.JSDocAllType); }, + get createJSDocUnknownType() { return getJSDocPrimaryTypeCreateFunction(SyntaxKind.JSDocUnknownType); }, + get createJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction(SyntaxKind.JSDocNonNullableType); }, + get updateJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction(SyntaxKind.JSDocNonNullableType); }, + get createJSDocNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction(SyntaxKind.JSDocNullableType); }, + get updateJSDocNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction(SyntaxKind.JSDocNullableType); }, + get createJSDocOptionalType() { return getJSDocUnaryTypeCreateFunction(SyntaxKind.JSDocOptionalType); }, + get updateJSDocOptionalType() { return getJSDocUnaryTypeUpdateFunction(SyntaxKind.JSDocOptionalType); }, + get createJSDocVariadicType() { return getJSDocUnaryTypeCreateFunction(SyntaxKind.JSDocVariadicType); }, + get updateJSDocVariadicType() { return getJSDocUnaryTypeUpdateFunction(SyntaxKind.JSDocVariadicType); }, + get createJSDocNamepathType() { return getJSDocUnaryTypeCreateFunction(SyntaxKind.JSDocNamepathType); }, + get updateJSDocNamepathType() { return getJSDocUnaryTypeUpdateFunction(SyntaxKind.JSDocNamepathType); }, createJSDocFunctionType, updateJSDocFunctionType, createJSDocTypeLiteral, @@ -378,30 +458,30 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN createJSDocLinkPlain, updateJSDocLinkPlain, // lazily load factory members for JSDoc tags with similar structure - get createJSDocTypeTag() { return getJSDocTypeLikeTagCreateFunction(ts.SyntaxKind.JSDocTypeTag); }, - get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction(ts.SyntaxKind.JSDocTypeTag); }, - get createJSDocReturnTag() { return getJSDocTypeLikeTagCreateFunction(ts.SyntaxKind.JSDocReturnTag); }, - get updateJSDocReturnTag() { return getJSDocTypeLikeTagUpdateFunction(ts.SyntaxKind.JSDocReturnTag); }, - get createJSDocThisTag() { return getJSDocTypeLikeTagCreateFunction(ts.SyntaxKind.JSDocThisTag); }, - get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction(ts.SyntaxKind.JSDocThisTag); }, - get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction(ts.SyntaxKind.JSDocEnumTag); }, - get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction(ts.SyntaxKind.JSDocEnumTag); }, - get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocAuthorTag); }, - get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocAuthorTag); }, - get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocClassTag); }, - get updateJSDocClassTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocClassTag); }, - get createJSDocPublicTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocPublicTag); }, - get updateJSDocPublicTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocPublicTag); }, - get createJSDocPrivateTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocPrivateTag); }, - get updateJSDocPrivateTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocPrivateTag); }, - get createJSDocProtectedTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocProtectedTag); }, - get updateJSDocProtectedTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocProtectedTag); }, - get createJSDocReadonlyTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocReadonlyTag); }, - get updateJSDocReadonlyTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocReadonlyTag); }, - get createJSDocOverrideTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocOverrideTag); }, - get updateJSDocOverrideTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocOverrideTag); }, - get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction(ts.SyntaxKind.JSDocDeprecatedTag); }, - get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction(ts.SyntaxKind.JSDocDeprecatedTag); }, + get createJSDocTypeTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocTypeTag); }, + get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocTypeTag); }, + get createJSDocReturnTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocReturnTag); }, + get updateJSDocReturnTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocReturnTag); }, + get createJSDocThisTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocThisTag); }, + get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocThisTag); }, + get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocEnumTag); }, + get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocEnumTag); }, + get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocAuthorTag); }, + get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocAuthorTag); }, + get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocClassTag); }, + get updateJSDocClassTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocClassTag); }, + get createJSDocPublicTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocPublicTag); }, + get updateJSDocPublicTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocPublicTag); }, + get createJSDocPrivateTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocPrivateTag); }, + get updateJSDocPrivateTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocPrivateTag); }, + get createJSDocProtectedTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocProtectedTag); }, + get updateJSDocProtectedTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocProtectedTag); }, + get createJSDocReadonlyTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocReadonlyTag); }, + get updateJSDocReadonlyTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocReadonlyTag); }, + get createJSDocOverrideTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocOverrideTag); }, + get updateJSDocOverrideTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocOverrideTag); }, + get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocDeprecatedTag); }, + get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocDeprecatedTag); }, createJSDocUnknownTag, updateJSDocUnknownTag, createJSDocText, @@ -470,38 +550,38 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN cloneNode, // Lazily load factory methods for common operator factories and utilities - get createComma() { return getBinaryCreateFunction(ts.SyntaxKind.CommaToken); }, - get createAssignment() { return getBinaryCreateFunction(ts.SyntaxKind.EqualsToken) as ts.NodeFactory["createAssignment"]; }, - get createLogicalOr() { return getBinaryCreateFunction(ts.SyntaxKind.BarBarToken); }, - get createLogicalAnd() { return getBinaryCreateFunction(ts.SyntaxKind.AmpersandAmpersandToken); }, - get createBitwiseOr() { return getBinaryCreateFunction(ts.SyntaxKind.BarToken); }, - get createBitwiseXor() { return getBinaryCreateFunction(ts.SyntaxKind.CaretToken); }, - get createBitwiseAnd() { return getBinaryCreateFunction(ts.SyntaxKind.AmpersandToken); }, - get createStrictEquality() { return getBinaryCreateFunction(ts.SyntaxKind.EqualsEqualsEqualsToken); }, - get createStrictInequality() { return getBinaryCreateFunction(ts.SyntaxKind.ExclamationEqualsEqualsToken); }, - get createEquality() { return getBinaryCreateFunction(ts.SyntaxKind.EqualsEqualsToken); }, - get createInequality() { return getBinaryCreateFunction(ts.SyntaxKind.ExclamationEqualsToken); }, - get createLessThan() { return getBinaryCreateFunction(ts.SyntaxKind.LessThanToken); }, - get createLessThanEquals() { return getBinaryCreateFunction(ts.SyntaxKind.LessThanEqualsToken); }, - get createGreaterThan() { return getBinaryCreateFunction(ts.SyntaxKind.GreaterThanToken); }, - get createGreaterThanEquals() { return getBinaryCreateFunction(ts.SyntaxKind.GreaterThanEqualsToken); }, - get createLeftShift() { return getBinaryCreateFunction(ts.SyntaxKind.LessThanLessThanToken); }, - get createRightShift() { return getBinaryCreateFunction(ts.SyntaxKind.GreaterThanGreaterThanToken); }, - get createUnsignedRightShift() { return getBinaryCreateFunction(ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken); }, - get createAdd() { return getBinaryCreateFunction(ts.SyntaxKind.PlusToken); }, - get createSubtract() { return getBinaryCreateFunction(ts.SyntaxKind.MinusToken); }, - get createMultiply() { return getBinaryCreateFunction(ts.SyntaxKind.AsteriskToken); }, - get createDivide() { return getBinaryCreateFunction(ts.SyntaxKind.SlashToken); }, - get createModulo() { return getBinaryCreateFunction(ts.SyntaxKind.PercentToken); }, - get createExponent() { return getBinaryCreateFunction(ts.SyntaxKind.AsteriskAsteriskToken); }, - get createPrefixPlus() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.PlusToken); }, - get createPrefixMinus() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.MinusToken); }, - get createPrefixIncrement() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.PlusPlusToken); }, - get createPrefixDecrement() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.MinusMinusToken); }, - get createBitwiseNot() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.TildeToken); }, - get createLogicalNot() { return getPrefixUnaryCreateFunction(ts.SyntaxKind.ExclamationToken); }, - get createPostfixIncrement() { return getPostfixUnaryCreateFunction(ts.SyntaxKind.PlusPlusToken); }, - get createPostfixDecrement() { return getPostfixUnaryCreateFunction(ts.SyntaxKind.MinusMinusToken); }, + get createComma() { return getBinaryCreateFunction(SyntaxKind.CommaToken); }, + get createAssignment() { return getBinaryCreateFunction(SyntaxKind.EqualsToken) as NodeFactory["createAssignment"]; }, + get createLogicalOr() { return getBinaryCreateFunction(SyntaxKind.BarBarToken); }, + get createLogicalAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandAmpersandToken); }, + get createBitwiseOr() { return getBinaryCreateFunction(SyntaxKind.BarToken); }, + get createBitwiseXor() { return getBinaryCreateFunction(SyntaxKind.CaretToken); }, + get createBitwiseAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandToken); }, + get createStrictEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsEqualsToken); }, + get createStrictInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsEqualsToken); }, + get createEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsToken); }, + get createInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsToken); }, + get createLessThan() { return getBinaryCreateFunction(SyntaxKind.LessThanToken); }, + get createLessThanEquals() { return getBinaryCreateFunction(SyntaxKind.LessThanEqualsToken); }, + get createGreaterThan() { return getBinaryCreateFunction(SyntaxKind.GreaterThanToken); }, + get createGreaterThanEquals() { return getBinaryCreateFunction(SyntaxKind.GreaterThanEqualsToken); }, + get createLeftShift() { return getBinaryCreateFunction(SyntaxKind.LessThanLessThanToken); }, + get createRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanToken); }, + get createUnsignedRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); }, + get createAdd() { return getBinaryCreateFunction(SyntaxKind.PlusToken); }, + get createSubtract() { return getBinaryCreateFunction(SyntaxKind.MinusToken); }, + get createMultiply() { return getBinaryCreateFunction(SyntaxKind.AsteriskToken); }, + get createDivide() { return getBinaryCreateFunction(SyntaxKind.SlashToken); }, + get createModulo() { return getBinaryCreateFunction(SyntaxKind.PercentToken); }, + get createExponent() { return getBinaryCreateFunction(SyntaxKind.AsteriskAsteriskToken); }, + get createPrefixPlus() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusToken); }, + get createPrefixMinus() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusToken); }, + get createPrefixIncrement() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusPlusToken); }, + get createPrefixDecrement() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusMinusToken); }, + get createBitwiseNot() { return getPrefixUnaryCreateFunction(SyntaxKind.TildeToken); }, + get createLogicalNot() { return getPrefixUnaryCreateFunction(SyntaxKind.ExclamationToken); }, + get createPostfixIncrement() { return getPostfixUnaryCreateFunction(SyntaxKind.PlusPlusToken); }, + get createPostfixDecrement() { return getPostfixUnaryCreateFunction(SyntaxKind.MinusMinusToken); }, // Compound nodes createImmediatelyInvokedFunctionExpression, @@ -544,34 +624,34 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN updateModifiers, } as any; - ts.forEach(nodeFactoryPatchers, fn => fn(factory)); + forEach(nodeFactoryPatchers, fn => fn(factory)); return factory; // @api - function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): ts.NodeArray { - if (elements === undefined || elements === ts.emptyArray) { + function createNodeArray(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray { + if (elements === undefined || elements === emptyArray) { elements = []; } - else if (ts.isNodeArray(elements)) { + else if (isNodeArray(elements)) { if (hasTrailingComma === undefined || elements.hasTrailingComma === hasTrailingComma) { // Ensure the transform flags have been aggregated for this NodeArray if (elements.transformFlags === undefined) { - aggregateChildrenFlags(elements as ts.MutableNodeArray); + aggregateChildrenFlags(elements as MutableNodeArray); } - ts.Debug.attachNodeArrayDebugInfo(elements); + Debug.attachNodeArrayDebugInfo(elements); return elements; } // This *was* a `NodeArray`, but the `hasTrailingComma` option differs. Recreate the // array with the same elements, text range, and transform flags but with the updated // value for `hasTrailingComma` - const array = elements.slice() as ts.MutableNodeArray; + const array = elements.slice() as MutableNodeArray; array.pos = elements.pos; array.end = elements.end; array.hasTrailingComma = hasTrailingComma; array.transformFlags = elements.transformFlags; - ts.Debug.attachNodeArrayDebugInfo(array); + Debug.attachNodeArrayDebugInfo(array); return array; } @@ -579,19 +659,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. const length = elements.length; - const array = (length >= 1 && length <= 4 ? elements.slice() : elements) as ts.MutableNodeArray; - ts.setTextRangePosEnd(array, -1, -1); + const array = (length >= 1 && length <= 4 ? elements.slice() : elements) as MutableNodeArray; + setTextRangePosEnd(array, -1, -1); array.hasTrailingComma = !!hasTrailingComma; aggregateChildrenFlags(array); - ts.Debug.attachNodeArrayDebugInfo(array); + Debug.attachNodeArrayDebugInfo(array); return array; } - function createBaseNode(kind: T["kind"]) { - return baseFactory.createBaseNode(kind) as ts.Mutable; + function createBaseNode(kind: T["kind"]) { + return baseFactory.createBaseNode(kind) as Mutable; } - function createBaseDeclaration( + function createBaseDeclaration( kind: T["kind"], ) { const node = createBaseNode(kind); @@ -604,17 +684,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseNamedDeclaration( + function createBaseNamedDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined ) { const node = createBaseDeclaration(kind); name = asName(name); node.name = name; - if (ts.canHaveModifiers(node)) { - (node as ts.Mutable).modifiers = asNodeArray(modifiers); - (node as ts.Mutable).transformFlags |= propagateChildrenFlags(node.modifiers); + if (canHaveModifiers(node)) { + (node as Mutable).modifiers = asNodeArray(modifiers); + (node as Mutable).transformFlags |= propagateChildrenFlags(node.modifiers); // node.decorators = filter(node.modifiers, isDecorator); } @@ -623,12 +703,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // don't propagate child flags. if (name) { switch (node.kind) { - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertyAssignment: - if (ts.isIdentifier(name)) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyAssignment: + if (isIdentifier(name)) { node.transformFlags |= propagateIdentifierNameFlags(name); break; } @@ -641,11 +721,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseGenericNamedDeclaration }>( + function createBaseGenericNamedDeclaration }>( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined ) { const node = createBaseNamedDeclaration( kind, @@ -654,17 +734,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); node.typeParameters = asNodeArray(typeParameters); node.transformFlags |= propagateChildrenFlags(node.typeParameters); - if (typeParameters) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + if (typeParameters) node.transformFlags |= TransformFlags.ContainsTypeScript; return node; } - function createBaseSignatureDeclaration( + function createBaseSignatureDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[] | undefined, - type: ts.TypeNode | undefined + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined ) { const node = createBaseGenericNamedDeclaration( kind, @@ -677,14 +757,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.transformFlags |= propagateChildrenFlags(node.parameters) | propagateChildFlags(node.type); - if (type) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + if (type) node.transformFlags |= TransformFlags.ContainsTypeScript; // The following properties are used for quick info node.typeArguments = undefined; return node; } - function finishUpdateBaseSignatureDeclaration(updated: ts.Mutable, original: T) { + function finishUpdateBaseSignatureDeclaration(updated: Mutable, original: T) { if (updated !== original) { // copy children used for quick info updated.typeArguments = original.typeArguments; @@ -692,13 +772,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return update(updated, original); } - function createBaseFunctionLikeDeclaration( + function createBaseFunctionLikeDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | ts.PrivateIdentifier | ts.StringLiteralLike | ts.NumericLiteral | ts.ComputedPropertyName | ts.BindingPattern | string | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[] | undefined, - type: ts.TypeNode | undefined, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, body: T["body"] ) { const node = createBaseSignatureDeclaration( @@ -710,17 +790,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN type ); node.body = body; - node.transformFlags |= propagateChildFlags(node.body) & ~ts.TransformFlags.ContainsPossibleTopLevelAwait; - if (!body) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait; + if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript; return node; } - function createBaseInterfaceOrClassLikeDeclaration( + function createBaseInterfaceOrClassLikeDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined ) { const node = createBaseGenericNamedDeclaration( kind, @@ -733,13 +813,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseClassLikeDeclaration( + function createBaseClassLikeDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { const node = createBaseInterfaceOrClassLikeDeclaration( kind, @@ -753,11 +833,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseBindingLikeDeclaration( + function createBaseBindingLikeDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, + modifiers: readonly ModifierLike[] | undefined, name: string | T["name"] | undefined, - initializer: ts.Expression | undefined + initializer: Expression | undefined ) { const node = createBaseNamedDeclaration( kind, @@ -769,12 +849,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return node; } - function createBaseVariableLikeDeclaration( + function createBaseVariableLikeDeclaration( kind: T["kind"], - modifiers: readonly ts.ModifierLike[] | undefined, + modifiers: readonly ModifierLike[] | undefined, name: string | T["name"] | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + type: TypeNode | undefined, + initializer: Expression | undefined ) { const node = createBaseBindingLikeDeclaration( kind, @@ -784,7 +864,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); node.type = type; node.transformFlags |= propagateChildFlags(type); - if (type) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + if (type) node.transformFlags |= TransformFlags.ContainsTypeScript; return node; } @@ -792,7 +872,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Literals // - function createBaseLiteral( + function createBaseLiteral( kind: T["kind"], text: string ) { @@ -802,57 +882,57 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNumericLiteral(value: string | number, numericLiteralFlags: ts.TokenFlags = ts.TokenFlags.None): ts.NumericLiteral { - const node = createBaseLiteral(ts.SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value); + function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { + const node = createBaseLiteral(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value); node.numericLiteralFlags = numericLiteralFlags; - if (numericLiteralFlags & ts.TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= ts.TransformFlags.ContainsES2015; + if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015; return node; } // @api - function createBigIntLiteral(value: string | ts.PseudoBigInt): ts.BigIntLiteral { - const node = createBaseLiteral(ts.SyntaxKind.BigIntLiteral, typeof value === "string" ? value : ts.pseudoBigIntToString(value) + "n"); - node.transformFlags |= ts.TransformFlags.ContainsESNext; + function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { + const node = createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); + node.transformFlags |= TransformFlags.ContainsESNext; return node; } function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { - const node = createBaseLiteral(ts.SyntaxKind.StringLiteral, text); + const node = createBaseLiteral(SyntaxKind.StringLiteral, text); node.singleQuote = isSingleQuote; return node; } // @api - function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): ts.StringLiteral { + function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral { const node = createBaseStringLiteral(text, isSingleQuote); node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; - if (hasExtendedUnicodeEscape) node.transformFlags |= ts.TransformFlags.ContainsES2015; + if (hasExtendedUnicodeEscape) node.transformFlags |= TransformFlags.ContainsES2015; return node; } // @api - function createStringLiteralFromNode(sourceNode: ts.PropertyNameLiteral | ts.PrivateIdentifier): ts.StringLiteral { - const node = createBaseStringLiteral(ts.getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); + function createStringLiteralFromNode(sourceNode: PropertyNameLiteral | PrivateIdentifier): StringLiteral { + const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined); node.textSourceNode = sourceNode; return node; } // @api - function createRegularExpressionLiteral(text: string): ts.RegularExpressionLiteral { - const node = createBaseLiteral(ts.SyntaxKind.RegularExpressionLiteral, text); + function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { + const node = createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); return node; } // @api - function createLiteralLikeNode(kind: ts.LiteralToken["kind"] | ts.SyntaxKind.JsxTextAllWhiteSpaces, text: string): ts.LiteralToken { + function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken { switch (kind) { - case ts.SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); - case ts.SyntaxKind.BigIntLiteral: return createBigIntLiteral(text); - case ts.SyntaxKind.StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined); - case ts.SyntaxKind.JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false); - case ts.SyntaxKind.JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true); - case ts.SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text); - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as ts.NoSubstitutionTemplateLiteral; + case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0); + case SyntaxKind.BigIntLiteral: return createBigIntLiteral(text); + case SyntaxKind.StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined); + case SyntaxKind.JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false); + case SyntaxKind.JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true); + case SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text); + case SyntaxKind.NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as NoSubstitutionTemplateLiteral; } } @@ -860,21 +940,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Identifiers // - function createBaseIdentifier(text: string, originalKeywordKind: ts.SyntaxKind | undefined) { + function createBaseIdentifier(text: string, originalKeywordKind: SyntaxKind | undefined) { if (originalKeywordKind === undefined && text) { - originalKeywordKind = ts.stringToToken(text); + originalKeywordKind = stringToToken(text); } - if (originalKeywordKind === ts.SyntaxKind.Identifier) { + if (originalKeywordKind === SyntaxKind.Identifier) { originalKeywordKind = undefined; } - const node = baseFactory.createBaseIdentifierNode(ts.SyntaxKind.Identifier) as ts.Mutable; + const node = baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as Mutable; node.originalKeywordKind = originalKeywordKind; - node.escapedText = ts.escapeLeadingUnderscores(text); + node.escapedText = escapeLeadingUnderscores(text); return node; } - function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: ts.GeneratedIdentifierFlags, prefix: string | ts.GeneratedNamePart | undefined, suffix: string | undefined) { - const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as ts.Mutable; + function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { + const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as Mutable; node.autoGenerateFlags = autoGenerateFlags; node.autoGenerateId = nextAutoGenerateId; node.autoGeneratePrefix = prefix; @@ -884,33 +964,33 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createIdentifier(text: string, typeArguments?: readonly (ts.TypeNode | ts.TypeParameterDeclaration)[], originalKeywordKind?: ts.SyntaxKind, hasExtendedUnicodeEscape?: boolean): ts.Identifier { + function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier { const node = createBaseIdentifier(text, originalKeywordKind); if (typeArguments) { // NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations node.typeArguments = createNodeArray(typeArguments); } - if (node.originalKeywordKind === ts.SyntaxKind.AwaitKeyword) { - node.transformFlags |= ts.TransformFlags.ContainsPossibleTopLevelAwait; + if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) { + node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait; } if (hasExtendedUnicodeEscape) { node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.transformFlags |= TransformFlags.ContainsES2015; } return node; } // @api - function updateIdentifier(node: ts.Identifier, typeArguments?: ts.NodeArray | undefined): ts.Identifier { + function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { return node.typeArguments !== typeArguments - ? update(createIdentifier(ts.idText(node), typeArguments), node) + ? update(createIdentifier(idText(node), typeArguments), node) : node; } // @api - function createTempVariable(recordTempVariable: ((node: ts.Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | ts.GeneratedNamePart, suffix?: string): ts.GeneratedIdentifier { - let flags = ts.GeneratedIdentifierFlags.Auto; - if (reservedInNestedScopes) flags |= ts.GeneratedIdentifierFlags.ReservedInNestedScopes; + function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | GeneratedNamePart, suffix?: string): GeneratedIdentifier { + let flags = GeneratedIdentifierFlags.Auto; + if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; const name = createBaseGeneratedIdentifier("", flags, prefix, suffix); if (recordTempVariable) { recordTempVariable(name); @@ -920,47 +1000,47 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN /** Create a unique temporary variable for use in a loop. */ // @api - function createLoopVariable(reservedInNestedScopes?: boolean): ts.Identifier { - let flags = ts.GeneratedIdentifierFlags.Loop; - if (reservedInNestedScopes) flags |= ts.GeneratedIdentifierFlags.ReservedInNestedScopes; + function createLoopVariable(reservedInNestedScopes?: boolean): Identifier { + let flags = GeneratedIdentifierFlags.Loop; + if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes; return createBaseGeneratedIdentifier("", flags, /*prefix*/ undefined, /*suffix*/ undefined); } /** Create a unique name based on the supplied text. */ // @api - function createUniqueName(text: string, flags: ts.GeneratedIdentifierFlags = ts.GeneratedIdentifierFlags.None, prefix?: string | ts.GeneratedNamePart, suffix?: string): ts.Identifier { - ts.Debug.assert(!(flags & ts.GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); - ts.Debug.assert((flags & (ts.GeneratedIdentifierFlags.Optimistic | ts.GeneratedIdentifierFlags.FileLevel)) !== ts.GeneratedIdentifierFlags.FileLevel, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic"); - return createBaseGeneratedIdentifier(text, ts.GeneratedIdentifierFlags.Unique | flags, prefix, suffix); + function createUniqueName(text: string, flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None, prefix?: string | GeneratedNamePart, suffix?: string): Identifier { + Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); + Debug.assert((flags & (GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)) !== GeneratedIdentifierFlags.FileLevel, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic"); + return createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | flags, prefix, suffix); } /** Create a unique name generated for a node. */ // @api - function getGeneratedNameForNode(node: ts.Node | undefined, flags: ts.GeneratedIdentifierFlags = 0, prefix?: string | ts.GeneratedNamePart, suffix?: string): ts.Identifier { - ts.Debug.assert(!(flags & ts.GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); + function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0, prefix?: string | GeneratedNamePart, suffix?: string): Identifier { + Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags"); const text = !node ? "" : - ts.isMemberName(node) ? ts.formatGeneratedName(/*privateName*/ false, prefix, node, suffix, ts.idText) : - `generated@${ts.getNodeId(node)}`; - if (prefix || suffix) flags |= ts.GeneratedIdentifierFlags.Optimistic; - const name = createBaseGeneratedIdentifier(text, ts.GeneratedIdentifierFlags.Node | flags, prefix, suffix); + isMemberName(node) ? formatGeneratedName(/*privateName*/ false, prefix, node, suffix, idText) : + `generated@${getNodeId(node)}`; + if (prefix || suffix) flags |= GeneratedIdentifierFlags.Optimistic; + const name = createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix); name.original = node; return name; } function createBasePrivateIdentifier(text: string) { - const node = baseFactory.createBasePrivateIdentifierNode(ts.SyntaxKind.PrivateIdentifier) as ts.Mutable; - node.escapedText = ts.escapeLeadingUnderscores(text); - node.transformFlags |= ts.TransformFlags.ContainsClassFields; + const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable; + node.escapedText = escapeLeadingUnderscores(text); + node.transformFlags |= TransformFlags.ContainsClassFields; return node; } // @api - function createPrivateIdentifier(text: string): ts.PrivateIdentifier { - if (!ts.startsWith(text, "#")) ts.Debug.fail("First character of private identifier must be #: " + text); + function createPrivateIdentifier(text: string): PrivateIdentifier { + if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); return createBasePrivateIdentifier(text); } - function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: ts.GeneratedIdentifierFlags, prefix: string | ts.GeneratedNamePart | undefined, suffix: string | undefined) { + function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { const node = createBasePrivateIdentifier(text); node.autoGenerateFlags = autoGenerateFlags; node.autoGenerateId = nextAutoGenerateId; @@ -972,19 +1052,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN /** Create a unique name based on the supplied text. */ // @api - function createUniquePrivateName(text?: string, prefix?: string | ts.GeneratedNamePart, suffix?: string): ts.PrivateIdentifier { - if (text && !ts.startsWith(text, "#")) ts.Debug.fail("First character of private identifier must be #: " + text); - const autoGenerateFlags = ts.GeneratedIdentifierFlags.ReservedInNestedScopes | - (text ? ts.GeneratedIdentifierFlags.Unique : ts.GeneratedIdentifierFlags.Auto); + function createUniquePrivateName(text?: string, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier { + if (text && !startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); + const autoGenerateFlags = GeneratedIdentifierFlags.ReservedInNestedScopes | + (text ? GeneratedIdentifierFlags.Unique : GeneratedIdentifierFlags.Auto); return createBaseGeneratedPrivateIdentifier(text ?? "", autoGenerateFlags, prefix, suffix); } // @api - function getGeneratedPrivateNameForNode(node: ts.Node, prefix?: string | ts.GeneratedNamePart, suffix?: string): ts.PrivateIdentifier { - const text = ts.isMemberName(node) ? ts.formatGeneratedName(/*privateName*/ true, prefix, node, suffix, ts.idText) : - `#generated@${ts.getNodeId(node)}`; - const flags = prefix || suffix ? ts.GeneratedIdentifierFlags.Optimistic : ts.GeneratedIdentifierFlags.None; - const name = createBaseGeneratedPrivateIdentifier(text, ts.GeneratedIdentifierFlags.Node | flags, prefix, suffix); + function getGeneratedPrivateNameForNode(node: Node, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier { + const text = isMemberName(node) ? formatGeneratedName(/*privateName*/ true, prefix, node, suffix, idText) : + `#generated@${getNodeId(node)}`; + const flags = prefix || suffix ? GeneratedIdentifierFlags.Optimistic : GeneratedIdentifierFlags.None; + const name = createBaseGeneratedPrivateIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix); name.original = node; return name; } @@ -993,72 +1073,72 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Punctuation // - function createBaseToken(kind: T["kind"]) { - return baseFactory.createBaseTokenNode(kind) as ts.Mutable; - } - - // @api - function createToken(token: ts.SyntaxKind.SuperKeyword): ts.SuperExpression; - function createToken(token: ts.SyntaxKind.ThisKeyword): ts.ThisExpression; - function createToken(token: ts.SyntaxKind.NullKeyword): ts.NullLiteral; - function createToken(token: ts.SyntaxKind.TrueKeyword): ts.TrueLiteral; - function createToken(token: ts.SyntaxKind.FalseKeyword): ts.FalseLiteral; - function createToken(token: TKind): ts.PunctuationToken; - function createToken(token: TKind): ts.KeywordTypeNode; - function createToken(token: TKind): ts.ModifierToken; - function createToken(token: TKind): ts.KeywordToken; - function createToken(token: TKind): ts.Token; - function createToken(token: TKind): ts.Token; - function createToken(token: TKind) { - ts.Debug.assert(token >= ts.SyntaxKind.FirstToken && token <= ts.SyntaxKind.LastToken, "Invalid token"); - ts.Debug.assert(token <= ts.SyntaxKind.FirstTemplateToken || token >= ts.SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); - ts.Debug.assert(token <= ts.SyntaxKind.FirstLiteralToken || token >= ts.SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); - ts.Debug.assert(token !== ts.SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); - const node = createBaseToken>(token); - let transformFlags = ts.TransformFlags.None; + function createBaseToken(kind: T["kind"]) { + return baseFactory.createBaseTokenNode(kind) as Mutable; + } + + // @api + function createToken(token: SyntaxKind.SuperKeyword): SuperExpression; + function createToken(token: SyntaxKind.ThisKeyword): ThisExpression; + function createToken(token: SyntaxKind.NullKeyword): NullLiteral; + function createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; + function createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + function createToken(token: TKind): PunctuationToken; + function createToken(token: TKind): KeywordTypeNode; + function createToken(token: TKind): ModifierToken; + function createToken(token: TKind): KeywordToken; + function createToken(token: TKind): Token; + function createToken(token: TKind): Token; + function createToken(token: TKind) { + Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); + Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals."); + Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals."); + Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers"); + const node = createBaseToken>(token); + let transformFlags = TransformFlags.None; switch (token) { - case ts.SyntaxKind.AsyncKeyword: + case SyntaxKind.AsyncKeyword: // 'async' modifier is ES2017 (async functions) or ES2018 (async generators) transformFlags = - ts.TransformFlags.ContainsES2017 | - ts.TransformFlags.ContainsES2018; + TransformFlags.ContainsES2017 | + TransformFlags.ContainsES2018; break; - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.ReadonlyKeyword: - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.ObjectKeyword: - case ts.SyntaxKind.InKeyword: - case ts.SyntaxKind.OutKeyword: - case ts.SyntaxKind.OverrideKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.UnknownKeyword: - case ts.SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case. - transformFlags = ts.TransformFlags.ContainsTypeScript; + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.InKeyword: + case SyntaxKind.OutKeyword: + case SyntaxKind.OverrideKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.UnknownKeyword: + case SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case. + transformFlags = TransformFlags.ContainsTypeScript; break; - case ts.SyntaxKind.SuperKeyword: - transformFlags = ts.TransformFlags.ContainsES2015 | ts.TransformFlags.ContainsLexicalSuper; + case SyntaxKind.SuperKeyword: + transformFlags = TransformFlags.ContainsES2015 | TransformFlags.ContainsLexicalSuper; break; - case ts.SyntaxKind.StaticKeyword: - transformFlags = ts.TransformFlags.ContainsES2015; + case SyntaxKind.StaticKeyword: + transformFlags = TransformFlags.ContainsES2015; break; - case ts.SyntaxKind.AccessorKeyword: - transformFlags = ts.TransformFlags.ContainsClassFields; + case SyntaxKind.AccessorKeyword: + transformFlags = TransformFlags.ContainsClassFields; break; - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.ThisKeyword: // 'this' indicates a lexical 'this' - transformFlags = ts.TransformFlags.ContainsLexicalThis; + transformFlags = TransformFlags.ContainsLexicalThis; break; } if (transformFlags) { @@ -1073,27 +1153,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createSuper() { - return createToken(ts.SyntaxKind.SuperKeyword); + return createToken(SyntaxKind.SuperKeyword); } // @api function createThis() { - return createToken(ts.SyntaxKind.ThisKeyword); + return createToken(SyntaxKind.ThisKeyword); } // @api function createNull() { - return createToken(ts.SyntaxKind.NullKeyword); + return createToken(SyntaxKind.NullKeyword); } // @api function createTrue() { - return createToken(ts.SyntaxKind.TrueKeyword); + return createToken(SyntaxKind.TrueKeyword); } // @api function createFalse() { - return createToken(ts.SyntaxKind.FalseKeyword); + return createToken(SyntaxKind.FalseKeyword); } // @@ -1101,28 +1181,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createModifier(kind: T) { + function createModifier(kind: T) { return createToken(kind); } // @api - function createModifiersFromModifierFlags(flags: ts.ModifierFlags) { - const result: ts.Modifier[] = []; - if (flags & ts.ModifierFlags.Export) result.push(createModifier(ts.SyntaxKind.ExportKeyword)); - if (flags & ts.ModifierFlags.Ambient) result.push(createModifier(ts.SyntaxKind.DeclareKeyword)); - if (flags & ts.ModifierFlags.Default) result.push(createModifier(ts.SyntaxKind.DefaultKeyword)); - if (flags & ts.ModifierFlags.Const) result.push(createModifier(ts.SyntaxKind.ConstKeyword)); - if (flags & ts.ModifierFlags.Public) result.push(createModifier(ts.SyntaxKind.PublicKeyword)); - if (flags & ts.ModifierFlags.Private) result.push(createModifier(ts.SyntaxKind.PrivateKeyword)); - if (flags & ts.ModifierFlags.Protected) result.push(createModifier(ts.SyntaxKind.ProtectedKeyword)); - if (flags & ts.ModifierFlags.Abstract) result.push(createModifier(ts.SyntaxKind.AbstractKeyword)); - if (flags & ts.ModifierFlags.Static) result.push(createModifier(ts.SyntaxKind.StaticKeyword)); - if (flags & ts.ModifierFlags.Override) result.push(createModifier(ts.SyntaxKind.OverrideKeyword)); - if (flags & ts.ModifierFlags.Readonly) result.push(createModifier(ts.SyntaxKind.ReadonlyKeyword)); - if (flags & ts.ModifierFlags.Accessor) result.push(createModifier(ts.SyntaxKind.AccessorKeyword)); - if (flags & ts.ModifierFlags.Async) result.push(createModifier(ts.SyntaxKind.AsyncKeyword)); - if (flags & ts.ModifierFlags.In) result.push(createModifier(ts.SyntaxKind.InKeyword)); - if (flags & ts.ModifierFlags.Out) result.push(createModifier(ts.SyntaxKind.OutKeyword)); + function createModifiersFromModifierFlags(flags: ModifierFlags) { + const result: Modifier[] = []; + if (flags & ModifierFlags.Export) result.push(createModifier(SyntaxKind.ExportKeyword)); + if (flags & ModifierFlags.Ambient) result.push(createModifier(SyntaxKind.DeclareKeyword)); + if (flags & ModifierFlags.Default) result.push(createModifier(SyntaxKind.DefaultKeyword)); + if (flags & ModifierFlags.Const) result.push(createModifier(SyntaxKind.ConstKeyword)); + if (flags & ModifierFlags.Public) result.push(createModifier(SyntaxKind.PublicKeyword)); + if (flags & ModifierFlags.Private) result.push(createModifier(SyntaxKind.PrivateKeyword)); + if (flags & ModifierFlags.Protected) result.push(createModifier(SyntaxKind.ProtectedKeyword)); + if (flags & ModifierFlags.Abstract) result.push(createModifier(SyntaxKind.AbstractKeyword)); + if (flags & ModifierFlags.Static) result.push(createModifier(SyntaxKind.StaticKeyword)); + if (flags & ModifierFlags.Override) result.push(createModifier(SyntaxKind.OverrideKeyword)); + if (flags & ModifierFlags.Readonly) result.push(createModifier(SyntaxKind.ReadonlyKeyword)); + if (flags & ModifierFlags.Accessor) result.push(createModifier(SyntaxKind.AccessorKeyword)); + if (flags & ModifierFlags.Async) result.push(createModifier(SyntaxKind.AsyncKeyword)); + if (flags & ModifierFlags.In) result.push(createModifier(SyntaxKind.InKeyword)); + if (flags & ModifierFlags.Out) result.push(createModifier(SyntaxKind.OutKeyword)); return result.length ? result : undefined; } @@ -1131,8 +1211,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createQualifiedName(left: ts.EntityName, right: string | ts.Identifier) { - const node = createBaseNode(ts.SyntaxKind.QualifiedName); + function createQualifiedName(left: EntityName, right: string | Identifier) { + const node = createBaseNode(SyntaxKind.QualifiedName); node.left = left; node.right = asName(right); node.transformFlags |= @@ -1142,7 +1222,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateQualifiedName(node: ts.QualifiedName, left: ts.EntityName, right: ts.Identifier) { + function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { return node.left !== left || node.right !== right ? update(createQualifiedName(left, right), node) @@ -1150,18 +1230,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createComputedPropertyName(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.ComputedPropertyName); + function createComputedPropertyName(expression: Expression) { + const node = createBaseNode(SyntaxKind.ComputedPropertyName); node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsComputedPropertyName; + TransformFlags.ContainsES2015 | + TransformFlags.ContainsComputedPropertyName; return node; } // @api - function updateComputedPropertyName(node: ts.ComputedPropertyName, expression: ts.Expression) { + function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { return node.expression !== expression ? update(createComputedPropertyName(expression), node) : node; @@ -1172,20 +1252,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createTypeParameterDeclaration(modifiers: readonly ts.Modifier[] | undefined, name: string | ts.Identifier, constraint?: ts.TypeNode, defaultType?: ts.TypeNode): ts.TypeParameterDeclaration { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.TypeParameter, + function createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration { + const node = createBaseNamedDeclaration( + SyntaxKind.TypeParameter, modifiers, name ); node.constraint = constraint; node.default = defaultType; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeParameterDeclaration(node: ts.TypeParameterDeclaration, modifiers: readonly ts.Modifier[] | undefined, name: ts.Identifier, constraint: ts.TypeNode | undefined, defaultType: ts.TypeNode | undefined): ts.TypeParameterDeclaration { + function updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration { return node.modifiers !== modifiers || node.name !== name || node.constraint !== constraint @@ -1196,15 +1276,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createParameterDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - dotDotDotToken: ts.DotDotDotToken | undefined, - name: string | ts.BindingName, - questionToken?: ts.QuestionToken, - type?: ts.TypeNode, - initializer?: ts.Expression + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken?: QuestionToken, + type?: TypeNode, + initializer?: Expression ) { - const node = createBaseVariableLikeDeclaration( - ts.SyntaxKind.Parameter, + const node = createBaseVariableLikeDeclaration( + SyntaxKind.Parameter, modifiers, name, type, @@ -1212,29 +1292,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); node.dotDotDotToken = dotDotDotToken; node.questionToken = questionToken; - if (ts.isThisIdentifier(node.name)) { - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + if (isThisIdentifier(node.name)) { + node.transformFlags = TransformFlags.ContainsTypeScript; } else { node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | propagateChildFlags(node.questionToken); - if (questionToken) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.ParameterPropertyModifier) node.transformFlags |= ts.TransformFlags.ContainsTypeScriptClassSyntax; - if (initializer || dotDotDotToken) node.transformFlags |= ts.TransformFlags.ContainsES2015; + if (questionToken) node.transformFlags |= TransformFlags.ContainsTypeScript; + if (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier) node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; + if (initializer || dotDotDotToken) node.transformFlags |= TransformFlags.ContainsES2015; } return node; } // @api function updateParameterDeclaration( - node: ts.ParameterDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - dotDotDotToken: ts.DotDotDotToken | undefined, - name: string | ts.BindingName, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + node: ParameterDeclaration, + modifiers: readonly ModifierLike[] | undefined, + dotDotDotToken: DotDotDotToken | undefined, + name: string | BindingName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined ) { return node.modifiers !== modifiers || node.dotDotDotToken !== dotDotDotToken @@ -1247,19 +1327,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createDecorator(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.Decorator); + function createDecorator(expression: Expression) { + const node = createBaseNode(SyntaxKind.Decorator); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsTypeScript | - ts.TransformFlags.ContainsTypeScriptClassSyntax | - ts.TransformFlags.ContainsDecorators; + TransformFlags.ContainsTypeScript | + TransformFlags.ContainsTypeScriptClassSyntax | + TransformFlags.ContainsDecorators; return node; } // @api - function updateDecorator(node: ts.Decorator, expression: ts.Expression) { + function updateDecorator(node: Decorator, expression: Expression) { return node.expression !== expression ? update(createDecorator(expression), node) : node; @@ -1271,19 +1351,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createPropertySignature( - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.PropertyName | string, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined - ): ts.PropertySignature { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.PropertySignature, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName | string, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined + ): PropertySignature { + const node = createBaseNamedDeclaration( + SyntaxKind.PropertySignature, modifiers, name ); node.type = type; node.questionToken = questionToken; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; // The following properties are used only to report grammar errors node.initializer = undefined; @@ -1292,11 +1372,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updatePropertySignature( - node: ts.PropertySignature, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - type: ts.TypeNode | undefined + node: PropertySignature, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + type: TypeNode | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1306,7 +1386,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdatePropertySignature(updated: ts.Mutable, original: ts.PropertySignature) { + function finishUpdatePropertySignature(updated: Mutable, original: PropertySignature) { if (updated !== original) { // copy children used only for error reporting updated.initializer = original.initializer; @@ -1316,47 +1396,47 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createPropertyDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | ts.ExclamationToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined ) { - const node = createBaseVariableLikeDeclaration( - ts.SyntaxKind.PropertyDeclaration, + const node = createBaseVariableLikeDeclaration( + SyntaxKind.PropertyDeclaration, modifiers, name, type, initializer ); - node.questionToken = questionOrExclamationToken && ts.isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; - node.exclamationToken = questionOrExclamationToken && ts.isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; + node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; + node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; node.transformFlags |= propagateChildFlags(node.questionToken) | propagateChildFlags(node.exclamationToken) | - ts.TransformFlags.ContainsClassFields; - if (ts.isComputedPropertyName(node.name) || (ts.hasStaticModifier(node) && node.initializer)) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScriptClassSyntax; + TransformFlags.ContainsClassFields; + if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { + node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; } - if (questionOrExclamationToken || ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Ambient) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + if (questionOrExclamationToken || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { + node.transformFlags |= TransformFlags.ContainsTypeScript; } return node; } // @api function updatePropertyDeclaration( - node: ts.PropertyDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.PropertyName, - questionOrExclamationToken: ts.QuestionToken | ts.ExclamationToken | undefined, - type: ts.TypeNode | undefined, - initializer: ts.Expression | undefined + node: PropertyDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionOrExclamationToken: QuestionToken | ExclamationToken | undefined, + type: TypeNode | undefined, + initializer: Expression | undefined ) { return node.modifiers !== modifiers || node.name !== name - || node.questionToken !== (questionOrExclamationToken !== undefined && ts.isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) - || node.exclamationToken !== (questionOrExclamationToken !== undefined && ts.isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) + || node.questionToken !== (questionOrExclamationToken !== undefined && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) + || node.exclamationToken !== (questionOrExclamationToken !== undefined && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) || node.type !== type || node.initializer !== initializer ? update(createPropertyDeclaration(modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -1365,15 +1445,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createMethodSignature( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined ) { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.MethodSignature, + const node = createBaseSignatureDeclaration( + SyntaxKind.MethodSignature, modifiers, name, typeParameters, @@ -1381,19 +1461,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN type ); node.questionToken = questionToken; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateMethodSignature( - node: ts.MethodSignature, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: MethodSignature, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1407,17 +1487,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createMethodDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: string | ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.MethodDeclaration, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.MethodDeclaration, modifiers, name, typeParameters, @@ -1430,20 +1510,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.transformFlags |= propagateChildFlags(node.asteriskToken) | propagateChildFlags(node.questionToken) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; if (questionToken) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Async) { + if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { if (asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2018; } else { - node.transformFlags |= ts.TransformFlags.ContainsES2017; + node.transformFlags |= TransformFlags.ContainsES2017; } } else if (asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsGenerator; + node.transformFlags |= TransformFlags.ContainsGenerator; } // The following properties are used only to report grammar errors @@ -1453,15 +1533,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateMethodDeclaration( - node: ts.MethodDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + node: MethodDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.modifiers !== modifiers || node.asteriskToken !== asteriskToken @@ -1475,7 +1555,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateMethodDeclaration(updated: ts.Mutable, original: ts.MethodDeclaration) { + function finishUpdateMethodDeclaration(updated: Mutable, original: MethodDeclaration) { if (updated !== original) { updated.exclamationToken = original.exclamationToken; } @@ -1484,16 +1564,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassStaticBlockDeclaration( - body: ts.Block - ): ts.ClassStaticBlockDeclaration { - const node = createBaseGenericNamedDeclaration( - ts.SyntaxKind.ClassStaticBlockDeclaration, + body: Block + ): ClassStaticBlockDeclaration { + const node = createBaseGenericNamedDeclaration( + SyntaxKind.ClassStaticBlockDeclaration, /*modifiers*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined ); node.body = body; - node.transformFlags = propagateChildFlags(body) | ts.TransformFlags.ContainsClassFields; + node.transformFlags = propagateChildFlags(body) | TransformFlags.ContainsClassFields; // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -1503,15 +1583,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateClassStaticBlockDeclaration( - node: ts.ClassStaticBlockDeclaration, - body: ts.Block - ): ts.ClassStaticBlockDeclaration { + node: ClassStaticBlockDeclaration, + body: Block + ): ClassStaticBlockDeclaration { return node.body !== body ? finishUpdateClassStaticBlockDeclaration(createClassStaticBlockDeclaration(body), node) : node; } - function finishUpdateClassStaticBlockDeclaration(updated: ts.Mutable, original: ts.ClassStaticBlockDeclaration) { + function finishUpdateClassStaticBlockDeclaration(updated: Mutable, original: ClassStaticBlockDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; updated.modifiers = original.modifiers; @@ -1521,12 +1601,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createConstructorDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.Constructor, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.Constructor, modifiers, /*name*/ undefined, /*typeParameters*/ undefined, @@ -1534,7 +1614,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN /*type*/ undefined, body ); - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.transformFlags |= TransformFlags.ContainsES2015; // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -1545,10 +1625,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateConstructorDeclaration( - node: ts.ConstructorDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + node: ConstructorDeclaration, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { return node.modifiers !== modifiers || node.parameters !== parameters @@ -1557,7 +1637,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateConstructorDeclaration(updated: ts.Mutable, original: ts.ConstructorDeclaration) { + function finishUpdateConstructorDeclaration(updated: Mutable, original: ConstructorDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; updated.typeParameters = original.typeParameters; @@ -1568,14 +1648,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createGetAccessorDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.GetAccessor, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.GetAccessor, modifiers, name, /*typeParameters*/ undefined, @@ -1591,12 +1671,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateGetAccessorDeclaration( - node: ts.GetAccessorDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + node: GetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1607,7 +1687,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateGetAccessorDeclaration(updated: ts.Mutable, original: ts.GetAccessorDeclaration) { + function finishUpdateGetAccessorDeclaration(updated: Mutable, original: GetAccessorDeclaration) { if (updated !== original) { updated.typeParameters = original.typeParameters; } @@ -1616,13 +1696,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createSetAccessorDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + modifiers: readonly ModifierLike[] | undefined, + name: string | PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.SetAccessor, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.SetAccessor, modifiers, name, /*typeParameters*/ undefined, @@ -1639,11 +1719,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateSetAccessorDeclaration( - node: ts.SetAccessorDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.PropertyName, - parameters: readonly ts.ParameterDeclaration[], - body: ts.Block | undefined + node: SetAccessorDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: PropertyName, + parameters: readonly ParameterDeclaration[], + body: Block | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -1653,7 +1733,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateSetAccessorDeclaration(updated: ts.Mutable, original: ts.SetAccessorDeclaration) { + function finishUpdateSetAccessorDeclaration(updated: Mutable, original: SetAccessorDeclaration) { if (updated !== original) { updated.typeParameters = original.typeParameters; updated.type = original.type; @@ -1663,28 +1743,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createCallSignature( - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.CallSignatureDeclaration { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.CallSignature, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): CallSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.CallSignature, /*modifiers*/ undefined, /*name*/ undefined, typeParameters, parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateCallSignature( - node: ts.CallSignatureDeclaration, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: CallSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.typeParameters !== typeParameters || node.parameters !== parameters @@ -1695,28 +1775,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createConstructSignature( - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.ConstructSignatureDeclaration { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.ConstructSignature, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): ConstructSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.ConstructSignature, /*modifiers*/ undefined, /*name*/ undefined, typeParameters, parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateConstructSignature( - node: ts.ConstructSignatureDeclaration, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: ConstructSignatureDeclaration, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.typeParameters !== typeParameters || node.parameters !== parameters @@ -1727,28 +1807,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createIndexSignature( - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.IndexSignatureDeclaration { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.IndexSignature, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): IndexSignatureDeclaration { + const node = createBaseSignatureDeclaration( + SyntaxKind.IndexSignature, modifiers, /*name*/ undefined, /*typeParameters*/ undefined, parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateIndexSignature( - node: ts.IndexSignatureDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode + node: IndexSignatureDeclaration, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode ) { return node.parameters !== parameters || node.type !== type @@ -1758,16 +1838,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTemplateLiteralTypeSpan(type: ts.TypeNode, literal: ts.TemplateMiddle | ts.TemplateTail) { - const node = createBaseNode(ts.SyntaxKind.TemplateLiteralTypeSpan); + function createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail) { + const node = createBaseNode(SyntaxKind.TemplateLiteralTypeSpan); node.type = type; node.literal = literal; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTemplateLiteralTypeSpan(node: ts.TemplateLiteralTypeSpan, type: ts.TypeNode, literal: ts.TemplateMiddle | ts.TemplateTail) { + function updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail) { return node.type !== type || node.literal !== literal ? update(createTemplateLiteralTypeSpan(type, literal), node) @@ -1779,22 +1859,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createKeywordTypeNode(kind: TKind) { + function createKeywordTypeNode(kind: TKind) { return createToken(kind); } // @api - function createTypePredicateNode(assertsModifier: ts.AssertsKeyword | undefined, parameterName: ts.Identifier | ts.ThisTypeNode | string, type: ts.TypeNode | undefined) { - const node = createBaseNode(ts.SyntaxKind.TypePredicate); + function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) { + const node = createBaseNode(SyntaxKind.TypePredicate); node.assertsModifier = assertsModifier; node.parameterName = asName(parameterName); node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypePredicateNode(node: ts.TypePredicateNode, assertsModifier: ts.AssertsKeyword | undefined, parameterName: ts.Identifier | ts.ThisTypeNode, type: ts.TypeNode | undefined) { + function updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) { return node.assertsModifier !== assertsModifier || node.parameterName !== parameterName || node.type !== type @@ -1803,16 +1883,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTypeReferenceNode(typeName: string | ts.EntityName, typeArguments: readonly ts.TypeNode[] | undefined) { - const node = createBaseNode(ts.SyntaxKind.TypeReference); + function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) { + const node = createBaseNode(SyntaxKind.TypeReference); node.typeName = asName(typeName); node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments)); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeReferenceNode(node: ts.TypeReferenceNode, typeName: ts.EntityName, typeArguments: ts.NodeArray | undefined) { + function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray | undefined) { return node.typeName !== typeName || node.typeArguments !== typeArguments ? update(createTypeReferenceNode(typeName, typeArguments), node) @@ -1821,19 +1901,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createFunctionTypeNode( - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.FunctionTypeNode { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.FunctionType, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): FunctionTypeNode { + const node = createBaseSignatureDeclaration( + SyntaxKind.FunctionType, /*modifiers*/ undefined, /*name*/ undefined, typeParameters, parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; // The following properties are used only to report grammar errors node.modifiers = undefined; @@ -1842,10 +1922,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateFunctionTypeNode( - node: ts.FunctionTypeNode, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: FunctionTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.typeParameters !== typeParameters || node.parameters !== parameters @@ -1854,7 +1934,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateFunctionTypeNode(updated: ts.Mutable, original: ts.FunctionTypeNode) { + function finishUpdateFunctionTypeNode(updated: Mutable, original: FunctionTypeNode) { if (updated !== original) { updated.modifiers = original.modifiers; } @@ -1865,33 +1945,33 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN function createConstructorTypeNode(...args: Parameters) { return args.length === 4 ? createConstructorTypeNode1(...args) : args.length === 3 ? createConstructorTypeNode2(...args) : - ts.Debug.fail("Incorrect number of arguments specified."); + Debug.fail("Incorrect number of arguments specified."); } function createConstructorTypeNode1( - modifiers: readonly ts.Modifier[] | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.ConstructorTypeNode { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.ConstructorType, + modifiers: readonly Modifier[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): ConstructorTypeNode { + const node = createBaseSignatureDeclaration( + SyntaxKind.ConstructorType, modifiers, /*name*/ undefined, typeParameters, parameters, type ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } /** @deprecated */ function createConstructorTypeNode2( - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined - ): ts.ConstructorTypeNode { + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined + ): ConstructorTypeNode { return createConstructorTypeNode1(/*modifiers*/ undefined, typeParameters, parameters, type); } @@ -1899,15 +1979,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN function updateConstructorTypeNode(...args: Parameters) { return args.length === 5 ? updateConstructorTypeNode1(...args) : args.length === 4 ? updateConstructorTypeNode2(...args) : - ts.Debug.fail("Incorrect number of arguments specified."); + Debug.fail("Incorrect number of arguments specified."); } function updateConstructorTypeNode1( - node: ts.ConstructorTypeNode, - modifiers: readonly ts.Modifier[] | undefined, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: ConstructorTypeNode, + modifiers: readonly Modifier[] | undefined, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return node.modifiers !== modifiers || node.typeParameters !== typeParameters @@ -1919,25 +1999,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN /** @deprecated */ function updateConstructorTypeNode2( - node: ts.ConstructorTypeNode, - typeParameters: ts.NodeArray | undefined, - parameters: ts.NodeArray, - type: ts.TypeNode | undefined + node: ConstructorTypeNode, + typeParameters: NodeArray | undefined, + parameters: NodeArray, + type: TypeNode | undefined ) { return updateConstructorTypeNode1(node, node.modifiers, typeParameters, parameters, type); } // @api - function createTypeQueryNode(exprName: ts.EntityName, typeArguments?: readonly ts.TypeNode[]) { - const node = createBaseNode(ts.SyntaxKind.TypeQuery); + function createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]) { + const node = createBaseNode(SyntaxKind.TypeQuery); node.exprName = exprName; node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeQueryNode(node: ts.TypeQueryNode, exprName: ts.EntityName, typeArguments?: readonly ts.TypeNode[]) { + function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName, typeArguments?: readonly TypeNode[]) { return node.exprName !== exprName || node.typeArguments !== typeArguments ? update(createTypeQueryNode(exprName, typeArguments), node) @@ -1945,63 +2025,63 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTypeLiteralNode(members: readonly ts.TypeElement[] | undefined) { - const node = createBaseNode(ts.SyntaxKind.TypeLiteral); + function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { + const node = createBaseNode(SyntaxKind.TypeLiteral); node.members = createNodeArray(members); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeLiteralNode(node: ts.TypeLiteralNode, members: ts.NodeArray) { + function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray) { return node.members !== members ? update(createTypeLiteralNode(members), node) : node; } // @api - function createArrayTypeNode(elementType: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.ArrayType); + function createArrayTypeNode(elementType: TypeNode) { + const node = createBaseNode(SyntaxKind.ArrayType); node.elementType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(elementType); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateArrayTypeNode(node: ts.ArrayTypeNode, elementType: ts.TypeNode): ts.ArrayTypeNode { + function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode { return node.elementType !== elementType ? update(createArrayTypeNode(elementType), node) : node; } // @api - function createTupleTypeNode(elements: readonly (ts.TypeNode | ts.NamedTupleMember)[]) { - const node = createBaseNode(ts.SyntaxKind.TupleType); + function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) { + const node = createBaseNode(SyntaxKind.TupleType); node.elements = createNodeArray(parenthesizerRules().parenthesizeElementTypesOfTupleType(elements)); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTupleTypeNode(node: ts.TupleTypeNode, elements: readonly (ts.TypeNode | ts.NamedTupleMember)[]) { + function updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]) { return node.elements !== elements ? update(createTupleTypeNode(elements), node) : node; } // @api - function createNamedTupleMember(dotDotDotToken: ts.DotDotDotToken | undefined, name: ts.Identifier, questionToken: ts.QuestionToken | undefined, type: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.NamedTupleMember); + function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { + const node = createBaseNode(SyntaxKind.NamedTupleMember); node.dotDotDotToken = dotDotDotToken; node.name = name; node.questionToken = questionToken; node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateNamedTupleMember(node: ts.NamedTupleMember, dotDotDotToken: ts.DotDotDotToken | undefined, name: ts.Identifier, questionToken: ts.QuestionToken | undefined, type: ts.TypeNode) { + function updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { return node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.questionToken !== questionToken @@ -2011,81 +2091,81 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createOptionalTypeNode(type: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.OptionalType); + function createOptionalTypeNode(type: TypeNode) { + const node = createBaseNode(SyntaxKind.OptionalType); node.type = parenthesizerRules().parenthesizeTypeOfOptionalType(type); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateOptionalTypeNode(node: ts.OptionalTypeNode, type: ts.TypeNode): ts.OptionalTypeNode { + function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode { return node.type !== type ? update(createOptionalTypeNode(type), node) : node; } // @api - function createRestTypeNode(type: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.RestType); + function createRestTypeNode(type: TypeNode) { + const node = createBaseNode(SyntaxKind.RestType); node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateRestTypeNode(node: ts.RestTypeNode, type: ts.TypeNode): ts.RestTypeNode { + function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode { return node.type !== type ? update(createRestTypeNode(type), node) : node; } - function createUnionOrIntersectionTypeNode(kind: ts.SyntaxKind.UnionType | ts.SyntaxKind.IntersectionType, types: readonly ts.TypeNode[], parenthesize: (nodes: readonly ts.TypeNode[]) => readonly ts.TypeNode[]) { - const node = createBaseNode(kind); + function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[], parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]) { + const node = createBaseNode(kind); node.types = factory.createNodeArray(parenthesize(types)); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } - function updateUnionOrIntersectionTypeNode(node: T, types: ts.NodeArray, parenthesize: (nodes: readonly ts.TypeNode[]) => readonly ts.TypeNode[]): T { + function updateUnionOrIntersectionTypeNode(node: T, types: NodeArray, parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]): T { return node.types !== types ? update(createUnionOrIntersectionTypeNode(node.kind, types, parenthesize) as T, node) : node; } // @api - function createUnionTypeNode(types: readonly ts.TypeNode[]): ts.UnionTypeNode { - return createUnionOrIntersectionTypeNode(ts.SyntaxKind.UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as ts.UnionTypeNode; + function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode { + return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as UnionTypeNode; } // @api - function updateUnionTypeNode(node: ts.UnionTypeNode, types: ts.NodeArray) { + function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray) { return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType); } // @api - function createIntersectionTypeNode(types: readonly ts.TypeNode[]): ts.IntersectionTypeNode { - return createUnionOrIntersectionTypeNode(ts.SyntaxKind.IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as ts.IntersectionTypeNode; + function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode { + return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode; } // @api - function updateIntersectionTypeNode(node: ts.IntersectionTypeNode, types: ts.NodeArray) { + function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray) { return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType); } // @api - function createConditionalTypeNode(checkType: ts.TypeNode, extendsType: ts.TypeNode, trueType: ts.TypeNode, falseType: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.ConditionalType); + function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { + const node = createBaseNode(SyntaxKind.ConditionalType); node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType); node.extendsType = parenthesizerRules().parenthesizeExtendsTypeOfConditionalType(extendsType); node.trueType = trueType; node.falseType = falseType; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateConditionalTypeNode(node: ts.ConditionalTypeNode, checkType: ts.TypeNode, extendsType: ts.TypeNode, trueType: ts.TypeNode, falseType: ts.TypeNode) { + function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) { return node.checkType !== checkType || node.extendsType !== extendsType || node.trueType !== trueType @@ -2095,31 +2175,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createInferTypeNode(typeParameter: ts.TypeParameterDeclaration) { - const node = createBaseNode(ts.SyntaxKind.InferType); + function createInferTypeNode(typeParameter: TypeParameterDeclaration) { + const node = createBaseNode(SyntaxKind.InferType); node.typeParameter = typeParameter; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateInferTypeNode(node: ts.InferTypeNode, typeParameter: ts.TypeParameterDeclaration) { + function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) { return node.typeParameter !== typeParameter ? update(createInferTypeNode(typeParameter), node) : node; } // @api - function createTemplateLiteralType(head: ts.TemplateHead, templateSpans: readonly ts.TemplateLiteralTypeSpan[]) { - const node = createBaseNode(ts.SyntaxKind.TemplateLiteralType); + function createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { + const node = createBaseNode(SyntaxKind.TemplateLiteralType); node.head = head; node.templateSpans = createNodeArray(templateSpans); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTemplateLiteralType(node: ts.TemplateLiteralTypeNode, head: ts.TemplateHead, templateSpans: readonly ts.TemplateLiteralTypeSpan[]) { + function updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) { return node.head !== head || node.templateSpans !== templateSpans ? update(createTemplateLiteralType(head, templateSpans), node) @@ -2128,31 +2208,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createImportTypeNode( - argument: ts.TypeNode, - assertions?: ts.ImportTypeAssertionContainer, - qualifier?: ts.EntityName, - typeArguments?: readonly ts.TypeNode[], + argument: TypeNode, + assertions?: ImportTypeAssertionContainer, + qualifier?: EntityName, + typeArguments?: readonly TypeNode[], isTypeOf = false - ): ts.ImportTypeNode { - const node = createBaseNode(ts.SyntaxKind.ImportType); + ): ImportTypeNode { + const node = createBaseNode(SyntaxKind.ImportType); node.argument = argument; node.assertions = assertions; node.qualifier = qualifier; node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); node.isTypeOf = isTypeOf; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api function updateImportTypeNode( - node: ts.ImportTypeNode, - argument: ts.TypeNode, - assertions: ts.ImportTypeAssertionContainer | undefined, - qualifier: ts.EntityName | undefined, - typeArguments: readonly ts.TypeNode[] | undefined, + node: ImportTypeNode, + argument: TypeNode, + assertions: ImportTypeAssertionContainer | undefined, + qualifier: EntityName | undefined, + typeArguments: readonly TypeNode[] | undefined, isTypeOf: boolean = node.isTypeOf - ): ts.ImportTypeNode { + ): ImportTypeNode { return node.argument !== argument || node.assertions !== assertions || node.qualifier !== qualifier @@ -2163,15 +2243,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createParenthesizedType(type: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.ParenthesizedType); + function createParenthesizedType(type: TypeNode) { + const node = createBaseNode(SyntaxKind.ParenthesizedType); node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateParenthesizedType(node: ts.ParenthesizedTypeNode, type: ts.TypeNode) { + function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) { return node.type !== type ? update(createParenthesizedType(type), node) : node; @@ -2179,40 +2259,40 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createThisTypeNode() { - const node = createBaseNode(ts.SyntaxKind.ThisType); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + const node = createBaseNode(SyntaxKind.ThisType); + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function createTypeOperatorNode(operator: ts.SyntaxKind.KeyOfKeyword | ts.SyntaxKind.UniqueKeyword | ts.SyntaxKind.ReadonlyKeyword, type: ts.TypeNode): ts.TypeOperatorNode { - const node = createBaseNode(ts.SyntaxKind.TypeOperator); + function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode { + const node = createBaseNode(SyntaxKind.TypeOperator); node.operator = operator; - node.type = operator === ts.SyntaxKind.ReadonlyKeyword ? + node.type = operator === SyntaxKind.ReadonlyKeyword ? parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) : parenthesizerRules().parenthesizeOperandOfTypeOperator(type); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeOperatorNode(node: ts.TypeOperatorNode, type: ts.TypeNode) { + function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) { return node.type !== type ? update(createTypeOperatorNode(node.operator, type), node) : node; } // @api - function createIndexedAccessTypeNode(objectType: ts.TypeNode, indexType: ts.TypeNode) { - const node = createBaseNode(ts.SyntaxKind.IndexedAccessType); + function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) { + const node = createBaseNode(SyntaxKind.IndexedAccessType); node.objectType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(objectType); node.indexType = indexType; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateIndexedAccessTypeNode(node: ts.IndexedAccessTypeNode, objectType: ts.TypeNode, indexType: ts.TypeNode) { + function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) { return node.objectType !== objectType || node.indexType !== indexType ? update(createIndexedAccessTypeNode(objectType, indexType), node) @@ -2220,20 +2300,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createMappedTypeNode(readonlyToken: ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken | undefined, typeParameter: ts.TypeParameterDeclaration, nameType: ts.TypeNode | undefined, questionToken: ts.QuestionToken | ts.PlusToken | ts.MinusToken | undefined, type: ts.TypeNode | undefined, members: readonly ts.TypeElement[] | undefined): ts.MappedTypeNode { - const node = createBaseNode(ts.SyntaxKind.MappedType); + function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { + const node = createBaseNode(SyntaxKind.MappedType); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; node.nameType = nameType; node.questionToken = questionToken; node.type = type; node.members = members && createNodeArray(members); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateMappedTypeNode(node: ts.MappedTypeNode, readonlyToken: ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken | undefined, typeParameter: ts.TypeParameterDeclaration, nameType: ts.TypeNode | undefined, questionToken: ts.QuestionToken | ts.PlusToken | ts.MinusToken | undefined, type: ts.TypeNode | undefined, members: readonly ts.TypeElement[] | undefined): ts.MappedTypeNode { + function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { return node.readonlyToken !== readonlyToken || node.typeParameter !== typeParameter || node.nameType !== nameType @@ -2245,15 +2325,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createLiteralTypeNode(literal: ts.LiteralTypeNode["literal"]) { - const node = createBaseNode(ts.SyntaxKind.LiteralType); + function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) { + const node = createBaseNode(SyntaxKind.LiteralType); node.literal = literal; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; return node; } // @api - function updateLiteralTypeNode(node: ts.LiteralTypeNode, literal: ts.LiteralTypeNode["literal"]) { + function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) { return node.literal !== literal ? update(createLiteralTypeNode(literal), node) : node; @@ -2264,50 +2344,50 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createObjectBindingPattern(elements: readonly ts.BindingElement[]) { - const node = createBaseNode(ts.SyntaxKind.ObjectBindingPattern); + function createObjectBindingPattern(elements: readonly BindingElement[]) { + const node = createBaseNode(SyntaxKind.ObjectBindingPattern); node.elements = createNodeArray(elements); node.transformFlags |= propagateChildrenFlags(node.elements) | - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsBindingPattern; - if (node.transformFlags & ts.TransformFlags.ContainsRestOrSpread) { + TransformFlags.ContainsES2015 | + TransformFlags.ContainsBindingPattern; + if (node.transformFlags & TransformFlags.ContainsRestOrSpread) { node.transformFlags |= - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsObjectRestOrSpread; + TransformFlags.ContainsES2018 | + TransformFlags.ContainsObjectRestOrSpread; } return node; } // @api - function updateObjectBindingPattern(node: ts.ObjectBindingPattern, elements: readonly ts.BindingElement[]) { + function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) { return node.elements !== elements ? update(createObjectBindingPattern(elements), node) : node; } // @api - function createArrayBindingPattern(elements: readonly ts.ArrayBindingElement[]) { - const node = createBaseNode(ts.SyntaxKind.ArrayBindingPattern); + function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) { + const node = createBaseNode(SyntaxKind.ArrayBindingPattern); node.elements = createNodeArray(elements); node.transformFlags |= propagateChildrenFlags(node.elements) | - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsBindingPattern; + TransformFlags.ContainsES2015 | + TransformFlags.ContainsBindingPattern; return node; } // @api - function updateArrayBindingPattern(node: ts.ArrayBindingPattern, elements: readonly ts.ArrayBindingElement[]) { + function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) { return node.elements !== elements ? update(createArrayBindingPattern(elements), node) : node; } // @api - function createBindingElement(dotDotDotToken: ts.DotDotDotToken | undefined, propertyName: string | ts.PropertyName | undefined, name: string | ts.BindingName, initializer?: ts.Expression) { - const node = createBaseBindingLikeDeclaration( - ts.SyntaxKind.BindingElement, + function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { + const node = createBaseBindingLikeDeclaration( + SyntaxKind.BindingElement, /*modifiers*/ undefined, name, initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) @@ -2316,18 +2396,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.dotDotDotToken = dotDotDotToken; node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; if (node.propertyName) { - node.transformFlags |= ts.isIdentifier(node.propertyName) ? + node.transformFlags |= isIdentifier(node.propertyName) ? propagateIdentifierNameFlags(node.propertyName) : propagateChildFlags(node.propertyName); } - if (dotDotDotToken) node.transformFlags |= ts.TransformFlags.ContainsRestOrSpread; + if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread; return node; } // @api - function updateBindingElement(node: ts.BindingElement, dotDotDotToken: ts.DotDotDotToken | undefined, propertyName: ts.PropertyName | undefined, name: ts.BindingName, initializer: ts.Expression | undefined) { + function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) { return node.propertyName !== propertyName || node.dotDotDotToken !== dotDotDotToken || node.name !== name @@ -2340,20 +2420,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Expression // - function createBaseExpression(kind: T["kind"]) { + function createBaseExpression(kind: T["kind"]) { const node = createBaseNode(kind); // the following properties are commonly set by the checker/binder return node; } // @api - function createArrayLiteralExpression(elements?: readonly ts.Expression[], multiLine?: boolean) { - const node = createBaseExpression(ts.SyntaxKind.ArrayLiteralExpression); + function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) { + const node = createBaseExpression(SyntaxKind.ArrayLiteralExpression); // Ensure we add a trailing comma for something like `[NumericLiteral(1), NumericLiteral(2), OmittedExpresion]` so that // we end up with `[1, 2, ,]` instead of `[1, 2, ]` otherwise the `OmittedExpression` will just end up being treated like // a trailing comma. - const lastElement = elements && ts.lastOrUndefined(elements); - const elementsArray = createNodeArray(elements, lastElement && ts.isOmittedExpression(lastElement) ? true : undefined); + const lastElement = elements && lastOrUndefined(elements); + const elementsArray = createNodeArray(elements, lastElement && isOmittedExpression(lastElement) ? true : undefined); node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(elementsArray); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.elements); @@ -2361,15 +2441,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateArrayLiteralExpression(node: ts.ArrayLiteralExpression, elements: readonly ts.Expression[]) { + function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) { return node.elements !== elements ? update(createArrayLiteralExpression(elements, node.multiLine), node) : node; } // @api - function createObjectLiteralExpression(properties?: readonly ts.ObjectLiteralElementLike[], multiLine?: boolean) { - const node = createBaseExpression(ts.SyntaxKind.ObjectLiteralExpression); + function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { + const node = createBaseExpression(SyntaxKind.ObjectLiteralExpression); node.properties = createNodeArray(properties); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.properties); @@ -2377,36 +2457,36 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateObjectLiteralExpression(node: ts.ObjectLiteralExpression, properties: readonly ts.ObjectLiteralElementLike[]) { + function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) { return node.properties !== properties ? update(createObjectLiteralExpression(properties, node.multiLine), node) : node; } // @api - function createPropertyAccessExpression(expression: ts.Expression, name: string | ts.Identifier | ts.PrivateIdentifier) { - const node = createBaseExpression(ts.SyntaxKind.PropertyAccessExpression); + function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) { + const node = createBaseExpression(SyntaxKind.PropertyAccessExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.name = asName(name); node.transformFlags = propagateChildFlags(node.expression) | - (ts.isIdentifier(node.name) ? + (isIdentifier(node.name) ? propagateIdentifierNameFlags(node.name) : - propagateChildFlags(node.name) | ts.TransformFlags.ContainsPrivateIdentifierInExpression); - if (ts.isSuperKeyword(expression)) { + propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); + if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators node.transformFlags |= - ts.TransformFlags.ContainsES2017 | - ts.TransformFlags.ContainsES2018; + TransformFlags.ContainsES2017 | + TransformFlags.ContainsES2018; } return node; } // @api - function updatePropertyAccessExpression(node: ts.PropertyAccessExpression, expression: ts.Expression, name: ts.Identifier | ts.PrivateIdentifier) { - if (ts.isPropertyAccessChain(node)) { - return updatePropertyAccessChain(node, expression, node.questionDotToken, ts.cast(name, ts.isIdentifier)); + function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) { + if (isPropertyAccessChain(node)) { + return updatePropertyAccessChain(node, expression, node.questionDotToken, cast(name, isIdentifier)); } return node.expression !== expression || node.name !== name @@ -2415,25 +2495,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createPropertyAccessChain(expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, name: string | ts.Identifier | ts.PrivateIdentifier) { - const node = createBaseExpression(ts.SyntaxKind.PropertyAccessExpression); - node.flags |= ts.NodeFlags.OptionalChain; + function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) { + const node = createBaseExpression(SyntaxKind.PropertyAccessExpression); + node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); node.questionDotToken = questionDotToken; node.name = asName(name); node.transformFlags |= - ts.TransformFlags.ContainsES2020 | + TransformFlags.ContainsES2020 | propagateChildFlags(node.expression) | propagateChildFlags(node.questionDotToken) | - (ts.isIdentifier(node.name) ? + (isIdentifier(node.name) ? propagateIdentifierNameFlags(node.name) : - propagateChildFlags(node.name) | ts.TransformFlags.ContainsPrivateIdentifierInExpression); + propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); return node; } // @api - function updatePropertyAccessChain(node: ts.PropertyAccessChain, expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, name: ts.Identifier | ts.PrivateIdentifier) { - ts.Debug.assert(!!(node.flags & ts.NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead."); + function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier | PrivateIdentifier) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead."); // Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags // instead of using the default from createPropertyAccess return node.expression !== expression @@ -2444,26 +2524,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createElementAccessExpression(expression: ts.Expression, index: number | ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.ElementAccessExpression); + function createElementAccessExpression(expression: Expression, index: number | Expression) { + const node = createBaseExpression(SyntaxKind.ElementAccessExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.argumentExpression = asExpression(index); node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.argumentExpression); - if (ts.isSuperKeyword(expression)) { + if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators node.transformFlags |= - ts.TransformFlags.ContainsES2017 | - ts.TransformFlags.ContainsES2018; + TransformFlags.ContainsES2017 | + TransformFlags.ContainsES2018; } return node; } // @api - function updateElementAccessExpression(node: ts.ElementAccessExpression, expression: ts.Expression, argumentExpression: ts.Expression) { - if (ts.isElementAccessChain(node)) { + function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { + if (isElementAccessChain(node)) { return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression); } return node.expression !== expression @@ -2473,9 +2553,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createElementAccessChain(expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, index: number | ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.ElementAccessExpression); - node.flags |= ts.NodeFlags.OptionalChain; + function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { + const node = createBaseExpression(SyntaxKind.ElementAccessExpression); + node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); node.questionDotToken = questionDotToken; node.argumentExpression = asExpression(index); @@ -2483,13 +2563,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.expression) | propagateChildFlags(node.questionDotToken) | propagateChildFlags(node.argumentExpression) | - ts.TransformFlags.ContainsES2020; + TransformFlags.ContainsES2020; return node; } // @api - function updateElementAccessChain(node: ts.ElementAccessChain, expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, argumentExpression: ts.Expression) { - ts.Debug.assert(!!(node.flags & ts.NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead."); + function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead."); // Because we are updating an existing ElementAccessChain we want to inherit its emitFlags // instead of using the default from createElementAccess return node.expression !== expression @@ -2500,8 +2580,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createCallExpression(expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[] | undefined) { - const node = createBaseExpression(ts.SyntaxKind.CallExpression); + function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseExpression(SyntaxKind.CallExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.typeArguments = asNodeArray(typeArguments); node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); @@ -2510,20 +2590,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildrenFlags(node.typeArguments) | propagateChildrenFlags(node.arguments); if (node.typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - if (ts.isImportKeyword(node.expression)) { - node.transformFlags |= ts.TransformFlags.ContainsDynamicImport; + if (isImportKeyword(node.expression)) { + node.transformFlags |= TransformFlags.ContainsDynamicImport; } - else if (ts.isSuperProperty(node.expression)) { - node.transformFlags |= ts.TransformFlags.ContainsLexicalThis; + else if (isSuperProperty(node.expression)) { + node.transformFlags |= TransformFlags.ContainsLexicalThis; } return node; } // @api - function updateCallExpression(node: ts.CallExpression, expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[]) { - if (ts.isCallChain(node)) { + function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + if (isCallChain(node)) { return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray); } return node.expression !== expression @@ -2534,9 +2614,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createCallChain(expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[] | undefined) { - const node = createBaseExpression(ts.SyntaxKind.CallExpression); - node.flags |= ts.NodeFlags.OptionalChain; + function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseExpression(SyntaxKind.CallExpression); + node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); node.questionDotToken = questionDotToken; node.typeArguments = asNodeArray(typeArguments); @@ -2546,19 +2626,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.questionDotToken) | propagateChildrenFlags(node.typeArguments) | propagateChildrenFlags(node.arguments) | - ts.TransformFlags.ContainsES2020; + TransformFlags.ContainsES2020; if (node.typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - if (ts.isSuperProperty(node.expression)) { - node.transformFlags |= ts.TransformFlags.ContainsLexicalThis; + if (isSuperProperty(node.expression)) { + node.transformFlags |= TransformFlags.ContainsLexicalThis; } return node; } // @api - function updateCallChain(node: ts.CallChain, expression: ts.Expression, questionDotToken: ts.QuestionDotToken | undefined, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[]) { - ts.Debug.assert(!!(node.flags & ts.NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead."); + function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead."); return node.expression !== expression || node.questionDotToken !== questionDotToken || node.typeArguments !== typeArguments @@ -2568,8 +2648,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNewExpression(expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[] | undefined) { - const node = createBaseExpression(ts.SyntaxKind.NewExpression); + function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseExpression(SyntaxKind.NewExpression); node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; @@ -2577,15 +2657,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.expression) | propagateChildrenFlags(node.typeArguments) | propagateChildrenFlags(node.arguments) | - ts.TransformFlags.ContainsES2020; + TransformFlags.ContainsES2020; if (node.typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } return node; } // @api - function updateNewExpression(node: ts.NewExpression, expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, argumentsArray: readonly ts.Expression[] | undefined) { + function updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { return node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray @@ -2594,8 +2674,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTaggedTemplateExpression(tag: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, template: ts.TemplateLiteral) { - const node = createBaseExpression(ts.SyntaxKind.TaggedTemplateExpression); + function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { + const node = createBaseExpression(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag, /*optionalChain*/ false); node.typeArguments = asNodeArray(typeArguments); node.template = template; @@ -2603,18 +2683,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.tag) | propagateChildrenFlags(node.typeArguments) | propagateChildFlags(node.template) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; if (node.typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - if (ts.hasInvalidEscape(node.template)) { - node.transformFlags |= ts.TransformFlags.ContainsES2018; + if (hasInvalidEscape(node.template)) { + node.transformFlags |= TransformFlags.ContainsES2018; } return node; } // @api - function updateTaggedTemplateExpression(node: ts.TaggedTemplateExpression, tag: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined, template: ts.TemplateLiteral) { + function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { return node.tag !== tag || node.typeArguments !== typeArguments || node.template !== template @@ -2623,19 +2703,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTypeAssertion(type: ts.TypeNode, expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.TypeAssertionExpression); + function createTypeAssertion(type: TypeNode, expression: Expression) { + const node = createBaseExpression(SyntaxKind.TypeAssertionExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.type = type; node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.type) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateTypeAssertion(node: ts.TypeAssertion, type: ts.TypeNode, expression: ts.Expression) { + function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { return node.type !== type || node.expression !== expression ? update(createTypeAssertion(type, expression), node) @@ -2643,15 +2723,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createParenthesizedExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.ParenthesizedExpression); + function createParenthesizedExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.ParenthesizedExpression); node.expression = expression; node.transformFlags = propagateChildFlags(node.expression); return node; } // @api - function updateParenthesizedExpression(node: ts.ParenthesizedExpression, expression: ts.Expression) { + function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) { return node.expression !== expression ? update(createParenthesizedExpression(expression), node) : node; @@ -2659,16 +2739,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createFunctionExpression( - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[] | undefined, - type: ts.TypeNode | undefined, - body: ts.Block + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[] | undefined, + type: TypeNode | undefined, + body: Block ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.FunctionExpression, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionExpression, modifiers, name, typeParameters, @@ -2679,32 +2759,32 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.asteriskToken = asteriskToken; node.transformFlags |= propagateChildFlags(node.asteriskToken); if (node.typeParameters) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Async) { + if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { if (node.asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2018; } else { - node.transformFlags |= ts.TransformFlags.ContainsES2017; + node.transformFlags |= TransformFlags.ContainsES2017; } } else if (node.asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsGenerator; + node.transformFlags |= TransformFlags.ContainsGenerator; } return node; } // @api function updateFunctionExpression( - node: ts.FunctionExpression, - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block + node: FunctionExpression, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block ) { return node.name !== name || node.modifiers !== modifiers @@ -2719,15 +2799,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createArrowFunction( - modifiers: readonly ts.ModifierLike[] | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - equalsGreaterThanToken: ts.EqualsGreaterThanToken | undefined, - body: ts.ConciseBody + modifiers: readonly ModifierLike[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken | undefined, + body: ConciseBody ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.ArrowFunction, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.ArrowFunction, modifiers, /*name*/ undefined, typeParameters, @@ -2735,26 +2815,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN type, parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body) ); - node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(ts.SyntaxKind.EqualsGreaterThanToken); + node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind.EqualsGreaterThanToken); node.transformFlags |= propagateChildFlags(node.equalsGreaterThanToken) | - ts.TransformFlags.ContainsES2015; - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Async) { - node.transformFlags |= ts.TransformFlags.ContainsES2017 | ts.TransformFlags.ContainsLexicalThis; + TransformFlags.ContainsES2015; + if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { + node.transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis; } return node; } // @api function updateArrowFunction( - node: ts.ArrowFunction, - modifiers: readonly ts.ModifierLike[] | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - equalsGreaterThanToken: ts.EqualsGreaterThanToken, - body: ts.ConciseBody - ): ts.ArrowFunction { + node: ArrowFunction, + modifiers: readonly ModifierLike[] | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + equalsGreaterThanToken: EqualsGreaterThanToken, + body: ConciseBody + ): ArrowFunction { return node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters @@ -2766,119 +2846,119 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createDeleteExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.DeleteExpression); + function createDeleteExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.DeleteExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; } // @api - function updateDeleteExpression(node: ts.DeleteExpression, expression: ts.Expression) { + function updateDeleteExpression(node: DeleteExpression, expression: Expression) { return node.expression !== expression ? update(createDeleteExpression(expression), node) : node; } // @api - function createTypeOfExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.TypeOfExpression); + function createTypeOfExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.TypeOfExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; } // @api - function updateTypeOfExpression(node: ts.TypeOfExpression, expression: ts.Expression) { + function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) { return node.expression !== expression ? update(createTypeOfExpression(expression), node) : node; } // @api - function createVoidExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.VoidExpression); + function createVoidExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.VoidExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; } // @api - function updateVoidExpression(node: ts.VoidExpression, expression: ts.Expression) { + function updateVoidExpression(node: VoidExpression, expression: Expression) { return node.expression !== expression ? update(createVoidExpression(expression), node) : node; } // @api - function createAwaitExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.AwaitExpression); + function createAwaitExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.AwaitExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsES2017 | - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsAwait; + TransformFlags.ContainsES2017 | + TransformFlags.ContainsES2018 | + TransformFlags.ContainsAwait; return node; } // @api - function updateAwaitExpression(node: ts.AwaitExpression, expression: ts.Expression) { + function updateAwaitExpression(node: AwaitExpression, expression: Expression) { return node.expression !== expression ? update(createAwaitExpression(expression), node) : node; } // @api - function createPrefixUnaryExpression(operator: ts.PrefixUnaryOperator, operand: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.PrefixUnaryExpression); + function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { + const node = createBaseExpression(SyntaxKind.PrefixUnaryExpression); node.operator = operator; node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand); node.transformFlags |= propagateChildFlags(node.operand); // Only set this flag for non-generated identifiers and non-"local" names. See the // comment in `visitPreOrPostfixUnaryExpression` in module.ts - if ((operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken) && - ts.isIdentifier(node.operand) && - !ts.isGeneratedIdentifier(node.operand) && - !ts.isLocalName(node.operand)) { - node.transformFlags |= ts.TransformFlags.ContainsUpdateExpressionForIdentifier; + if ((operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken) && + isIdentifier(node.operand) && + !isGeneratedIdentifier(node.operand) && + !isLocalName(node.operand)) { + node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier; } return node; } // @api - function updatePrefixUnaryExpression(node: ts.PrefixUnaryExpression, operand: ts.Expression) { + function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) { return node.operand !== operand ? update(createPrefixUnaryExpression(node.operator, operand), node) : node; } // @api - function createPostfixUnaryExpression(operand: ts.Expression, operator: ts.PostfixUnaryOperator) { - const node = createBaseExpression(ts.SyntaxKind.PostfixUnaryExpression); + function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { + const node = createBaseExpression(SyntaxKind.PostfixUnaryExpression); node.operator = operator; node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand); node.transformFlags |= propagateChildFlags(node.operand); // Only set this flag for non-generated identifiers and non-"local" names. See the // comment in `visitPreOrPostfixUnaryExpression` in module.ts - if (ts.isIdentifier(node.operand) && - !ts.isGeneratedIdentifier(node.operand) && - !ts.isLocalName(node.operand)) { - node.transformFlags |= ts.TransformFlags.ContainsUpdateExpressionForIdentifier; + if (isIdentifier(node.operand) && + !isGeneratedIdentifier(node.operand) && + !isLocalName(node.operand)) { + node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier; } return node; } // @api - function updatePostfixUnaryExpression(node: ts.PostfixUnaryExpression, operand: ts.Expression) { + function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) { return node.operand !== operand ? update(createPostfixUnaryExpression(operand, node.operator), node) : node; } // @api - function createBinaryExpression(left: ts.Expression, operator: ts.BinaryOperator | ts.BinaryOperatorToken, right: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.BinaryExpression); + function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { + const node = createBaseExpression(SyntaxKind.BinaryExpression); const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left); @@ -2888,59 +2968,59 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.left) | propagateChildFlags(node.operatorToken) | propagateChildFlags(node.right); - if (operatorKind === ts.SyntaxKind.QuestionQuestionToken) { - node.transformFlags |= ts.TransformFlags.ContainsES2020; + if (operatorKind === SyntaxKind.QuestionQuestionToken) { + node.transformFlags |= TransformFlags.ContainsES2020; } - else if (operatorKind === ts.SyntaxKind.EqualsToken) { - if (ts.isObjectLiteralExpression(node.left)) { + else if (operatorKind === SyntaxKind.EqualsToken) { + if (isObjectLiteralExpression(node.left)) { node.transformFlags |= - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsDestructuringAssignment | + TransformFlags.ContainsES2015 | + TransformFlags.ContainsES2018 | + TransformFlags.ContainsDestructuringAssignment | propagateAssignmentPatternFlags(node.left); } - else if (ts.isArrayLiteralExpression(node.left)) { + else if (isArrayLiteralExpression(node.left)) { node.transformFlags |= - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsDestructuringAssignment | + TransformFlags.ContainsES2015 | + TransformFlags.ContainsDestructuringAssignment | propagateAssignmentPatternFlags(node.left); } } - else if (operatorKind === ts.SyntaxKind.AsteriskAsteriskToken || operatorKind === ts.SyntaxKind.AsteriskAsteriskEqualsToken) { - node.transformFlags |= ts.TransformFlags.ContainsES2016; + else if (operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken) { + node.transformFlags |= TransformFlags.ContainsES2016; } - else if (ts.isLogicalOrCoalescingAssignmentOperator(operatorKind)) { - node.transformFlags |= ts.TransformFlags.ContainsES2021; + else if (isLogicalOrCoalescingAssignmentOperator(operatorKind)) { + node.transformFlags |= TransformFlags.ContainsES2021; } - if (operatorKind === ts.SyntaxKind.InKeyword && ts.isPrivateIdentifier(node.left)) { - node.transformFlags |= ts.TransformFlags.ContainsPrivateIdentifierInExpression; + if (operatorKind === SyntaxKind.InKeyword && isPrivateIdentifier(node.left)) { + node.transformFlags |= TransformFlags.ContainsPrivateIdentifierInExpression; } return node; } - function propagateAssignmentPatternFlags(node: ts.AssignmentPattern): ts.TransformFlags { - if (node.transformFlags & ts.TransformFlags.ContainsObjectRestOrSpread) return ts.TransformFlags.ContainsObjectRestOrSpread; - if (node.transformFlags & ts.TransformFlags.ContainsES2018) { + function propagateAssignmentPatternFlags(node: AssignmentPattern): TransformFlags { + if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) return TransformFlags.ContainsObjectRestOrSpread; + if (node.transformFlags & TransformFlags.ContainsES2018) { // check for nested spread assignments, otherwise '{ x: { a, ...b } = foo } = c' // will not be correctly interpreted by the ES2018 transformer - for (const element of ts.getElementsOfBindingOrAssignmentPattern(node)) { - const target = ts.getTargetOfBindingOrAssignmentElement(element); - if (target && ts.isAssignmentPattern(target)) { - if (target.transformFlags & ts.TransformFlags.ContainsObjectRestOrSpread) { - return ts.TransformFlags.ContainsObjectRestOrSpread; + for (const element of getElementsOfBindingOrAssignmentPattern(node)) { + const target = getTargetOfBindingOrAssignmentElement(element); + if (target && isAssignmentPattern(target)) { + if (target.transformFlags & TransformFlags.ContainsObjectRestOrSpread) { + return TransformFlags.ContainsObjectRestOrSpread; } - if (target.transformFlags & ts.TransformFlags.ContainsES2018) { + if (target.transformFlags & TransformFlags.ContainsES2018) { const flags = propagateAssignmentPatternFlags(target); if (flags) return flags; } } } } - return ts.TransformFlags.None; + return TransformFlags.None; } // @api - function updateBinaryExpression(node: ts.BinaryExpression, left: ts.Expression, operator: ts.BinaryOperatorToken, right: ts.Expression) { + function updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperatorToken, right: Expression) { return node.left !== left || node.operatorToken !== operator || node.right !== right @@ -2949,12 +3029,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createConditionalExpression(condition: ts.Expression, questionToken: ts.QuestionToken | undefined, whenTrue: ts.Expression, colonToken: ts.ColonToken | undefined, whenFalse: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.ConditionalExpression); + function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) { + const node = createBaseExpression(SyntaxKind.ConditionalExpression); node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition); - node.questionToken = questionToken ?? createToken(ts.SyntaxKind.QuestionToken); + node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken); node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue); - node.colonToken = colonToken ?? createToken(ts.SyntaxKind.ColonToken); + node.colonToken = colonToken ?? createToken(SyntaxKind.ColonToken); node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse); node.transformFlags |= propagateChildFlags(node.condition) | @@ -2967,13 +3047,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateConditionalExpression( - node: ts.ConditionalExpression, - condition: ts.Expression, - questionToken: ts.Token, - whenTrue: ts.Expression, - colonToken: ts.Token, - whenFalse: ts.Expression - ): ts.ConditionalExpression { + node: ConditionalExpression, + condition: Expression, + questionToken: Token, + whenTrue: Expression, + colonToken: Token, + whenFalse: Expression + ): ConditionalExpression { return node.condition !== condition || node.questionToken !== questionToken || node.whenTrue !== whenTrue @@ -2984,98 +3064,98 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createTemplateExpression(head: ts.TemplateHead, templateSpans: readonly ts.TemplateSpan[]) { - const node = createBaseExpression(ts.SyntaxKind.TemplateExpression); + function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { + const node = createBaseExpression(SyntaxKind.TemplateExpression); node.head = head; node.templateSpans = createNodeArray(templateSpans); node.transformFlags |= propagateChildFlags(node.head) | propagateChildrenFlags(node.templateSpans) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; return node; } // @api - function updateTemplateExpression(node: ts.TemplateExpression, head: ts.TemplateHead, templateSpans: readonly ts.TemplateSpan[]) { + function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) { return node.head !== head || node.templateSpans !== templateSpans ? update(createTemplateExpression(head, templateSpans), node) : node; } - function createTemplateLiteralLikeNodeChecked(kind: ts.TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = ts.TokenFlags.None) { - ts.Debug.assert(!(templateFlags & ~ts.TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags."); + function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) { + Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags."); // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`. // eslint-disable-next-line no-undef-init let cooked: string | object | undefined = undefined; if (rawText !== undefined && rawText !== text) { cooked = getCookedText(kind, rawText); if (typeof cooked === "object") { - return ts.Debug.fail("Invalid raw text"); + return Debug.fail("Invalid raw text"); } } if (text === undefined) { if (cooked === undefined) { - return ts.Debug.fail("Arguments 'text' and 'rawText' may not both be undefined."); + return Debug.fail("Arguments 'text' and 'rawText' may not both be undefined."); } text = cooked; } else if (cooked !== undefined) { - ts.Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); + Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); } return createTemplateLiteralLikeNode(kind, text, rawText, templateFlags); } // @api - function createTemplateLiteralLikeNode(kind: ts.TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: ts.TokenFlags | undefined) { - const node = createBaseToken(kind); + function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + const node = createBaseToken(kind); node.text = text; node.rawText = rawText; - node.templateFlags = templateFlags! & ts.TokenFlags.TemplateLiteralLikeFlags; - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags; + node.transformFlags |= TransformFlags.ContainsES2015; if (node.templateFlags) { - node.transformFlags |= ts.TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2018; } return node; } // @api - function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: ts.TokenFlags) { - return createTemplateLiteralLikeNodeChecked(ts.SyntaxKind.TemplateHead, text, rawText, templateFlags) as ts.TemplateHead; + function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateHead, text, rawText, templateFlags) as TemplateHead; } // @api - function createTemplateMiddle(text: string | undefined, rawText?: string, templateFlags?: ts.TokenFlags) { - return createTemplateLiteralLikeNodeChecked(ts.SyntaxKind.TemplateMiddle, text, rawText, templateFlags) as ts.TemplateMiddle; + function createTemplateMiddle(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateMiddle, text, rawText, templateFlags) as TemplateMiddle; } // @api - function createTemplateTail(text: string | undefined, rawText?: string, templateFlags?: ts.TokenFlags) { - return createTemplateLiteralLikeNodeChecked(ts.SyntaxKind.TemplateTail, text, rawText, templateFlags) as ts.TemplateTail; + function createTemplateTail(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateTail, text, rawText, templateFlags) as TemplateTail; } // @api - function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: ts.TokenFlags) { - return createTemplateLiteralLikeNodeChecked(ts.SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as ts.NoSubstitutionTemplateLiteral; + function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { + return createTemplateLiteralLikeNodeChecked(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as NoSubstitutionTemplateLiteral; } // @api - function createYieldExpression(asteriskToken: ts.AsteriskToken | undefined, expression: ts.Expression | undefined): ts.YieldExpression { - ts.Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); - const node = createBaseExpression(ts.SyntaxKind.YieldExpression); + function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { + Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); + const node = createBaseExpression(SyntaxKind.YieldExpression); node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.asteriskToken = asteriskToken; node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.asteriskToken) | - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsYield; + TransformFlags.ContainsES2015 | + TransformFlags.ContainsES2018 | + TransformFlags.ContainsYield; return node; } // @api - function updateYieldExpression(node: ts.YieldExpression, asteriskToken: ts.AsteriskToken | undefined, expression: ts.Expression) { + function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) { return node.expression !== expression || node.asteriskToken !== asteriskToken ? update(createYieldExpression(asteriskToken, expression), node) @@ -3083,18 +3163,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createSpreadElement(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.SpreadElement); + function createSpreadElement(expression: Expression) { + const node = createBaseExpression(SyntaxKind.SpreadElement); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsRestOrSpread; + TransformFlags.ContainsES2015 | + TransformFlags.ContainsRestOrSpread; return node; } // @api - function updateSpreadElement(node: ts.SpreadElement, expression: ts.Expression) { + function updateSpreadElement(node: SpreadElement, expression: Expression) { return node.expression !== expression ? update(createSpreadElement(expression), node) : node; @@ -3102,32 +3182,32 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassExpression( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { - const node = createBaseClassLikeDeclaration( - ts.SyntaxKind.ClassExpression, + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassExpression, modifiers, name, typeParameters, heritageClauses, members ); - node.transformFlags |= ts.TransformFlags.ContainsES2015; + node.transformFlags |= TransformFlags.ContainsES2015; return node; } // @api function updateClassExpression( - node: ts.ClassExpression, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + node: ClassExpression, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { return node.modifiers !== modifiers || node.name !== name @@ -3140,23 +3220,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createOmittedExpression() { - return createBaseExpression(ts.SyntaxKind.OmittedExpression); + return createBaseExpression(SyntaxKind.OmittedExpression); } // @api - function createExpressionWithTypeArguments(expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined) { - const node = createBaseNode(ts.SyntaxKind.ExpressionWithTypeArguments); + function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) { + const node = createBaseNode(SyntaxKind.ExpressionWithTypeArguments); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments); node.transformFlags |= propagateChildFlags(node.expression) | propagateChildrenFlags(node.typeArguments) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; return node; } // @api - function updateExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments, expression: ts.Expression, typeArguments: readonly ts.TypeNode[] | undefined) { + function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) { return node.expression !== expression || node.typeArguments !== typeArguments ? update(createExpressionWithTypeArguments(expression, typeArguments), node) @@ -3164,19 +3244,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createAsExpression(expression: ts.Expression, type: ts.TypeNode) { - const node = createBaseExpression(ts.SyntaxKind.AsExpression); + function createAsExpression(expression: Expression, type: TypeNode) { + const node = createBaseExpression(SyntaxKind.AsExpression); node.expression = expression; node.type = type; node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.type) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateAsExpression(node: ts.AsExpression, expression: ts.Expression, type: ts.TypeNode) { + function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { return node.expression !== expression || node.type !== type ? update(createAsExpression(expression, type), node) @@ -3184,18 +3264,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNonNullExpression(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.NonNullExpression); + function createNonNullExpression(expression: Expression) { + const node = createBaseExpression(SyntaxKind.NonNullExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateNonNullExpression(node: ts.NonNullExpression, expression: ts.Expression) { - if (ts.isNonNullChain(node)) { + function updateNonNullExpression(node: NonNullExpression, expression: Expression) { + if (isNonNullChain(node)) { return updateNonNullChain(node, expression); } return node.expression !== expression @@ -3204,19 +3284,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createSatisfiesExpression(expression: ts.Expression, type: ts.TypeNode) { - const node = createBaseExpression(ts.SyntaxKind.SatisfiesExpression); + function createSatisfiesExpression(expression: Expression, type: TypeNode) { + const node = createBaseExpression(SyntaxKind.SatisfiesExpression); node.expression = expression; node.type = type; node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.type) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateSatisfiesExpression(node: ts.SatisfiesExpression, expression: ts.Expression, type: ts.TypeNode) { + function updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode) { return node.expression !== expression || node.type !== type ? update(createSatisfiesExpression(expression, type), node) @@ -3224,45 +3304,45 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNonNullChain(expression: ts.Expression) { - const node = createBaseExpression(ts.SyntaxKind.NonNullExpression); - node.flags |= ts.NodeFlags.OptionalChain; + function createNonNullChain(expression: Expression) { + const node = createBaseExpression(SyntaxKind.NonNullExpression); + node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateNonNullChain(node: ts.NonNullChain, expression: ts.Expression) { - ts.Debug.assert(!!(node.flags & ts.NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead."); + function updateNonNullChain(node: NonNullChain, expression: Expression) { + Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead."); return node.expression !== expression ? update(createNonNullChain(expression), node) : node; } // @api - function createMetaProperty(keywordToken: ts.MetaProperty["keywordToken"], name: ts.Identifier) { - const node = createBaseExpression(ts.SyntaxKind.MetaProperty); + function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { + const node = createBaseExpression(SyntaxKind.MetaProperty); node.keywordToken = keywordToken; node.name = name; node.transformFlags |= propagateChildFlags(node.name); switch (keywordToken) { - case ts.SyntaxKind.NewKeyword: - node.transformFlags |= ts.TransformFlags.ContainsES2015; + case SyntaxKind.NewKeyword: + node.transformFlags |= TransformFlags.ContainsES2015; break; - case ts.SyntaxKind.ImportKeyword: - node.transformFlags |= ts.TransformFlags.ContainsESNext; + case SyntaxKind.ImportKeyword: + node.transformFlags |= TransformFlags.ContainsESNext; break; default: - return ts.Debug.assertNever(keywordToken); + return Debug.assertNever(keywordToken); } return node; } // @api - function updateMetaProperty(node: ts.MetaProperty, name: ts.Identifier) { + function updateMetaProperty(node: MetaProperty, name: Identifier) { return node.name !== name ? update(createMetaProperty(node.keywordToken, name), node) : node; @@ -3273,19 +3353,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createTemplateSpan(expression: ts.Expression, literal: ts.TemplateMiddle | ts.TemplateTail) { - const node = createBaseNode(ts.SyntaxKind.TemplateSpan); + function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { + const node = createBaseNode(SyntaxKind.TemplateSpan); node.expression = expression; node.literal = literal; node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.literal) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; return node; } // @api - function updateTemplateSpan(node: ts.TemplateSpan, expression: ts.Expression, literal: ts.TemplateMiddle | ts.TemplateTail) { + function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { return node.expression !== expression || node.literal !== literal ? update(createTemplateSpan(expression, literal), node) @@ -3294,8 +3374,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createSemicolonClassElement() { - const node = createBaseNode(ts.SyntaxKind.SemicolonClassElement); - node.transformFlags |= ts.TransformFlags.ContainsES2015; + const node = createBaseNode(SyntaxKind.SemicolonClassElement); + node.transformFlags |= TransformFlags.ContainsES2015; return node; } @@ -3304,8 +3384,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createBlock(statements: readonly ts.Statement[], multiLine?: boolean): ts.Block { - const node = createBaseNode(ts.SyntaxKind.Block); + function createBlock(statements: readonly Statement[], multiLine?: boolean): Block { + const node = createBaseNode(SyntaxKind.Block); node.statements = createNodeArray(statements); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.statements); @@ -3313,28 +3393,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateBlock(node: ts.Block, statements: readonly ts.Statement[]) { + function updateBlock(node: Block, statements: readonly Statement[]) { return node.statements !== statements ? update(createBlock(statements, node.multiLine), node) : node; } // @api - function createVariableStatement(modifiers: readonly ts.Modifier[] | undefined, declarationList: ts.VariableDeclarationList | readonly ts.VariableDeclaration[]) { - const node = createBaseDeclaration(ts.SyntaxKind.VariableStatement); + function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { + const node = createBaseDeclaration(SyntaxKind.VariableStatement); node.modifiers = asNodeArray(modifiers); - node.declarationList = ts.isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; + node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.declarationList); - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Ambient) { - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { + node.transformFlags = TransformFlags.ContainsTypeScript; } return node; } // @api - function updateVariableStatement(node: ts.VariableStatement, modifiers: readonly ts.Modifier[] | undefined, declarationList: ts.VariableDeclarationList) { + function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) { return node.modifiers !== modifiers || node.declarationList !== declarationList ? update(createVariableStatement(modifiers, declarationList), node) @@ -3343,27 +3423,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createEmptyStatement() { - return createBaseNode(ts.SyntaxKind.EmptyStatement); + return createBaseNode(SyntaxKind.EmptyStatement); } // @api - function createExpressionStatement(expression: ts.Expression): ts.ExpressionStatement { - const node = createBaseNode(ts.SyntaxKind.ExpressionStatement); + function createExpressionStatement(expression: Expression): ExpressionStatement { + const node = createBaseNode(SyntaxKind.ExpressionStatement); node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; } // @api - function updateExpressionStatement(node: ts.ExpressionStatement, expression: ts.Expression) { + function updateExpressionStatement(node: ExpressionStatement, expression: Expression) { return node.expression !== expression ? update(createExpressionStatement(expression), node) : node; } // @api - function createIfStatement(expression: ts.Expression, thenStatement: ts.Statement, elseStatement?: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.IfStatement); + function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { + const node = createBaseNode(SyntaxKind.IfStatement); node.expression = expression; node.thenStatement = asEmbeddedStatement(thenStatement); node.elseStatement = asEmbeddedStatement(elseStatement); @@ -3375,7 +3455,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateIfStatement(node: ts.IfStatement, expression: ts.Expression, thenStatement: ts.Statement, elseStatement: ts.Statement | undefined) { + function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) { return node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement @@ -3384,8 +3464,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createDoStatement(statement: ts.Statement, expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.DoStatement); + function createDoStatement(statement: Statement, expression: Expression) { + const node = createBaseNode(SyntaxKind.DoStatement); node.statement = asEmbeddedStatement(statement); node.expression = expression; node.transformFlags |= @@ -3395,7 +3475,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateDoStatement(node: ts.DoStatement, statement: ts.Statement, expression: ts.Expression) { + function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) { return node.statement !== statement || node.expression !== expression ? update(createDoStatement(statement, expression), node) @@ -3403,8 +3483,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createWhileStatement(expression: ts.Expression, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.WhileStatement); + function createWhileStatement(expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.WhileStatement); node.expression = expression; node.statement = asEmbeddedStatement(statement); node.transformFlags |= @@ -3414,7 +3494,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateWhileStatement(node: ts.WhileStatement, expression: ts.Expression, statement: ts.Statement) { + function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement ? update(createWhileStatement(expression, statement), node) @@ -3422,8 +3502,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createForStatement(initializer: ts.ForInitializer | undefined, condition: ts.Expression | undefined, incrementor: ts.Expression | undefined, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.ForStatement); + function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForStatement); node.initializer = initializer; node.condition = condition; node.incrementor = incrementor; @@ -3437,7 +3517,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateForStatement(node: ts.ForStatement, initializer: ts.ForInitializer | undefined, condition: ts.Expression | undefined, incrementor: ts.Expression | undefined, statement: ts.Statement) { + function updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) { return node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor @@ -3447,8 +3527,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createForInStatement(initializer: ts.ForInitializer, expression: ts.Expression, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.ForInStatement); + function createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForInStatement); node.initializer = initializer; node.expression = expression; node.statement = asEmbeddedStatement(statement); @@ -3460,7 +3540,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateForInStatement(node: ts.ForInStatement, initializer: ts.ForInitializer, expression: ts.Expression, statement: ts.Statement) { + function updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { return node.initializer !== initializer || node.expression !== expression || node.statement !== statement @@ -3469,8 +3549,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createForOfStatement(awaitModifier: ts.AwaitKeyword | undefined, initializer: ts.ForInitializer, expression: ts.Expression, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.ForOfStatement); + function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.ForOfStatement); node.awaitModifier = awaitModifier; node.initializer = initializer; node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); @@ -3480,13 +3560,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.initializer) | propagateChildFlags(node.expression) | propagateChildFlags(node.statement) | - ts.TransformFlags.ContainsES2015; - if (awaitModifier) node.transformFlags |= ts.TransformFlags.ContainsES2018; + TransformFlags.ContainsES2015; + if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018; return node; } // @api - function updateForOfStatement(node: ts.ForOfStatement, awaitModifier: ts.AwaitKeyword | undefined, initializer: ts.ForInitializer, expression: ts.Expression, statement: ts.Statement) { + function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) { return node.awaitModifier !== awaitModifier || node.initializer !== initializer || node.expression !== expression @@ -3496,61 +3576,61 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createContinueStatement(label?: string | ts.Identifier): ts.ContinueStatement { - const node = createBaseNode(ts.SyntaxKind.ContinueStatement); + function createContinueStatement(label?: string | Identifier): ContinueStatement { + const node = createBaseNode(SyntaxKind.ContinueStatement); node.label = asName(label); node.transformFlags |= propagateChildFlags(node.label) | - ts.TransformFlags.ContainsHoistedDeclarationOrCompletion; + TransformFlags.ContainsHoistedDeclarationOrCompletion; return node; } // @api - function updateContinueStatement(node: ts.ContinueStatement, label: ts.Identifier | undefined) { + function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) { return node.label !== label ? update(createContinueStatement(label), node) : node; } // @api - function createBreakStatement(label?: string | ts.Identifier): ts.BreakStatement { - const node = createBaseNode(ts.SyntaxKind.BreakStatement); + function createBreakStatement(label?: string | Identifier): BreakStatement { + const node = createBaseNode(SyntaxKind.BreakStatement); node.label = asName(label); node.transformFlags |= propagateChildFlags(node.label) | - ts.TransformFlags.ContainsHoistedDeclarationOrCompletion; + TransformFlags.ContainsHoistedDeclarationOrCompletion; return node; } // @api - function updateBreakStatement(node: ts.BreakStatement, label: ts.Identifier | undefined) { + function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) { return node.label !== label ? update(createBreakStatement(label), node) : node; } // @api - function createReturnStatement(expression?: ts.Expression): ts.ReturnStatement { - const node = createBaseNode(ts.SyntaxKind.ReturnStatement); + function createReturnStatement(expression?: Expression): ReturnStatement { + const node = createBaseNode(SyntaxKind.ReturnStatement); node.expression = expression; // return in an ES2018 async generator must be awaited node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsHoistedDeclarationOrCompletion; + TransformFlags.ContainsES2018 | + TransformFlags.ContainsHoistedDeclarationOrCompletion; return node; } // @api - function updateReturnStatement(node: ts.ReturnStatement, expression: ts.Expression | undefined) { + function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) { return node.expression !== expression ? update(createReturnStatement(expression), node) : node; } // @api - function createWithStatement(expression: ts.Expression, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.WithStatement); + function createWithStatement(expression: Expression, statement: Statement) { + const node = createBaseNode(SyntaxKind.WithStatement); node.expression = expression; node.statement = asEmbeddedStatement(statement); node.transformFlags |= @@ -3560,7 +3640,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateWithStatement(node: ts.WithStatement, expression: ts.Expression, statement: ts.Statement) { + function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) { return node.expression !== expression || node.statement !== statement ? update(createWithStatement(expression, statement), node) @@ -3568,8 +3648,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createSwitchStatement(expression: ts.Expression, caseBlock: ts.CaseBlock): ts.SwitchStatement { - const node = createBaseNode(ts.SyntaxKind.SwitchStatement); + function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement { + const node = createBaseNode(SyntaxKind.SwitchStatement); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.caseBlock = caseBlock; node.transformFlags |= @@ -3579,7 +3659,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateSwitchStatement(node: ts.SwitchStatement, expression: ts.Expression, caseBlock: ts.CaseBlock) { + function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { return node.expression !== expression || node.caseBlock !== caseBlock ? update(createSwitchStatement(expression, caseBlock), node) @@ -3587,8 +3667,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createLabeledStatement(label: string | ts.Identifier, statement: ts.Statement) { - const node = createBaseNode(ts.SyntaxKind.LabeledStatement); + function createLabeledStatement(label: string | Identifier, statement: Statement) { + const node = createBaseNode(SyntaxKind.LabeledStatement); node.label = asName(label); node.statement = asEmbeddedStatement(statement); node.transformFlags |= @@ -3598,7 +3678,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateLabeledStatement(node: ts.LabeledStatement, label: ts.Identifier, statement: ts.Statement) { + function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) { return node.label !== label || node.statement !== statement ? update(createLabeledStatement(label, statement), node) @@ -3606,23 +3686,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createThrowStatement(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.ThrowStatement); + function createThrowStatement(expression: Expression) { + const node = createBaseNode(SyntaxKind.ThrowStatement); node.expression = expression; node.transformFlags |= propagateChildFlags(node.expression); return node; } // @api - function updateThrowStatement(node: ts.ThrowStatement, expression: ts.Expression) { + function updateThrowStatement(node: ThrowStatement, expression: Expression) { return node.expression !== expression ? update(createThrowStatement(expression), node) : node; } // @api - function createTryStatement(tryBlock: ts.Block, catchClause: ts.CatchClause | undefined, finallyBlock: ts.Block | undefined) { - const node = createBaseNode(ts.SyntaxKind.TryStatement); + function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { + const node = createBaseNode(SyntaxKind.TryStatement); node.tryBlock = tryBlock; node.catchClause = catchClause; node.finallyBlock = finallyBlock; @@ -3634,7 +3714,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateTryStatement(node: ts.TryStatement, tryBlock: ts.Block, catchClause: ts.CatchClause | undefined, finallyBlock: ts.Block | undefined) { + function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) { return node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock @@ -3644,13 +3724,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createDebuggerStatement() { - return createBaseNode(ts.SyntaxKind.DebuggerStatement); + return createBaseNode(SyntaxKind.DebuggerStatement); } // @api - function createVariableDeclaration(name: string | ts.BindingName, exclamationToken: ts.ExclamationToken | undefined, type: ts.TypeNode | undefined, initializer: ts.Expression | undefined) { - const node = createBaseVariableLikeDeclaration( - ts.SyntaxKind.VariableDeclaration, + function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { + const node = createBaseVariableLikeDeclaration( + SyntaxKind.VariableDeclaration, /*modifiers*/ undefined, name, type, @@ -3659,13 +3739,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.exclamationToken = exclamationToken; node.transformFlags |= propagateChildFlags(node.exclamationToken); if (exclamationToken) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } return node; } // @api - function updateVariableDeclaration(node: ts.VariableDeclaration, name: ts.BindingName, exclamationToken: ts.ExclamationToken | undefined, type: ts.TypeNode | undefined, initializer: ts.Expression | undefined) { + function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { return node.name !== name || node.type !== type || node.exclamationToken !== exclamationToken @@ -3675,23 +3755,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createVariableDeclarationList(declarations: readonly ts.VariableDeclaration[], flags = ts.NodeFlags.None) { - const node = createBaseNode(ts.SyntaxKind.VariableDeclarationList); - node.flags |= flags & ts.NodeFlags.BlockScoped; + function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) { + const node = createBaseNode(SyntaxKind.VariableDeclarationList); + node.flags |= flags & NodeFlags.BlockScoped; node.declarations = createNodeArray(declarations); node.transformFlags |= propagateChildrenFlags(node.declarations) | - ts.TransformFlags.ContainsHoistedDeclarationOrCompletion; - if (flags & ts.NodeFlags.BlockScoped) { + TransformFlags.ContainsHoistedDeclarationOrCompletion; + if (flags & NodeFlags.BlockScoped) { node.transformFlags |= - ts.TransformFlags.ContainsES2015 | - ts.TransformFlags.ContainsBlockScopedBinding; + TransformFlags.ContainsES2015 | + TransformFlags.ContainsBlockScopedBinding; } return node; } // @api - function updateVariableDeclarationList(node: ts.VariableDeclarationList, declarations: readonly ts.VariableDeclaration[]) { + function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) { return node.declarations !== declarations ? update(createVariableDeclarationList(declarations, node.flags), node) : node; @@ -3699,16 +3779,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createFunctionDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - ts.SyntaxKind.FunctionDeclaration, + const node = createBaseFunctionLikeDeclaration( + SyntaxKind.FunctionDeclaration, modifiers, name, typeParameters, @@ -3717,23 +3797,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN body ); node.asteriskToken = asteriskToken; - if (!node.body || ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Ambient) { - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + if (!node.body || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { + node.transformFlags = TransformFlags.ContainsTypeScript; } else { node.transformFlags |= propagateChildFlags(node.asteriskToken) | - ts.TransformFlags.ContainsHoistedDeclarationOrCompletion; - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Async) { + TransformFlags.ContainsHoistedDeclarationOrCompletion; + if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { if (node.asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsES2018; + node.transformFlags |= TransformFlags.ContainsES2018; } else { - node.transformFlags |= ts.TransformFlags.ContainsES2017; + node.transformFlags |= TransformFlags.ContainsES2017; } } else if (node.asteriskToken) { - node.transformFlags |= ts.TransformFlags.ContainsGenerator; + node.transformFlags |= TransformFlags.ContainsGenerator; } } @@ -3744,14 +3824,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateFunctionDeclaration( - node: ts.FunctionDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - parameters: readonly ts.ParameterDeclaration[], - type: ts.TypeNode | undefined, - body: ts.Block | undefined + node: FunctionDeclaration, + modifiers: readonly ModifierLike[] | undefined, + asteriskToken: AsteriskToken | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode | undefined, + body: Block | undefined ) { return node.modifiers !== modifiers || node.asteriskToken !== asteriskToken @@ -3764,7 +3844,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateFunctionDeclaration(updated: ts.Mutable, original: ts.FunctionDeclaration) { + function finishUpdateFunctionDeclaration(updated: Mutable, original: FunctionDeclaration) { if (updated !== original) { // copy children used only for error reporting updated.illegalDecorators = original.illegalDecorators; @@ -3774,27 +3854,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createClassDeclaration( - modifiers: readonly ts.ModifierLike[] | undefined, - name: string | ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + modifiers: readonly ModifierLike[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { - const node = createBaseClassLikeDeclaration( - ts.SyntaxKind.ClassDeclaration, + const node = createBaseClassLikeDeclaration( + SyntaxKind.ClassDeclaration, modifiers, name, typeParameters, heritageClauses, members ); - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Ambient) { - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { + node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= ts.TransformFlags.ContainsES2015; - if (node.transformFlags & ts.TransformFlags.ContainsTypeScriptClassSyntax) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsES2015; + if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) { + node.transformFlags |= TransformFlags.ContainsTypeScript; } } return node; @@ -3802,12 +3882,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateClassDeclaration( - node: ts.ClassDeclaration, - modifiers: readonly ts.ModifierLike[] | undefined, - name: ts.Identifier | undefined, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.ClassElement[] + node: ClassDeclaration, + modifiers: readonly ModifierLike[] | undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly ClassElement[] ) { return node.modifiers !== modifiers || node.name !== name @@ -3820,21 +3900,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createInterfaceDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.TypeElement[] + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[] ) { - const node = createBaseInterfaceOrClassLikeDeclaration( - ts.SyntaxKind.InterfaceDeclaration, + const node = createBaseInterfaceOrClassLikeDeclaration( + SyntaxKind.InterfaceDeclaration, modifiers, name, typeParameters, heritageClauses ); node.members = createNodeArray(members); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -3843,12 +3923,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateInterfaceDeclaration( - node: ts.InterfaceDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - heritageClauses: readonly ts.HeritageClause[] | undefined, - members: readonly ts.TypeElement[] + node: InterfaceDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: readonly HeritageClause[] | undefined, + members: readonly TypeElement[] ) { return node.modifiers !== modifiers || node.name !== name @@ -3859,7 +3939,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateInterfaceDeclaration(updated: ts.Mutable, original: ts.InterfaceDeclaration) { + function finishUpdateInterfaceDeclaration(updated: Mutable, original: InterfaceDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -3868,19 +3948,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createTypeAliasDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - type: ts.TypeNode + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode ) { - const node = createBaseGenericNamedDeclaration( - ts.SyntaxKind.TypeAliasDeclaration, + const node = createBaseGenericNamedDeclaration( + SyntaxKind.TypeAliasDeclaration, modifiers, name, typeParameters ); node.type = type; - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -3889,11 +3969,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateTypeAliasDeclaration( - node: ts.TypeAliasDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - typeParameters: readonly ts.TypeParameterDeclaration[] | undefined, - type: ts.TypeNode + node: TypeAliasDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + type: TypeNode ) { return node.modifiers !== modifiers || node.name !== name @@ -3903,7 +3983,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateTypeAliasDeclaration(updated: ts.Mutable, original: ts.TypeAliasDeclaration) { + function finishUpdateTypeAliasDeclaration(updated: Mutable, original: TypeAliasDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -3912,20 +3992,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createEnumDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - name: string | ts.Identifier, - members: readonly ts.EnumMember[] + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + members: readonly EnumMember[] ) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.EnumDeclaration, + const node = createBaseNamedDeclaration( + SyntaxKind.EnumDeclaration, modifiers, name ); node.members = createNodeArray(members); node.transformFlags |= propagateChildrenFlags(node.members) | - ts.TransformFlags.ContainsTypeScript; - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` + TransformFlags.ContainsTypeScript; + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -3934,10 +4014,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateEnumDeclaration( - node: ts.EnumDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.Identifier, - members: readonly ts.EnumMember[]) { + node: EnumDeclaration, + modifiers: readonly Modifier[] | undefined, + name: Identifier, + members: readonly EnumMember[]) { return node.modifiers !== modifiers || node.name !== name || node.members !== members @@ -3945,7 +4025,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateEnumDeclaration(updated: ts.Mutable, original: ts.EnumDeclaration) { + function finishUpdateEnumDeclaration(updated: Mutable, original: EnumDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -3954,27 +4034,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createModuleDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - name: ts.ModuleName, - body: ts.ModuleBody | undefined, - flags = ts.NodeFlags.None + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined, + flags = NodeFlags.None ) { - const node = createBaseDeclaration(ts.SyntaxKind.ModuleDeclaration); + const node = createBaseDeclaration(SyntaxKind.ModuleDeclaration); node.modifiers = asNodeArray(modifiers); - node.flags |= flags & (ts.NodeFlags.Namespace | ts.NodeFlags.NestedNamespace | ts.NodeFlags.GlobalAugmentation); + node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation); node.name = name; node.body = body; - if (ts.modifiersToFlags(node.modifiers) & ts.ModifierFlags.Ambient) { - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { + node.transformFlags = TransformFlags.ContainsTypeScript; } else { node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.name) | propagateChildFlags(node.body) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; } - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -3983,10 +4063,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateModuleDeclaration( - node: ts.ModuleDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - name: ts.ModuleName, - body: ts.ModuleBody | undefined + node: ModuleDeclaration, + modifiers: readonly Modifier[] | undefined, + name: ModuleName, + body: ModuleBody | undefined ) { return node.modifiers !== modifiers || node.name !== name @@ -3995,7 +4075,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateModuleDeclaration(updated: ts.Mutable, original: ts.ModuleDeclaration) { + function finishUpdateModuleDeclaration(updated: Mutable, original: ModuleDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -4003,43 +4083,43 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createModuleBlock(statements: readonly ts.Statement[]) { - const node = createBaseNode(ts.SyntaxKind.ModuleBlock); + function createModuleBlock(statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.ModuleBlock); node.statements = createNodeArray(statements); node.transformFlags |= propagateChildrenFlags(node.statements); return node; } // @api - function updateModuleBlock(node: ts.ModuleBlock, statements: readonly ts.Statement[]) { + function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) { return node.statements !== statements ? update(createModuleBlock(statements), node) : node; } // @api - function createCaseBlock(clauses: readonly ts.CaseOrDefaultClause[]): ts.CaseBlock { - const node = createBaseNode(ts.SyntaxKind.CaseBlock); + function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock { + const node = createBaseNode(SyntaxKind.CaseBlock); node.clauses = createNodeArray(clauses); node.transformFlags |= propagateChildrenFlags(node.clauses); return node; } // @api - function updateCaseBlock(node: ts.CaseBlock, clauses: readonly ts.CaseOrDefaultClause[]) { + function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) { return node.clauses !== clauses ? update(createCaseBlock(clauses), node) : node; } // @api - function createNamespaceExportDeclaration(name: string | ts.Identifier) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.NamespaceExportDeclaration, + function createNamespaceExportDeclaration(name: string | Identifier) { + const node = createBaseNamedDeclaration( + SyntaxKind.NamespaceExportDeclaration, /*modifiers*/ undefined, name ); - node.transformFlags = ts.TransformFlags.ContainsTypeScript; + node.transformFlags = TransformFlags.ContainsTypeScript; // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -4048,13 +4128,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration, name: ts.Identifier) { + function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) { return node.name !== name ? finishUpdateNamespaceExportDeclaration(createNamespaceExportDeclaration(name), node) : node; } - function finishUpdateNamespaceExportDeclaration(updated: ts.Mutable, original: ts.NamespaceExportDeclaration) { + function finishUpdateNamespaceExportDeclaration(updated: Mutable, original: NamespaceExportDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; updated.modifiers = original.modifiers; @@ -4064,21 +4144,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createImportEqualsDeclaration( - modifiers: readonly ts.Modifier[] | undefined, + modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, - name: string | ts.Identifier, - moduleReference: ts.ModuleReference + name: string | Identifier, + moduleReference: ModuleReference ) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.ImportEqualsDeclaration, + const node = createBaseNamedDeclaration( + SyntaxKind.ImportEqualsDeclaration, modifiers, name ); node.isTypeOnly = isTypeOnly; node.moduleReference = moduleReference; node.transformFlags |= propagateChildFlags(node.moduleReference); - if (!ts.isExternalModuleReference(node.moduleReference)) node.transformFlags |= ts.TransformFlags.ContainsTypeScript; - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context + if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript; + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -4087,11 +4167,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateImportEqualsDeclaration( - node: ts.ImportEqualsDeclaration, - modifiers: readonly ts.Modifier[] | undefined, + node: ImportEqualsDeclaration, + modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, - name: ts.Identifier, - moduleReference: ts.ModuleReference + name: Identifier, + moduleReference: ModuleReference ) { return node.modifiers !== modifiers || node.isTypeOnly !== isTypeOnly @@ -4101,7 +4181,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateImportEqualsDeclaration(updated: ts.Mutable, original: ts.ImportEqualsDeclaration) { + function finishUpdateImportEqualsDeclaration(updated: Mutable, original: ImportEqualsDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -4110,12 +4190,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createImportDeclaration( - modifiers: readonly ts.Modifier[] | undefined, - importClause: ts.ImportClause | undefined, - moduleSpecifier: ts.Expression, - assertClause: ts.AssertClause | undefined - ): ts.ImportDeclaration { - const node = createBaseDeclaration(ts.SyntaxKind.ImportDeclaration); + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined + ): ImportDeclaration { + const node = createBaseDeclaration(SyntaxKind.ImportDeclaration); node.modifiers = asNodeArray(modifiers); node.importClause = importClause; node.moduleSpecifier = moduleSpecifier; @@ -4123,7 +4203,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.transformFlags |= propagateChildFlags(node.importClause) | propagateChildFlags(node.moduleSpecifier); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -4132,11 +4212,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateImportDeclaration( - node: ts.ImportDeclaration, - modifiers: readonly ts.Modifier[] | undefined, - importClause: ts.ImportClause | undefined, - moduleSpecifier: ts.Expression, - assertClause: ts.AssertClause | undefined + node: ImportDeclaration, + modifiers: readonly Modifier[] | undefined, + importClause: ImportClause | undefined, + moduleSpecifier: Expression, + assertClause: AssertClause | undefined ) { return node.modifiers !== modifiers || node.importClause !== importClause @@ -4146,7 +4226,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateImportDeclaration(updated: ts.Mutable, original: ts.ImportDeclaration) { + function finishUpdateImportDeclaration(updated: Mutable, original: ImportDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -4154,8 +4234,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createImportClause(isTypeOnly: boolean, name: ts.Identifier | undefined, namedBindings: ts.NamedImportBindings | undefined): ts.ImportClause { - const node = createBaseNode(ts.SyntaxKind.ImportClause); + function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { + const node = createBaseNode(SyntaxKind.ImportClause); node.isTypeOnly = isTypeOnly; node.name = name; node.namedBindings = namedBindings; @@ -4163,14 +4243,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.name) | propagateChildFlags(node.namedBindings); if (isTypeOnly) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateImportClause(node: ts.ImportClause, isTypeOnly: boolean, name: ts.Identifier | undefined, namedBindings: ts.NamedImportBindings | undefined) { + function updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { return node.isTypeOnly !== isTypeOnly || node.name !== name || node.namedBindings !== namedBindings @@ -4179,16 +4259,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createAssertClause(elements: readonly ts.AssertEntry[], multiLine?: boolean): ts.AssertClause { - const node = createBaseNode(ts.SyntaxKind.AssertClause); + function createAssertClause(elements: readonly AssertEntry[], multiLine?: boolean): AssertClause { + const node = createBaseNode(SyntaxKind.AssertClause); node.elements = createNodeArray(elements); node.multiLine = multiLine; - node.transformFlags |= ts.TransformFlags.ContainsESNext; + node.transformFlags |= TransformFlags.ContainsESNext; return node; } // @api - function updateAssertClause(node: ts.AssertClause, elements: readonly ts.AssertEntry[], multiLine?: boolean): ts.AssertClause { + function updateAssertClause(node: AssertClause, elements: readonly AssertEntry[], multiLine?: boolean): AssertClause { return node.elements !== elements || node.multiLine !== multiLine ? update(createAssertClause(elements, multiLine), node) @@ -4196,16 +4276,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createAssertEntry(name: ts.AssertionKey, value: ts.Expression): ts.AssertEntry { - const node = createBaseNode(ts.SyntaxKind.AssertEntry); + function createAssertEntry(name: AssertionKey, value: Expression): AssertEntry { + const node = createBaseNode(SyntaxKind.AssertEntry); node.name = name; node.value = value; - node.transformFlags |= ts.TransformFlags.ContainsESNext; + node.transformFlags |= TransformFlags.ContainsESNext; return node; } // @api - function updateAssertEntry(node: ts.AssertEntry, name: ts.AssertionKey, value: ts.Expression): ts.AssertEntry { + function updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry { return node.name !== name || node.value !== value ? update(createAssertEntry(name, value), node) @@ -4213,15 +4293,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createImportTypeAssertionContainer(clause: ts.AssertClause, multiLine?: boolean): ts.ImportTypeAssertionContainer { - const node = createBaseNode(ts.SyntaxKind.ImportTypeAssertionContainer); + function createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer { + const node = createBaseNode(SyntaxKind.ImportTypeAssertionContainer); node.assertClause = clause; node.multiLine = multiLine; return node; } // @api - function updateImportTypeAssertionContainer(node: ts.ImportTypeAssertionContainer, clause: ts.AssertClause, multiLine?: boolean): ts.ImportTypeAssertionContainer { + function updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer { return node.assertClause !== clause || node.multiLine !== multiLine ? update(createImportTypeAssertionContainer(clause, multiLine), node) @@ -4229,70 +4309,70 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNamespaceImport(name: ts.Identifier): ts.NamespaceImport { - const node = createBaseNode(ts.SyntaxKind.NamespaceImport); + function createNamespaceImport(name: Identifier): NamespaceImport { + const node = createBaseNode(SyntaxKind.NamespaceImport); node.name = name; node.transformFlags |= propagateChildFlags(node.name); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateNamespaceImport(node: ts.NamespaceImport, name: ts.Identifier) { + function updateNamespaceImport(node: NamespaceImport, name: Identifier) { return node.name !== name ? update(createNamespaceImport(name), node) : node; } // @api - function createNamespaceExport(name: ts.Identifier): ts.NamespaceExport { - const node = createBaseNode(ts.SyntaxKind.NamespaceExport); + function createNamespaceExport(name: Identifier): NamespaceExport { + const node = createBaseNode(SyntaxKind.NamespaceExport); node.name = name; node.transformFlags |= propagateChildFlags(node.name) | - ts.TransformFlags.ContainsESNext; - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + TransformFlags.ContainsESNext; + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateNamespaceExport(node: ts.NamespaceExport, name: ts.Identifier) { + function updateNamespaceExport(node: NamespaceExport, name: Identifier) { return node.name !== name ? update(createNamespaceExport(name), node) : node; } // @api - function createNamedImports(elements: readonly ts.ImportSpecifier[]): ts.NamedImports { - const node = createBaseNode(ts.SyntaxKind.NamedImports); + function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports { + const node = createBaseNode(SyntaxKind.NamedImports); node.elements = createNodeArray(elements); node.transformFlags |= propagateChildrenFlags(node.elements); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateNamedImports(node: ts.NamedImports, elements: readonly ts.ImportSpecifier[]) { + function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) { return node.elements !== elements ? update(createNamedImports(elements), node) : node; } // @api - function createImportSpecifier(isTypeOnly: boolean, propertyName: ts.Identifier | undefined, name: ts.Identifier) { - const node = createBaseNode(ts.SyntaxKind.ImportSpecifier); + function createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { + const node = createBaseNode(SyntaxKind.ImportSpecifier); node.isTypeOnly = isTypeOnly; node.propertyName = propertyName; node.name = name; node.transformFlags |= propagateChildFlags(node.propertyName) | propagateChildFlags(node.name); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateImportSpecifier(node: ts.ImportSpecifier, isTypeOnly: boolean, propertyName: ts.Identifier | undefined, name: ts.Identifier) { + function updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { return node.isTypeOnly !== isTypeOnly || node.propertyName !== propertyName || node.name !== name @@ -4302,18 +4382,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createExportAssignment( - modifiers: readonly ts.Modifier[] | undefined, + modifiers: readonly Modifier[] | undefined, isExportEquals: boolean | undefined, - expression: ts.Expression + expression: Expression ) { - const node = createBaseDeclaration(ts.SyntaxKind.ExportAssignment); + const node = createBaseDeclaration(SyntaxKind.ExportAssignment); node.modifiers = asNodeArray(modifiers); node.isExportEquals = isExportEquals; node.expression = isExportEquals - ? parenthesizerRules().parenthesizeRightSideOfBinary(ts.SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) + ? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression) : parenthesizerRules().parenthesizeExpressionOfExportDefault(expression); node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.expression); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -4322,9 +4402,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateExportAssignment( - node: ts.ExportAssignment, - modifiers: readonly ts.Modifier[] | undefined, - expression: ts.Expression + node: ExportAssignment, + modifiers: readonly Modifier[] | undefined, + expression: Expression ) { return node.modifiers !== modifiers || node.expression !== expression @@ -4332,7 +4412,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateExportAssignment(updated: ts.Mutable, original: ts.ExportAssignment) { + function finishUpdateExportAssignment(updated: Mutable, original: ExportAssignment) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -4341,13 +4421,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createExportDeclaration( - modifiers: readonly ts.Modifier[] | undefined, + modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, - exportClause: ts.NamedExportBindings | undefined, - moduleSpecifier?: ts.Expression, - assertClause?: ts.AssertClause + exportClause: NamedExportBindings | undefined, + moduleSpecifier?: Expression, + assertClause?: AssertClause ) { - const node = createBaseDeclaration(ts.SyntaxKind.ExportDeclaration); + const node = createBaseDeclaration(SyntaxKind.ExportDeclaration); node.modifiers = asNodeArray(modifiers); node.isTypeOnly = isTypeOnly; node.exportClause = exportClause; @@ -4357,7 +4437,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.exportClause) | propagateChildFlags(node.moduleSpecifier); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context // The following properties are used only to report grammar errors node.illegalDecorators = undefined; @@ -4366,12 +4446,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateExportDeclaration( - node: ts.ExportDeclaration, - modifiers: readonly ts.Modifier[] | undefined, + node: ExportDeclaration, + modifiers: readonly Modifier[] | undefined, isTypeOnly: boolean, - exportClause: ts.NamedExportBindings | undefined, - moduleSpecifier: ts.Expression | undefined, - assertClause: ts.AssertClause | undefined + exportClause: NamedExportBindings | undefined, + moduleSpecifier: Expression | undefined, + assertClause: AssertClause | undefined ) { return node.modifiers !== modifiers || node.isTypeOnly !== isTypeOnly @@ -4382,7 +4462,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function finishUpdateExportDeclaration(updated: ts.Mutable, original: ts.ExportDeclaration) { + function finishUpdateExportDeclaration(updated: Mutable, original: ExportDeclaration) { if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; } @@ -4390,36 +4470,36 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createNamedExports(elements: readonly ts.ExportSpecifier[]) { - const node = createBaseNode(ts.SyntaxKind.NamedExports); + function createNamedExports(elements: readonly ExportSpecifier[]) { + const node = createBaseNode(SyntaxKind.NamedExports); node.elements = createNodeArray(elements); node.transformFlags |= propagateChildrenFlags(node.elements); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateNamedExports(node: ts.NamedExports, elements: readonly ts.ExportSpecifier[]) { + function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) { return node.elements !== elements ? update(createNamedExports(elements), node) : node; } // @api - function createExportSpecifier(isTypeOnly: boolean, propertyName: string | ts.Identifier | undefined, name: string | ts.Identifier) { - const node = createBaseNode(ts.SyntaxKind.ExportSpecifier); + function createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier) { + const node = createBaseNode(SyntaxKind.ExportSpecifier); node.isTypeOnly = isTypeOnly; node.propertyName = asName(propertyName); node.name = asName(name); node.transformFlags |= propagateChildFlags(node.propertyName) | propagateChildFlags(node.name); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateExportSpecifier(node: ts.ExportSpecifier, isTypeOnly: boolean, propertyName: ts.Identifier | undefined, name: ts.Identifier) { + function updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { return node.isTypeOnly !== isTypeOnly || node.propertyName !== propertyName || node.name !== name @@ -4428,8 +4508,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createMissingDeclaration(): ts.MissingDeclaration { - const node = createBaseDeclaration(ts.SyntaxKind.MissingDeclaration); + function createMissingDeclaration(): MissingDeclaration { + const node = createBaseDeclaration(SyntaxKind.MissingDeclaration); return node; } @@ -4438,16 +4518,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createExternalModuleReference(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.ExternalModuleReference); + function createExternalModuleReference(expression: Expression) { + const node = createBaseNode(SyntaxKind.ExternalModuleReference); node.expression = expression; node.transformFlags |= propagateChildFlags(node.expression); - node.transformFlags &= ~ts.TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return node; } // @api - function updateExternalModuleReference(node: ts.ExternalModuleReference, expression: ts.Expression) { + function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { return node.expression !== expression ? update(createExternalModuleReference(expression), node) : node; @@ -4460,18 +4540,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api // createJSDocAllType // createJSDocUnknownType - function createJSDocPrimaryTypeWorker(kind: T["kind"]) { + function createJSDocPrimaryTypeWorker(kind: T["kind"]) { return createBaseNode(kind); } // @api // createJSDocNullableType // createJSDocNonNullableType - function createJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], type: T["type"], postfix = false): T { + function createJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], type: T["type"], postfix = false): T { const node = createJSDocUnaryTypeWorker( kind, postfix ? type && parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(type) : type - ) as ts.Mutable; + ) as Mutable; node.postfix = postfix; return node; } @@ -4480,7 +4560,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // createJSDocOptionalType // createJSDocVariadicType // createJSDocNamepathType - function createJSDocUnaryTypeWorker(kind: T["kind"], type: T["type"]): T { + function createJSDocUnaryTypeWorker(kind: T["kind"], type: T["type"]): T { const node = createBaseNode(kind); node.type = type; return node; @@ -4489,7 +4569,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api // updateJSDocNonNullableType // updateJSDocNullableType - function updateJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { + function updateJSDocPrePostfixUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { return node.type !== type ? update(createJSDocPrePostfixUnaryTypeWorker(kind, type, node.postfix), node) : node; @@ -4499,16 +4579,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // updateJSDocOptionalType // updateJSDocVariadicType // updateJSDocNamepathType - function updateJSDocUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { + function updateJSDocUnaryTypeWorker(kind: T["kind"], node: T, type: T["type"]): T { return node.type !== type ? update(createJSDocUnaryTypeWorker(kind, type), node) : node; } // @api - function createJSDocFunctionType(parameters: readonly ts.ParameterDeclaration[], type: ts.TypeNode | undefined): ts.JSDocFunctionType { - const node = createBaseSignatureDeclaration( - ts.SyntaxKind.JSDocFunctionType, + function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { + const node = createBaseSignatureDeclaration( + SyntaxKind.JSDocFunctionType, /*modifiers*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, @@ -4519,7 +4599,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateJSDocFunctionType(node: ts.JSDocFunctionType, parameters: readonly ts.ParameterDeclaration[], type: ts.TypeNode | undefined): ts.JSDocFunctionType { + function updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { return node.parameters !== parameters || node.type !== type ? update(createJSDocFunctionType(parameters, type), node) @@ -4527,15 +4607,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocTypeLiteral(propertyTags?: readonly ts.JSDocPropertyLikeTag[], isArrayType = false): ts.JSDocTypeLiteral { - const node = createBaseNode(ts.SyntaxKind.JSDocTypeLiteral); + function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral { + const node = createBaseNode(SyntaxKind.JSDocTypeLiteral); node.jsDocPropertyTags = asNodeArray(propertyTags); node.isArrayType = isArrayType; return node; } // @api - function updateJSDocTypeLiteral(node: ts.JSDocTypeLiteral, propertyTags: readonly ts.JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): ts.JSDocTypeLiteral { + function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral { return node.jsDocPropertyTags !== propertyTags || node.isArrayType !== isArrayType ? update(createJSDocTypeLiteral(propertyTags, isArrayType), node) @@ -4543,22 +4623,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocTypeExpression(type: ts.TypeNode): ts.JSDocTypeExpression { - const node = createBaseNode(ts.SyntaxKind.JSDocTypeExpression); + function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression { + const node = createBaseNode(SyntaxKind.JSDocTypeExpression); node.type = type; return node; } // @api - function updateJSDocTypeExpression(node: ts.JSDocTypeExpression, type: ts.TypeNode): ts.JSDocTypeExpression { + function updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression { return node.type !== type ? update(createJSDocTypeExpression(type), node) : node; } // @api - function createJSDocSignature(typeParameters: readonly ts.JSDocTemplateTag[] | undefined, parameters: readonly ts.JSDocParameterTag[], type?: ts.JSDocReturnTag): ts.JSDocSignature { - const node = createBaseNode(ts.SyntaxKind.JSDocSignature); + function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { + const node = createBaseNode(SyntaxKind.JSDocSignature); node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; @@ -4566,7 +4646,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateJSDocSignature(node: ts.JSDocSignature, typeParameters: readonly ts.JSDocTemplateTag[] | undefined, parameters: readonly ts.JSDocParameterTag[], type: ts.JSDocReturnTag | undefined): ts.JSDocSignature { + function updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature { return node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type @@ -4574,15 +4654,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN : node; } - function getDefaultTagName(node: ts.JSDocTag) { + function getDefaultTagName(node: JSDocTag) { const defaultTagName = getDefaultTagNameForKind(node.kind); - return node.tagName.escapedText === ts.escapeLeadingUnderscores(defaultTagName) + return node.tagName.escapedText === escapeLeadingUnderscores(defaultTagName) ? node.tagName : createIdentifier(defaultTagName); } // @api - function createBaseJSDocTag(kind: T["kind"], tagName: ts.Identifier, comment: string | ts.NodeArray | undefined) { + function createBaseJSDocTag(kind: T["kind"], tagName: Identifier, comment: string | NodeArray | undefined) { const node = createBaseNode(kind); node.tagName = tagName; node.comment = comment; @@ -4590,15 +4670,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocTemplateTag(tagName: ts.Identifier | undefined, constraint: ts.JSDocTypeExpression | undefined, typeParameters: readonly ts.TypeParameterDeclaration[], comment?: string | ts.NodeArray): ts.JSDocTemplateTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment); + function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment); node.constraint = constraint; node.typeParameters = createNodeArray(typeParameters); return node; } // @api - function updateJSDocTemplateTag(node: ts.JSDocTemplateTag, tagName: ts.Identifier = getDefaultTagName(node), constraint: ts.JSDocTypeExpression | undefined, typeParameters: readonly ts.TypeParameterDeclaration[], comment: string | ts.NodeArray | undefined): ts.JSDocTemplateTag { + function updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier = getDefaultTagName(node), constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray | undefined): JSDocTemplateTag { return node.tagName !== tagName || node.constraint !== constraint || node.typeParameters !== typeParameters @@ -4608,16 +4688,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocTypedefTag(tagName: ts.Identifier | undefined, typeExpression?: ts.JSDocTypeExpression, fullName?: ts.Identifier | ts.JSDocNamespaceDeclaration, comment?: string | ts.NodeArray): ts.JSDocTypedefTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); + function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); node.typeExpression = typeExpression; node.fullName = fullName; - node.name = ts.getJSDocTypeAliasName(fullName); + node.name = getJSDocTypeAliasName(fullName); return node; } // @api - function updateJSDocTypedefTag(node: ts.JSDocTypedefTag, tagName: ts.Identifier = getDefaultTagName(node), typeExpression: ts.JSDocTypeExpression | undefined, fullName: ts.Identifier | ts.JSDocNamespaceDeclaration | undefined, comment: string | ts.NodeArray | undefined): ts.JSDocTypedefTag { + function updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocTypedefTag { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.fullName !== fullName @@ -4627,8 +4707,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocParameterTag(tagName: ts.Identifier | undefined, name: ts.EntityName, isBracketed: boolean, typeExpression?: ts.JSDocTypeExpression, isNameFirst?: boolean, comment?: string | ts.NodeArray): ts.JSDocParameterTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment); + function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -4637,7 +4717,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateJSDocParameterTag(node: ts.JSDocParameterTag, tagName: ts.Identifier = getDefaultTagName(node), name: ts.EntityName, isBracketed: boolean, typeExpression: ts.JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | ts.NodeArray | undefined): ts.JSDocParameterTag { + function updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocParameterTag { return node.tagName !== tagName || node.name !== name || node.isBracketed !== isBracketed @@ -4649,8 +4729,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocPropertyTag(tagName: ts.Identifier | undefined, name: ts.EntityName, isBracketed: boolean, typeExpression?: ts.JSDocTypeExpression, isNameFirst?: boolean, comment?: string | ts.NodeArray): ts.JSDocPropertyTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); + function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -4659,7 +4739,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateJSDocPropertyTag(node: ts.JSDocPropertyTag, tagName: ts.Identifier = getDefaultTagName(node), name: ts.EntityName, isBracketed: boolean, typeExpression: ts.JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | ts.NodeArray | undefined): ts.JSDocPropertyTag { + function updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray | undefined): JSDocPropertyTag { return node.tagName !== tagName || node.name !== name || node.isBracketed !== isBracketed @@ -4671,16 +4751,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocCallbackTag(tagName: ts.Identifier | undefined, typeExpression: ts.JSDocSignature, fullName?: ts.Identifier | ts.JSDocNamespaceDeclaration, comment?: string | ts.NodeArray): ts.JSDocCallbackTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); + function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); node.typeExpression = typeExpression; node.fullName = fullName; - node.name = ts.getJSDocTypeAliasName(fullName); + node.name = getJSDocTypeAliasName(fullName); return node; } // @api - function updateJSDocCallbackTag(node: ts.JSDocCallbackTag, tagName: ts.Identifier = getDefaultTagName(node), typeExpression: ts.JSDocSignature, fullName: ts.Identifier | ts.JSDocNamespaceDeclaration | undefined, comment: string | ts.NodeArray | undefined): ts.JSDocCallbackTag { + function updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.fullName !== fullName @@ -4690,14 +4770,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocAugmentsTag(tagName: ts.Identifier | undefined, className: ts.JSDocAugmentsTag["class"], comment?: string | ts.NodeArray): ts.JSDocAugmentsTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment); + function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment); node.class = className; return node; } // @api - function updateJSDocAugmentsTag(node: ts.JSDocAugmentsTag, tagName: ts.Identifier = getDefaultTagName(node), className: ts.JSDocAugmentsTag["class"], comment: string | ts.NodeArray | undefined): ts.JSDocAugmentsTag { + function updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag { return node.tagName !== tagName || node.class !== className || node.comment !== comment @@ -4706,21 +4786,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocImplementsTag(tagName: ts.Identifier | undefined, className: ts.JSDocImplementsTag["class"], comment?: string | ts.NodeArray): ts.JSDocImplementsTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment); + function createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment); node.class = className; return node; } // @api - function createJSDocSeeTag(tagName: ts.Identifier | undefined, name: ts.JSDocNameReference | undefined, comment?: string | ts.NodeArray): ts.JSDocSeeTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocSeeTag, tagName ?? createIdentifier("see"), comment); + function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocSeeTag, tagName ?? createIdentifier("see"), comment); node.name = name; return node; } // @api - function updateJSDocSeeTag(node: ts.JSDocSeeTag, tagName: ts.Identifier | undefined, name: ts.JSDocNameReference | undefined, comment?: string | ts.NodeArray): ts.JSDocSeeTag { + function updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray): JSDocSeeTag { return node.tagName !== tagName || node.name !== name || node.comment !== comment @@ -4729,22 +4809,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocNameReference(name: ts.EntityName | ts.JSDocMemberName): ts.JSDocNameReference { - const node = createBaseNode(ts.SyntaxKind.JSDocNameReference); + function createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference { + const node = createBaseNode(SyntaxKind.JSDocNameReference); node.name = name; return node; } // @api - function updateJSDocNameReference(node: ts.JSDocNameReference, name: ts.EntityName | ts.JSDocMemberName): ts.JSDocNameReference { + function updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference { return node.name !== name ? update(createJSDocNameReference(name), node) : node; } // @api - function createJSDocMemberName(left: ts.EntityName | ts.JSDocMemberName, right: ts.Identifier) { - const node = createBaseNode(ts.SyntaxKind.JSDocMemberName); + function createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier) { + const node = createBaseNode(SyntaxKind.JSDocMemberName); node.left = left; node.right = right; node.transformFlags |= @@ -4754,7 +4834,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateJSDocMemberName(node: ts.JSDocMemberName, left: ts.EntityName | ts.JSDocMemberName, right: ts.Identifier) { + function updateJSDocMemberName(node: JSDocMemberName, left: EntityName | JSDocMemberName, right: Identifier) { return node.left !== left || node.right !== right ? update(createJSDocMemberName(left, right), node) @@ -4762,52 +4842,52 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocLink(name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLink { - const node = createBaseNode(ts.SyntaxKind.JSDocLink); + function createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink { + const node = createBaseNode(SyntaxKind.JSDocLink); node.name = name; node.text = text; return node; } // @api - function updateJSDocLink(node: ts.JSDocLink, name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLink { + function updateJSDocLink(node: JSDocLink, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink { return node.name !== name ? update(createJSDocLink(name, text), node) : node; } // @api - function createJSDocLinkCode(name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLinkCode { - const node = createBaseNode(ts.SyntaxKind.JSDocLinkCode); + function createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode { + const node = createBaseNode(SyntaxKind.JSDocLinkCode); node.name = name; node.text = text; return node; } // @api - function updateJSDocLinkCode(node: ts.JSDocLinkCode, name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLinkCode { + function updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode { return node.name !== name ? update(createJSDocLinkCode(name, text), node) : node; } // @api - function createJSDocLinkPlain(name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLinkPlain { - const node = createBaseNode(ts.SyntaxKind.JSDocLinkPlain); + function createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain { + const node = createBaseNode(SyntaxKind.JSDocLinkPlain); node.name = name; node.text = text; return node; } // @api - function updateJSDocLinkPlain(node: ts.JSDocLinkPlain, name: ts.EntityName | ts.JSDocMemberName | undefined, text: string): ts.JSDocLinkPlain { + function updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain { return node.name !== name ? update(createJSDocLinkPlain(name, text), node) : node; } // @api - function updateJSDocImplementsTag(node: ts.JSDocImplementsTag, tagName: ts.Identifier = getDefaultTagName(node), className: ts.JSDocImplementsTag["class"], comment: string | ts.NodeArray | undefined): ts.JSDocImplementsTag { + function updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocImplementsTag["class"], comment: string | NodeArray | undefined): JSDocImplementsTag { return node.tagName !== tagName || node.class !== className || node.comment !== comment @@ -4823,7 +4903,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // createJSDocProtectedTag // createJSDocReadonlyTag // createJSDocDeprecatedTag - function createJSDocSimpleTagWorker(kind: T["kind"], tagName: ts.Identifier | undefined, comment?: string | ts.NodeArray) { + function createJSDocSimpleTagWorker(kind: T["kind"], tagName: Identifier | undefined, comment?: string | NodeArray) { const node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); return node; } @@ -4836,7 +4916,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // updateJSDocProtectedTag // updateJSDocReadonlyTag // updateJSDocDeprecatedTag - function updateJSDocSimpleTagWorker(kind: T["kind"], node: T, tagName: ts.Identifier = getDefaultTagName(node), comment: string | ts.NodeArray | undefined) { + function updateJSDocSimpleTagWorker(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | NodeArray | undefined) { return node.tagName !== tagName || node.comment !== comment ? update(createJSDocSimpleTagWorker(kind, tagName, comment), node) : @@ -4848,7 +4928,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // createJSDocReturnTag // createJSDocThisTag // createJSDocEnumTag - function createJSDocTypeLikeTagWorker(kind: T["kind"], tagName: ts.Identifier | undefined, typeExpression?: ts.JSDocTypeExpression, comment?: string | ts.NodeArray) { + function createJSDocTypeLikeTagWorker(kind: T["kind"], tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray) { const node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); node.typeExpression = typeExpression; return node; @@ -4859,7 +4939,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // updateJSDocReturnTag // updateJSDocThisTag // updateJSDocEnumTag - function updateJSDocTypeLikeTagWorker(kind: T["kind"], node: T, tagName: ts.Identifier = getDefaultTagName(node), typeExpression: ts.JSDocTypeExpression | undefined, comment: string | ts.NodeArray | undefined) { + function updateJSDocTypeLikeTagWorker(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray | undefined) { return node.tagName !== tagName || node.typeExpression !== typeExpression || node.comment !== comment @@ -4868,13 +4948,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocUnknownTag(tagName: ts.Identifier, comment?: string | ts.NodeArray): ts.JSDocUnknownTag { - const node = createBaseJSDocTag(ts.SyntaxKind.JSDocTag, tagName, comment); + function createJSDocUnknownTag(tagName: Identifier, comment?: string | NodeArray): JSDocUnknownTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocTag, tagName, comment); return node; } // @api - function updateJSDocUnknownTag(node: ts.JSDocUnknownTag, tagName: ts.Identifier, comment: string | ts.NodeArray | undefined): ts.JSDocUnknownTag { + function updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag { return node.tagName !== tagName || node.comment !== comment ? update(createJSDocUnknownTag(tagName, comment), node) @@ -4882,29 +4962,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJSDocText(text: string): ts.JSDocText { - const node = createBaseNode(ts.SyntaxKind.JSDocText); + function createJSDocText(text: string): JSDocText { + const node = createBaseNode(SyntaxKind.JSDocText); node.text = text; return node; } // @api - function updateJSDocText(node: ts.JSDocText, text: string): ts.JSDocText { + function updateJSDocText(node: JSDocText, text: string): JSDocText { return node.text !== text ? update(createJSDocText(text), node) : node; } // @api - function createJSDocComment(comment?: string | ts.NodeArray | undefined, tags?: readonly ts.JSDocTag[] | undefined) { - const node = createBaseNode(ts.SyntaxKind.JSDoc); + function createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined) { + const node = createBaseNode(SyntaxKind.JSDoc); node.comment = comment; node.tags = asNodeArray(tags); return node; } // @api - function updateJSDocComment(node: ts.JSDoc, comment: string | ts.NodeArray | undefined, tags: readonly ts.JSDocTag[] | undefined) { + function updateJSDocComment(node: JSDoc, comment: string | NodeArray | undefined, tags: readonly JSDocTag[] | undefined) { return node.comment !== comment || node.tags !== tags ? update(createJSDocComment(comment, tags), node) @@ -4916,8 +4996,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createJsxElement(openingElement: ts.JsxOpeningElement, children: readonly ts.JsxChild[], closingElement: ts.JsxClosingElement) { - const node = createBaseNode(ts.SyntaxKind.JsxElement); + function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { + const node = createBaseNode(SyntaxKind.JsxElement); node.openingElement = openingElement; node.children = createNodeArray(children); node.closingElement = closingElement; @@ -4925,12 +5005,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.openingElement) | propagateChildrenFlags(node.children) | propagateChildFlags(node.closingElement) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxElement(node: ts.JsxElement, openingElement: ts.JsxOpeningElement, children: readonly ts.JsxChild[], closingElement: ts.JsxClosingElement) { + function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) { return node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement @@ -4939,8 +5019,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJsxSelfClosingElement(tagName: ts.JsxTagNameExpression, typeArguments: readonly ts.TypeNode[] | undefined, attributes: ts.JsxAttributes) { - const node = createBaseNode(ts.SyntaxKind.JsxSelfClosingElement); + function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + const node = createBaseNode(SyntaxKind.JsxSelfClosingElement); node.tagName = tagName; node.typeArguments = asNodeArray(typeArguments); node.attributes = attributes; @@ -4948,15 +5028,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.tagName) | propagateChildrenFlags(node.typeArguments) | propagateChildFlags(node.attributes) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; if (node.typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } return node; } // @api - function updateJsxSelfClosingElement(node: ts.JsxSelfClosingElement, tagName: ts.JsxTagNameExpression, typeArguments: readonly ts.TypeNode[] | undefined, attributes: ts.JsxAttributes) { + function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes @@ -4965,8 +5045,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJsxOpeningElement(tagName: ts.JsxTagNameExpression, typeArguments: readonly ts.TypeNode[] | undefined, attributes: ts.JsxAttributes) { - const node = createBaseNode(ts.SyntaxKind.JsxOpeningElement); + function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { + const node = createBaseNode(SyntaxKind.JsxOpeningElement); node.tagName = tagName; node.typeArguments = asNodeArray(typeArguments); node.attributes = attributes; @@ -4974,15 +5054,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.tagName) | propagateChildrenFlags(node.typeArguments) | propagateChildFlags(node.attributes) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; if (typeArguments) { - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + node.transformFlags |= TransformFlags.ContainsTypeScript; } return node; } // @api - function updateJsxOpeningElement(node: ts.JsxOpeningElement, tagName: ts.JsxTagNameExpression, typeArguments: readonly ts.TypeNode[] | undefined, attributes: ts.JsxAttributes) { + function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) { return node.tagName !== tagName || node.typeArguments !== typeArguments || node.attributes !== attributes @@ -4991,25 +5071,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJsxClosingElement(tagName: ts.JsxTagNameExpression) { - const node = createBaseNode(ts.SyntaxKind.JsxClosingElement); + function createJsxClosingElement(tagName: JsxTagNameExpression) { + const node = createBaseNode(SyntaxKind.JsxClosingElement); node.tagName = tagName; node.transformFlags |= propagateChildFlags(node.tagName) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxClosingElement(node: ts.JsxClosingElement, tagName: ts.JsxTagNameExpression) { + function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { return node.tagName !== tagName ? update(createJsxClosingElement(tagName), node) : node; } // @api - function createJsxFragment(openingFragment: ts.JsxOpeningFragment, children: readonly ts.JsxChild[], closingFragment: ts.JsxClosingFragment) { - const node = createBaseNode(ts.SyntaxKind.JsxFragment); + function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { + const node = createBaseNode(SyntaxKind.JsxFragment); node.openingFragment = openingFragment; node.children = createNodeArray(children); node.closingFragment = closingFragment; @@ -5017,12 +5097,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN propagateChildFlags(node.openingFragment) | propagateChildrenFlags(node.children) | propagateChildFlags(node.closingFragment) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxFragment(node: ts.JsxFragment, openingFragment: ts.JsxOpeningFragment, children: readonly ts.JsxChild[], closingFragment: ts.JsxClosingFragment) { + function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) { return node.openingFragment !== openingFragment || node.children !== children || node.closingFragment !== closingFragment @@ -5032,15 +5112,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) { - const node = createBaseNode(ts.SyntaxKind.JsxText); + const node = createBaseNode(SyntaxKind.JsxText); node.text = text; node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces; - node.transformFlags |= ts.TransformFlags.ContainsJsx; + node.transformFlags |= TransformFlags.ContainsJsx; return node; } // @api - function updateJsxText(node: ts.JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { + function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) { return node.text !== text || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces ? update(createJsxText(text, containsOnlyTriviaWhiteSpaces), node) @@ -5049,32 +5129,32 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createJsxOpeningFragment() { - const node = createBaseNode(ts.SyntaxKind.JsxOpeningFragment); - node.transformFlags |= ts.TransformFlags.ContainsJsx; + const node = createBaseNode(SyntaxKind.JsxOpeningFragment); + node.transformFlags |= TransformFlags.ContainsJsx; return node; } // @api function createJsxJsxClosingFragment() { - const node = createBaseNode(ts.SyntaxKind.JsxClosingFragment); - node.transformFlags |= ts.TransformFlags.ContainsJsx; + const node = createBaseNode(SyntaxKind.JsxClosingFragment); + node.transformFlags |= TransformFlags.ContainsJsx; return node; } // @api - function createJsxAttribute(name: ts.Identifier, initializer: ts.JsxAttributeValue | undefined) { - const node = createBaseNode(ts.SyntaxKind.JsxAttribute); + function createJsxAttribute(name: Identifier, initializer: JsxAttributeValue | undefined) { + const node = createBaseNode(SyntaxKind.JsxAttribute); node.name = name; node.initializer = initializer; node.transformFlags |= propagateChildFlags(node.name) | propagateChildFlags(node.initializer) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxAttribute(node: ts.JsxAttribute, name: ts.Identifier, initializer: ts.JsxAttributeValue | undefined) { + function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: JsxAttributeValue | undefined) { return node.name !== name || node.initializer !== initializer ? update(createJsxAttribute(name, initializer), node) @@ -5082,53 +5162,53 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createJsxAttributes(properties: readonly ts.JsxAttributeLike[]) { - const node = createBaseNode(ts.SyntaxKind.JsxAttributes); + function createJsxAttributes(properties: readonly JsxAttributeLike[]) { + const node = createBaseNode(SyntaxKind.JsxAttributes); node.properties = createNodeArray(properties); node.transformFlags |= propagateChildrenFlags(node.properties) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxAttributes(node: ts.JsxAttributes, properties: readonly ts.JsxAttributeLike[]) { + function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) { return node.properties !== properties ? update(createJsxAttributes(properties), node) : node; } // @api - function createJsxSpreadAttribute(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.JsxSpreadAttribute); + function createJsxSpreadAttribute(expression: Expression) { + const node = createBaseNode(SyntaxKind.JsxSpreadAttribute); node.expression = expression; node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxSpreadAttribute(node: ts.JsxSpreadAttribute, expression: ts.Expression) { + function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { return node.expression !== expression ? update(createJsxSpreadAttribute(expression), node) : node; } // @api - function createJsxExpression(dotDotDotToken: ts.DotDotDotToken | undefined, expression: ts.Expression | undefined) { - const node = createBaseNode(ts.SyntaxKind.JsxExpression); + function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) { + const node = createBaseNode(SyntaxKind.JsxExpression); node.dotDotDotToken = dotDotDotToken; node.expression = expression; node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsJsx; + TransformFlags.ContainsJsx; return node; } // @api - function updateJsxExpression(node: ts.JsxExpression, expression: ts.Expression | undefined) { + function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) { return node.expression !== expression ? update(createJsxExpression(node.dotDotDotToken, expression), node) : node; @@ -5139,8 +5219,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createCaseClause(expression: ts.Expression, statements: readonly ts.Statement[]) { - const node = createBaseNode(ts.SyntaxKind.CaseClause); + function createCaseClause(expression: Expression, statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.CaseClause); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.statements = createNodeArray(statements); node.transformFlags |= @@ -5150,7 +5230,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateCaseClause(node: ts.CaseClause, expression: ts.Expression, statements: readonly ts.Statement[]) { + function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) { return node.expression !== expression || node.statements !== statements ? update(createCaseClause(expression, statements), node) @@ -5158,50 +5238,50 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createDefaultClause(statements: readonly ts.Statement[]) { - const node = createBaseNode(ts.SyntaxKind.DefaultClause); + function createDefaultClause(statements: readonly Statement[]) { + const node = createBaseNode(SyntaxKind.DefaultClause); node.statements = createNodeArray(statements); node.transformFlags = propagateChildrenFlags(node.statements); return node; } // @api - function updateDefaultClause(node: ts.DefaultClause, statements: readonly ts.Statement[]) { + function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) { return node.statements !== statements ? update(createDefaultClause(statements), node) : node; } // @api - function createHeritageClause(token: ts.HeritageClause["token"], types: readonly ts.ExpressionWithTypeArguments[]) { - const node = createBaseNode(ts.SyntaxKind.HeritageClause); + function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) { + const node = createBaseNode(SyntaxKind.HeritageClause); node.token = token; node.types = createNodeArray(types); node.transformFlags |= propagateChildrenFlags(node.types); switch (token) { - case ts.SyntaxKind.ExtendsKeyword: - node.transformFlags |= ts.TransformFlags.ContainsES2015; + case SyntaxKind.ExtendsKeyword: + node.transformFlags |= TransformFlags.ContainsES2015; break; - case ts.SyntaxKind.ImplementsKeyword: - node.transformFlags |= ts.TransformFlags.ContainsTypeScript; + case SyntaxKind.ImplementsKeyword: + node.transformFlags |= TransformFlags.ContainsTypeScript; break; default: - return ts.Debug.assertNever(token); + return Debug.assertNever(token); } return node; } // @api - function updateHeritageClause(node: ts.HeritageClause, types: readonly ts.ExpressionWithTypeArguments[]) { + function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) { return node.types !== types ? update(createHeritageClause(node.token, types), node) : node; } // @api - function createCatchClause(variableDeclaration: string | ts.BindingName | ts.VariableDeclaration | undefined, block: ts.Block) { - const node = createBaseNode(ts.SyntaxKind.CatchClause); - if (typeof variableDeclaration === "string" || variableDeclaration && !ts.isVariableDeclaration(variableDeclaration)) { + function createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block) { + const node = createBaseNode(SyntaxKind.CatchClause); + if (typeof variableDeclaration === "string" || variableDeclaration && !isVariableDeclaration(variableDeclaration)) { variableDeclaration = createVariableDeclaration( variableDeclaration, /*exclamationToken*/ undefined, @@ -5214,12 +5294,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN node.transformFlags |= propagateChildFlags(node.variableDeclaration) | propagateChildFlags(node.block); - if (!variableDeclaration) node.transformFlags |= ts.TransformFlags.ContainsES2019; + if (!variableDeclaration) node.transformFlags |= TransformFlags.ContainsES2019; return node; } // @api - function updateCatchClause(node: ts.CatchClause, variableDeclaration: ts.VariableDeclaration | undefined, block: ts.Block) { + function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) { return node.variableDeclaration !== variableDeclaration || node.block !== block ? update(createCatchClause(variableDeclaration, block), node) @@ -5231,9 +5311,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createPropertyAssignment(name: string | ts.PropertyName, initializer: ts.Expression) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.PropertyAssignment, + function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { + const node = createBaseNamedDeclaration( + SyntaxKind.PropertyAssignment, /*modifiers*/ undefined, name ); @@ -5251,14 +5331,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updatePropertyAssignment(node: ts.PropertyAssignment, name: ts.PropertyName, initializer: ts.Expression) { + function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) { return node.name !== name || node.initializer !== initializer ? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node) : node; } - function finishUpdatePropertyAssignment(updated: ts.Mutable, original: ts.PropertyAssignment) { + function finishUpdatePropertyAssignment(updated: Mutable, original: PropertyAssignment) { // copy children used only for error reporting if (updated !== original) { updated.illegalDecorators = original.illegalDecorators; @@ -5270,16 +5350,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createShorthandPropertyAssignment(name: string | ts.Identifier, objectAssignmentInitializer?: ts.Expression) { - const node = createBaseNamedDeclaration( - ts.SyntaxKind.ShorthandPropertyAssignment, + function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { + const node = createBaseNamedDeclaration( + SyntaxKind.ShorthandPropertyAssignment, /*modifiers*/ undefined, name ); node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); node.transformFlags |= propagateChildFlags(node.objectAssignmentInitializer) | - ts.TransformFlags.ContainsES2015; + TransformFlags.ContainsES2015; // The following properties are used only to report grammar errors node.equalsToken = undefined; @@ -5291,14 +5371,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateShorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, name: ts.Identifier, objectAssignmentInitializer: ts.Expression | undefined) { + function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) { return node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node) : node; } - function finishUpdateShorthandPropertyAssignment(updated: ts.Mutable, original: ts.ShorthandPropertyAssignment) { + function finishUpdateShorthandPropertyAssignment(updated: Mutable, original: ShorthandPropertyAssignment) { if (updated !== original) { // copy children used only for error reporting updated.equalsToken = original.equalsToken; @@ -5311,18 +5391,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createSpreadAssignment(expression: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.SpreadAssignment); + function createSpreadAssignment(expression: Expression) { + const node = createBaseNode(SyntaxKind.SpreadAssignment); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsES2018 | - ts.TransformFlags.ContainsObjectRestOrSpread; + TransformFlags.ContainsES2018 | + TransformFlags.ContainsObjectRestOrSpread; return node; } // @api - function updateSpreadAssignment(node: ts.SpreadAssignment, expression: ts.Expression) { + function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { return node.expression !== expression ? update(createSpreadAssignment(expression), node) : node; @@ -5333,19 +5413,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createEnumMember(name: string | ts.PropertyName, initializer?: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.EnumMember); + function createEnumMember(name: string | PropertyName, initializer?: Expression) { + const node = createBaseNode(SyntaxKind.EnumMember); node.name = asName(name); node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); node.transformFlags |= propagateChildFlags(node.name) | propagateChildFlags(node.initializer) | - ts.TransformFlags.ContainsTypeScript; + TransformFlags.ContainsTypeScript; return node; } // @api - function updateEnumMember(node: ts.EnumMember, name: ts.PropertyName, initializer: ts.Expression | undefined) { + function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { return node.name !== name || node.initializer !== initializer ? update(createEnumMember(name, initializer), node) @@ -5358,11 +5438,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function createSourceFile( - statements: readonly ts.Statement[], - endOfFileToken: ts.EndOfFileToken, - flags: ts.NodeFlags + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + flags: NodeFlags ) { - const node = baseFactory.createBaseSourceFileNode(ts.SyntaxKind.SourceFile) as ts.Mutable; + const node = baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as Mutable; node.statements = createNodeArray(statements); node.endOfFileToken = endOfFileToken; node.flags |= flags; @@ -5380,17 +5460,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } function cloneSourceFileWithChanges( - source: ts.SourceFile, - statements: readonly ts.Statement[], + source: SourceFile, + statements: readonly Statement[], isDeclarationFile: boolean, - referencedFiles: readonly ts.FileReference[], - typeReferences: readonly ts.FileReference[], + referencedFiles: readonly FileReference[], + typeReferences: readonly FileReference[], hasNoDefaultLib: boolean, - libReferences: readonly ts.FileReference[] + libReferences: readonly FileReference[] ) { - const node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : baseFactory.createBaseSourceFileNode(ts.SyntaxKind.SourceFile)) as ts.Mutable; + const node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile)) as Mutable; for (const p in source) { - if (p === "emitNode" || ts.hasProperty(node, p) || !ts.hasProperty(source, p)) continue; + if (p === "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue; (node as any)[p] = (source as any)[p]; } node.flags |= source.flags; @@ -5410,8 +5490,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // @api function updateSourceFile( - node: ts.SourceFile, - statements: readonly ts.Statement[], + node: SourceFile, + statements: readonly Statement[], isDeclarationFile = node.isDeclarationFile, referencedFiles = node.referencedFiles, typeReferenceDirectives = node.typeReferenceDirectives, @@ -5429,15 +5509,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createBundle(sourceFiles: readonly ts.SourceFile[], prepends: readonly (ts.UnparsedSource | ts.InputFiles)[] = ts.emptyArray) { - const node = createBaseNode(ts.SyntaxKind.Bundle); + function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { + const node = createBaseNode(SyntaxKind.Bundle); node.prepends = prepends; node.sourceFiles = sourceFiles; return node; } // @api - function updateBundle(node: ts.Bundle, sourceFiles: readonly ts.SourceFile[], prepends: readonly (ts.UnparsedSource | ts.InputFiles)[] = ts.emptyArray) { + function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { return node.sourceFiles !== sourceFiles || node.prepends !== prepends ? update(createBundle(sourceFiles, prepends), node) @@ -5445,53 +5525,53 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createUnparsedSource(prologues: readonly ts.UnparsedPrologue[], syntheticReferences: readonly ts.UnparsedSyntheticReference[] | undefined, texts: readonly ts.UnparsedSourceText[]) { - const node = createBaseNode(ts.SyntaxKind.UnparsedSource); + function createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]) { + const node = createBaseNode(SyntaxKind.UnparsedSource); node.prologues = prologues; node.syntheticReferences = syntheticReferences; node.texts = texts; node.fileName = ""; node.text = ""; - node.referencedFiles = ts.emptyArray; - node.libReferenceDirectives = ts.emptyArray; - node.getLineAndCharacterOfPosition = pos => ts.getLineAndCharacterOfPosition(node, pos); + node.referencedFiles = emptyArray; + node.libReferenceDirectives = emptyArray; + node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos); return node; } - function createBaseUnparsedNode(kind: T["kind"], data?: string) { + function createBaseUnparsedNode(kind: T["kind"], data?: string) { const node = createBaseNode(kind); node.data = data; return node; } // @api - function createUnparsedPrologue(data?: string): ts.UnparsedPrologue { - return createBaseUnparsedNode(ts.SyntaxKind.UnparsedPrologue, data); + function createUnparsedPrologue(data?: string): UnparsedPrologue { + return createBaseUnparsedNode(SyntaxKind.UnparsedPrologue, data); } // @api - function createUnparsedPrepend(data: string | undefined, texts: readonly ts.UnparsedTextLike[]): ts.UnparsedPrepend { - const node = createBaseUnparsedNode(ts.SyntaxKind.UnparsedPrepend, data); + function createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedTextLike[]): UnparsedPrepend { + const node = createBaseUnparsedNode(SyntaxKind.UnparsedPrepend, data); node.texts = texts; return node; } // @api - function createUnparsedTextLike(data: string | undefined, internal: boolean): ts.UnparsedTextLike { - return createBaseUnparsedNode(internal ? ts.SyntaxKind.UnparsedInternalText : ts.SyntaxKind.UnparsedText, data); + function createUnparsedTextLike(data: string | undefined, internal: boolean): UnparsedTextLike { + return createBaseUnparsedNode(internal ? SyntaxKind.UnparsedInternalText : SyntaxKind.UnparsedText, data); } // @api - function createUnparsedSyntheticReference(section: ts.BundleFileHasNoDefaultLib | ts.BundleFileReference): ts.UnparsedSyntheticReference { - const node = createBaseNode(ts.SyntaxKind.UnparsedSyntheticReference); + function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference { + const node = createBaseNode(SyntaxKind.UnparsedSyntheticReference); node.data = section.data; node.section = section; return node; } // @api - function createInputFiles(): ts.InputFiles { - const node = createBaseNode(ts.SyntaxKind.InputFiles); + function createInputFiles(): InputFiles { + const node = createBaseNode(SyntaxKind.InputFiles); node.javascriptText = ""; node.declarationText = ""; return node; @@ -5502,8 +5582,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // // @api - function createSyntheticExpression(type: ts.Type, isSpread = false, tupleNameSource?: ts.ParameterDeclaration | ts.NamedTupleMember) { - const node = createBaseNode(ts.SyntaxKind.SyntheticExpression); + function createSyntheticExpression(type: Type, isSpread = false, tupleNameSource?: ParameterDeclaration | NamedTupleMember) { + const node = createBaseNode(SyntaxKind.SyntheticExpression); node.type = type; node.isSpread = isSpread; node.tupleNameSource = tupleNameSource; @@ -5511,8 +5591,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createSyntaxList(children: ts.Node[]) { - const node = createBaseNode(ts.SyntaxKind.SyntaxList); + function createSyntaxList(children: Node[]) { + const node = createBaseNode(SyntaxKind.SyntaxList); node._children = children; return node; } @@ -5528,10 +5608,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param original The original statement. */ // @api - function createNotEmittedStatement(original: ts.Node) { - const node = createBaseNode(ts.SyntaxKind.NotEmittedStatement); + function createNotEmittedStatement(original: Node) { + const node = createBaseNode(SyntaxKind.NotEmittedStatement); node.original = original; - ts.setTextRange(node, original); + setTextRange(node, original); return node; } @@ -5543,30 +5623,30 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param original The original outer expression. */ // @api - function createPartiallyEmittedExpression(expression: ts.Expression, original?: ts.Node) { - const node = createBaseNode(ts.SyntaxKind.PartiallyEmittedExpression); + function createPartiallyEmittedExpression(expression: Expression, original?: Node) { + const node = createBaseNode(SyntaxKind.PartiallyEmittedExpression); node.expression = expression; node.original = original; node.transformFlags |= propagateChildFlags(node.expression) | - ts.TransformFlags.ContainsTypeScript; - ts.setTextRange(node, original); + TransformFlags.ContainsTypeScript; + setTextRange(node, original); return node; } // @api - function updatePartiallyEmittedExpression(node: ts.PartiallyEmittedExpression, expression: ts.Expression) { + function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { return node.expression !== expression ? update(createPartiallyEmittedExpression(expression, node.original), node) : node; } - function flattenCommaElements(node: ts.Expression): ts.Expression | readonly ts.Expression[] { - if (ts.nodeIsSynthesized(node) && !ts.isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { - if (ts.isCommaListExpression(node)) { + function flattenCommaElements(node: Expression): Expression | readonly Expression[] { + if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { + if (isCommaListExpression(node)) { return node.elements; } - if (ts.isBinaryExpression(node) && ts.isCommaToken(node.operatorToken)) { + if (isBinaryExpression(node) && isCommaToken(node.operatorToken)) { return [node.left, node.right]; } } @@ -5574,15 +5654,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function createCommaListExpression(elements: readonly ts.Expression[]) { - const node = createBaseNode(ts.SyntaxKind.CommaListExpression); - node.elements = createNodeArray(ts.sameFlatMap(elements, flattenCommaElements)); + function createCommaListExpression(elements: readonly Expression[]) { + const node = createBaseNode(SyntaxKind.CommaListExpression); + node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements)); node.transformFlags |= propagateChildrenFlags(node.elements); return node; } // @api - function updateCommaListExpression(node: ts.CommaListExpression, elements: readonly ts.Expression[]) { + function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) { return node.elements !== elements ? update(createCommaListExpression(elements), node) : node; @@ -5593,9 +5673,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * order to properly emit exports. */ // @api - function createEndOfDeclarationMarker(original: ts.Node) { - const node = createBaseNode(ts.SyntaxKind.EndOfDeclarationMarker); - node.emitNode = {} as ts.EmitNode; + function createEndOfDeclarationMarker(original: Node) { + const node = createBaseNode(SyntaxKind.EndOfDeclarationMarker); + node.emitNode = {} as EmitNode; node.original = original; return node; } @@ -5605,16 +5685,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * order to properly emit exports. */ // @api - function createMergeDeclarationMarker(original: ts.Node) { - const node = createBaseNode(ts.SyntaxKind.MergeDeclarationMarker); - node.emitNode = {} as ts.EmitNode; + function createMergeDeclarationMarker(original: Node) { + const node = createBaseNode(SyntaxKind.MergeDeclarationMarker); + node.emitNode = {} as EmitNode; node.original = original; return node; } // @api - function createSyntheticReferenceExpression(expression: ts.Expression, thisArg: ts.Expression) { - const node = createBaseNode(ts.SyntaxKind.SyntheticReferenceExpression); + function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) { + const node = createBaseNode(SyntaxKind.SyntheticReferenceExpression); node.expression = expression; node.thisArg = thisArg; node.transformFlags |= @@ -5624,7 +5704,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function updateSyntheticReferenceExpression(node: ts.SyntheticReferenceExpression, expression: ts.Expression, thisArg: ts.Expression) { + function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) { return node.expression !== expression || node.thisArg !== thisArg ? update(createSyntheticReferenceExpression(expression, thisArg), node) @@ -5632,8 +5712,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // @api - function cloneNode(node: T): T; - function cloneNode(node: T) { + function cloneNode(node: T): T; + function cloneNode(node: T) { // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). @@ -5642,18 +5722,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } const clone = - ts.isSourceFile(node) ? baseFactory.createBaseSourceFileNode(ts.SyntaxKind.SourceFile) as T : - ts.isIdentifier(node) ? baseFactory.createBaseIdentifierNode(ts.SyntaxKind.Identifier) as T : - ts.isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(ts.SyntaxKind.PrivateIdentifier) as T : - !ts.isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : + isSourceFile(node) ? baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as T : + isIdentifier(node) ? baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as T : + isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as T : + !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : baseFactory.createBaseNode(node.kind) as T; - (clone as ts.Mutable).flags |= (node.flags & ~ts.NodeFlags.Synthesized); - (clone as ts.Mutable).transformFlags = node.transformFlags; + (clone as Mutable).flags |= (node.flags & ~NodeFlags.Synthesized); + (clone as Mutable).transformFlags = node.transformFlags; setOriginalNode(clone, node); for (const key in node) { - if (ts.hasProperty(clone, key) || !ts.hasProperty(node, key)) { + if (hasProperty(clone, key) || !hasProperty(node, key)) { continue; } @@ -5664,9 +5744,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } // compound nodes - function createImmediatelyInvokedFunctionExpression(statements: readonly ts.Statement[]): ts.CallExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly ts.Statement[], param: ts.ParameterDeclaration, paramValue: ts.Expression): ts.CallExpression; - function createImmediatelyInvokedFunctionExpression(statements: readonly ts.Statement[], param?: ts.ParameterDeclaration, paramValue?: ts.Expression) { + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression; + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { return createCallExpression( createFunctionExpression( /*modifiers*/ undefined, @@ -5682,9 +5762,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); } - function createImmediatelyInvokedArrowFunction(statements: readonly ts.Statement[]): ts.CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly ts.Statement[], param: ts.ParameterDeclaration, paramValue: ts.Expression): ts.CallExpression; - function createImmediatelyInvokedArrowFunction(statements: readonly ts.Statement[], param?: ts.ParameterDeclaration, paramValue?: ts.Expression) { + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression; + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression; + function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) { return createCallExpression( createArrowFunction( /*modifiers*/ undefined, @@ -5703,14 +5783,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return createVoidExpression(createNumericLiteral("0")); } - function createExportDefault(expression: ts.Expression) { + function createExportDefault(expression: Expression) { return createExportAssignment( /*modifiers*/ undefined, /*isExportEquals*/ false, expression); } - function createExternalModuleExport(exportName: ts.Identifier) { + function createExternalModuleExport(exportName: Identifier) { return createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, @@ -5724,15 +5804,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // Utilities // - function createTypeCheck(value: ts.Expression, tag: ts.TypeOfTag) { + function createTypeCheck(value: Expression, tag: TypeOfTag) { return tag === "undefined" ? factory.createStrictEquality(value, createVoidZero()) : factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag)); } - function createMethodCall(object: ts.Expression, methodName: string | ts.Identifier, argumentsList: readonly ts.Expression[]) { + function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) { // Preserve the optionality of `object`. - if (ts.isCallChain(object)) { + if (isCallChain(object)) { return createCallChain( createPropertyAccessChain(object, /*questionDotToken*/ undefined, methodName), /*questionDotToken*/ undefined, @@ -5747,43 +5827,43 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); } - function createFunctionBindCall(target: ts.Expression, thisArg: ts.Expression, argumentsList: readonly ts.Expression[]) { + function createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) { return createMethodCall(target, "bind", [thisArg, ...argumentsList]); } - function createFunctionCallCall(target: ts.Expression, thisArg: ts.Expression, argumentsList: readonly ts.Expression[]) { + function createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) { return createMethodCall(target, "call", [thisArg, ...argumentsList]); } - function createFunctionApplyCall(target: ts.Expression, thisArg: ts.Expression, argumentsExpression: ts.Expression) { + function createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression) { return createMethodCall(target, "apply", [thisArg, argumentsExpression]); } - function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly ts.Expression[]) { + function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) { return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList); } - function createArraySliceCall(array: ts.Expression, start?: number | ts.Expression) { + function createArraySliceCall(array: Expression, start?: number | Expression) { return createMethodCall(array, "slice", start === undefined ? [] : [asExpression(start)]); } - function createArrayConcatCall(array: ts.Expression, argumentsList: readonly ts.Expression[]) { + function createArrayConcatCall(array: Expression, argumentsList: readonly Expression[]) { return createMethodCall(array, "concat", argumentsList); } - function createObjectDefinePropertyCall(target: ts.Expression, propertyName: string | ts.Expression, attributes: ts.Expression) { + function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) { return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]); } - function createReflectGetCall(target: ts.Expression, propertyKey: ts.Expression, receiver?: ts.Expression): ts.CallExpression { + function createReflectGetCall(target: Expression, propertyKey: Expression, receiver?: Expression): CallExpression { return createGlobalMethodCall("Reflect", "get", receiver ? [target, propertyKey, receiver] : [target, propertyKey]); } - function createReflectSetCall(target: ts.Expression, propertyKey: ts.Expression, value: ts.Expression, receiver?: ts.Expression): ts.CallExpression { + function createReflectSetCall(target: Expression, propertyKey: Expression, value: Expression, receiver?: Expression): CallExpression { return createGlobalMethodCall("Reflect", "set", receiver ? [target, propertyKey, value, receiver] : [target, propertyKey, value]); } - function tryAddPropertyAssignment(properties: ts.Push, propertyName: string, expression: ts.Expression | undefined) { + function tryAddPropertyAssignment(properties: Push, propertyName: string, expression: Expression | undefined) { if (expression) { properties.push(createPropertyAssignment(propertyName, expression)); return true; @@ -5791,8 +5871,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return false; } - function createPropertyDescriptor(attributes: ts.PropertyDescriptorAttributes, singleLine?: boolean) { - const properties: ts.PropertyAssignment[] = []; + function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) { + const properties: PropertyAssignment[] = []; tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable)); tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable)); @@ -5802,18 +5882,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get); isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor; - ts.Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); + Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor."); return createObjectLiteralExpression(properties, !singleLine); } - function updateOuterExpression(outerExpression: ts.OuterExpression, expression: ts.Expression) { + function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) { switch (outerExpression.kind) { - case ts.SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression); - case ts.SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression); - case ts.SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type); - case ts.SyntaxKind.SatisfiesExpression: return updateSatisfiesExpression(outerExpression, expression, outerExpression.type); - case ts.SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression); - case ts.SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); + case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression); + case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression); + case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type); + case SyntaxKind.SatisfiesExpression: return updateSatisfiesExpression(outerExpression, expression, outerExpression.type); + case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression); + case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression); } } @@ -5831,17 +5911,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * the expression to maintain precedence, a new parenthesized expression should be created automatically when * the containing expression is created/updated. */ - function isIgnorableParen(node: ts.Expression) { - return ts.isParenthesizedExpression(node) - && ts.nodeIsSynthesized(node) - && ts.nodeIsSynthesized(ts.getSourceMapRange(node)) - && ts.nodeIsSynthesized(ts.getCommentRange(node)) - && !ts.some(ts.getSyntheticLeadingComments(node)) - && !ts.some(ts.getSyntheticTrailingComments(node)); + function isIgnorableParen(node: Expression) { + return isParenthesizedExpression(node) + && nodeIsSynthesized(node) + && nodeIsSynthesized(getSourceMapRange(node)) + && nodeIsSynthesized(getCommentRange(node)) + && !some(getSyntheticLeadingComments(node)) + && !some(getSyntheticTrailingComments(node)); } - function restoreOuterExpressions(outerExpression: ts.Expression | undefined, innerExpression: ts.Expression, kinds = ts.OuterExpressionKinds.All): ts.Expression { - if (outerExpression && ts.isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { + function restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression { + if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression( outerExpression, restoreOuterExpressions(outerExpression.expression, innerExpression) @@ -5850,14 +5930,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return innerExpression; } - function restoreEnclosingLabel(node: ts.Statement, outermostLabeledStatement: ts.LabeledStatement | undefined, afterRestoreLabelCallback?: (node: ts.LabeledStatement) => void): ts.Statement { + function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement { if (!outermostLabeledStatement) { return node; } const updated = updateLabeledStatement( outermostLabeledStatement, outermostLabeledStatement.label, - ts.isLabeledStatement(outermostLabeledStatement.statement) + isLabeledStatement(outermostLabeledStatement.statement) ? restoreEnclosingLabel(node, outermostLabeledStatement.statement) : node ); @@ -5867,53 +5947,53 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return updated; } - function shouldBeCapturedInTempVariable(node: ts.Expression, cacheIdentifiers: boolean): boolean { - const target = ts.skipParentheses(node); + function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean { + const target = skipParentheses(node); switch (target.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: return cacheIdentifiers; - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.StringLiteral: + case SyntaxKind.ThisKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: return false; - case ts.SyntaxKind.ArrayLiteralExpression: - const elements = (target as ts.ArrayLiteralExpression).elements; + case SyntaxKind.ArrayLiteralExpression: + const elements = (target as ArrayLiteralExpression).elements; if (elements.length === 0) { return false; } return true; - case ts.SyntaxKind.ObjectLiteralExpression: - return (target as ts.ObjectLiteralExpression).properties.length > 0; + case SyntaxKind.ObjectLiteralExpression: + return (target as ObjectLiteralExpression).properties.length > 0; default: return true; } } - function createCallBinding(expression: ts.Expression, recordTempVariable: (temp: ts.Identifier) => void, languageVersion?: ts.ScriptTarget, cacheIdentifiers = false): ts.CallBinding { - const callee = ts.skipOuterExpressions(expression, ts.OuterExpressionKinds.All); - let thisArg: ts.Expression; - let target: ts.LeftHandSideExpression; - if (ts.isSuperProperty(callee)) { + function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding { + const callee = skipOuterExpressions(expression, OuterExpressionKinds.All); + let thisArg: Expression; + let target: LeftHandSideExpression; + if (isSuperProperty(callee)) { thisArg = createThis(); target = callee; } - else if (ts.isSuperKeyword(callee)) { + else if (isSuperKeyword(callee)) { thisArg = createThis(); - target = languageVersion !== undefined && languageVersion < ts.ScriptTarget.ES2015 - ? ts.setTextRange(createIdentifier("_super"), callee) - : callee as ts.PrimaryExpression; + target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015 + ? setTextRange(createIdentifier("_super"), callee) + : callee as PrimaryExpression; } - else if (ts.getEmitFlags(callee) & ts.EmitFlags.HelperName) { + else if (getEmitFlags(callee) & EmitFlags.HelperName) { thisArg = createVoidZero(); target = parenthesizerRules().parenthesizeLeftSideOfAccess(callee, /*optionalChain*/ false); } - else if (ts.isPropertyAccessExpression(callee)) { + else if (isPropertyAccessExpression(callee)) { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a.b()` target is `(_a = a).b` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); target = createPropertyAccessExpression( - ts.setTextRange( + setTextRange( factory.createAssignment( thisArg, callee.expression @@ -5922,19 +6002,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ), callee.name ); - ts.setTextRange(target, callee); + setTextRange(target, callee); } else { thisArg = callee.expression; target = callee; } } - else if (ts.isElementAccessExpression(callee)) { + else if (isElementAccessExpression(callee)) { if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) { // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); target = createElementAccessExpression( - ts.setTextRange( + setTextRange( factory.createAssignment( thisArg, callee.expression @@ -5943,7 +6023,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ), callee.argumentExpression ); - ts.setTextRange(target, callee); + setTextRange(target, callee); } else { thisArg = callee.expression; @@ -5959,7 +6039,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return { target, thisArg }; } - function createAssignmentTargetWrapper(paramName: ts.Identifier, expression: ts.Expression): ts.LeftHandSideExpression { + function createAssignmentTargetWrapper(paramName: Identifier, expression: Expression): LeftHandSideExpression { return createPropertyAccessExpression( // Explicit parens required because of v8 regression (https://bugs.chromium.org/p/v8/issues/detail?id=9560) createParenthesizedExpression( @@ -5985,23 +6065,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN ); } - function inlineExpressions(expressions: readonly ts.Expression[]) { + function inlineExpressions(expressions: readonly Expression[]) { // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call // stack size exceeded" errors. return expressions.length > 10 ? createCommaListExpression(expressions) - : ts.reduceLeft(expressions, factory.createComma)!; + : reduceLeft(expressions, factory.createComma)!; } - function getName(node: ts.Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: ts.EmitFlags = 0) { - const nodeName = ts.getNameOfDeclaration(node); - if (nodeName && ts.isIdentifier(nodeName) && !ts.isGeneratedIdentifier(nodeName)) { + function getName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) { + const nodeName = getNameOfDeclaration(node); + if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) { // TODO(rbuckton): Does this need to be parented? - const name = ts.setParent(ts.setTextRange(cloneNode(nodeName), nodeName), nodeName.parent); - emitFlags |= ts.getEmitFlags(nodeName); - if (!allowSourceMaps) emitFlags |= ts.EmitFlags.NoSourceMap; - if (!allowComments) emitFlags |= ts.EmitFlags.NoComments; - if (emitFlags) ts.setEmitFlags(name, emitFlags); + const name = setParent(setTextRange(cloneNode(nodeName), nodeName), nodeName.parent); + emitFlags |= getEmitFlags(nodeName); + if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags |= EmitFlags.NoComments; + if (emitFlags) setEmitFlags(name, emitFlags); return name; } return getGeneratedNameForNode(node); @@ -6018,8 +6098,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getInternalName(node: ts.Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getName(node, allowComments, allowSourceMaps, ts.EmitFlags.LocalName | ts.EmitFlags.InternalName); + function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { + return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName); } /** @@ -6032,8 +6112,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getLocalName(node: ts.Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { - return getName(node, allowComments, allowSourceMaps, ts.EmitFlags.LocalName); + function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) { + return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName); } /** @@ -6046,8 +6126,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getExportName(node: ts.Declaration, allowComments?: boolean, allowSourceMaps?: boolean): ts.Identifier { - return getName(node, allowComments, allowSourceMaps, ts.EmitFlags.ExportName); + function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier { + return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName); } /** @@ -6057,7 +6137,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getDeclarationName(node: ts.Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean) { + function getDeclarationName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean) { return getName(node, allowComments, allowSourceMaps); } @@ -6069,13 +6149,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getNamespaceMemberName(ns: ts.Identifier, name: ts.Identifier, allowComments?: boolean, allowSourceMaps?: boolean): ts.PropertyAccessExpression { - const qualifiedName = createPropertyAccessExpression(ns, ts.nodeIsSynthesized(name) ? name : cloneNode(name)); - ts.setTextRange(qualifiedName, name); - let emitFlags: ts.EmitFlags = 0; - if (!allowSourceMaps) emitFlags |= ts.EmitFlags.NoSourceMap; - if (!allowComments) emitFlags |= ts.EmitFlags.NoComments; - if (emitFlags) ts.setEmitFlags(qualifiedName, emitFlags); + function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { + const qualifiedName = createPropertyAccessExpression(ns, nodeIsSynthesized(name) ? name : cloneNode(name)); + setTextRange(qualifiedName, name); + let emitFlags: EmitFlags = 0; + if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; + if (!allowComments) emitFlags |= EmitFlags.NoComments; + if (emitFlags) setEmitFlags(qualifiedName, emitFlags); return qualifiedName; } @@ -6090,8 +6170,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param allowComments A value indicating whether comments may be emitted for the name. * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ - function getExternalModuleOrNamespaceExportName(ns: ts.Identifier | undefined, node: ts.Declaration, allowComments?: boolean, allowSourceMaps?: boolean): ts.Identifier | ts.PropertyAccessExpression { - if (ns && ts.hasSyntacticModifier(node, ts.ModifierFlags.Export)) { + function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression { + if (ns && hasSyntacticModifier(node, ModifierFlags.Export)) { return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps); } return getExportName(node, allowComments, allowSourceMaps); @@ -6104,17 +6184,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param ensureUseStrict boolean determining whether the function need to add prologue-directives * @param visitor Optional callback used to visit any custom prologue directives. */ - function copyPrologue(source: readonly ts.Statement[], target: ts.Push, ensureUseStrict?: boolean, visitor?: (node: ts.Node) => ts.VisitResult): number { + function copyPrologue(source: readonly Statement[], target: Push, ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult): number { const offset = copyStandardPrologue(source, target, 0, ensureUseStrict); return copyCustomPrologue(source, target, offset, visitor); } - function isUseStrictPrologue(node: ts.ExpressionStatement): boolean { - return ts.isStringLiteral(node.expression) && node.expression.text === "use strict"; + function isUseStrictPrologue(node: ExpressionStatement): boolean { + return isStringLiteral(node.expression) && node.expression.text === "use strict"; } function createUseStrictPrologue() { - return ts.startOnNewLine(createExpressionStatement(createStringLiteral("use strict"))) as ts.PrologueDirective; + return startOnNewLine(createExpressionStatement(createStringLiteral("use strict"))) as PrologueDirective; } /** @@ -6125,13 +6205,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param ensureUseStrict boolean determining whether the function need to add prologue-directives * @returns Count of how many directive statements were copied. */ - function copyStandardPrologue(source: readonly ts.Statement[], target: ts.Push, statementOffset = 0, ensureUseStrict?: boolean): number { - ts.Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); + function copyStandardPrologue(source: readonly Statement[], target: Push, statementOffset = 0, ensureUseStrict?: boolean): number { + Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array"); let foundUseStrict = false; const numStatements = source.length; while (statementOffset < numStatements) { const statement = source[statementOffset]; - if (ts.isPrologueDirective(statement)) { + if (isPrologueDirective(statement)) { if (isUseStrictPrologue(statement)) { foundUseStrict = true; } @@ -6155,14 +6235,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * @param statementOffset The offset at which to begin the copy. * @param visitor Optional callback used to visit any custom prologue directives. */ - function copyCustomPrologue(source: readonly ts.Statement[], target: ts.Push, statementOffset: number, visitor?: (node: ts.Node) => ts.VisitResult, filter?: (node: ts.Node) => boolean): number; - function copyCustomPrologue(source: readonly ts.Statement[], target: ts.Push, statementOffset: number | undefined, visitor?: (node: ts.Node) => ts.VisitResult, filter?: (node: ts.Node) => boolean): number | undefined; - function copyCustomPrologue(source: readonly ts.Statement[], target: ts.Push, statementOffset: number | undefined, visitor?: (node: ts.Node) => ts.VisitResult, filter: (node: ts.Node) => boolean = ts.returnTrue): number | undefined { + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number, visitor?: (node: Node) => VisitResult, filter?: (node: Node) => boolean): number; + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter?: (node: Node) => boolean): number | undefined; + function copyCustomPrologue(source: readonly Statement[], target: Push, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult, filter: (node: Node) => boolean = returnTrue): number | undefined { const numStatements = source.length; while (statementOffset !== undefined && statementOffset < numStatements) { const statement = source[statementOffset]; - if (ts.getEmitFlags(statement) & ts.EmitFlags.CustomPrologue && filter(statement)) { - ts.append(target, visitor ? ts.visitNode(statement, visitor, ts.isStatement) : statement); + if (getEmitFlags(statement) & EmitFlags.CustomPrologue && filter(statement)) { + append(target, visitor ? visitNode(statement, visitor, isStatement) : statement); } else { break; @@ -6177,11 +6257,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * * @param statements An array of statements */ - function ensureUseStrict(statements: ts.NodeArray): ts.NodeArray { - const foundUseStrict = ts.findUseStrictPrologue(statements); + function ensureUseStrict(statements: NodeArray): NodeArray { + const foundUseStrict = findUseStrictPrologue(statements); if (!foundUseStrict) { - return ts.setTextRange(createNodeArray([createUseStrictPrologue(), ...statements]), statements); + return setTextRange(createNodeArray([createUseStrictPrologue(), ...statements]), statements); } return statements; @@ -6192,9 +6272,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN * * @param nodes The NodeArray. */ - function liftToBlock(nodes: readonly ts.Node[]): ts.Statement { - ts.Debug.assert(ts.every(nodes, ts.isStatementOrBlock), "Cannot lift nodes to a Block."); - return ts.singleOrUndefined(nodes) as ts.Statement || createBlock(nodes as readonly ts.Statement[]); + function liftToBlock(nodes: readonly Node[]): Statement { + Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block."); + return singleOrUndefined(nodes) as Statement || createBlock(nodes as readonly Statement[]); } function findSpanEnd(array: readonly T[], test: (value: T) => boolean, start: number) { @@ -6205,10 +6285,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN return i; } - function mergeLexicalEnvironment(statements: ts.NodeArray, declarations: readonly ts.Statement[] | undefined): ts.NodeArray; - function mergeLexicalEnvironment(statements: ts.Statement[], declarations: readonly ts.Statement[] | undefined): ts.Statement[]; - function mergeLexicalEnvironment(statements: ts.Statement[] | ts.NodeArray, declarations: readonly ts.Statement[] | undefined) { - if (!ts.some(declarations)) { + function mergeLexicalEnvironment(statements: NodeArray, declarations: readonly Statement[] | undefined): NodeArray; + function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[]; + function mergeLexicalEnvironment(statements: Statement[] | NodeArray, declarations: readonly Statement[] | undefined) { + if (!some(declarations)) { return statements; } @@ -6242,20 +6322,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN // as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state. // find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom - const leftStandardPrologueEnd = findSpanEnd(statements, ts.isPrologueDirective, 0); - const leftHoistedFunctionsEnd = findSpanEnd(statements, ts.isHoistedFunction, leftStandardPrologueEnd); - const leftHoistedVariablesEnd = findSpanEnd(statements, ts.isHoistedVariableStatement, leftHoistedFunctionsEnd); + const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0); + const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd); + const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd); // find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom - const rightStandardPrologueEnd = findSpanEnd(declarations, ts.isPrologueDirective, 0); - const rightHoistedFunctionsEnd = findSpanEnd(declarations, ts.isHoistedFunction, rightStandardPrologueEnd); - const rightHoistedVariablesEnd = findSpanEnd(declarations, ts.isHoistedVariableStatement, rightHoistedFunctionsEnd); - const rightCustomPrologueEnd = findSpanEnd(declarations, ts.isCustomPrologue, rightHoistedVariablesEnd); - ts.Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues"); + const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0); + const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd); + const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd); + const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd); + Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues"); // splice prologues from the right into the left. We do this in reverse order // so that we don't need to recompute the index on the left when we insert items. - const left = ts.isNodeArray(statements) ? statements.slice() : statements; + const left = isNodeArray(statements) ? statements.slice() : statements; // splice other custom prologues from right into left if (rightCustomPrologueEnd > rightHoistedVariablesEnd) { @@ -6278,13 +6358,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd)); } else { - const leftPrologues = new ts.Map(); + const leftPrologues = new Map(); for (let i = 0; i < leftStandardPrologueEnd; i++) { - const leftPrologue = statements[i] as ts.PrologueDirective; + const leftPrologue = statements[i] as PrologueDirective; leftPrologues.set(leftPrologue.expression.text, true); } for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) { - const rightPrologue = declarations[i] as ts.PrologueDirective; + const rightPrologue = declarations[i] as PrologueDirective; if (!leftPrologues.has(rightPrologue.expression.text)) { left.unshift(rightPrologue); } @@ -6292,15 +6372,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN } } - if (ts.isNodeArray(statements)) { - return ts.setTextRange(createNodeArray(left, statements.hasTrailingComma), statements); + if (isNodeArray(statements)) { + return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements); } return statements; } - function updateModifiers(node: T, modifiers: readonly ts.Modifier[] | ts.ModifierFlags): T; - function updateModifiers(node: ts.HasModifiers, modifiers: readonly ts.Modifier[] | ts.ModifierFlags) { + function updateModifiers(node: T, modifiers: readonly Modifier[] | ModifierFlags): T; + function updateModifiers(node: HasModifiers, modifiers: readonly Modifier[] | ModifierFlags) { let modifierArray; if (typeof modifiers === "number") { modifierArray = createModifiersFromModifierFlags(modifiers); @@ -6308,127 +6388,127 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: ts.BaseN else { modifierArray = modifiers; } - return ts.isTypeParameterDeclaration(node) ? updateTypeParameterDeclaration(node, modifierArray, node.name, node.constraint, node.default) : - ts.isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : - ts.isConstructorTypeNode(node) ? updateConstructorTypeNode1(node, modifierArray, node.typeParameters, node.parameters, node.type) : - ts.isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) : - ts.isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) : - ts.isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) : - ts.isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : - ts.isConstructorDeclaration(node) ? updateConstructorDeclaration(node, modifierArray, node.parameters, node.body) : - ts.isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) : - ts.isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) : - ts.isIndexSignatureDeclaration(node) ? updateIndexSignature(node, modifierArray, node.parameters, node.type) : - ts.isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : - ts.isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) : - ts.isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) : - ts.isFunctionDeclaration(node) ? updateFunctionDeclaration(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : - ts.isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : - ts.isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, modifierArray, node.name, node.typeParameters, node.type) : - ts.isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) : - ts.isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) : - ts.isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) : - ts.isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) : - ts.isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) : - ts.isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) : - ts.Debug.assertNever(node); - } - - function asNodeArray(array: readonly T[]): ts.NodeArray; - function asNodeArray(array: readonly T[] | undefined): ts.NodeArray | undefined; - function asNodeArray(array: readonly T[] | undefined): ts.NodeArray | undefined { + return isTypeParameterDeclaration(node) ? updateTypeParameterDeclaration(node, modifierArray, node.name, node.constraint, node.default) : + isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) : + isConstructorTypeNode(node) ? updateConstructorTypeNode1(node, modifierArray, node.typeParameters, node.parameters, node.type) : + isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) : + isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) : + isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) : + isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) : + isConstructorDeclaration(node) ? updateConstructorDeclaration(node, modifierArray, node.parameters, node.body) : + isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) : + isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) : + isIndexSignatureDeclaration(node) ? updateIndexSignature(node, modifierArray, node.parameters, node.type) : + isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : + isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) : + isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) : + isFunctionDeclaration(node) ? updateFunctionDeclaration(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) : + isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) : + isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, modifierArray, node.name, node.typeParameters, node.type) : + isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) : + isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) : + isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) : + isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) : + isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) : + isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) : + Debug.assertNever(node); + } + + function asNodeArray(array: readonly T[]): NodeArray; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined; + function asNodeArray(array: readonly T[] | undefined): NodeArray | undefined { return array ? createNodeArray(array) : undefined; } - function asName(name: string | T): T | ts.Identifier { + function asName(name: string | T): T | Identifier { return typeof name === "string" ? createIdentifier(name) : name; } - function asExpression(value: string | number | boolean | T): T | ts.StringLiteral | ts.NumericLiteral | ts.BooleanLiteral { + function asExpression(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral { return typeof value === "string" ? createStringLiteral(value) : typeof value === "number" ? createNumericLiteral(value) : typeof value === "boolean" ? value ? createTrue() : createFalse() : value; } - function asToken(value: TKind | ts.Token): ts.Token { + function asToken(value: TKind | Token): Token { return typeof value === "number" ? createToken(value) : value; } - function asEmbeddedStatement(statement: T): T | ts.EmptyStatement; - function asEmbeddedStatement(statement: T | undefined): T | ts.EmptyStatement | undefined; - function asEmbeddedStatement(statement: T | undefined): T | ts.EmptyStatement | undefined { - return statement && ts.isNotEmittedStatement(statement) ? ts.setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; + function asEmbeddedStatement(statement: T): T | EmptyStatement; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined; + function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { + return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; } } -function updateWithoutOriginal(updated: ts.Mutable, original: T): T { +function updateWithoutOriginal(updated: Mutable, original: T): T { if (updated !== original) { - ts.setTextRange(updated, original); + setTextRange(updated, original); } return updated; } -function updateWithOriginal(updated: ts.Mutable, original: T): T { +function updateWithOriginal(updated: Mutable, original: T): T { if (updated !== original) { setOriginalNode(updated, original); - ts.setTextRange(updated, original); + setTextRange(updated, original); } return updated; } -function getDefaultTagNameForKind(kind: ts.JSDocTag["kind"]): string { +function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string { switch (kind) { - case ts.SyntaxKind.JSDocTypeTag: return "type"; - case ts.SyntaxKind.JSDocReturnTag: return "returns"; - case ts.SyntaxKind.JSDocThisTag: return "this"; - case ts.SyntaxKind.JSDocEnumTag: return "enum"; - case ts.SyntaxKind.JSDocAuthorTag: return "author"; - case ts.SyntaxKind.JSDocClassTag: return "class"; - case ts.SyntaxKind.JSDocPublicTag: return "public"; - case ts.SyntaxKind.JSDocPrivateTag: return "private"; - case ts.SyntaxKind.JSDocProtectedTag: return "protected"; - case ts.SyntaxKind.JSDocReadonlyTag: return "readonly"; - case ts.SyntaxKind.JSDocOverrideTag: return "override"; - case ts.SyntaxKind.JSDocTemplateTag: return "template"; - case ts.SyntaxKind.JSDocTypedefTag: return "typedef"; - case ts.SyntaxKind.JSDocParameterTag: return "param"; - case ts.SyntaxKind.JSDocPropertyTag: return "prop"; - case ts.SyntaxKind.JSDocCallbackTag: return "callback"; - case ts.SyntaxKind.JSDocAugmentsTag: return "augments"; - case ts.SyntaxKind.JSDocImplementsTag: return "implements"; + case SyntaxKind.JSDocTypeTag: return "type"; + case SyntaxKind.JSDocReturnTag: return "returns"; + case SyntaxKind.JSDocThisTag: return "this"; + case SyntaxKind.JSDocEnumTag: return "enum"; + case SyntaxKind.JSDocAuthorTag: return "author"; + case SyntaxKind.JSDocClassTag: return "class"; + case SyntaxKind.JSDocPublicTag: return "public"; + case SyntaxKind.JSDocPrivateTag: return "private"; + case SyntaxKind.JSDocProtectedTag: return "protected"; + case SyntaxKind.JSDocReadonlyTag: return "readonly"; + case SyntaxKind.JSDocOverrideTag: return "override"; + case SyntaxKind.JSDocTemplateTag: return "template"; + case SyntaxKind.JSDocTypedefTag: return "typedef"; + case SyntaxKind.JSDocParameterTag: return "param"; + case SyntaxKind.JSDocPropertyTag: return "prop"; + case SyntaxKind.JSDocCallbackTag: return "callback"; + case SyntaxKind.JSDocAugmentsTag: return "augments"; + case SyntaxKind.JSDocImplementsTag: return "implements"; default: - return ts.Debug.fail(`Unsupported kind: ${ts.Debug.formatSyntaxKind(kind)}`); + return Debug.fail(`Unsupported kind: ${Debug.formatSyntaxKind(kind)}`); } } -let rawTextScanner: ts.Scanner | undefined; +let rawTextScanner: Scanner | undefined; const invalidValueSentinel: object = { }; -function getCookedText(kind: ts.TemplateLiteralToken["kind"], rawText: string) { +function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) { if (!rawTextScanner) { - rawTextScanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ false, ts.LanguageVariant.Standard); + rawTextScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard); } switch (kind) { - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: rawTextScanner.setText("`" + rawText + "`"); break; - case ts.SyntaxKind.TemplateHead: + case SyntaxKind.TemplateHead: rawTextScanner.setText("`" + rawText + "${"); break; - case ts.SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateMiddle: rawTextScanner.setText("}" + rawText + "${"); break; - case ts.SyntaxKind.TemplateTail: + case SyntaxKind.TemplateTail: rawTextScanner.setText("}" + rawText + "`"); break; } let token = rawTextScanner.scan(); - if (token === ts.SyntaxKind.CloseBraceToken) { + if (token === SyntaxKind.CloseBraceToken) { token = rawTextScanner.reScanTemplateToken(/*isTaggedTemplate*/ false); } @@ -6439,15 +6519,15 @@ function getCookedText(kind: ts.TemplateLiteralToken["kind"], rawText: string) { let tokenValue: string | undefined; switch (token) { - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.TemplateMiddle: - case ts.SyntaxKind.TemplateTail: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: tokenValue = rawTextScanner.getTokenValue(); break; } - if (tokenValue === undefined || rawTextScanner.scan() !== ts.SyntaxKind.EndOfFileToken) { + if (tokenValue === undefined || rawTextScanner.scan() !== SyntaxKind.EndOfFileToken) { rawTextScanner.setText(undefined); return invalidValueSentinel; } @@ -6456,27 +6536,27 @@ function getCookedText(kind: ts.TemplateLiteralToken["kind"], rawText: string) { return tokenValue; } -function propagateIdentifierNameFlags(node: ts.Identifier) { +function propagateIdentifierNameFlags(node: Identifier) { // An IdentifierName is allowed to be `await` - return propagateChildFlags(node) & ~ts.TransformFlags.ContainsPossibleTopLevelAwait; + return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait; } -function propagatePropertyNameFlagsOfChild(node: ts.PropertyName, transformFlags: ts.TransformFlags) { - return transformFlags | (node.transformFlags & ts.TransformFlags.PropertyNamePropagatingFlags); +function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) { + return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags); } -function propagateChildFlags(child: ts.Node | undefined): ts.TransformFlags { - if (!child) return ts.TransformFlags.None; +function propagateChildFlags(child: Node | undefined): TransformFlags { + if (!child) return TransformFlags.None; const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind); - return ts.isNamedDeclaration(child) && ts.isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags; + return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags; } -function propagateChildrenFlags(children: ts.NodeArray | undefined): ts.TransformFlags { - return children ? children.transformFlags : ts.TransformFlags.None; +function propagateChildrenFlags(children: NodeArray | undefined): TransformFlags { + return children ? children.transformFlags : TransformFlags.None; } -function aggregateChildrenFlags(children: ts.MutableNodeArray) { - let subtreeFlags = ts.TransformFlags.None; +function aggregateChildrenFlags(children: MutableNodeArray) { + let subtreeFlags = TransformFlags.None; for (const child of children) { subtreeFlags |= propagateChildFlags(child); } @@ -6487,86 +6567,86 @@ function aggregateChildrenFlags(children: ts.MutableNodeArray) { * Gets the transform flags to exclude when unioning the transform flags of a subtree. */ /* @internal */ -export function getTransformFlagsSubtreeExclusions(kind: ts.SyntaxKind) { - if (kind >= ts.SyntaxKind.FirstTypeNode && kind <= ts.SyntaxKind.LastTypeNode) { - return ts.TransformFlags.TypeExcludes; +export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) { + if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) { + return TransformFlags.TypeExcludes; } switch (kind) { - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.ArrayLiteralExpression: - return ts.TransformFlags.ArrayLiteralOrCallOrNewExcludes; - case ts.SyntaxKind.ModuleDeclaration: - return ts.TransformFlags.ModuleExcludes; - case ts.SyntaxKind.Parameter: - return ts.TransformFlags.ParameterExcludes; - case ts.SyntaxKind.ArrowFunction: - return ts.TransformFlags.ArrowFunctionExcludes; - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: - return ts.TransformFlags.FunctionExcludes; - case ts.SyntaxKind.VariableDeclarationList: - return ts.TransformFlags.VariableDeclarationListExcludes; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - return ts.TransformFlags.ClassExcludes; - case ts.SyntaxKind.Constructor: - return ts.TransformFlags.ConstructorExcludes; - case ts.SyntaxKind.PropertyDeclaration: - return ts.TransformFlags.PropertyExcludes; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return ts.TransformFlags.MethodOrAccessorExcludes; - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.ObjectKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.TypeParameter: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - return ts.TransformFlags.TypeExcludes; - case ts.SyntaxKind.ObjectLiteralExpression: - return ts.TransformFlags.ObjectLiteralExcludes; - case ts.SyntaxKind.CatchClause: - return ts.TransformFlags.CatchClauseExcludes; - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - return ts.TransformFlags.BindingPatternExcludes; - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.SatisfiesExpression: - case ts.SyntaxKind.AsExpression: - case ts.SyntaxKind.PartiallyEmittedExpression: - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.SuperKeyword: - return ts.TransformFlags.OuterExpressionExcludes; - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: - return ts.TransformFlags.PropertyAccessExcludes; + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ArrayLiteralExpression: + return TransformFlags.ArrayLiteralOrCallOrNewExcludes; + case SyntaxKind.ModuleDeclaration: + return TransformFlags.ModuleExcludes; + case SyntaxKind.Parameter: + return TransformFlags.ParameterExcludes; + case SyntaxKind.ArrowFunction: + return TransformFlags.ArrowFunctionExcludes; + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + return TransformFlags.FunctionExcludes; + case SyntaxKind.VariableDeclarationList: + return TransformFlags.VariableDeclarationListExcludes; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return TransformFlags.ClassExcludes; + case SyntaxKind.Constructor: + return TransformFlags.ConstructorExcludes; + case SyntaxKind.PropertyDeclaration: + return TransformFlags.PropertyExcludes; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return TransformFlags.MethodOrAccessorExcludes; + case SyntaxKind.AnyKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.TypeParameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + return TransformFlags.TypeExcludes; + case SyntaxKind.ObjectLiteralExpression: + return TransformFlags.ObjectLiteralExcludes; + case SyntaxKind.CatchClause: + return TransformFlags.CatchClauseExcludes; + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return TransformFlags.BindingPatternExcludes; + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.SatisfiesExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.PartiallyEmittedExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.SuperKeyword: + return TransformFlags.OuterExpressionExcludes; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + return TransformFlags.PropertyAccessExcludes; default: - return ts.TransformFlags.NodeExcludes; + return TransformFlags.NodeExcludes; } } -const baseFactory = ts.createBaseNodeFactory(); +const baseFactory = createBaseNodeFactory(); -function makeSynthetic(node: ts.Node) { - (node as ts.Mutable).flags |= ts.NodeFlags.Synthesized; +function makeSynthetic(node: Node) { + (node as Mutable).flags |= NodeFlags.Synthesized; return node; } -const syntheticFactory: ts.BaseNodeFactory = { +const syntheticFactory: BaseNodeFactory = { createBaseSourceFileNode: kind => makeSynthetic(baseFactory.createBaseSourceFileNode(kind)), createBaseIdentifierNode: kind => makeSynthetic(baseFactory.createBaseIdentifierNode(kind)), createBasePrivateIdentifierNode: kind => makeSynthetic(baseFactory.createBasePrivateIdentifierNode(kind)), @@ -6576,12 +6656,12 @@ const syntheticFactory: ts.BaseNodeFactory = { export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory); -export function createUnparsedSourceFile(text: string): ts.UnparsedSource; -export function createUnparsedSourceFile(inputFile: ts.InputFiles, type: "js" | "dts", stripInternal?: boolean): ts.UnparsedSource; -export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): ts.UnparsedSource; -export function createUnparsedSourceFile(textOrInputFiles: string | ts.InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): ts.UnparsedSource { +export function createUnparsedSourceFile(text: string): UnparsedSource; +export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource; +export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource; +export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource { let stripInternal: boolean | undefined; - let bundleFileInfo: ts.BundleFileInfo | undefined; + let bundleFileInfo: BundleFileInfo | undefined; let fileName: string; let text: string | undefined; let length: number | (() => number); @@ -6591,15 +6671,15 @@ export function createUnparsedSourceFile(textOrInputFiles: string | ts.InputFile let getSourceMapText: (() => string | undefined) | undefined; let oldFileOfCurrentEmit: boolean | undefined; - if (!ts.isString(textOrInputFiles)) { - ts.Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts"); + if (!isString(textOrInputFiles)) { + Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts"); fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || ""; sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath; getText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText; getSourceMapText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText; length = () => getText!().length; if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) { - ts.Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean"); + Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean"); stripInternal = mapTextOrStripInternal; bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts; oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit; @@ -6613,7 +6693,7 @@ export function createUnparsedSourceFile(textOrInputFiles: string | ts.InputFile sourceMapText = mapTextOrStripInternal as string; } const node = oldFileOfCurrentEmit ? - parseOldFileOfCurrentEmit(ts.Debug.checkDefined(bundleFileInfo)) : + parseOldFileOfCurrentEmit(Debug.checkDefined(bundleFileInfo)) : parseUnparsedSourceFile(bundleFileInfo, stripInternal, length); node.fileName = fileName; node.sourceMapPath = sourceMapPath; @@ -6623,7 +6703,7 @@ export function createUnparsedSourceFile(textOrInputFiles: string | ts.InputFile Object.defineProperty(node, "sourceMapText", { get: getSourceMapText }); } else { - ts.Debug.assert(!oldFileOfCurrentEmit); + Debug.assert(!oldFileOfCurrentEmit); node.text = text ?? ""; node.sourceMapText = sourceMapText; } @@ -6631,119 +6711,119 @@ export function createUnparsedSourceFile(textOrInputFiles: string | ts.InputFile return node; } -function parseUnparsedSourceFile(bundleFileInfo: ts.BundleFileInfo | undefined, stripInternal: boolean | undefined, length: number | (() => number)) { - let prologues: ts.UnparsedPrologue[] | undefined; - let helpers: ts.UnscopedEmitHelper[] | undefined; - let referencedFiles: ts.FileReference[] | undefined; - let typeReferenceDirectives: ts.FileReference[] | undefined; - let libReferenceDirectives: ts.FileReference[] | undefined; - let prependChildren: ts.UnparsedTextLike[] | undefined; - let texts: ts.UnparsedSourceText[] | undefined; +function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined, length: number | (() => number)) { + let prologues: UnparsedPrologue[] | undefined; + let helpers: UnscopedEmitHelper[] | undefined; + let referencedFiles: FileReference[] | undefined; + let typeReferenceDirectives: FileReference[] | undefined; + let libReferenceDirectives: FileReference[] | undefined; + let prependChildren: UnparsedTextLike[] | undefined; + let texts: UnparsedSourceText[] | undefined; let hasNoDefaultLib: boolean | undefined; - for (const section of bundleFileInfo ? bundleFileInfo.sections : ts.emptyArray) { + for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) { switch (section.kind) { - case ts.BundleFileSectionKind.Prologue: - prologues = ts.append(prologues, ts.setTextRange(factory.createUnparsedPrologue(section.data), section)); + case BundleFileSectionKind.Prologue: + prologues = append(prologues, setTextRange(factory.createUnparsedPrologue(section.data), section)); break; - case ts.BundleFileSectionKind.EmitHelpers: - helpers = ts.append(helpers, ts.getAllUnscopedEmitHelpers().get(section.data)!); + case BundleFileSectionKind.EmitHelpers: + helpers = append(helpers, getAllUnscopedEmitHelpers().get(section.data)!); break; - case ts.BundleFileSectionKind.NoDefaultLib: + case BundleFileSectionKind.NoDefaultLib: hasNoDefaultLib = true; break; - case ts.BundleFileSectionKind.Reference: - referencedFiles = ts.append(referencedFiles, { pos: -1, end: -1, fileName: section.data }); + case BundleFileSectionKind.Reference: + referencedFiles = append(referencedFiles, { pos: -1, end: -1, fileName: section.data }); break; - case ts.BundleFileSectionKind.Type: - typeReferenceDirectives = ts.append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); + case BundleFileSectionKind.Type: + typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); break; - case ts.BundleFileSectionKind.TypeResolutionModeImport: - typeReferenceDirectives = ts.append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ts.ModuleKind.ESNext }); + case BundleFileSectionKind.TypeResolutionModeImport: + typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.ESNext }); break; - case ts.BundleFileSectionKind.TypeResolutionModeRequire: - typeReferenceDirectives = ts.append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ts.ModuleKind.CommonJS }); + case BundleFileSectionKind.TypeResolutionModeRequire: + typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.CommonJS }); break; - case ts.BundleFileSectionKind.Lib: - libReferenceDirectives = ts.append(libReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); + case BundleFileSectionKind.Lib: + libReferenceDirectives = append(libReferenceDirectives, { pos: -1, end: -1, fileName: section.data }); break; - case ts.BundleFileSectionKind.Prepend: - let prependTexts: ts.UnparsedTextLike[] | undefined; + case BundleFileSectionKind.Prepend: + let prependTexts: UnparsedTextLike[] | undefined; for (const text of section.texts) { - if (!stripInternal || text.kind !== ts.BundleFileSectionKind.Internal) { - prependTexts = ts.append(prependTexts, ts.setTextRange(factory.createUnparsedTextLike(text.data, text.kind === ts.BundleFileSectionKind.Internal), text)); + if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) { + prependTexts = append(prependTexts, setTextRange(factory.createUnparsedTextLike(text.data, text.kind === BundleFileSectionKind.Internal), text)); } } - prependChildren = ts.addRange(prependChildren, prependTexts); - texts = ts.append(texts, factory.createUnparsedPrepend(section.data, prependTexts ?? ts.emptyArray)); + prependChildren = addRange(prependChildren, prependTexts); + texts = append(texts, factory.createUnparsedPrepend(section.data, prependTexts ?? emptyArray)); break; - case ts.BundleFileSectionKind.Internal: + case BundleFileSectionKind.Internal: if (stripInternal) { if (!texts) texts = []; break; } // falls through - case ts.BundleFileSectionKind.Text: - texts = ts.append(texts, ts.setTextRange(factory.createUnparsedTextLike(section.data, section.kind === ts.BundleFileSectionKind.Internal), section)); + case BundleFileSectionKind.Text: + texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section)); break; default: - ts.Debug.assertNever(section); + Debug.assertNever(section); } } if (!texts) { const textNode = factory.createUnparsedTextLike(/*data*/ undefined, /*internal*/ false); - ts.setTextRangePosWidth(textNode, 0, typeof length === "function" ? length() : length); + setTextRangePosWidth(textNode, 0, typeof length === "function" ? length() : length); texts = [textNode]; } - const node = ts.parseNodeFactory.createUnparsedSource(prologues ?? ts.emptyArray, /*syntheticReferences*/ undefined, texts); - ts.setEachParent(prologues, node); - ts.setEachParent(texts, node); - ts.setEachParent(prependChildren, node); + const node = parseNodeFactory.createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts); + setEachParent(prologues, node); + setEachParent(texts, node); + setEachParent(prependChildren, node); node.hasNoDefaultLib = hasNoDefaultLib; node.helpers = helpers; - node.referencedFiles = referencedFiles || ts.emptyArray; + node.referencedFiles = referencedFiles || emptyArray; node.typeReferenceDirectives = typeReferenceDirectives; - node.libReferenceDirectives = libReferenceDirectives || ts.emptyArray; + node.libReferenceDirectives = libReferenceDirectives || emptyArray; return node; } -function parseOldFileOfCurrentEmit(bundleFileInfo: ts.BundleFileInfo) { - let texts: ts.UnparsedTextLike[] | undefined; - let syntheticReferences: ts.UnparsedSyntheticReference[] | undefined; +function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) { + let texts: UnparsedTextLike[] | undefined; + let syntheticReferences: UnparsedSyntheticReference[] | undefined; for (const section of bundleFileInfo.sections) { switch (section.kind) { - case ts.BundleFileSectionKind.Internal: - case ts.BundleFileSectionKind.Text: - texts = ts.append(texts, ts.setTextRange(factory.createUnparsedTextLike(section.data, section.kind === ts.BundleFileSectionKind.Internal), section)); + case BundleFileSectionKind.Internal: + case BundleFileSectionKind.Text: + texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section)); break; - case ts.BundleFileSectionKind.NoDefaultLib: - case ts.BundleFileSectionKind.Reference: - case ts.BundleFileSectionKind.Type: - case ts.BundleFileSectionKind.TypeResolutionModeImport: - case ts.BundleFileSectionKind.TypeResolutionModeRequire: - case ts.BundleFileSectionKind.Lib: - syntheticReferences = ts.append(syntheticReferences, ts.setTextRange(factory.createUnparsedSyntheticReference(section), section)); + case BundleFileSectionKind.NoDefaultLib: + case BundleFileSectionKind.Reference: + case BundleFileSectionKind.Type: + case BundleFileSectionKind.TypeResolutionModeImport: + case BundleFileSectionKind.TypeResolutionModeRequire: + case BundleFileSectionKind.Lib: + syntheticReferences = append(syntheticReferences, setTextRange(factory.createUnparsedSyntheticReference(section), section)); break; // Ignore - case ts.BundleFileSectionKind.Prologue: - case ts.BundleFileSectionKind.EmitHelpers: - case ts.BundleFileSectionKind.Prepend: + case BundleFileSectionKind.Prologue: + case BundleFileSectionKind.EmitHelpers: + case BundleFileSectionKind.Prepend: break; default: - ts.Debug.assertNever(section); + Debug.assertNever(section); } } - const node = factory.createUnparsedSource(ts.emptyArray, syntheticReferences, texts ?? ts.emptyArray); - ts.setEachParent(syntheticReferences, node); - ts.setEachParent(texts, node); - node.helpers = ts.map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => ts.getAllUnscopedEmitHelpers().get(name)!); + const node = factory.createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray); + setEachParent(syntheticReferences, node); + setEachParent(texts, node); + node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!); return node; } @@ -6751,7 +6831,7 @@ function parseOldFileOfCurrentEmit(bundleFileInfo: ts.BundleFileInfo) { export function createInputFiles( javascriptText: string, declarationText: string -): ts.InputFiles; +): InputFiles; export function createInputFiles( javascriptText: string, declarationText: string, @@ -6759,7 +6839,7 @@ export function createInputFiles( javascriptMapText: string | undefined, declarationMapPath: string | undefined, declarationMapText: string | undefined -): ts.InputFiles; +): InputFiles; export function createInputFiles( readFileText: (path: string) => string | undefined, javascriptPath: string, @@ -6767,7 +6847,7 @@ export function createInputFiles( declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined -): ts.InputFiles; +): InputFiles; export function createInputFiles( javascriptTextOrReadFileText: string | ((path: string) => string | undefined), declarationTextOrJavascriptPath: string, @@ -6775,8 +6855,8 @@ export function createInputFiles( javascriptMapTextOrDeclarationPath?: string, declarationMapPath?: string, declarationMapTextOrBuildInfoPath?: string, -): ts.InputFiles { - return !ts.isString(javascriptTextOrReadFileText) ? +): InputFiles { + return !isString(javascriptTextOrReadFileText) ? createInputFilesWithFilePaths( javascriptTextOrReadFileText, declarationTextOrJavascriptPath, @@ -6804,16 +6884,16 @@ export function createInputFilesWithFilePaths( declarationPath: string, declarationMapPath: string | undefined, buildInfoPath: string | undefined, - host?: ts.CompilerHost, - options?: ts.CompilerOptions, -): ts.InputFiles { - const node = ts.parseNodeFactory.createInputFiles(); + host?: CompilerHost, + options?: CompilerOptions, +): InputFiles { + const node = parseNodeFactory.createInputFiles(); node.javascriptPath = javascriptPath; node.javascriptMapPath = javascriptMapPath; node.declarationPath = declarationPath; node.declarationMapPath = declarationMapPath; node.buildInfoPath = buildInfoPath; - const cache = new ts.Map(); + const cache = new Map(); const textGetter = (path: string | undefined) => { if (path === undefined) return undefined; let value = cache.get(path); @@ -6827,7 +6907,7 @@ export function createInputFilesWithFilePaths( const result = textGetter(path); return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`; }; - let buildInfo: ts.BuildInfo | false; + let buildInfo: BuildInfo | false; const getAndCacheBuildInfo = () => { if (buildInfo === undefined && buildInfoPath) { if (host?.getBuildInfo) { @@ -6835,7 +6915,7 @@ export function createInputFilesWithFilePaths( } else { const result = textGetter(buildInfoPath); - buildInfo = result !== undefined ? ts.getBuildInfo(buildInfoPath, result) ?? false : false; + buildInfo = result !== undefined ? getBuildInfo(buildInfoPath, result) ?? false : false; } } return buildInfo || undefined; @@ -6843,7 +6923,7 @@ export function createInputFilesWithFilePaths( Object.defineProperties(node, { javascriptText: { get: () => definedTextGetter(javascriptPath) }, javascriptMapText: { get: () => textGetter(javascriptMapPath) }, // TODO:: if there is inline sourceMap in jsFile, use that - declarationText: { get: () => definedTextGetter(ts.Debug.checkDefined(declarationPath)) }, + declarationText: { get: () => definedTextGetter(Debug.checkDefined(declarationPath)) }, declarationMapText: { get: () => textGetter(declarationMapPath) }, // TODO:: if there is inline sourceMap in dtsFile, use that buildInfo: { get: getAndCacheBuildInfo }, }); @@ -6860,10 +6940,10 @@ export function createInputFilesWithFileTexts( declarationMapPath: string | undefined, declarationMapText: string | undefined, buildInfoPath?: string, - buildInfo?: ts.BuildInfo, + buildInfo?: BuildInfo, oldFileOfCurrentEmit?: boolean, -): ts.InputFiles { - const node = ts.parseNodeFactory.createInputFiles(); +): InputFiles { + const node = parseNodeFactory.createInputFiles(); node.javascriptPath = javascriptPath; node.javascriptText = javascriptText; node.javascriptMapPath = javascriptMapPath; @@ -6878,18 +6958,18 @@ export function createInputFilesWithFileTexts( return node; } -let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => ts.SourceMapSource; +let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; /** * Create an external source map source file reference */ -export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): ts.SourceMapSource { - return new (SourceMapSource || (SourceMapSource = ts.objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); +export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource { + return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia); } // Utilities -export function setOriginalNode(node: T, original: ts.Node | undefined): T { +export function setOriginalNode(node: T, original: Node | undefined): T { node.original = original; if (original) { const emitNode = original.emitNode; @@ -6898,7 +6978,7 @@ export function setOriginalNode(node: T, original: ts.Node | return node; } -function mergeEmitNode(sourceEmitNode: ts.EmitNode, destEmitNode: ts.EmitNode | undefined) { +function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) { const { flags, leadingComments, @@ -6911,18 +6991,18 @@ function mergeEmitNode(sourceEmitNode: ts.EmitNode, destEmitNode: ts.EmitNode | startsOnNewLine, snippetElement, } = sourceEmitNode; - if (!destEmitNode) destEmitNode = {} as ts.EmitNode; + if (!destEmitNode) destEmitNode = {} as EmitNode; // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later. - if (leadingComments) destEmitNode.leadingComments = ts.addRange(leadingComments.slice(), destEmitNode.leadingComments); - if (trailingComments) destEmitNode.trailingComments = ts.addRange(trailingComments.slice(), destEmitNode.trailingComments); - if (flags) destEmitNode.flags = flags & ~ts.EmitFlags.Immutable; + if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments); + if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments); + if (flags) destEmitNode.flags = flags & ~EmitFlags.Immutable; if (commentRange) destEmitNode.commentRange = commentRange; if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!); if (constantValue !== undefined) destEmitNode.constantValue = constantValue; if (helpers) { for (const helper of helpers) { - destEmitNode.helpers = ts.appendIfUnique(destEmitNode.helpers, helper); + destEmitNode.helpers = appendIfUnique(destEmitNode.helpers, helper); } } if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine; @@ -6930,7 +7010,7 @@ function mergeEmitNode(sourceEmitNode: ts.EmitNode, destEmitNode: ts.EmitNode | return destEmitNode; } -function mergeTokenSourceMapRanges(sourceRanges: (ts.TextRange | undefined)[], destRanges: (ts.TextRange | undefined)[]) { +function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) { if (!destRanges) destRanges = []; for (const key in sourceRanges) { destRanges[key] = sourceRanges[key]; diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index f13d8dd0b2790..172b7d332a9c4 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -1,780 +1,819 @@ -import * as ts from "../_namespaces/ts"; +import { + AbstractKeyword, AccessorKeyword, ArrayBindingPattern, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, + AsExpression, AssertClause, AssertEntry, AssertsKeyword, AsteriskToken, AsyncKeyword, AwaitExpression, AwaitKeyword, + BigIntLiteral, BinaryExpression, BindingElement, Block, BreakStatement, Bundle, CallExpression, + CallSignatureDeclaration, CaseBlock, CaseClause, CatchClause, ClassDeclaration, ClassExpression, + ClassStaticBlockDeclaration, ColonToken, CommaListExpression, ComputedPropertyName, ConditionalExpression, + ConditionalTypeNode, ConstructorDeclaration, ConstructorTypeNode, ConstructSignatureDeclaration, ContinueStatement, + DebuggerStatement, Decorator, DefaultClause, DeleteExpression, DoStatement, DotDotDotToken, ElementAccessExpression, + EmptyStatement, EndOfDeclarationMarker, EnumDeclaration, EnumMember, EqualsGreaterThanToken, ExclamationToken, + ExportAssignment, ExportDeclaration, ExportKeyword, ExportSpecifier, ExpressionStatement, + ExpressionWithTypeArguments, ExternalModuleReference, ForInStatement, ForOfStatement, ForStatement, + FunctionDeclaration, FunctionExpression, FunctionTypeNode, GetAccessorDeclaration, HeritageClause, Identifier, + IfStatement, ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportExpression, ImportSpecifier, + ImportTypeAssertionContainer, ImportTypeNode, IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, + InterfaceDeclaration, IntersectionTypeNode, JSDoc, JSDocAllType, JSDocAugmentsTag, JSDocAuthorTag, JSDocCallbackTag, + JSDocClassTag, JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, JSDocImplementsTag, JSDocLink, JSDocLinkCode, + JSDocLinkPlain, JSDocMemberName, JSDocNamepathType, JSDocNameReference, JSDocNonNullableType, JSDocNullableType, + JSDocOptionalType, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, JSDocPropertyTag, JSDocProtectedTag, + JSDocPublicTag, JSDocReadonlyTag, JSDocReturnTag, JSDocSeeTag, JSDocSignature, JSDocTemplateTag, JSDocThisTag, + JSDocTypedefTag, JSDocTypeExpression, JSDocTypeLiteral, JSDocTypeTag, JSDocUnknownTag, JSDocUnknownType, + JSDocVariadicType, JsxAttribute, JsxAttributes, JsxClosingElement, JsxClosingFragment, JsxElement, JsxExpression, + JsxFragment, JsxOpeningElement, JsxOpeningFragment, JsxSelfClosingElement, JsxSpreadAttribute, JsxText, + LabeledStatement, LiteralTypeNode, MappedTypeNode, MergeDeclarationMarker, MetaProperty, MethodDeclaration, + MethodSignature, MinusToken, MissingDeclaration, ModuleBlock, ModuleDeclaration, NamedExports, NamedImports, + NamedTupleMember, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, Node, + NonNullExpression, NoSubstitutionTemplateLiteral, NotEmittedStatement, NumericLiteral, ObjectBindingPattern, + ObjectLiteralExpression, OmittedExpression, OptionalTypeNode, OverrideKeyword, ParameterDeclaration, + ParenthesizedExpression, ParenthesizedTypeNode, PartiallyEmittedExpression, PlusToken, PostfixUnaryExpression, + PrefixUnaryExpression, PrivateIdentifier, PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, + PropertySignature, QualifiedName, QuestionDotToken, QuestionToken, ReadonlyKeyword, RegularExpressionLiteral, + RestTypeNode, ReturnStatement, SatisfiesExpression, SemicolonClassElement, SetAccessorDeclaration, + ShorthandPropertyAssignment, SourceFile, SpreadAssignment, SpreadElement, StaticKeyword, StringLiteral, + SuperExpression, SwitchStatement, SyntaxKind, SyntaxList, SyntheticExpression, SyntheticReferenceExpression, + TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteralTypeNode, TemplateLiteralTypeSpan, + TemplateMiddle, TemplateSpan, TemplateTail, ThisTypeNode, ThrowStatement, Token, TryStatement, TupleTypeNode, + TypeAliasDeclaration, TypeAssertion, TypeLiteralNode, TypeOfExpression, TypeOperatorNode, TypeParameterDeclaration, + TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnionTypeNode, UnparsedPrepend, UnparsedSource, + VariableDeclaration, VariableDeclarationList, VariableStatement, VoidExpression, WhileStatement, WithStatement, + YieldExpression, +} from "../_namespaces/ts"; // Literals -export function isNumericLiteral(node: ts.Node): node is ts.NumericLiteral { - return node.kind === ts.SyntaxKind.NumericLiteral; +export function isNumericLiteral(node: Node): node is NumericLiteral { + return node.kind === SyntaxKind.NumericLiteral; } -export function isBigIntLiteral(node: ts.Node): node is ts.BigIntLiteral { - return node.kind === ts.SyntaxKind.BigIntLiteral; +export function isBigIntLiteral(node: Node): node is BigIntLiteral { + return node.kind === SyntaxKind.BigIntLiteral; } -export function isStringLiteral(node: ts.Node): node is ts.StringLiteral { - return node.kind === ts.SyntaxKind.StringLiteral; +export function isStringLiteral(node: Node): node is StringLiteral { + return node.kind === SyntaxKind.StringLiteral; } -export function isJsxText(node: ts.Node): node is ts.JsxText { - return node.kind === ts.SyntaxKind.JsxText; +export function isJsxText(node: Node): node is JsxText { + return node.kind === SyntaxKind.JsxText; } -export function isRegularExpressionLiteral(node: ts.Node): node is ts.RegularExpressionLiteral { - return node.kind === ts.SyntaxKind.RegularExpressionLiteral; +export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral { + return node.kind === SyntaxKind.RegularExpressionLiteral; } -export function isNoSubstitutionTemplateLiteral(node: ts.Node): node is ts.NoSubstitutionTemplateLiteral { - return node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral; +export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral { + return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; } // Pseudo-literals -export function isTemplateHead(node: ts.Node): node is ts.TemplateHead { - return node.kind === ts.SyntaxKind.TemplateHead; +export function isTemplateHead(node: Node): node is TemplateHead { + return node.kind === SyntaxKind.TemplateHead; } -export function isTemplateMiddle(node: ts.Node): node is ts.TemplateMiddle { - return node.kind === ts.SyntaxKind.TemplateMiddle; +export function isTemplateMiddle(node: Node): node is TemplateMiddle { + return node.kind === SyntaxKind.TemplateMiddle; } -export function isTemplateTail(node: ts.Node): node is ts.TemplateTail { - return node.kind === ts.SyntaxKind.TemplateTail; +export function isTemplateTail(node: Node): node is TemplateTail { + return node.kind === SyntaxKind.TemplateTail; } // Punctuation -export function isDotDotDotToken(node: ts.Node): node is ts.DotDotDotToken { - return node.kind === ts.SyntaxKind.DotDotDotToken; +export function isDotDotDotToken(node: Node): node is DotDotDotToken { + return node.kind === SyntaxKind.DotDotDotToken; } /*@internal*/ -export function isCommaToken(node: ts.Node): node is ts.Token { - return node.kind === ts.SyntaxKind.CommaToken; +export function isCommaToken(node: Node): node is Token { + return node.kind === SyntaxKind.CommaToken; } -export function isPlusToken(node: ts.Node): node is ts.PlusToken { - return node.kind === ts.SyntaxKind.PlusToken; +export function isPlusToken(node: Node): node is PlusToken { + return node.kind === SyntaxKind.PlusToken; } -export function isMinusToken(node: ts.Node): node is ts.MinusToken { - return node.kind === ts.SyntaxKind.MinusToken; +export function isMinusToken(node: Node): node is MinusToken { + return node.kind === SyntaxKind.MinusToken; } -export function isAsteriskToken(node: ts.Node): node is ts.AsteriskToken { - return node.kind === ts.SyntaxKind.AsteriskToken; +export function isAsteriskToken(node: Node): node is AsteriskToken { + return node.kind === SyntaxKind.AsteriskToken; } /*@internal*/ -export function isExclamationToken(node: ts.Node): node is ts.ExclamationToken { - return node.kind === ts.SyntaxKind.ExclamationToken; +export function isExclamationToken(node: Node): node is ExclamationToken { + return node.kind === SyntaxKind.ExclamationToken; } /*@internal*/ -export function isQuestionToken(node: ts.Node): node is ts.QuestionToken { - return node.kind === ts.SyntaxKind.QuestionToken; +export function isQuestionToken(node: Node): node is QuestionToken { + return node.kind === SyntaxKind.QuestionToken; } /*@internal*/ -export function isColonToken(node: ts.Node): node is ts.ColonToken { - return node.kind === ts.SyntaxKind.ColonToken; +export function isColonToken(node: Node): node is ColonToken { + return node.kind === SyntaxKind.ColonToken; } /*@internal*/ -export function isQuestionDotToken(node: ts.Node): node is ts.QuestionDotToken { - return node.kind === ts.SyntaxKind.QuestionDotToken; +export function isQuestionDotToken(node: Node): node is QuestionDotToken { + return node.kind === SyntaxKind.QuestionDotToken; } /*@internal*/ -export function isEqualsGreaterThanToken(node: ts.Node): node is ts.EqualsGreaterThanToken { - return node.kind === ts.SyntaxKind.EqualsGreaterThanToken; +export function isEqualsGreaterThanToken(node: Node): node is EqualsGreaterThanToken { + return node.kind === SyntaxKind.EqualsGreaterThanToken; } // Identifiers -export function isIdentifier(node: ts.Node): node is ts.Identifier { - return node.kind === ts.SyntaxKind.Identifier; +export function isIdentifier(node: Node): node is Identifier { + return node.kind === SyntaxKind.Identifier; } -export function isPrivateIdentifier(node: ts.Node): node is ts.PrivateIdentifier { - return node.kind === ts.SyntaxKind.PrivateIdentifier; +export function isPrivateIdentifier(node: Node): node is PrivateIdentifier { + return node.kind === SyntaxKind.PrivateIdentifier; } // Reserved Words /* @internal */ -export function isExportModifier(node: ts.Node): node is ts.ExportKeyword { - return node.kind === ts.SyntaxKind.ExportKeyword; +export function isExportModifier(node: Node): node is ExportKeyword { + return node.kind === SyntaxKind.ExportKeyword; } /* @internal */ -export function isAsyncModifier(node: ts.Node): node is ts.AsyncKeyword { - return node.kind === ts.SyntaxKind.AsyncKeyword; +export function isAsyncModifier(node: Node): node is AsyncKeyword { + return node.kind === SyntaxKind.AsyncKeyword; } /* @internal */ -export function isAssertsKeyword(node: ts.Node): node is ts.AssertsKeyword { - return node.kind === ts.SyntaxKind.AssertsKeyword; +export function isAssertsKeyword(node: Node): node is AssertsKeyword { + return node.kind === SyntaxKind.AssertsKeyword; } /* @internal */ -export function isAwaitKeyword(node: ts.Node): node is ts.AwaitKeyword { - return node.kind === ts.SyntaxKind.AwaitKeyword; +export function isAwaitKeyword(node: Node): node is AwaitKeyword { + return node.kind === SyntaxKind.AwaitKeyword; } /* @internal */ -export function isReadonlyKeyword(node: ts.Node): node is ts.ReadonlyKeyword { - return node.kind === ts.SyntaxKind.ReadonlyKeyword; +export function isReadonlyKeyword(node: Node): node is ReadonlyKeyword { + return node.kind === SyntaxKind.ReadonlyKeyword; } /* @internal */ -export function isStaticModifier(node: ts.Node): node is ts.StaticKeyword { - return node.kind === ts.SyntaxKind.StaticKeyword; +export function isStaticModifier(node: Node): node is StaticKeyword { + return node.kind === SyntaxKind.StaticKeyword; } /* @internal */ -export function isAbstractModifier(node: ts.Node): node is ts.AbstractKeyword { - return node.kind === ts.SyntaxKind.AbstractKeyword; +export function isAbstractModifier(node: Node): node is AbstractKeyword { + return node.kind === SyntaxKind.AbstractKeyword; } /* @internal */ -export function isOverrideModifier(node: ts.Node): node is ts.OverrideKeyword { - return node.kind === ts.SyntaxKind.OverrideKeyword; +export function isOverrideModifier(node: Node): node is OverrideKeyword { + return node.kind === SyntaxKind.OverrideKeyword; } /* @internal */ -export function isAccessorModifier(node: ts.Node): node is ts.AccessorKeyword { - return node.kind === ts.SyntaxKind.AccessorKeyword; +export function isAccessorModifier(node: Node): node is AccessorKeyword { + return node.kind === SyntaxKind.AccessorKeyword; } /*@internal*/ -export function isSuperKeyword(node: ts.Node): node is ts.SuperExpression { - return node.kind === ts.SyntaxKind.SuperKeyword; +export function isSuperKeyword(node: Node): node is SuperExpression { + return node.kind === SyntaxKind.SuperKeyword; } /*@internal*/ -export function isImportKeyword(node: ts.Node): node is ts.ImportExpression { - return node.kind === ts.SyntaxKind.ImportKeyword; +export function isImportKeyword(node: Node): node is ImportExpression { + return node.kind === SyntaxKind.ImportKeyword; } // Names -export function isQualifiedName(node: ts.Node): node is ts.QualifiedName { - return node.kind === ts.SyntaxKind.QualifiedName; +export function isQualifiedName(node: Node): node is QualifiedName { + return node.kind === SyntaxKind.QualifiedName; } -export function isComputedPropertyName(node: ts.Node): node is ts.ComputedPropertyName { - return node.kind === ts.SyntaxKind.ComputedPropertyName; +export function isComputedPropertyName(node: Node): node is ComputedPropertyName { + return node.kind === SyntaxKind.ComputedPropertyName; } // Signature elements -export function isTypeParameterDeclaration(node: ts.Node): node is ts.TypeParameterDeclaration { - return node.kind === ts.SyntaxKind.TypeParameter; +export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration { + return node.kind === SyntaxKind.TypeParameter; } // TODO(rbuckton): Rename to 'isParameterDeclaration' -export function isParameter(node: ts.Node): node is ts.ParameterDeclaration { - return node.kind === ts.SyntaxKind.Parameter; +export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter; } -export function isDecorator(node: ts.Node): node is ts.Decorator { - return node.kind === ts.SyntaxKind.Decorator; +export function isDecorator(node: Node): node is Decorator { + return node.kind === SyntaxKind.Decorator; } // TypeMember -export function isPropertySignature(node: ts.Node): node is ts.PropertySignature { - return node.kind === ts.SyntaxKind.PropertySignature; +export function isPropertySignature(node: Node): node is PropertySignature { + return node.kind === SyntaxKind.PropertySignature; } -export function isPropertyDeclaration(node: ts.Node): node is ts.PropertyDeclaration { - return node.kind === ts.SyntaxKind.PropertyDeclaration; +export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { + return node.kind === SyntaxKind.PropertyDeclaration; } -export function isMethodSignature(node: ts.Node): node is ts.MethodSignature { - return node.kind === ts.SyntaxKind.MethodSignature; +export function isMethodSignature(node: Node): node is MethodSignature { + return node.kind === SyntaxKind.MethodSignature; } -export function isMethodDeclaration(node: ts.Node): node is ts.MethodDeclaration { - return node.kind === ts.SyntaxKind.MethodDeclaration; +export function isMethodDeclaration(node: Node): node is MethodDeclaration { + return node.kind === SyntaxKind.MethodDeclaration; } -export function isClassStaticBlockDeclaration(node: ts.Node): node is ts.ClassStaticBlockDeclaration { - return node.kind === ts.SyntaxKind.ClassStaticBlockDeclaration; +export function isClassStaticBlockDeclaration(node: Node): node is ClassStaticBlockDeclaration { + return node.kind === SyntaxKind.ClassStaticBlockDeclaration; } -export function isConstructorDeclaration(node: ts.Node): node is ts.ConstructorDeclaration { - return node.kind === ts.SyntaxKind.Constructor; +export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration { + return node.kind === SyntaxKind.Constructor; } -export function isGetAccessorDeclaration(node: ts.Node): node is ts.GetAccessorDeclaration { - return node.kind === ts.SyntaxKind.GetAccessor; +export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { + return node.kind === SyntaxKind.GetAccessor; } -export function isSetAccessorDeclaration(node: ts.Node): node is ts.SetAccessorDeclaration { - return node.kind === ts.SyntaxKind.SetAccessor; +export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor; } -export function isCallSignatureDeclaration(node: ts.Node): node is ts.CallSignatureDeclaration { - return node.kind === ts.SyntaxKind.CallSignature; +export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration { + return node.kind === SyntaxKind.CallSignature; } -export function isConstructSignatureDeclaration(node: ts.Node): node is ts.ConstructSignatureDeclaration { - return node.kind === ts.SyntaxKind.ConstructSignature; +export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration { + return node.kind === SyntaxKind.ConstructSignature; } -export function isIndexSignatureDeclaration(node: ts.Node): node is ts.IndexSignatureDeclaration { - return node.kind === ts.SyntaxKind.IndexSignature; +export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration { + return node.kind === SyntaxKind.IndexSignature; } // Type -export function isTypePredicateNode(node: ts.Node): node is ts.TypePredicateNode { - return node.kind === ts.SyntaxKind.TypePredicate; +export function isTypePredicateNode(node: Node): node is TypePredicateNode { + return node.kind === SyntaxKind.TypePredicate; } -export function isTypeReferenceNode(node: ts.Node): node is ts.TypeReferenceNode { - return node.kind === ts.SyntaxKind.TypeReference; +export function isTypeReferenceNode(node: Node): node is TypeReferenceNode { + return node.kind === SyntaxKind.TypeReference; } -export function isFunctionTypeNode(node: ts.Node): node is ts.FunctionTypeNode { - return node.kind === ts.SyntaxKind.FunctionType; +export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { + return node.kind === SyntaxKind.FunctionType; } -export function isConstructorTypeNode(node: ts.Node): node is ts.ConstructorTypeNode { - return node.kind === ts.SyntaxKind.ConstructorType; +export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode { + return node.kind === SyntaxKind.ConstructorType; } -export function isTypeQueryNode(node: ts.Node): node is ts.TypeQueryNode { - return node.kind === ts.SyntaxKind.TypeQuery; +export function isTypeQueryNode(node: Node): node is TypeQueryNode { + return node.kind === SyntaxKind.TypeQuery; } -export function isTypeLiteralNode(node: ts.Node): node is ts.TypeLiteralNode { - return node.kind === ts.SyntaxKind.TypeLiteral; +export function isTypeLiteralNode(node: Node): node is TypeLiteralNode { + return node.kind === SyntaxKind.TypeLiteral; } -export function isArrayTypeNode(node: ts.Node): node is ts.ArrayTypeNode { - return node.kind === ts.SyntaxKind.ArrayType; +export function isArrayTypeNode(node: Node): node is ArrayTypeNode { + return node.kind === SyntaxKind.ArrayType; } -export function isTupleTypeNode(node: ts.Node): node is ts.TupleTypeNode { - return node.kind === ts.SyntaxKind.TupleType; +export function isTupleTypeNode(node: Node): node is TupleTypeNode { + return node.kind === SyntaxKind.TupleType; } -export function isNamedTupleMember(node: ts.Node): node is ts.NamedTupleMember { - return node.kind === ts.SyntaxKind.NamedTupleMember; +export function isNamedTupleMember(node: Node): node is NamedTupleMember { + return node.kind === SyntaxKind.NamedTupleMember; } -export function isOptionalTypeNode(node: ts.Node): node is ts.OptionalTypeNode { - return node.kind === ts.SyntaxKind.OptionalType; +export function isOptionalTypeNode(node: Node): node is OptionalTypeNode { + return node.kind === SyntaxKind.OptionalType; } -export function isRestTypeNode(node: ts.Node): node is ts.RestTypeNode { - return node.kind === ts.SyntaxKind.RestType; +export function isRestTypeNode(node: Node): node is RestTypeNode { + return node.kind === SyntaxKind.RestType; } -export function isUnionTypeNode(node: ts.Node): node is ts.UnionTypeNode { - return node.kind === ts.SyntaxKind.UnionType; +export function isUnionTypeNode(node: Node): node is UnionTypeNode { + return node.kind === SyntaxKind.UnionType; } -export function isIntersectionTypeNode(node: ts.Node): node is ts.IntersectionTypeNode { - return node.kind === ts.SyntaxKind.IntersectionType; +export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode { + return node.kind === SyntaxKind.IntersectionType; } -export function isConditionalTypeNode(node: ts.Node): node is ts.ConditionalTypeNode { - return node.kind === ts.SyntaxKind.ConditionalType; +export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode { + return node.kind === SyntaxKind.ConditionalType; } -export function isInferTypeNode(node: ts.Node): node is ts.InferTypeNode { - return node.kind === ts.SyntaxKind.InferType; +export function isInferTypeNode(node: Node): node is InferTypeNode { + return node.kind === SyntaxKind.InferType; } -export function isParenthesizedTypeNode(node: ts.Node): node is ts.ParenthesizedTypeNode { - return node.kind === ts.SyntaxKind.ParenthesizedType; +export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode { + return node.kind === SyntaxKind.ParenthesizedType; } -export function isThisTypeNode(node: ts.Node): node is ts.ThisTypeNode { - return node.kind === ts.SyntaxKind.ThisType; +export function isThisTypeNode(node: Node): node is ThisTypeNode { + return node.kind === SyntaxKind.ThisType; } -export function isTypeOperatorNode(node: ts.Node): node is ts.TypeOperatorNode { - return node.kind === ts.SyntaxKind.TypeOperator; +export function isTypeOperatorNode(node: Node): node is TypeOperatorNode { + return node.kind === SyntaxKind.TypeOperator; } -export function isIndexedAccessTypeNode(node: ts.Node): node is ts.IndexedAccessTypeNode { - return node.kind === ts.SyntaxKind.IndexedAccessType; +export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode { + return node.kind === SyntaxKind.IndexedAccessType; } -export function isMappedTypeNode(node: ts.Node): node is ts.MappedTypeNode { - return node.kind === ts.SyntaxKind.MappedType; +export function isMappedTypeNode(node: Node): node is MappedTypeNode { + return node.kind === SyntaxKind.MappedType; } -export function isLiteralTypeNode(node: ts.Node): node is ts.LiteralTypeNode { - return node.kind === ts.SyntaxKind.LiteralType; +export function isLiteralTypeNode(node: Node): node is LiteralTypeNode { + return node.kind === SyntaxKind.LiteralType; } -export function isImportTypeNode(node: ts.Node): node is ts.ImportTypeNode { - return node.kind === ts.SyntaxKind.ImportType; +export function isImportTypeNode(node: Node): node is ImportTypeNode { + return node.kind === SyntaxKind.ImportType; } -export function isTemplateLiteralTypeSpan(node: ts.Node): node is ts.TemplateLiteralTypeSpan { - return node.kind === ts.SyntaxKind.TemplateLiteralTypeSpan; +export function isTemplateLiteralTypeSpan(node: Node): node is TemplateLiteralTypeSpan { + return node.kind === SyntaxKind.TemplateLiteralTypeSpan; } -export function isTemplateLiteralTypeNode(node: ts.Node): node is ts.TemplateLiteralTypeNode { - return node.kind === ts.SyntaxKind.TemplateLiteralType; +export function isTemplateLiteralTypeNode(node: Node): node is TemplateLiteralTypeNode { + return node.kind === SyntaxKind.TemplateLiteralType; } // Binding patterns -export function isObjectBindingPattern(node: ts.Node): node is ts.ObjectBindingPattern { - return node.kind === ts.SyntaxKind.ObjectBindingPattern; +export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern { + return node.kind === SyntaxKind.ObjectBindingPattern; } -export function isArrayBindingPattern(node: ts.Node): node is ts.ArrayBindingPattern { - return node.kind === ts.SyntaxKind.ArrayBindingPattern; +export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern { + return node.kind === SyntaxKind.ArrayBindingPattern; } -export function isBindingElement(node: ts.Node): node is ts.BindingElement { - return node.kind === ts.SyntaxKind.BindingElement; +export function isBindingElement(node: Node): node is BindingElement { + return node.kind === SyntaxKind.BindingElement; } // Expression -export function isArrayLiteralExpression(node: ts.Node): node is ts.ArrayLiteralExpression { - return node.kind === ts.SyntaxKind.ArrayLiteralExpression; +export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression { + return node.kind === SyntaxKind.ArrayLiteralExpression; } -export function isObjectLiteralExpression(node: ts.Node): node is ts.ObjectLiteralExpression { - return node.kind === ts.SyntaxKind.ObjectLiteralExpression; +export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression { + return node.kind === SyntaxKind.ObjectLiteralExpression; } -export function isPropertyAccessExpression(node: ts.Node): node is ts.PropertyAccessExpression { - return node.kind === ts.SyntaxKind.PropertyAccessExpression; +export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { + return node.kind === SyntaxKind.PropertyAccessExpression; } -export function isElementAccessExpression(node: ts.Node): node is ts.ElementAccessExpression { - return node.kind === ts.SyntaxKind.ElementAccessExpression; +export function isElementAccessExpression(node: Node): node is ElementAccessExpression { + return node.kind === SyntaxKind.ElementAccessExpression; } -export function isCallExpression(node: ts.Node): node is ts.CallExpression { - return node.kind === ts.SyntaxKind.CallExpression; +export function isCallExpression(node: Node): node is CallExpression { + return node.kind === SyntaxKind.CallExpression; } -export function isNewExpression(node: ts.Node): node is ts.NewExpression { - return node.kind === ts.SyntaxKind.NewExpression; +export function isNewExpression(node: Node): node is NewExpression { + return node.kind === SyntaxKind.NewExpression; } -export function isTaggedTemplateExpression(node: ts.Node): node is ts.TaggedTemplateExpression { - return node.kind === ts.SyntaxKind.TaggedTemplateExpression; +export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression { + return node.kind === SyntaxKind.TaggedTemplateExpression; } -export function isTypeAssertionExpression(node: ts.Node): node is ts.TypeAssertion { - return node.kind === ts.SyntaxKind.TypeAssertionExpression; +export function isTypeAssertionExpression(node: Node): node is TypeAssertion { + return node.kind === SyntaxKind.TypeAssertionExpression; } -export function isParenthesizedExpression(node: ts.Node): node is ts.ParenthesizedExpression { - return node.kind === ts.SyntaxKind.ParenthesizedExpression; +export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression { + return node.kind === SyntaxKind.ParenthesizedExpression; } -export function isFunctionExpression(node: ts.Node): node is ts.FunctionExpression { - return node.kind === ts.SyntaxKind.FunctionExpression; +export function isFunctionExpression(node: Node): node is FunctionExpression { + return node.kind === SyntaxKind.FunctionExpression; } -export function isArrowFunction(node: ts.Node): node is ts.ArrowFunction { - return node.kind === ts.SyntaxKind.ArrowFunction; +export function isArrowFunction(node: Node): node is ArrowFunction { + return node.kind === SyntaxKind.ArrowFunction; } -export function isDeleteExpression(node: ts.Node): node is ts.DeleteExpression { - return node.kind === ts.SyntaxKind.DeleteExpression; +export function isDeleteExpression(node: Node): node is DeleteExpression { + return node.kind === SyntaxKind.DeleteExpression; } -export function isTypeOfExpression(node: ts.Node): node is ts.TypeOfExpression { - return node.kind === ts.SyntaxKind.TypeOfExpression; +export function isTypeOfExpression(node: Node): node is TypeOfExpression { + return node.kind === SyntaxKind.TypeOfExpression; } -export function isVoidExpression(node: ts.Node): node is ts.VoidExpression { - return node.kind === ts.SyntaxKind.VoidExpression; +export function isVoidExpression(node: Node): node is VoidExpression { + return node.kind === SyntaxKind.VoidExpression; } -export function isAwaitExpression(node: ts.Node): node is ts.AwaitExpression { - return node.kind === ts.SyntaxKind.AwaitExpression; +export function isAwaitExpression(node: Node): node is AwaitExpression { + return node.kind === SyntaxKind.AwaitExpression; } -export function isPrefixUnaryExpression(node: ts.Node): node is ts.PrefixUnaryExpression { - return node.kind === ts.SyntaxKind.PrefixUnaryExpression; +export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression { + return node.kind === SyntaxKind.PrefixUnaryExpression; } -export function isPostfixUnaryExpression(node: ts.Node): node is ts.PostfixUnaryExpression { - return node.kind === ts.SyntaxKind.PostfixUnaryExpression; +export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression { + return node.kind === SyntaxKind.PostfixUnaryExpression; } -export function isBinaryExpression(node: ts.Node): node is ts.BinaryExpression { - return node.kind === ts.SyntaxKind.BinaryExpression; +export function isBinaryExpression(node: Node): node is BinaryExpression { + return node.kind === SyntaxKind.BinaryExpression; } -export function isConditionalExpression(node: ts.Node): node is ts.ConditionalExpression { - return node.kind === ts.SyntaxKind.ConditionalExpression; +export function isConditionalExpression(node: Node): node is ConditionalExpression { + return node.kind === SyntaxKind.ConditionalExpression; } -export function isTemplateExpression(node: ts.Node): node is ts.TemplateExpression { - return node.kind === ts.SyntaxKind.TemplateExpression; +export function isTemplateExpression(node: Node): node is TemplateExpression { + return node.kind === SyntaxKind.TemplateExpression; } -export function isYieldExpression(node: ts.Node): node is ts.YieldExpression { - return node.kind === ts.SyntaxKind.YieldExpression; +export function isYieldExpression(node: Node): node is YieldExpression { + return node.kind === SyntaxKind.YieldExpression; } -export function isSpreadElement(node: ts.Node): node is ts.SpreadElement { - return node.kind === ts.SyntaxKind.SpreadElement; +export function isSpreadElement(node: Node): node is SpreadElement { + return node.kind === SyntaxKind.SpreadElement; } -export function isClassExpression(node: ts.Node): node is ts.ClassExpression { - return node.kind === ts.SyntaxKind.ClassExpression; +export function isClassExpression(node: Node): node is ClassExpression { + return node.kind === SyntaxKind.ClassExpression; } -export function isOmittedExpression(node: ts.Node): node is ts.OmittedExpression { - return node.kind === ts.SyntaxKind.OmittedExpression; +export function isOmittedExpression(node: Node): node is OmittedExpression { + return node.kind === SyntaxKind.OmittedExpression; } -export function isExpressionWithTypeArguments(node: ts.Node): node is ts.ExpressionWithTypeArguments { - return node.kind === ts.SyntaxKind.ExpressionWithTypeArguments; +export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments { + return node.kind === SyntaxKind.ExpressionWithTypeArguments; } -export function isAsExpression(node: ts.Node): node is ts.AsExpression { - return node.kind === ts.SyntaxKind.AsExpression; +export function isAsExpression(node: Node): node is AsExpression { + return node.kind === SyntaxKind.AsExpression; } -export function isSatisfiesExpression(node: ts.Node): node is ts.SatisfiesExpression { - return node.kind === ts.SyntaxKind.SatisfiesExpression; +export function isSatisfiesExpression(node: Node): node is SatisfiesExpression { + return node.kind === SyntaxKind.SatisfiesExpression; } -export function isNonNullExpression(node: ts.Node): node is ts.NonNullExpression { - return node.kind === ts.SyntaxKind.NonNullExpression; +export function isNonNullExpression(node: Node): node is NonNullExpression { + return node.kind === SyntaxKind.NonNullExpression; } -export function isMetaProperty(node: ts.Node): node is ts.MetaProperty { - return node.kind === ts.SyntaxKind.MetaProperty; +export function isMetaProperty(node: Node): node is MetaProperty { + return node.kind === SyntaxKind.MetaProperty; } -export function isSyntheticExpression(node: ts.Node): node is ts.SyntheticExpression { - return node.kind === ts.SyntaxKind.SyntheticExpression; +export function isSyntheticExpression(node: Node): node is SyntheticExpression { + return node.kind === SyntaxKind.SyntheticExpression; } -export function isPartiallyEmittedExpression(node: ts.Node): node is ts.PartiallyEmittedExpression { - return node.kind === ts.SyntaxKind.PartiallyEmittedExpression; +export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression { + return node.kind === SyntaxKind.PartiallyEmittedExpression; } -export function isCommaListExpression(node: ts.Node): node is ts.CommaListExpression { - return node.kind === ts.SyntaxKind.CommaListExpression; +export function isCommaListExpression(node: Node): node is CommaListExpression { + return node.kind === SyntaxKind.CommaListExpression; } // Misc -export function isTemplateSpan(node: ts.Node): node is ts.TemplateSpan { - return node.kind === ts.SyntaxKind.TemplateSpan; +export function isTemplateSpan(node: Node): node is TemplateSpan { + return node.kind === SyntaxKind.TemplateSpan; } -export function isSemicolonClassElement(node: ts.Node): node is ts.SemicolonClassElement { - return node.kind === ts.SyntaxKind.SemicolonClassElement; +export function isSemicolonClassElement(node: Node): node is SemicolonClassElement { + return node.kind === SyntaxKind.SemicolonClassElement; } // Elements -export function isBlock(node: ts.Node): node is ts.Block { - return node.kind === ts.SyntaxKind.Block; +export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block; } -export function isVariableStatement(node: ts.Node): node is ts.VariableStatement { - return node.kind === ts.SyntaxKind.VariableStatement; +export function isVariableStatement(node: Node): node is VariableStatement { + return node.kind === SyntaxKind.VariableStatement; } -export function isEmptyStatement(node: ts.Node): node is ts.EmptyStatement { - return node.kind === ts.SyntaxKind.EmptyStatement; +export function isEmptyStatement(node: Node): node is EmptyStatement { + return node.kind === SyntaxKind.EmptyStatement; } -export function isExpressionStatement(node: ts.Node): node is ts.ExpressionStatement { - return node.kind === ts.SyntaxKind.ExpressionStatement; +export function isExpressionStatement(node: Node): node is ExpressionStatement { + return node.kind === SyntaxKind.ExpressionStatement; } -export function isIfStatement(node: ts.Node): node is ts.IfStatement { - return node.kind === ts.SyntaxKind.IfStatement; +export function isIfStatement(node: Node): node is IfStatement { + return node.kind === SyntaxKind.IfStatement; } -export function isDoStatement(node: ts.Node): node is ts.DoStatement { - return node.kind === ts.SyntaxKind.DoStatement; +export function isDoStatement(node: Node): node is DoStatement { + return node.kind === SyntaxKind.DoStatement; } -export function isWhileStatement(node: ts.Node): node is ts.WhileStatement { - return node.kind === ts.SyntaxKind.WhileStatement; +export function isWhileStatement(node: Node): node is WhileStatement { + return node.kind === SyntaxKind.WhileStatement; } -export function isForStatement(node: ts.Node): node is ts.ForStatement { - return node.kind === ts.SyntaxKind.ForStatement; +export function isForStatement(node: Node): node is ForStatement { + return node.kind === SyntaxKind.ForStatement; } -export function isForInStatement(node: ts.Node): node is ts.ForInStatement { - return node.kind === ts.SyntaxKind.ForInStatement; +export function isForInStatement(node: Node): node is ForInStatement { + return node.kind === SyntaxKind.ForInStatement; } -export function isForOfStatement(node: ts.Node): node is ts.ForOfStatement { - return node.kind === ts.SyntaxKind.ForOfStatement; +export function isForOfStatement(node: Node): node is ForOfStatement { + return node.kind === SyntaxKind.ForOfStatement; } -export function isContinueStatement(node: ts.Node): node is ts.ContinueStatement { - return node.kind === ts.SyntaxKind.ContinueStatement; +export function isContinueStatement(node: Node): node is ContinueStatement { + return node.kind === SyntaxKind.ContinueStatement; } -export function isBreakStatement(node: ts.Node): node is ts.BreakStatement { - return node.kind === ts.SyntaxKind.BreakStatement; +export function isBreakStatement(node: Node): node is BreakStatement { + return node.kind === SyntaxKind.BreakStatement; } -export function isReturnStatement(node: ts.Node): node is ts.ReturnStatement { - return node.kind === ts.SyntaxKind.ReturnStatement; +export function isReturnStatement(node: Node): node is ReturnStatement { + return node.kind === SyntaxKind.ReturnStatement; } -export function isWithStatement(node: ts.Node): node is ts.WithStatement { - return node.kind === ts.SyntaxKind.WithStatement; +export function isWithStatement(node: Node): node is WithStatement { + return node.kind === SyntaxKind.WithStatement; } -export function isSwitchStatement(node: ts.Node): node is ts.SwitchStatement { - return node.kind === ts.SyntaxKind.SwitchStatement; +export function isSwitchStatement(node: Node): node is SwitchStatement { + return node.kind === SyntaxKind.SwitchStatement; } -export function isLabeledStatement(node: ts.Node): node is ts.LabeledStatement { - return node.kind === ts.SyntaxKind.LabeledStatement; +export function isLabeledStatement(node: Node): node is LabeledStatement { + return node.kind === SyntaxKind.LabeledStatement; } -export function isThrowStatement(node: ts.Node): node is ts.ThrowStatement { - return node.kind === ts.SyntaxKind.ThrowStatement; +export function isThrowStatement(node: Node): node is ThrowStatement { + return node.kind === SyntaxKind.ThrowStatement; } -export function isTryStatement(node: ts.Node): node is ts.TryStatement { - return node.kind === ts.SyntaxKind.TryStatement; +export function isTryStatement(node: Node): node is TryStatement { + return node.kind === SyntaxKind.TryStatement; } -export function isDebuggerStatement(node: ts.Node): node is ts.DebuggerStatement { - return node.kind === ts.SyntaxKind.DebuggerStatement; +export function isDebuggerStatement(node: Node): node is DebuggerStatement { + return node.kind === SyntaxKind.DebuggerStatement; } -export function isVariableDeclaration(node: ts.Node): node is ts.VariableDeclaration { - return node.kind === ts.SyntaxKind.VariableDeclaration; +export function isVariableDeclaration(node: Node): node is VariableDeclaration { + return node.kind === SyntaxKind.VariableDeclaration; } -export function isVariableDeclarationList(node: ts.Node): node is ts.VariableDeclarationList { - return node.kind === ts.SyntaxKind.VariableDeclarationList; +export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { + return node.kind === SyntaxKind.VariableDeclarationList; } -export function isFunctionDeclaration(node: ts.Node): node is ts.FunctionDeclaration { - return node.kind === ts.SyntaxKind.FunctionDeclaration; +export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { + return node.kind === SyntaxKind.FunctionDeclaration; } -export function isClassDeclaration(node: ts.Node): node is ts.ClassDeclaration { - return node.kind === ts.SyntaxKind.ClassDeclaration; +export function isClassDeclaration(node: Node): node is ClassDeclaration { + return node.kind === SyntaxKind.ClassDeclaration; } -export function isInterfaceDeclaration(node: ts.Node): node is ts.InterfaceDeclaration { - return node.kind === ts.SyntaxKind.InterfaceDeclaration; +export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration { + return node.kind === SyntaxKind.InterfaceDeclaration; } -export function isTypeAliasDeclaration(node: ts.Node): node is ts.TypeAliasDeclaration { - return node.kind === ts.SyntaxKind.TypeAliasDeclaration; +export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration { + return node.kind === SyntaxKind.TypeAliasDeclaration; } -export function isEnumDeclaration(node: ts.Node): node is ts.EnumDeclaration { - return node.kind === ts.SyntaxKind.EnumDeclaration; +export function isEnumDeclaration(node: Node): node is EnumDeclaration { + return node.kind === SyntaxKind.EnumDeclaration; } -export function isModuleDeclaration(node: ts.Node): node is ts.ModuleDeclaration { - return node.kind === ts.SyntaxKind.ModuleDeclaration; +export function isModuleDeclaration(node: Node): node is ModuleDeclaration { + return node.kind === SyntaxKind.ModuleDeclaration; } -export function isModuleBlock(node: ts.Node): node is ts.ModuleBlock { - return node.kind === ts.SyntaxKind.ModuleBlock; +export function isModuleBlock(node: Node): node is ModuleBlock { + return node.kind === SyntaxKind.ModuleBlock; } -export function isCaseBlock(node: ts.Node): node is ts.CaseBlock { - return node.kind === ts.SyntaxKind.CaseBlock; +export function isCaseBlock(node: Node): node is CaseBlock { + return node.kind === SyntaxKind.CaseBlock; } -export function isNamespaceExportDeclaration(node: ts.Node): node is ts.NamespaceExportDeclaration { - return node.kind === ts.SyntaxKind.NamespaceExportDeclaration; +export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration { + return node.kind === SyntaxKind.NamespaceExportDeclaration; } -export function isImportEqualsDeclaration(node: ts.Node): node is ts.ImportEqualsDeclaration { - return node.kind === ts.SyntaxKind.ImportEqualsDeclaration; +export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration { + return node.kind === SyntaxKind.ImportEqualsDeclaration; } -export function isImportDeclaration(node: ts.Node): node is ts.ImportDeclaration { - return node.kind === ts.SyntaxKind.ImportDeclaration; +export function isImportDeclaration(node: Node): node is ImportDeclaration { + return node.kind === SyntaxKind.ImportDeclaration; } -export function isImportClause(node: ts.Node): node is ts.ImportClause { - return node.kind === ts.SyntaxKind.ImportClause; +export function isImportClause(node: Node): node is ImportClause { + return node.kind === SyntaxKind.ImportClause; } -export function isImportTypeAssertionContainer(node: ts.Node): node is ts.ImportTypeAssertionContainer { - return node.kind === ts.SyntaxKind.ImportTypeAssertionContainer; +export function isImportTypeAssertionContainer(node: Node): node is ImportTypeAssertionContainer { + return node.kind === SyntaxKind.ImportTypeAssertionContainer; } -export function isAssertClause(node: ts.Node): node is ts.AssertClause { - return node.kind === ts.SyntaxKind.AssertClause; +export function isAssertClause(node: Node): node is AssertClause { + return node.kind === SyntaxKind.AssertClause; } -export function isAssertEntry(node: ts.Node): node is ts.AssertEntry { - return node.kind === ts.SyntaxKind.AssertEntry; +export function isAssertEntry(node: Node): node is AssertEntry { + return node.kind === SyntaxKind.AssertEntry; } -export function isNamespaceImport(node: ts.Node): node is ts.NamespaceImport { - return node.kind === ts.SyntaxKind.NamespaceImport; +export function isNamespaceImport(node: Node): node is NamespaceImport { + return node.kind === SyntaxKind.NamespaceImport; } -export function isNamespaceExport(node: ts.Node): node is ts.NamespaceExport { - return node.kind === ts.SyntaxKind.NamespaceExport; +export function isNamespaceExport(node: Node): node is NamespaceExport { + return node.kind === SyntaxKind.NamespaceExport; } -export function isNamedImports(node: ts.Node): node is ts.NamedImports { - return node.kind === ts.SyntaxKind.NamedImports; +export function isNamedImports(node: Node): node is NamedImports { + return node.kind === SyntaxKind.NamedImports; } -export function isImportSpecifier(node: ts.Node): node is ts.ImportSpecifier { - return node.kind === ts.SyntaxKind.ImportSpecifier; +export function isImportSpecifier(node: Node): node is ImportSpecifier { + return node.kind === SyntaxKind.ImportSpecifier; } -export function isExportAssignment(node: ts.Node): node is ts.ExportAssignment { - return node.kind === ts.SyntaxKind.ExportAssignment; +export function isExportAssignment(node: Node): node is ExportAssignment { + return node.kind === SyntaxKind.ExportAssignment; } -export function isExportDeclaration(node: ts.Node): node is ts.ExportDeclaration { - return node.kind === ts.SyntaxKind.ExportDeclaration; +export function isExportDeclaration(node: Node): node is ExportDeclaration { + return node.kind === SyntaxKind.ExportDeclaration; } -export function isNamedExports(node: ts.Node): node is ts.NamedExports { - return node.kind === ts.SyntaxKind.NamedExports; +export function isNamedExports(node: Node): node is NamedExports { + return node.kind === SyntaxKind.NamedExports; } -export function isExportSpecifier(node: ts.Node): node is ts.ExportSpecifier { - return node.kind === ts.SyntaxKind.ExportSpecifier; +export function isExportSpecifier(node: Node): node is ExportSpecifier { + return node.kind === SyntaxKind.ExportSpecifier; } -export function isMissingDeclaration(node: ts.Node): node is ts.MissingDeclaration { - return node.kind === ts.SyntaxKind.MissingDeclaration; +export function isMissingDeclaration(node: Node): node is MissingDeclaration { + return node.kind === SyntaxKind.MissingDeclaration; } -export function isNotEmittedStatement(node: ts.Node): node is ts.NotEmittedStatement { - return node.kind === ts.SyntaxKind.NotEmittedStatement; +export function isNotEmittedStatement(node: Node): node is NotEmittedStatement { + return node.kind === SyntaxKind.NotEmittedStatement; } /* @internal */ -export function isSyntheticReference(node: ts.Node): node is ts.SyntheticReferenceExpression { - return node.kind === ts.SyntaxKind.SyntheticReferenceExpression; +export function isSyntheticReference(node: Node): node is SyntheticReferenceExpression { + return node.kind === SyntaxKind.SyntheticReferenceExpression; } /* @internal */ -export function isMergeDeclarationMarker(node: ts.Node): node is ts.MergeDeclarationMarker { - return node.kind === ts.SyntaxKind.MergeDeclarationMarker; +export function isMergeDeclarationMarker(node: Node): node is MergeDeclarationMarker { + return node.kind === SyntaxKind.MergeDeclarationMarker; } /* @internal */ -export function isEndOfDeclarationMarker(node: ts.Node): node is ts.EndOfDeclarationMarker { - return node.kind === ts.SyntaxKind.EndOfDeclarationMarker; +export function isEndOfDeclarationMarker(node: Node): node is EndOfDeclarationMarker { + return node.kind === SyntaxKind.EndOfDeclarationMarker; } // Module References -export function isExternalModuleReference(node: ts.Node): node is ts.ExternalModuleReference { - return node.kind === ts.SyntaxKind.ExternalModuleReference; +export function isExternalModuleReference(node: Node): node is ExternalModuleReference { + return node.kind === SyntaxKind.ExternalModuleReference; } // JSX -export function isJsxElement(node: ts.Node): node is ts.JsxElement { - return node.kind === ts.SyntaxKind.JsxElement; +export function isJsxElement(node: Node): node is JsxElement { + return node.kind === SyntaxKind.JsxElement; } -export function isJsxSelfClosingElement(node: ts.Node): node is ts.JsxSelfClosingElement { - return node.kind === ts.SyntaxKind.JsxSelfClosingElement; +export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement { + return node.kind === SyntaxKind.JsxSelfClosingElement; } -export function isJsxOpeningElement(node: ts.Node): node is ts.JsxOpeningElement { - return node.kind === ts.SyntaxKind.JsxOpeningElement; +export function isJsxOpeningElement(node: Node): node is JsxOpeningElement { + return node.kind === SyntaxKind.JsxOpeningElement; } -export function isJsxClosingElement(node: ts.Node): node is ts.JsxClosingElement { - return node.kind === ts.SyntaxKind.JsxClosingElement; +export function isJsxClosingElement(node: Node): node is JsxClosingElement { + return node.kind === SyntaxKind.JsxClosingElement; } -export function isJsxFragment(node: ts.Node): node is ts.JsxFragment { - return node.kind === ts.SyntaxKind.JsxFragment; +export function isJsxFragment(node: Node): node is JsxFragment { + return node.kind === SyntaxKind.JsxFragment; } -export function isJsxOpeningFragment(node: ts.Node): node is ts.JsxOpeningFragment { - return node.kind === ts.SyntaxKind.JsxOpeningFragment; +export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment { + return node.kind === SyntaxKind.JsxOpeningFragment; } -export function isJsxClosingFragment(node: ts.Node): node is ts.JsxClosingFragment { - return node.kind === ts.SyntaxKind.JsxClosingFragment; +export function isJsxClosingFragment(node: Node): node is JsxClosingFragment { + return node.kind === SyntaxKind.JsxClosingFragment; } -export function isJsxAttribute(node: ts.Node): node is ts.JsxAttribute { - return node.kind === ts.SyntaxKind.JsxAttribute; +export function isJsxAttribute(node: Node): node is JsxAttribute { + return node.kind === SyntaxKind.JsxAttribute; } -export function isJsxAttributes(node: ts.Node): node is ts.JsxAttributes { - return node.kind === ts.SyntaxKind.JsxAttributes; +export function isJsxAttributes(node: Node): node is JsxAttributes { + return node.kind === SyntaxKind.JsxAttributes; } -export function isJsxSpreadAttribute(node: ts.Node): node is ts.JsxSpreadAttribute { - return node.kind === ts.SyntaxKind.JsxSpreadAttribute; +export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute { + return node.kind === SyntaxKind.JsxSpreadAttribute; } -export function isJsxExpression(node: ts.Node): node is ts.JsxExpression { - return node.kind === ts.SyntaxKind.JsxExpression; +export function isJsxExpression(node: Node): node is JsxExpression { + return node.kind === SyntaxKind.JsxExpression; } // Clauses -export function isCaseClause(node: ts.Node): node is ts.CaseClause { - return node.kind === ts.SyntaxKind.CaseClause; +export function isCaseClause(node: Node): node is CaseClause { + return node.kind === SyntaxKind.CaseClause; } -export function isDefaultClause(node: ts.Node): node is ts.DefaultClause { - return node.kind === ts.SyntaxKind.DefaultClause; +export function isDefaultClause(node: Node): node is DefaultClause { + return node.kind === SyntaxKind.DefaultClause; } -export function isHeritageClause(node: ts.Node): node is ts.HeritageClause { - return node.kind === ts.SyntaxKind.HeritageClause; +export function isHeritageClause(node: Node): node is HeritageClause { + return node.kind === SyntaxKind.HeritageClause; } -export function isCatchClause(node: ts.Node): node is ts.CatchClause { - return node.kind === ts.SyntaxKind.CatchClause; +export function isCatchClause(node: Node): node is CatchClause { + return node.kind === SyntaxKind.CatchClause; } // Property assignments -export function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment { - return node.kind === ts.SyntaxKind.PropertyAssignment; +export function isPropertyAssignment(node: Node): node is PropertyAssignment { + return node.kind === SyntaxKind.PropertyAssignment; } -export function isShorthandPropertyAssignment(node: ts.Node): node is ts.ShorthandPropertyAssignment { - return node.kind === ts.SyntaxKind.ShorthandPropertyAssignment; +export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment { + return node.kind === SyntaxKind.ShorthandPropertyAssignment; } -export function isSpreadAssignment(node: ts.Node): node is ts.SpreadAssignment { - return node.kind === ts.SyntaxKind.SpreadAssignment; +export function isSpreadAssignment(node: Node): node is SpreadAssignment { + return node.kind === SyntaxKind.SpreadAssignment; } // Enum -export function isEnumMember(node: ts.Node): node is ts.EnumMember { - return node.kind === ts.SyntaxKind.EnumMember; +export function isEnumMember(node: Node): node is EnumMember { + return node.kind === SyntaxKind.EnumMember; } // Unparsed // TODO(rbuckton): isUnparsedPrologue -export function isUnparsedPrepend(node: ts.Node): node is ts.UnparsedPrepend { - return node.kind === ts.SyntaxKind.UnparsedPrepend; +export function isUnparsedPrepend(node: Node): node is UnparsedPrepend { + return node.kind === SyntaxKind.UnparsedPrepend; } // TODO(rbuckton): isUnparsedText @@ -782,179 +821,179 @@ export function isUnparsedPrepend(node: ts.Node): node is ts.UnparsedPrepend { // TODO(rbuckton): isUnparsedSyntheticReference // Top-level nodes -export function isSourceFile(node: ts.Node): node is ts.SourceFile { - return node.kind === ts.SyntaxKind.SourceFile; +export function isSourceFile(node: Node): node is SourceFile { + return node.kind === SyntaxKind.SourceFile; } -export function isBundle(node: ts.Node): node is ts.Bundle { - return node.kind === ts.SyntaxKind.Bundle; +export function isBundle(node: Node): node is Bundle { + return node.kind === SyntaxKind.Bundle; } -export function isUnparsedSource(node: ts.Node): node is ts.UnparsedSource { - return node.kind === ts.SyntaxKind.UnparsedSource; +export function isUnparsedSource(node: Node): node is UnparsedSource { + return node.kind === SyntaxKind.UnparsedSource; } // TODO(rbuckton): isInputFiles // JSDoc Elements -export function isJSDocTypeExpression(node: ts.Node): node is ts.JSDocTypeExpression { - return node.kind === ts.SyntaxKind.JSDocTypeExpression; +export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression { + return node.kind === SyntaxKind.JSDocTypeExpression; } -export function isJSDocNameReference(node: ts.Node): node is ts.JSDocNameReference { - return node.kind === ts.SyntaxKind.JSDocNameReference; +export function isJSDocNameReference(node: Node): node is JSDocNameReference { + return node.kind === SyntaxKind.JSDocNameReference; } -export function isJSDocMemberName(node: ts.Node): node is ts.JSDocMemberName { - return node.kind === ts.SyntaxKind.JSDocMemberName; +export function isJSDocMemberName(node: Node): node is JSDocMemberName { + return node.kind === SyntaxKind.JSDocMemberName; } -export function isJSDocLink(node: ts.Node): node is ts.JSDocLink { - return node.kind === ts.SyntaxKind.JSDocLink; +export function isJSDocLink(node: Node): node is JSDocLink { + return node.kind === SyntaxKind.JSDocLink; } -export function isJSDocLinkCode(node: ts.Node): node is ts.JSDocLinkCode { - return node.kind === ts.SyntaxKind.JSDocLinkCode; +export function isJSDocLinkCode(node: Node): node is JSDocLinkCode { + return node.kind === SyntaxKind.JSDocLinkCode; } -export function isJSDocLinkPlain(node: ts.Node): node is ts.JSDocLinkPlain { - return node.kind === ts.SyntaxKind.JSDocLinkPlain; +export function isJSDocLinkPlain(node: Node): node is JSDocLinkPlain { + return node.kind === SyntaxKind.JSDocLinkPlain; } -export function isJSDocAllType(node: ts.Node): node is ts.JSDocAllType { - return node.kind === ts.SyntaxKind.JSDocAllType; +export function isJSDocAllType(node: Node): node is JSDocAllType { + return node.kind === SyntaxKind.JSDocAllType; } -export function isJSDocUnknownType(node: ts.Node): node is ts.JSDocUnknownType { - return node.kind === ts.SyntaxKind.JSDocUnknownType; +export function isJSDocUnknownType(node: Node): node is JSDocUnknownType { + return node.kind === SyntaxKind.JSDocUnknownType; } -export function isJSDocNullableType(node: ts.Node): node is ts.JSDocNullableType { - return node.kind === ts.SyntaxKind.JSDocNullableType; +export function isJSDocNullableType(node: Node): node is JSDocNullableType { + return node.kind === SyntaxKind.JSDocNullableType; } -export function isJSDocNonNullableType(node: ts.Node): node is ts.JSDocNonNullableType { - return node.kind === ts.SyntaxKind.JSDocNonNullableType; +export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType { + return node.kind === SyntaxKind.JSDocNonNullableType; } -export function isJSDocOptionalType(node: ts.Node): node is ts.JSDocOptionalType { - return node.kind === ts.SyntaxKind.JSDocOptionalType; +export function isJSDocOptionalType(node: Node): node is JSDocOptionalType { + return node.kind === SyntaxKind.JSDocOptionalType; } -export function isJSDocFunctionType(node: ts.Node): node is ts.JSDocFunctionType { - return node.kind === ts.SyntaxKind.JSDocFunctionType; +export function isJSDocFunctionType(node: Node): node is JSDocFunctionType { + return node.kind === SyntaxKind.JSDocFunctionType; } -export function isJSDocVariadicType(node: ts.Node): node is ts.JSDocVariadicType { - return node.kind === ts.SyntaxKind.JSDocVariadicType; +export function isJSDocVariadicType(node: Node): node is JSDocVariadicType { + return node.kind === SyntaxKind.JSDocVariadicType; } -export function isJSDocNamepathType(node: ts.Node): node is ts.JSDocNamepathType { - return node.kind === ts.SyntaxKind.JSDocNamepathType; +export function isJSDocNamepathType(node: Node): node is JSDocNamepathType { + return node.kind === SyntaxKind.JSDocNamepathType; } -export function isJSDoc(node: ts.Node): node is ts.JSDoc { - return node.kind === ts.SyntaxKind.JSDoc; +export function isJSDoc(node: Node): node is JSDoc { + return node.kind === SyntaxKind.JSDoc; } -export function isJSDocTypeLiteral(node: ts.Node): node is ts.JSDocTypeLiteral { - return node.kind === ts.SyntaxKind.JSDocTypeLiteral; +export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral { + return node.kind === SyntaxKind.JSDocTypeLiteral; } -export function isJSDocSignature(node: ts.Node): node is ts.JSDocSignature { - return node.kind === ts.SyntaxKind.JSDocSignature; +export function isJSDocSignature(node: Node): node is JSDocSignature { + return node.kind === SyntaxKind.JSDocSignature; } // JSDoc Tags -export function isJSDocAugmentsTag(node: ts.Node): node is ts.JSDocAugmentsTag { - return node.kind === ts.SyntaxKind.JSDocAugmentsTag; +export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag { + return node.kind === SyntaxKind.JSDocAugmentsTag; } -export function isJSDocAuthorTag(node: ts.Node): node is ts.JSDocAuthorTag { - return node.kind === ts.SyntaxKind.JSDocAuthorTag; +export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { + return node.kind === SyntaxKind.JSDocAuthorTag; } -export function isJSDocClassTag(node: ts.Node): node is ts.JSDocClassTag { - return node.kind === ts.SyntaxKind.JSDocClassTag; +export function isJSDocClassTag(node: Node): node is JSDocClassTag { + return node.kind === SyntaxKind.JSDocClassTag; } -export function isJSDocCallbackTag(node: ts.Node): node is ts.JSDocCallbackTag { - return node.kind === ts.SyntaxKind.JSDocCallbackTag; +export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag { + return node.kind === SyntaxKind.JSDocCallbackTag; } -export function isJSDocPublicTag(node: ts.Node): node is ts.JSDocPublicTag { - return node.kind === ts.SyntaxKind.JSDocPublicTag; +export function isJSDocPublicTag(node: Node): node is JSDocPublicTag { + return node.kind === SyntaxKind.JSDocPublicTag; } -export function isJSDocPrivateTag(node: ts.Node): node is ts.JSDocPrivateTag { - return node.kind === ts.SyntaxKind.JSDocPrivateTag; +export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag { + return node.kind === SyntaxKind.JSDocPrivateTag; } -export function isJSDocProtectedTag(node: ts.Node): node is ts.JSDocProtectedTag { - return node.kind === ts.SyntaxKind.JSDocProtectedTag; +export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag { + return node.kind === SyntaxKind.JSDocProtectedTag; } -export function isJSDocReadonlyTag(node: ts.Node): node is ts.JSDocReadonlyTag { - return node.kind === ts.SyntaxKind.JSDocReadonlyTag; +export function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag { + return node.kind === SyntaxKind.JSDocReadonlyTag; } -export function isJSDocOverrideTag(node: ts.Node): node is ts.JSDocOverrideTag { - return node.kind === ts.SyntaxKind.JSDocOverrideTag; +export function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag { + return node.kind === SyntaxKind.JSDocOverrideTag; } -export function isJSDocDeprecatedTag(node: ts.Node): node is ts.JSDocDeprecatedTag { - return node.kind === ts.SyntaxKind.JSDocDeprecatedTag; +export function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag { + return node.kind === SyntaxKind.JSDocDeprecatedTag; } -export function isJSDocSeeTag(node: ts.Node): node is ts.JSDocSeeTag { - return node.kind === ts.SyntaxKind.JSDocSeeTag; +export function isJSDocSeeTag(node: Node): node is JSDocSeeTag { + return node.kind === SyntaxKind.JSDocSeeTag; } -export function isJSDocEnumTag(node: ts.Node): node is ts.JSDocEnumTag { - return node.kind === ts.SyntaxKind.JSDocEnumTag; +export function isJSDocEnumTag(node: Node): node is JSDocEnumTag { + return node.kind === SyntaxKind.JSDocEnumTag; } -export function isJSDocParameterTag(node: ts.Node): node is ts.JSDocParameterTag { - return node.kind === ts.SyntaxKind.JSDocParameterTag; +export function isJSDocParameterTag(node: Node): node is JSDocParameterTag { + return node.kind === SyntaxKind.JSDocParameterTag; } -export function isJSDocReturnTag(node: ts.Node): node is ts.JSDocReturnTag { - return node.kind === ts.SyntaxKind.JSDocReturnTag; +export function isJSDocReturnTag(node: Node): node is JSDocReturnTag { + return node.kind === SyntaxKind.JSDocReturnTag; } -export function isJSDocThisTag(node: ts.Node): node is ts.JSDocThisTag { - return node.kind === ts.SyntaxKind.JSDocThisTag; +export function isJSDocThisTag(node: Node): node is JSDocThisTag { + return node.kind === SyntaxKind.JSDocThisTag; } -export function isJSDocTypeTag(node: ts.Node): node is ts.JSDocTypeTag { - return node.kind === ts.SyntaxKind.JSDocTypeTag; +export function isJSDocTypeTag(node: Node): node is JSDocTypeTag { + return node.kind === SyntaxKind.JSDocTypeTag; } -export function isJSDocTemplateTag(node: ts.Node): node is ts.JSDocTemplateTag { - return node.kind === ts.SyntaxKind.JSDocTemplateTag; +export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag { + return node.kind === SyntaxKind.JSDocTemplateTag; } -export function isJSDocTypedefTag(node: ts.Node): node is ts.JSDocTypedefTag { - return node.kind === ts.SyntaxKind.JSDocTypedefTag; +export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag { + return node.kind === SyntaxKind.JSDocTypedefTag; } -export function isJSDocUnknownTag(node: ts.Node): node is ts.JSDocUnknownTag { - return node.kind === ts.SyntaxKind.JSDocTag; +export function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag { + return node.kind === SyntaxKind.JSDocTag; } -export function isJSDocPropertyTag(node: ts.Node): node is ts.JSDocPropertyTag { - return node.kind === ts.SyntaxKind.JSDocPropertyTag; +export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag { + return node.kind === SyntaxKind.JSDocPropertyTag; } -export function isJSDocImplementsTag(node: ts.Node): node is ts.JSDocImplementsTag { - return node.kind === ts.SyntaxKind.JSDocImplementsTag; +export function isJSDocImplementsTag(node: Node): node is JSDocImplementsTag { + return node.kind === SyntaxKind.JSDocImplementsTag; } // Synthesized list /* @internal */ -export function isSyntaxList(n: ts.Node): n is ts.SyntaxList { - return n.kind === ts.SyntaxKind.SyntaxList; +export function isSyntaxList(n: Node): n is SyntaxList { + return n.kind === SyntaxKind.SyntaxList; } diff --git a/src/compiler/factory/parenthesizerRules.ts b/src/compiler/factory/parenthesizerRules.ts index d261780fb571e..78abbbc097563 100644 --- a/src/compiler/factory/parenthesizerRules.ts +++ b/src/compiler/factory/parenthesizerRules.ts @@ -1,13 +1,23 @@ -import * as ts from "../_namespaces/ts"; +import { + Associativity, BinaryExpression, BinaryOperator, cast, compareValues, Comparison, ConciseBody, ESMap, Expression, + getExpressionAssociativity, getExpressionPrecedence, getLeftmostExpression, getOperatorAssociativity, + getOperatorPrecedence, identity, isBinaryExpression, isBlock, isCallExpression, isCommaSequence, + isConditionalTypeNode, isConstructorTypeNode, isFunctionOrConstructorTypeNode, isFunctionTypeNode, isInferTypeNode, + isIntersectionTypeNode, isJSDocNullableType, isLeftHandSideExpression, isLiteralKind, isNamedTupleMember, + isNodeArray, isOptionalChain, isTypeOperatorNode, isUnaryExpression, isUnionTypeNode, last, LeftHandSideExpression, + Map, NamedTupleMember, NewExpression, NodeArray, NodeFactory, OperatorPrecedence, OuterExpressionKinds, + ParenthesizerRules, sameMap, setTextRange, skipPartiallyEmittedExpressions, some, SyntaxKind, TypeNode, + UnaryExpression, +} from "../_namespaces/ts"; /** @internal */ -export function createParenthesizerRules(factory: ts.NodeFactory): ts.ParenthesizerRules { - interface BinaryPlusExpression extends ts.BinaryExpression { - cachedLiteralKind: ts.SyntaxKind; +export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRules { + interface BinaryPlusExpression extends BinaryExpression { + cachedLiteralKind: SyntaxKind; } - let binaryLeftOperandParenthesizerCache: ts.ESMap ts.Expression> | undefined; - let binaryRightOperandParenthesizerCache: ts.ESMap ts.Expression> | undefined; + let binaryLeftOperandParenthesizerCache: ESMap Expression> | undefined; + let binaryRightOperandParenthesizerCache: ESMap Expression> | undefined; return { getParenthesizeLeftSideOfBinaryForOperator, @@ -42,8 +52,8 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi parenthesizeLeadingTypeArgument, }; - function getParenthesizeLeftSideOfBinaryForOperator(operatorKind: ts.BinaryOperator) { - binaryLeftOperandParenthesizerCache ||= new ts.Map(); + function getParenthesizeLeftSideOfBinaryForOperator(operatorKind: BinaryOperator) { + binaryLeftOperandParenthesizerCache ||= new Map(); let parenthesizerRule = binaryLeftOperandParenthesizerCache.get(operatorKind); if (!parenthesizerRule) { parenthesizerRule = node => parenthesizeLeftSideOfBinary(operatorKind, node); @@ -52,8 +62,8 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi return parenthesizerRule; } - function getParenthesizeRightSideOfBinaryForOperator(operatorKind: ts.BinaryOperator) { - binaryRightOperandParenthesizerCache ||= new ts.Map(); + function getParenthesizeRightSideOfBinaryForOperator(operatorKind: BinaryOperator) { + binaryRightOperandParenthesizerCache ||= new Map(); let parenthesizerRule = binaryRightOperandParenthesizerCache.get(operatorKind); if (!parenthesizerRule) { parenthesizerRule = node => parenthesizeRightSideOfBinary(operatorKind, /*leftSide*/ undefined, node); @@ -70,7 +80,7 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the * BinaryExpression. */ - function binaryOperandNeedsParentheses(binaryOperator: ts.SyntaxKind, operand: ts.Expression, isLeftSideOfBinary: boolean, leftOperand: ts.Expression | undefined) { + function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) { // If the operand has lower precedence, then it needs to be parenthesized to preserve the // intent of the expression. For example, if the operand is `a + b` and the operator is // `*`, then we need to parenthesize the operand to preserve the intended order of @@ -88,31 +98,31 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // // If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve // the intended order of operations: `(a ** b) ** c` - const binaryOperatorPrecedence = ts.getOperatorPrecedence(ts.SyntaxKind.BinaryExpression, binaryOperator); - const binaryOperatorAssociativity = ts.getOperatorAssociativity(ts.SyntaxKind.BinaryExpression, binaryOperator); - const emittedOperand = ts.skipPartiallyEmittedExpressions(operand); - if (!isLeftSideOfBinary && operand.kind === ts.SyntaxKind.ArrowFunction && binaryOperatorPrecedence > ts.OperatorPrecedence.Assignment) { + const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); + const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); + const emittedOperand = skipPartiallyEmittedExpressions(operand); + if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) { // We need to parenthesize arrow functions on the right side to avoid it being // parsed as parenthesized expression: `a && (() => {})` return true; } - const operandPrecedence = ts.getExpressionPrecedence(emittedOperand); - switch (ts.compareValues(operandPrecedence, binaryOperatorPrecedence)) { - case ts.Comparison.LessThan: + const operandPrecedence = getExpressionPrecedence(emittedOperand); + switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) { + case Comparison.LessThan: // If the operand is the right side of a right-associative binary operation // and is a yield expression, then we do not need parentheses. if (!isLeftSideOfBinary - && binaryOperatorAssociativity === ts.Associativity.Right - && operand.kind === ts.SyntaxKind.YieldExpression) { + && binaryOperatorAssociativity === Associativity.Right + && operand.kind === SyntaxKind.YieldExpression) { return false; } return true; - case ts.Comparison.GreaterThan: + case Comparison.GreaterThan: return false; - case ts.Comparison.EqualTo: + case Comparison.EqualTo: if (isLeftSideOfBinary) { // No need to parenthesize the left operand when the binary operator is // left associative: @@ -123,10 +133,10 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // right associative: // (a/b)**x -> (a/b)**x // (a**b)**x -> (a**b)**x - return binaryOperatorAssociativity === ts.Associativity.Right; + return binaryOperatorAssociativity === Associativity.Right; } else { - if (ts.isBinaryExpression(emittedOperand) + if (isBinaryExpression(emittedOperand) && emittedOperand.operatorToken.kind === binaryOperator) { // No need to parenthesize the right operand when the binary operator and // operand are the same and one of the following: @@ -144,9 +154,9 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // the same kind (recursively). // "a"+(1+2) => "a"+(1+2) // "a"+("b"+"c") => "a"+"b"+"c" - if (binaryOperator === ts.SyntaxKind.PlusToken) { - const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : ts.SyntaxKind.Unknown; - if (ts.isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { + if (binaryOperator === SyntaxKind.PlusToken) { + const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown; + if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) { return false; } } @@ -161,8 +171,8 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // associative: // x/(a*b) -> x/(a*b) // x**(a/b) -> x**(a/b) - const operandAssociativity = ts.getExpressionAssociativity(emittedOperand); - return operandAssociativity === ts.Associativity.Left; + const operandAssociativity = getExpressionAssociativity(emittedOperand); + return operandAssociativity === Associativity.Left; } } } @@ -172,7 +182,7 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * * @param binaryOperator The binary operator. */ - function operatorHasAssociativeProperty(binaryOperator: ts.SyntaxKind) { + function operatorHasAssociativeProperty(binaryOperator: SyntaxKind) { // The following operators are associative in JavaScript: // (a*b)*c -> a*(b*c) -> a*b*c // (a|b)|c -> a|(b|c) -> a|b|c @@ -182,11 +192,11 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // // While addition is associative in mathematics, JavaScript's `+` is not // guaranteed to be associative as it is overloaded with string concatenation. - return binaryOperator === ts.SyntaxKind.AsteriskToken - || binaryOperator === ts.SyntaxKind.BarToken - || binaryOperator === ts.SyntaxKind.AmpersandToken - || binaryOperator === ts.SyntaxKind.CaretToken - || binaryOperator === ts.SyntaxKind.CommaToken; + return binaryOperator === SyntaxKind.AsteriskToken + || binaryOperator === SyntaxKind.BarToken + || binaryOperator === SyntaxKind.AmpersandToken + || binaryOperator === SyntaxKind.CaretToken + || binaryOperator === SyntaxKind.CommaToken; } /** @@ -195,29 +205,29 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * It is used to determine whether the right-hand operand of a binary plus expression can be * emitted without parentheses. */ - function getLiteralKindOfBinaryPlusOperand(node: ts.Expression): ts.SyntaxKind { - node = ts.skipPartiallyEmittedExpressions(node); + function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind { + node = skipPartiallyEmittedExpressions(node); - if (ts.isLiteralKind(node.kind)) { + if (isLiteralKind(node.kind)) { return node.kind; } - if (node.kind === ts.SyntaxKind.BinaryExpression && (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.PlusToken) { + if (node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken) { if ((node as BinaryPlusExpression).cachedLiteralKind !== undefined) { return (node as BinaryPlusExpression).cachedLiteralKind; } - const leftKind = getLiteralKindOfBinaryPlusOperand((node as ts.BinaryExpression).left); - const literalKind = ts.isLiteralKind(leftKind) - && leftKind === getLiteralKindOfBinaryPlusOperand((node as ts.BinaryExpression).right) + const leftKind = getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).left); + const literalKind = isLiteralKind(leftKind) + && leftKind === getLiteralKindOfBinaryPlusOperand((node as BinaryExpression).right) ? leftKind - : ts.SyntaxKind.Unknown; + : SyntaxKind.Unknown; (node as BinaryPlusExpression).cachedLiteralKind = literalKind; return literalKind; } - return ts.SyntaxKind.Unknown; + return SyntaxKind.Unknown; } /** @@ -229,11 +239,11 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * @param isLeftSideOfBinary A value indicating whether the operand is the left side of the * BinaryExpression. */ - function parenthesizeBinaryOperand(binaryOperator: ts.SyntaxKind, operand: ts.Expression, isLeftSideOfBinary: boolean, leftOperand?: ts.Expression) { - const skipped = ts.skipPartiallyEmittedExpressions(operand); + function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) { + const skipped = skipPartiallyEmittedExpressions(operand); // If the resulting expression is already parenthesized, we do not need to do any further processing. - if (skipped.kind === ts.SyntaxKind.ParenthesizedExpression) { + if (skipped.kind === SyntaxKind.ParenthesizedExpression) { return operand; } @@ -243,34 +253,34 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi } - function parenthesizeLeftSideOfBinary(binaryOperator: ts.SyntaxKind, leftSide: ts.Expression): ts.Expression { + function parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression { return parenthesizeBinaryOperand(binaryOperator, leftSide, /*isLeftSideOfBinary*/ true); } - function parenthesizeRightSideOfBinary(binaryOperator: ts.SyntaxKind, leftSide: ts.Expression | undefined, rightSide: ts.Expression): ts.Expression { + function parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression | undefined, rightSide: Expression): Expression { return parenthesizeBinaryOperand(binaryOperator, rightSide, /*isLeftSideOfBinary*/ false, leftSide); } - function parenthesizeExpressionOfComputedPropertyName(expression: ts.Expression): ts.Expression { - return ts.isCommaSequence(expression) ? factory.createParenthesizedExpression(expression) : expression; + function parenthesizeExpressionOfComputedPropertyName(expression: Expression): Expression { + return isCommaSequence(expression) ? factory.createParenthesizedExpression(expression) : expression; } - function parenthesizeConditionOfConditionalExpression(condition: ts.Expression): ts.Expression { - const conditionalPrecedence = ts.getOperatorPrecedence(ts.SyntaxKind.ConditionalExpression, ts.SyntaxKind.QuestionToken); - const emittedCondition = ts.skipPartiallyEmittedExpressions(condition); - const conditionPrecedence = ts.getExpressionPrecedence(emittedCondition); - if (ts.compareValues(conditionPrecedence, conditionalPrecedence) !== ts.Comparison.GreaterThan) { + function parenthesizeConditionOfConditionalExpression(condition: Expression): Expression { + const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken); + const emittedCondition = skipPartiallyEmittedExpressions(condition); + const conditionPrecedence = getExpressionPrecedence(emittedCondition); + if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) { return factory.createParenthesizedExpression(condition); } return condition; } - function parenthesizeBranchOfConditionalExpression(branch: ts.Expression): ts.Expression { + function parenthesizeBranchOfConditionalExpression(branch: Expression): Expression { // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions // so in case when comma expression is introduced as a part of previous transformations // if should be wrapped in parens since comma operator has the lowest precedence - const emittedExpression = ts.skipPartiallyEmittedExpressions(branch); - return ts.isCommaSequence(emittedExpression) + const emittedExpression = skipPartiallyEmittedExpressions(branch); + return isCommaSequence(emittedExpression) ? factory.createParenthesizedExpression(branch) : branch; } @@ -286,13 +296,13 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * - FunctionExpression * - ClassExpression */ - function parenthesizeExpressionOfExportDefault(expression: ts.Expression): ts.Expression { - const check = ts.skipPartiallyEmittedExpressions(expression); - let needsParens = ts.isCommaSequence(check); + function parenthesizeExpressionOfExportDefault(expression: Expression): Expression { + const check = skipPartiallyEmittedExpressions(expression); + let needsParens = isCommaSequence(check); if (!needsParens) { - switch (ts.getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) { - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.FunctionExpression: + switch (getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) { + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: needsParens = true; } } @@ -303,16 +313,16 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * Wraps an expression in parentheses if it is needed in order to use the expression * as the expression of a `NewExpression` node. */ - function parenthesizeExpressionOfNew(expression: ts.Expression): ts.LeftHandSideExpression { - const leftmostExpr = ts.getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); + function parenthesizeExpressionOfNew(expression: Expression): LeftHandSideExpression { + const leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true); switch (leftmostExpr.kind) { - case ts.SyntaxKind.CallExpression: + case SyntaxKind.CallExpression: return factory.createParenthesizedExpression(expression); - case ts.SyntaxKind.NewExpression: - return !(leftmostExpr as ts.NewExpression).arguments + case SyntaxKind.NewExpression: + return !(leftmostExpr as NewExpression).arguments ? factory.createParenthesizedExpression(expression) - : expression as ts.LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds + : expression as LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds } return parenthesizeLeftSideOfAccess(expression); @@ -322,80 +332,80 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi * Wraps an expression in parentheses if it is needed in order to use the expression for * property or element access. */ - function parenthesizeLeftSideOfAccess(expression: ts.Expression, optionalChain?: boolean): ts.LeftHandSideExpression { + function parenthesizeLeftSideOfAccess(expression: Expression, optionalChain?: boolean): LeftHandSideExpression { // isLeftHandSideExpression is almost the correct criterion for when it is not necessary // to parenthesize the expression before a dot. The known exception is: // // NewExpression: // new C.x -> not the same as (new C).x // - const emittedExpression = ts.skipPartiallyEmittedExpressions(expression); - if (ts.isLeftHandSideExpression(emittedExpression) - && (emittedExpression.kind !== ts.SyntaxKind.NewExpression || (emittedExpression as ts.NewExpression).arguments) - && (optionalChain || !ts.isOptionalChain(emittedExpression))) { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isLeftHandSideExpression(emittedExpression) + && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression as NewExpression).arguments) + && (optionalChain || !isOptionalChain(emittedExpression))) { // TODO(rbuckton): Verify whether this assertion holds. - return expression as ts.LeftHandSideExpression; + return expression as LeftHandSideExpression; } // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return ts.setTextRange(factory.createParenthesizedExpression(expression), expression); + return setTextRange(factory.createParenthesizedExpression(expression), expression); } - function parenthesizeOperandOfPostfixUnary(operand: ts.Expression): ts.LeftHandSideExpression { + function parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return ts.isLeftHandSideExpression(operand) ? operand : ts.setTextRange(factory.createParenthesizedExpression(operand), operand); + return isLeftHandSideExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand); } - function parenthesizeOperandOfPrefixUnary(operand: ts.Expression): ts.UnaryExpression { + function parenthesizeOperandOfPrefixUnary(operand: Expression): UnaryExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return ts.isUnaryExpression(operand) ? operand : ts.setTextRange(factory.createParenthesizedExpression(operand), operand); + return isUnaryExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand); } - function parenthesizeExpressionsOfCommaDelimitedList(elements: ts.NodeArray): ts.NodeArray { - const result = ts.sameMap(elements, parenthesizeExpressionForDisallowedComma); - return ts.setTextRange(factory.createNodeArray(result, elements.hasTrailingComma), elements); + function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray): NodeArray { + const result = sameMap(elements, parenthesizeExpressionForDisallowedComma); + return setTextRange(factory.createNodeArray(result, elements.hasTrailingComma), elements); } - function parenthesizeExpressionForDisallowedComma(expression: ts.Expression): ts.Expression { - const emittedExpression = ts.skipPartiallyEmittedExpressions(expression); - const expressionPrecedence = ts.getExpressionPrecedence(emittedExpression); - const commaPrecedence = ts.getOperatorPrecedence(ts.SyntaxKind.BinaryExpression, ts.SyntaxKind.CommaToken); + function parenthesizeExpressionForDisallowedComma(expression: Expression): Expression { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + const expressionPrecedence = getExpressionPrecedence(emittedExpression); + const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return expressionPrecedence > commaPrecedence ? expression : ts.setTextRange(factory.createParenthesizedExpression(expression), expression); + return expressionPrecedence > commaPrecedence ? expression : setTextRange(factory.createParenthesizedExpression(expression), expression); } - function parenthesizeExpressionOfExpressionStatement(expression: ts.Expression): ts.Expression { - const emittedExpression = ts.skipPartiallyEmittedExpressions(expression); - if (ts.isCallExpression(emittedExpression)) { + function parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression { + const emittedExpression = skipPartiallyEmittedExpressions(expression); + if (isCallExpression(emittedExpression)) { const callee = emittedExpression.expression; - const kind = ts.skipPartiallyEmittedExpressions(callee).kind; - if (kind === ts.SyntaxKind.FunctionExpression || kind === ts.SyntaxKind.ArrowFunction) { + const kind = skipPartiallyEmittedExpressions(callee).kind; + if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. const updated = factory.updateCallExpression( emittedExpression, - ts.setTextRange(factory.createParenthesizedExpression(callee), callee), + setTextRange(factory.createParenthesizedExpression(callee), callee), emittedExpression.typeArguments, emittedExpression.arguments ); - return factory.restoreOuterExpressions(expression, updated, ts.OuterExpressionKinds.PartiallyEmittedExpressions); + return factory.restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions); } } - const leftmostExpressionKind = ts.getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; - if (leftmostExpressionKind === ts.SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === ts.SyntaxKind.FunctionExpression) { + const leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind; + if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return ts.setTextRange(factory.createParenthesizedExpression(expression), expression); + return setTextRange(factory.createParenthesizedExpression(expression), expression); } return expression; } - function parenthesizeConciseBodyOfArrowFunction(body: ts.Expression): ts.Expression; - function parenthesizeConciseBodyOfArrowFunction(body: ts.ConciseBody): ts.ConciseBody; - function parenthesizeConciseBodyOfArrowFunction(body: ts.ConciseBody): ts.ConciseBody { - if (!ts.isBlock(body) && (ts.isCommaSequence(body) || ts.getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === ts.SyntaxKind.ObjectLiteralExpression)) { + function parenthesizeConciseBodyOfArrowFunction(body: Expression): Expression; + function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody; + function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody { + if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return ts.setTextRange(factory.createParenthesizedExpression(body), body); + return setTextRange(factory.createParenthesizedExpression(body), body); } return body; @@ -412,19 +422,19 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // - The check type (the `UnionType`, above) does not allow function, constructor, or conditional types (they must be parenthesized) // - The extends type (the first `Type`, above) does not allow conditional types (they must be parenthesized). Function and constructor types are fine. // - The true and false branch types (the second and third `Type` non-terminals, above) allow any type - function parenthesizeCheckTypeOfConditionalType(checkType: ts.TypeNode): ts.TypeNode { + function parenthesizeCheckTypeOfConditionalType(checkType: TypeNode): TypeNode { switch (checkType.kind) { - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ConditionalType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConditionalType: return factory.createParenthesizedType(checkType); } return checkType; } - function parenthesizeExtendsTypeOfConditionalType(extendsType: ts.TypeNode): ts.TypeNode { + function parenthesizeExtendsTypeOfConditionalType(extendsType: TypeNode): TypeNode { switch (extendsType.kind) { - case ts.SyntaxKind.ConditionalType: + case SyntaxKind.ConditionalType: return factory.createParenthesizedType(extendsType); } return extendsType; @@ -435,17 +445,17 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // UnionType[?Extends] `|` IntersectionType[?Extends] // // - A union type constituent has the same precedence as the check type of a conditional type - function parenthesizeConstituentTypeOfUnionType(type: ts.TypeNode) { + function parenthesizeConstituentTypeOfUnionType(type: TypeNode) { switch (type.kind) { - case ts.SyntaxKind.UnionType: // Not strictly necessary, but a union containing a union should have been flattened - case ts.SyntaxKind.IntersectionType: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests + case SyntaxKind.UnionType: // Not strictly necessary, but a union containing a union should have been flattened + case SyntaxKind.IntersectionType: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests return factory.createParenthesizedType(type); } return parenthesizeCheckTypeOfConditionalType(type); } - function parenthesizeConstituentTypesOfUnionType(members: readonly ts.TypeNode[]): ts.NodeArray { - return factory.createNodeArray(ts.sameMap(members, parenthesizeConstituentTypeOfUnionType)); + function parenthesizeConstituentTypesOfUnionType(members: readonly TypeNode[]): NodeArray { + return factory.createNodeArray(sameMap(members, parenthesizeConstituentTypeOfUnionType)); } // IntersectionType[Extends] : @@ -453,17 +463,17 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // IntersectionType[?Extends] `&` TypeOperator[?Extends] // // - An intersection type constituent does not allow function, constructor, conditional, or union types (they must be parenthesized) - function parenthesizeConstituentTypeOfIntersectionType(type: ts.TypeNode) { + function parenthesizeConstituentTypeOfIntersectionType(type: TypeNode) { switch (type.kind) { - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: // Not strictly necessary, but an intersection containing an intersection should have been flattened + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: // Not strictly necessary, but an intersection containing an intersection should have been flattened return factory.createParenthesizedType(type); } return parenthesizeConstituentTypeOfUnionType(type); } - function parenthesizeConstituentTypesOfIntersectionType(members: readonly ts.TypeNode[]): ts.NodeArray { - return factory.createNodeArray(ts.sameMap(members, parenthesizeConstituentTypeOfIntersectionType)); + function parenthesizeConstituentTypesOfIntersectionType(members: readonly TypeNode[]): NodeArray { + return factory.createNodeArray(sameMap(members, parenthesizeConstituentTypeOfIntersectionType)); } // TypeOperator[Extends] : @@ -473,17 +483,17 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // `unique` TypeOperator[?Extends] // `readonly` TypeOperator[?Extends] // - function parenthesizeOperandOfTypeOperator(type: ts.TypeNode) { + function parenthesizeOperandOfTypeOperator(type: TypeNode) { switch (type.kind) { - case ts.SyntaxKind.IntersectionType: + case SyntaxKind.IntersectionType: return factory.createParenthesizedType(type); } return parenthesizeConstituentTypeOfIntersectionType(type); } - function parenthesizeOperandOfReadonlyTypeOperator(type: ts.TypeNode) { + function parenthesizeOperandOfReadonlyTypeOperator(type: TypeNode) { switch (type.kind) { - case ts.SyntaxKind.TypeOperator: + case SyntaxKind.TypeOperator: return factory.createParenthesizedType(type); } return parenthesizeOperandOfTypeOperator(type); @@ -502,11 +512,11 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // ArrayType : // NonArrayType `[` `]` // - function parenthesizeNonArrayTypeOfPostfixType(type: ts.TypeNode) { + function parenthesizeNonArrayTypeOfPostfixType(type: TypeNode) { switch (type.kind) { - case ts.SyntaxKind.InferType: - case ts.SyntaxKind.TypeOperator: - case ts.SyntaxKind.TypeQuery: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests + case SyntaxKind.InferType: + case SyntaxKind.TypeOperator: + case SyntaxKind.TypeQuery: // Not strictly necessary, but makes generated output more readable and avoids breaks in DT tests return factory.createParenthesizedType(type); } return parenthesizeOperandOfTypeOperator(type); @@ -542,27 +552,27 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // RestType : // `...` Type[~Extends] // - function parenthesizeElementTypesOfTupleType(types: readonly (ts.TypeNode | ts.NamedTupleMember)[]): ts.NodeArray { - return factory.createNodeArray(ts.sameMap(types, parenthesizeElementTypeOfTupleType)); + function parenthesizeElementTypesOfTupleType(types: readonly (TypeNode | NamedTupleMember)[]): NodeArray { + return factory.createNodeArray(sameMap(types, parenthesizeElementTypeOfTupleType)); } - function parenthesizeElementTypeOfTupleType(type: ts.TypeNode | ts.NamedTupleMember): ts.TypeNode { + function parenthesizeElementTypeOfTupleType(type: TypeNode | NamedTupleMember): TypeNode { if (hasJSDocPostfixQuestion(type)) return factory.createParenthesizedType(type); return type; } - function hasJSDocPostfixQuestion(type: ts.TypeNode | ts.NamedTupleMember): boolean { - if (ts.isJSDocNullableType(type)) return type.postfix; - if (ts.isNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.type); - if (ts.isFunctionTypeNode(type) || ts.isConstructorTypeNode(type) || ts.isTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.type); - if (ts.isConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.falseType); - if (ts.isUnionTypeNode(type)) return hasJSDocPostfixQuestion(ts.last(type.types)); - if (ts.isIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(ts.last(type.types)); - if (ts.isInferTypeNode(type)) return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint); + function hasJSDocPostfixQuestion(type: TypeNode | NamedTupleMember): boolean { + if (isJSDocNullableType(type)) return type.postfix; + if (isNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.type); + if (isFunctionTypeNode(type) || isConstructorTypeNode(type) || isTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.type); + if (isConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.falseType); + if (isUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); + if (isIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.types)); + if (isInferTypeNode(type)) return !!type.typeParameter.constraint && hasJSDocPostfixQuestion(type.typeParameter.constraint); return false; } - function parenthesizeTypeOfOptionalType(type: ts.TypeNode): ts.TypeNode { + function parenthesizeTypeOfOptionalType(type: TypeNode): TypeNode { if (hasJSDocPostfixQuestion(type)) return factory.createParenthesizedType(type); return parenthesizeNonArrayTypeOfPostfixType(type); } @@ -588,51 +598,51 @@ export function createParenthesizerRules(factory: ts.NodeFactory): ts.Parenthesi // return parenthesizeMemberOfElementType(member); // } - function parenthesizeLeadingTypeArgument(node: ts.TypeNode) { - return ts.isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node; + function parenthesizeLeadingTypeArgument(node: TypeNode) { + return isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node; } - function parenthesizeOrdinalTypeArgument(node: ts.TypeNode, i: number) { + function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) { return i === 0 ? parenthesizeLeadingTypeArgument(node) : node; } - function parenthesizeTypeArguments(typeArguments: ts.NodeArray | undefined): ts.NodeArray | undefined { - if (ts.some(typeArguments)) { - return factory.createNodeArray(ts.sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); + function parenthesizeTypeArguments(typeArguments: NodeArray | undefined): NodeArray | undefined { + if (some(typeArguments)) { + return factory.createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument)); } } } /** @internal */ -export const nullParenthesizerRules: ts.ParenthesizerRules = { - getParenthesizeLeftSideOfBinaryForOperator: _ => ts.identity, - getParenthesizeRightSideOfBinaryForOperator: _ => ts.identity, +export const nullParenthesizerRules: ParenthesizerRules = { + getParenthesizeLeftSideOfBinaryForOperator: _ => identity, + getParenthesizeRightSideOfBinaryForOperator: _ => identity, parenthesizeLeftSideOfBinary: (_binaryOperator, leftSide) => leftSide, parenthesizeRightSideOfBinary: (_binaryOperator, _leftSide, rightSide) => rightSide, - parenthesizeExpressionOfComputedPropertyName: ts.identity, - parenthesizeConditionOfConditionalExpression: ts.identity, - parenthesizeBranchOfConditionalExpression: ts.identity, - parenthesizeExpressionOfExportDefault: ts.identity, - parenthesizeExpressionOfNew: expression => ts.cast(expression, ts.isLeftHandSideExpression), - parenthesizeLeftSideOfAccess: expression => ts.cast(expression, ts.isLeftHandSideExpression), - parenthesizeOperandOfPostfixUnary: operand => ts.cast(operand, ts.isLeftHandSideExpression), - parenthesizeOperandOfPrefixUnary: operand => ts.cast(operand, ts.isUnaryExpression), - parenthesizeExpressionsOfCommaDelimitedList: nodes => ts.cast(nodes, ts.isNodeArray), - parenthesizeExpressionForDisallowedComma: ts.identity, - parenthesizeExpressionOfExpressionStatement: ts.identity, - parenthesizeConciseBodyOfArrowFunction: ts.identity, - parenthesizeCheckTypeOfConditionalType: ts.identity, - parenthesizeExtendsTypeOfConditionalType: ts.identity, - parenthesizeConstituentTypesOfUnionType: nodes => ts.cast(nodes, ts.isNodeArray), - parenthesizeConstituentTypeOfUnionType: ts.identity, - parenthesizeConstituentTypesOfIntersectionType: nodes => ts.cast(nodes, ts.isNodeArray), - parenthesizeConstituentTypeOfIntersectionType: ts.identity, - parenthesizeOperandOfTypeOperator: ts.identity, - parenthesizeOperandOfReadonlyTypeOperator: ts.identity, - parenthesizeNonArrayTypeOfPostfixType: ts.identity, - parenthesizeElementTypesOfTupleType: nodes => ts.cast(nodes, ts.isNodeArray), - parenthesizeElementTypeOfTupleType: ts.identity, - parenthesizeTypeOfOptionalType: ts.identity, - parenthesizeTypeArguments: nodes => nodes && ts.cast(nodes, ts.isNodeArray), - parenthesizeLeadingTypeArgument: ts.identity, + parenthesizeExpressionOfComputedPropertyName: identity, + parenthesizeConditionOfConditionalExpression: identity, + parenthesizeBranchOfConditionalExpression: identity, + parenthesizeExpressionOfExportDefault: identity, + parenthesizeExpressionOfNew: expression => cast(expression, isLeftHandSideExpression), + parenthesizeLeftSideOfAccess: expression => cast(expression, isLeftHandSideExpression), + parenthesizeOperandOfPostfixUnary: operand => cast(operand, isLeftHandSideExpression), + parenthesizeOperandOfPrefixUnary: operand => cast(operand, isUnaryExpression), + parenthesizeExpressionsOfCommaDelimitedList: nodes => cast(nodes, isNodeArray), + parenthesizeExpressionForDisallowedComma: identity, + parenthesizeExpressionOfExpressionStatement: identity, + parenthesizeConciseBodyOfArrowFunction: identity, + parenthesizeCheckTypeOfConditionalType: identity, + parenthesizeExtendsTypeOfConditionalType: identity, + parenthesizeConstituentTypesOfUnionType: nodes => cast(nodes, isNodeArray), + parenthesizeConstituentTypeOfUnionType: identity, + parenthesizeConstituentTypesOfIntersectionType: nodes => cast(nodes, isNodeArray), + parenthesizeConstituentTypeOfIntersectionType: identity, + parenthesizeOperandOfTypeOperator: identity, + parenthesizeOperandOfReadonlyTypeOperator: identity, + parenthesizeNonArrayTypeOfPostfixType: identity, + parenthesizeElementTypesOfTupleType: nodes => cast(nodes, isNodeArray), + parenthesizeElementTypeOfTupleType: identity, + parenthesizeTypeOfOptionalType: identity, + parenthesizeTypeArguments: nodes => nodes && cast(nodes, isNodeArray), + parenthesizeLeadingTypeArgument: identity, }; diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 18566ea39b608..e04d06a40651c 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -1,54 +1,85 @@ -import * as ts from "../_namespaces/ts"; +import { + AccessorDeclaration, addEmitFlags, AdditiveOperator, AdditiveOperatorOrHigher, AssertionLevel, + AssignmentOperatorOrHigher, BinaryExpression, BinaryOperator, BinaryOperatorToken, BindingOrAssignmentElement, + BindingOrAssignmentElementRestIndicator, BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, + BitwiseOperator, BitwiseOperatorOrHigher, BooleanLiteral, CharacterCodes, CommaListExpression, + compareStringsCaseSensitive, CompilerOptions, Debug, Declaration, EmitFlags, EmitHelperFactory, EmitHost, + EmitResolver, EntityName, EqualityOperator, EqualityOperatorOrHigher, ExclamationToken, ExponentiationOperator, + ExportDeclaration, Expression, ExpressionStatement, externalHelpersModuleNameText, first, firstOrUndefined, + ForInitializer, GeneratedIdentifier, GeneratedIdentifierFlags, GeneratedNamePart, GeneratedPrivateIdentifier, + getAllAccessorDeclarations, getEmitFlags, getEmitHelpers, getEmitModuleKind, getESModuleInterop, + getExternalModuleName, getExternalModuleNameFromPath, getJSDocType, getJSDocTypeTag, getModifiers, + getNamespaceDeclarationNode, getOrCreateEmitNode, getOriginalNode, getParseTreeNode, + getSourceTextOfNodeFromSourceFile, HasIllegalDecorators, HasIllegalModifiers, HasIllegalType, + HasIllegalTypeParameters, Identifier, idText, ImportCall, ImportDeclaration, ImportEqualsDeclaration, + isAssignmentExpression, isAssignmentOperator, isBlock, isComputedPropertyName, isDeclarationBindingElement, + isDefaultImport, isEffectiveExternalModule, isExclamationToken, isExportNamespaceAsDefaultDeclaration, + isFileLevelUniqueName, isGeneratedIdentifier, isGeneratedPrivateIdentifier, isIdentifier, isInJSFile, + isLiteralExpression, isMemberName, isMinusToken, isObjectLiteralElementLike, isParenthesizedExpression, isPlusToken, + isPostfixUnaryExpression, isPrefixUnaryExpression, isPrivateIdentifier, isPrologueDirective, isPropertyAssignment, + isPropertyName, isQualifiedName, isQuestionToken, isReadonlyKeyword, isShorthandPropertyAssignment, isSourceFile, + isSpreadAssignment, isSpreadElement, isStringLiteral, isThisTypeNode, isTypeNode, isTypeParameterDeclaration, + isVariableDeclarationList, JSDocNamespaceBody, JSDocTypeAssertion, JsxOpeningFragment, JsxOpeningLikeElement, + LeftHandSideExpression, LiteralExpression, LogicalOperator, LogicalOperatorOrHigher, map, MemberExpression, + MethodDeclaration, MinusToken, ModifiersArray, ModuleKind, ModuleName, MultiplicativeOperator, + MultiplicativeOperatorOrHigher, Mutable, NamedImportBindings, Node, NodeArray, NodeFactory, NullLiteral, + NumericLiteral, ObjectLiteralElementLike, ObjectLiteralExpression, or, OuterExpression, OuterExpressionKinds, + outFile, parseNodeFactory, PlusToken, PostfixUnaryExpression, PrefixUnaryExpression, PrivateIdentifier, + PropertyAssignment, PropertyDeclaration, PropertyName, pushIfUnique, QuestionToken, ReadonlyKeyword, + RelationalOperator, RelationalOperatorOrHigher, setOriginalNode, setParent, setStartsOnNewLine, setTextRange, + ShiftOperator, ShiftOperatorOrHigher, ShorthandPropertyAssignment, some, SourceFile, Statement, StringLiteral, + SyntaxKind, TextRange, ThisTypeNode, Token, TypeNode, TypeParameterDeclaration, +} from "../_namespaces/ts"; // Compound nodes /** @internal */ -export function createEmptyExports(factory: ts.NodeFactory) { +export function createEmptyExports(factory: NodeFactory) { return factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([]), /*moduleSpecifier*/ undefined); } /** @internal */ -export function createMemberAccessForPropertyName(factory: ts.NodeFactory, target: ts.Expression, memberName: ts.PropertyName, location?: ts.TextRange): ts.MemberExpression { - if (ts.isComputedPropertyName(memberName)) { - return ts.setTextRange(factory.createElementAccessExpression(target, memberName.expression), location); +export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { + if (isComputedPropertyName(memberName)) { + return setTextRange(factory.createElementAccessExpression(target, memberName.expression), location); } else { - const expression = ts.setTextRange( - ts.isMemberName(memberName) + const expression = setTextRange( + isMemberName(memberName) ? factory.createPropertyAccessExpression(target, memberName) : factory.createElementAccessExpression(target, memberName), memberName ); - ts.getOrCreateEmitNode(expression).flags |= ts.EmitFlags.NoNestedSourceMaps; + getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; return expression; } } -function createReactNamespace(reactNamespace: string, parent: ts.JsxOpeningLikeElement | ts.JsxOpeningFragment) { +function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) { // To ensure the emit resolver can properly resolve the namespace, we need to // treat this identifier as if it were a source tree node by clearing the `Synthesized` // flag and setting a parent node. - const react = ts.parseNodeFactory.createIdentifier(reactNamespace || "React"); + const react = parseNodeFactory.createIdentifier(reactNamespace || "React"); // Set the parent that is in parse tree // this makes sure that parent chain is intact for checker to traverse complete scope tree - ts.setParent(react, ts.getParseTreeNode(parent)); + setParent(react, getParseTreeNode(parent)); return react; } -function createJsxFactoryExpressionFromEntityName(factory: ts.NodeFactory, jsxFactory: ts.EntityName, parent: ts.JsxOpeningLikeElement | ts.JsxOpeningFragment): ts.Expression { - if (ts.isQualifiedName(jsxFactory)) { +function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { + if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent); - const right = factory.createIdentifier(ts.idText(jsxFactory.right)) as ts.Mutable; + const right = factory.createIdentifier(idText(jsxFactory.right)) as Mutable; right.escapedText = jsxFactory.right.escapedText; return factory.createPropertyAccessExpression(left, right); } else { - return createReactNamespace(ts.idText(jsxFactory), parent); + return createReactNamespace(idText(jsxFactory), parent); } } /** @internal */ -export function createJsxFactoryExpression(factory: ts.NodeFactory, jsxFactoryEntity: ts.EntityName | undefined, reactNamespace: string, parent: ts.JsxOpeningLikeElement | ts.JsxOpeningFragment): ts.Expression { +export function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { return jsxFactoryEntity ? createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) : factory.createPropertyAccessExpression( @@ -57,7 +88,7 @@ export function createJsxFactoryExpression(factory: ts.NodeFactory, jsxFactoryEn ); } -function createJsxFragmentFactoryExpression(factory: ts.NodeFactory, jsxFragmentFactoryEntity: ts.EntityName | undefined, reactNamespace: string, parent: ts.JsxOpeningLikeElement | ts.JsxOpeningFragment): ts.Expression { +function createJsxFragmentFactoryExpression(factory: NodeFactory, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression { return jsxFragmentFactoryEntity ? createJsxFactoryExpressionFromEntityName(factory, jsxFragmentFactoryEntity, parent) : factory.createPropertyAccessExpression( @@ -67,7 +98,7 @@ function createJsxFragmentFactoryExpression(factory: ts.NodeFactory, jsxFragment } /** @internal */ -export function createExpressionForJsxElement(factory: ts.NodeFactory, callee: ts.Expression, tagName: ts.Expression, props: ts.Expression | undefined, children: readonly ts.Expression[] | undefined, location: ts.TextRange): ts.LeftHandSideExpression { +export function createExpressionForJsxElement(factory: NodeFactory, callee: Expression, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, location: TextRange): LeftHandSideExpression { const argumentsList = [tagName]; if (props) { argumentsList.push(props); @@ -89,7 +120,7 @@ export function createExpressionForJsxElement(factory: ts.NodeFactory, callee: t } } - return ts.setTextRange( + return setTextRange( factory.createCallExpression( callee, /*typeArguments*/ undefined, @@ -100,7 +131,7 @@ export function createExpressionForJsxElement(factory: ts.NodeFactory, callee: t } /** @internal */ -export function createExpressionForJsxFragment(factory: ts.NodeFactory, jsxFactoryEntity: ts.EntityName | undefined, jsxFragmentFactoryEntity: ts.EntityName | undefined, reactNamespace: string, children: readonly ts.Expression[], parentElement: ts.JsxOpeningFragment, location: ts.TextRange): ts.LeftHandSideExpression { +export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression { const tagName = createJsxFragmentFactoryExpression(factory, jsxFragmentFactoryEntity, reactNamespace, parentElement); const argumentsList = [tagName, factory.createNull()]; @@ -116,7 +147,7 @@ export function createExpressionForJsxFragment(factory: ts.NodeFactory, jsxFacto } } - return ts.setTextRange( + return setTextRange( factory.createCallExpression( createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement), /*typeArguments*/ undefined, @@ -129,9 +160,9 @@ export function createExpressionForJsxFragment(factory: ts.NodeFactory, jsxFacto // Utilities /** @internal */ -export function createForOfBindingStatement(factory: ts.NodeFactory, node: ts.ForInitializer, boundValue: ts.Expression): ts.Statement { - if (ts.isVariableDeclarationList(node)) { - const firstDeclaration = ts.first(node.declarations); +export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement { + if (isVariableDeclarationList(node)) { + const firstDeclaration = first(node.declarations); const updatedDeclaration = factory.updateVariableDeclaration( firstDeclaration, firstDeclaration.name, @@ -139,7 +170,7 @@ export function createForOfBindingStatement(factory: ts.NodeFactory, node: ts.Fo /*type*/ undefined, boundValue ); - return ts.setTextRange( + return setTextRange( factory.createVariableStatement( /*modifiers*/ undefined, factory.updateVariableDeclarationList(node, [updatedDeclaration]) @@ -148,15 +179,15 @@ export function createForOfBindingStatement(factory: ts.NodeFactory, node: ts.Fo ); } else { - const updatedExpression = ts.setTextRange(factory.createAssignment(node, boundValue), /*location*/ node); - return ts.setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node); + const updatedExpression = setTextRange(factory.createAssignment(node, boundValue), /*location*/ node); + return setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node); } } /** @internal */ -export function insertLeadingStatement(factory: ts.NodeFactory, dest: ts.Statement, source: ts.Statement) { - if (ts.isBlock(dest)) { - return factory.updateBlock(dest, ts.setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); +export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement) { + if (isBlock(dest)) { + return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements)); } else { return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true); @@ -164,48 +195,48 @@ export function insertLeadingStatement(factory: ts.NodeFactory, dest: ts.Stateme } /** @internal */ -export function createExpressionFromEntityName(factory: ts.NodeFactory, node: ts.EntityName | ts.Expression): ts.Expression { - if (ts.isQualifiedName(node)) { +export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression { + if (isQualifiedName(node)) { const left = createExpressionFromEntityName(factory, node.left); // TODO(rbuckton): Does this need to be parented? - const right = ts.setParent(ts.setTextRange(factory.cloneNode(node.right), node.right), node.right.parent); - return ts.setTextRange(factory.createPropertyAccessExpression(left, right), node); + const right = setParent(setTextRange(factory.cloneNode(node.right), node.right), node.right.parent); + return setTextRange(factory.createPropertyAccessExpression(left, right), node); } else { // TODO(rbuckton): Does this need to be parented? - return ts.setParent(ts.setTextRange(factory.cloneNode(node), node), node.parent); + return setParent(setTextRange(factory.cloneNode(node), node), node.parent); } } /** @internal */ -export function createExpressionForPropertyName(factory: ts.NodeFactory, memberName: Exclude): ts.Expression { - if (ts.isIdentifier(memberName)) { +export function createExpressionForPropertyName(factory: NodeFactory, memberName: Exclude): Expression { + if (isIdentifier(memberName)) { return factory.createStringLiteralFromNode(memberName); } - else if (ts.isComputedPropertyName(memberName)) { + else if (isComputedPropertyName(memberName)) { // TODO(rbuckton): Does this need to be parented? - return ts.setParent(ts.setTextRange(factory.cloneNode(memberName.expression), memberName.expression), memberName.expression.parent); + return setParent(setTextRange(factory.cloneNode(memberName.expression), memberName.expression), memberName.expression.parent); } else { // TODO(rbuckton): Does this need to be parented? - return ts.setParent(ts.setTextRange(factory.cloneNode(memberName), memberName), memberName.parent); + return setParent(setTextRange(factory.cloneNode(memberName), memberName), memberName.parent); } } -function createExpressionForAccessorDeclaration(factory: ts.NodeFactory, properties: ts.NodeArray, property: ts.AccessorDeclaration & { readonly name: Exclude; }, receiver: ts.Expression, multiLine: boolean) { - const { firstAccessor, getAccessor, setAccessor } = ts.getAllAccessorDeclarations(properties, property); +function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray, property: AccessorDeclaration & { readonly name: Exclude; }, receiver: Expression, multiLine: boolean) { + const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property); if (property === firstAccessor) { - return ts.setTextRange( + return setTextRange( factory.createObjectDefinePropertyCall( receiver, createExpressionForPropertyName(factory, property.name), factory.createPropertyDescriptor({ enumerable: factory.createFalse(), configurable: true, - get: getAccessor && ts.setTextRange( - ts.setOriginalNode( + get: getAccessor && setTextRange( + setOriginalNode( factory.createFunctionExpression( - ts.getModifiers(getAccessor), + getModifiers(getAccessor), /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, @@ -217,10 +248,10 @@ function createExpressionForAccessorDeclaration(factory: ts.NodeFactory, propert ), getAccessor ), - set: setAccessor && ts.setTextRange( - ts.setOriginalNode( + set: setAccessor && setTextRange( + setOriginalNode( factory.createFunctionExpression( - ts.getModifiers(setAccessor), + getModifiers(setAccessor), /*asteriskToken*/ undefined, /*name*/ undefined, /*typeParameters*/ undefined, @@ -241,9 +272,9 @@ function createExpressionForAccessorDeclaration(factory: ts.NodeFactory, propert return undefined; } -function createExpressionForPropertyAssignment(factory: ts.NodeFactory, property: ts.PropertyAssignment, receiver: ts.Expression) { - return ts.setOriginalNode( - ts.setTextRange( +function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) { + return setOriginalNode( + setTextRange( factory.createAssignment( createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), property.initializer @@ -254,9 +285,9 @@ function createExpressionForPropertyAssignment(factory: ts.NodeFactory, property ); } -function createExpressionForShorthandPropertyAssignment(factory: ts.NodeFactory, property: ts.ShorthandPropertyAssignment, receiver: ts.Expression) { - return ts.setOriginalNode( - ts.setTextRange( +function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) { + return setOriginalNode( + setTextRange( factory.createAssignment( createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name), factory.cloneNode(property.name) @@ -267,15 +298,15 @@ function createExpressionForShorthandPropertyAssignment(factory: ts.NodeFactory, ); } -function createExpressionForMethodDeclaration(factory: ts.NodeFactory, method: ts.MethodDeclaration, receiver: ts.Expression) { - return ts.setOriginalNode( - ts.setTextRange( +function createExpressionForMethodDeclaration(factory: NodeFactory, method: MethodDeclaration, receiver: Expression) { + return setOriginalNode( + setTextRange( factory.createAssignment( createMemberAccessForPropertyName(factory, receiver, method.name, /*location*/ method.name), - ts.setOriginalNode( - ts.setTextRange( + setOriginalNode( + setTextRange( factory.createFunctionExpression( - ts.getModifiers(method), + getModifiers(method), method.asteriskToken, /*name*/ undefined, /*typeParameters*/ undefined, @@ -295,19 +326,19 @@ function createExpressionForMethodDeclaration(factory: ts.NodeFactory, method: t } /** @internal */ -export function createExpressionForObjectLiteralElementLike(factory: ts.NodeFactory, node: ts.ObjectLiteralExpression, property: ts.ObjectLiteralElementLike, receiver: ts.Expression): ts.Expression | undefined { - if (property.name && ts.isPrivateIdentifier(property.name)) { - ts.Debug.failBadSyntaxKind(property.name, "Private identifiers are not allowed in object literals."); +export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined { + if (property.name && isPrivateIdentifier(property.name)) { + Debug.failBadSyntaxKind(property.name, "Private identifiers are not allowed in object literals."); } switch (property.kind) { - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return createExpressionForAccessorDeclaration(factory, node.properties, property as typeof property & { readonly name: Exclude }, receiver, !!node.multiLine); - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return createExpressionForAccessorDeclaration(factory, node.properties, property as typeof property & { readonly name: Exclude }, receiver, !!node.multiLine); + case SyntaxKind.PropertyAssignment: return createExpressionForPropertyAssignment(factory, property, receiver); - case ts.SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: return createExpressionForShorthandPropertyAssignment(factory, property, receiver); - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: return createExpressionForMethodDeclaration(factory, property, receiver); } } @@ -345,30 +376,30 @@ export function createExpressionForObjectLiteralElementLike(factory: ts.NodeFact * @param expression The expression to use as the value to increment or decrement * @param resultVariable A temporary variable in which to store the result. Pass `undefined` if the result is discarded, or if the value of `` is the expected result. */ -export function expandPreOrPostfixIncrementOrDecrementExpression(factory: ts.NodeFactory, node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, expression: ts.Expression, recordTempVariable: (node: ts.Identifier) => void, resultVariable: ts.Identifier | undefined) { +export function expandPreOrPostfixIncrementOrDecrementExpression(factory: NodeFactory, node: PrefixUnaryExpression | PostfixUnaryExpression, expression: Expression, recordTempVariable: (node: Identifier) => void, resultVariable: Identifier | undefined) { const operator = node.operator; - ts.Debug.assert(operator === ts.SyntaxKind.PlusPlusToken || operator === ts.SyntaxKind.MinusMinusToken, "Expected 'node' to be a pre- or post-increment or pre- or post-decrement expression"); + Debug.assert(operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken, "Expected 'node' to be a pre- or post-increment or pre- or post-decrement expression"); const temp = factory.createTempVariable(recordTempVariable); expression = factory.createAssignment(temp, expression); - ts.setTextRange(expression, node.operand); + setTextRange(expression, node.operand); - let operation: ts.Expression = ts.isPrefixUnaryExpression(node) ? + let operation: Expression = isPrefixUnaryExpression(node) ? factory.createPrefixUnaryExpression(operator, temp) : factory.createPostfixUnaryExpression(temp, operator); - ts.setTextRange(operation, node); + setTextRange(operation, node); if (resultVariable) { operation = factory.createAssignment(resultVariable, operation); - ts.setTextRange(operation, node); + setTextRange(operation, node); } expression = factory.createComma(expression, operation); - ts.setTextRange(expression, node); + setTextRange(expression, node); - if (ts.isPostfixUnaryExpression(node)) { + if (isPostfixUnaryExpression(node)) { expression = factory.createComma(expression, temp); - ts.setTextRange(expression, node); + setTextRange(expression, node); } return expression; @@ -378,16 +409,16 @@ export function expandPreOrPostfixIncrementOrDecrementExpression(factory: ts.Nod /** * Gets whether an identifier should only be referred to by its internal name. */ -export function isInternalName(node: ts.Identifier) { - return (ts.getEmitFlags(node) & ts.EmitFlags.InternalName) !== 0; +export function isInternalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.InternalName) !== 0; } /** @internal */ /** * Gets whether an identifier should only be referred to by its local name. */ -export function isLocalName(node: ts.Identifier) { - return (ts.getEmitFlags(node) & ts.EmitFlags.LocalName) !== 0; +export function isLocalName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.LocalName) !== 0; } /** @internal */ @@ -395,18 +426,18 @@ export function isLocalName(node: ts.Identifier) { * Gets whether an identifier should only be referred to by its export representation if the * name points to an exported symbol. */ -export function isExportName(node: ts.Identifier) { - return (ts.getEmitFlags(node) & ts.EmitFlags.ExportName) !== 0; +export function isExportName(node: Identifier) { + return (getEmitFlags(node) & EmitFlags.ExportName) !== 0; } -function isUseStrictPrologue(node: ts.ExpressionStatement): boolean { - return ts.isStringLiteral(node.expression) && node.expression.text === "use strict"; +function isUseStrictPrologue(node: ExpressionStatement): boolean { + return isStringLiteral(node.expression) && node.expression.text === "use strict"; } /** @internal */ -export function findUseStrictPrologue(statements: readonly ts.Statement[]): ts.Statement | undefined { +export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined { for (const statement of statements) { - if (ts.isPrologueDirective(statement)) { + if (isPrologueDirective(statement)) { if (isUseStrictPrologue(statement)) { return statement; } @@ -419,59 +450,59 @@ export function findUseStrictPrologue(statements: readonly ts.Statement[]): ts.S } /** @internal */ -export function startsWithUseStrict(statements: readonly ts.Statement[]) { - const firstStatement = ts.firstOrUndefined(statements); +export function startsWithUseStrict(statements: readonly Statement[]) { + const firstStatement = firstOrUndefined(statements); return firstStatement !== undefined - && ts.isPrologueDirective(firstStatement) + && isPrologueDirective(firstStatement) && isUseStrictPrologue(firstStatement); } /** @internal */ -export function isCommaSequence(node: ts.Expression): node is ts.BinaryExpression & {operatorToken: ts.Token} | ts.CommaListExpression { - return node.kind === ts.SyntaxKind.BinaryExpression && (node as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.CommaToken || - node.kind === ts.SyntaxKind.CommaListExpression; +export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token} | CommaListExpression { + return node.kind === SyntaxKind.BinaryExpression && (node as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken || + node.kind === SyntaxKind.CommaListExpression; } /** @internal */ -export function isJSDocTypeAssertion(node: ts.Node): node is ts.JSDocTypeAssertion { - return ts.isParenthesizedExpression(node) - && ts.isInJSFile(node) - && !!ts.getJSDocTypeTag(node); +export function isJSDocTypeAssertion(node: Node): node is JSDocTypeAssertion { + return isParenthesizedExpression(node) + && isInJSFile(node) + && !!getJSDocTypeTag(node); } /** @internal */ -export function getJSDocTypeAssertionType(node: ts.JSDocTypeAssertion) { - const type = ts.getJSDocType(node); - ts.Debug.assertIsDefined(type); +export function getJSDocTypeAssertionType(node: JSDocTypeAssertion) { + const type = getJSDocType(node); + Debug.assertIsDefined(type); return type; } /** @internal */ -export function isOuterExpression(node: ts.Node, kinds = ts.OuterExpressionKinds.All): node is ts.OuterExpression { +export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression { switch (node.kind) { - case ts.SyntaxKind.ParenthesizedExpression: - if (kinds & ts.OuterExpressionKinds.ExcludeJSDocTypeAssertion && isJSDocTypeAssertion(node)) { + case SyntaxKind.ParenthesizedExpression: + if (kinds & OuterExpressionKinds.ExcludeJSDocTypeAssertion && isJSDocTypeAssertion(node)) { return false; } - return (kinds & ts.OuterExpressionKinds.Parentheses) !== 0; - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.AsExpression: - case ts.SyntaxKind.SatisfiesExpression: - return (kinds & ts.OuterExpressionKinds.TypeAssertions) !== 0; - case ts.SyntaxKind.NonNullExpression: - return (kinds & ts.OuterExpressionKinds.NonNullAssertions) !== 0; - case ts.SyntaxKind.PartiallyEmittedExpression: - return (kinds & ts.OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; + return (kinds & OuterExpressionKinds.Parentheses) !== 0; + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.AsExpression: + case SyntaxKind.SatisfiesExpression: + return (kinds & OuterExpressionKinds.TypeAssertions) !== 0; + case SyntaxKind.NonNullExpression: + return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0; + case SyntaxKind.PartiallyEmittedExpression: + return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; } return false; } /** @internal */ -export function skipOuterExpressions(node: ts.Expression, kinds?: ts.OuterExpressionKinds): ts.Expression; +export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression; /** @internal */ -export function skipOuterExpressions(node: ts.Node, kinds?: ts.OuterExpressionKinds): ts.Node; +export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; /** @internal */ -export function skipOuterExpressions(node: ts.Node, kinds = ts.OuterExpressionKinds.All) { +export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { while (isOuterExpression(node, kinds)) { node = node.expression; } @@ -479,63 +510,63 @@ export function skipOuterExpressions(node: ts.Node, kinds = ts.OuterExpressionKi } /** @internal */ -export function skipAssertions(node: ts.Expression): ts.Expression; +export function skipAssertions(node: Expression): Expression; /** @internal */ -export function skipAssertions(node: ts.Node): ts.Node; +export function skipAssertions(node: Node): Node; /** @internal */ -export function skipAssertions(node: ts.Node): ts.Node { - return skipOuterExpressions(node, ts.OuterExpressionKinds.Assertions); +export function skipAssertions(node: Node): Node { + return skipOuterExpressions(node, OuterExpressionKinds.Assertions); } /** @internal */ -export function startOnNewLine(node: T): T { - return ts.setStartsOnNewLine(node, /*newLine*/ true); +export function startOnNewLine(node: T): T { + return setStartsOnNewLine(node, /*newLine*/ true); } /** @internal */ -export function getExternalHelpersModuleName(node: ts.SourceFile) { - const parseNode = ts.getOriginalNode(node, ts.isSourceFile); +export function getExternalHelpersModuleName(node: SourceFile) { + const parseNode = getOriginalNode(node, isSourceFile); const emitNode = parseNode && parseNode.emitNode; return emitNode && emitNode.externalHelpersModuleName; } /** @internal */ -export function hasRecordedExternalHelpers(sourceFile: ts.SourceFile) { - const parseNode = ts.getOriginalNode(sourceFile, ts.isSourceFile); +export function hasRecordedExternalHelpers(sourceFile: SourceFile) { + const parseNode = getOriginalNode(sourceFile, isSourceFile); const emitNode = parseNode && parseNode.emitNode; return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers); } /** @internal */ -export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: ts.NodeFactory, helperFactory: ts.EmitHelperFactory, sourceFile: ts.SourceFile, compilerOptions: ts.CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { - if (compilerOptions.importHelpers && ts.isEffectiveExternalModule(sourceFile, compilerOptions)) { - let namedBindings: ts.NamedImportBindings | undefined; - const moduleKind = ts.getEmitModuleKind(compilerOptions); - if ((moduleKind >= ts.ModuleKind.ES2015 && moduleKind <= ts.ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ts.ModuleKind.ESNext) { +export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) { + let namedBindings: NamedImportBindings | undefined; + const moduleKind = getEmitModuleKind(compilerOptions); + if ((moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) || sourceFile.impliedNodeFormat === ModuleKind.ESNext) { // use named imports - const helpers = ts.getEmitHelpers(sourceFile); + const helpers = getEmitHelpers(sourceFile); if (helpers) { const helperNames: string[] = []; for (const helper of helpers) { if (!helper.scoped) { const importName = helper.importName; if (importName) { - ts.pushIfUnique(helperNames, importName); + pushIfUnique(helperNames, importName); } } } - if (ts.some(helperNames)) { - helperNames.sort(ts.compareStringsCaseSensitive); + if (some(helperNames)) { + helperNames.sort(compareStringsCaseSensitive); // Alias the imports if the names are used somewhere in the file. // NOTE: We don't need to care about global import collisions as this is a module. namedBindings = nodeFactory.createNamedImports( - ts.map(helperNames, name => ts.isFileLevelUniqueName(sourceFile, name) + map(helperNames, name => isFileLevelUniqueName(sourceFile, name) ? nodeFactory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, nodeFactory.createIdentifier(name)) : nodeFactory.createImportSpecifier(/*isTypeOnly*/ false, nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name)) ) ); - const parseNode = ts.getOriginalNode(sourceFile, ts.isSourceFile); - const emitNode = ts.getOrCreateEmitNode(parseNode); + const parseNode = getOriginalNode(sourceFile, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); emitNode.externalHelpers = true; } } @@ -551,29 +582,29 @@ export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: ts.N const externalHelpersImportDeclaration = nodeFactory.createImportDeclaration( /*modifiers*/ undefined, nodeFactory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, namedBindings), - nodeFactory.createStringLiteral(ts.externalHelpersModuleNameText), + nodeFactory.createStringLiteral(externalHelpersModuleNameText), /*assertClause*/ undefined ); - ts.addEmitFlags(externalHelpersImportDeclaration, ts.EmitFlags.NeverApplyImportHelper); + addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper); return externalHelpersImportDeclaration; } } } /** @internal */ -export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: ts.NodeFactory, node: ts.SourceFile, compilerOptions: ts.CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { - if (compilerOptions.importHelpers && ts.isEffectiveExternalModule(node, compilerOptions)) { +export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) { + if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) { const externalHelpersModuleName = getExternalHelpersModuleName(node); if (externalHelpersModuleName) { return externalHelpersModuleName; } - const moduleKind = ts.getEmitModuleKind(compilerOptions); - let create = (hasExportStarsToExportValues || (ts.getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault)) - && moduleKind !== ts.ModuleKind.System - && (moduleKind < ts.ModuleKind.ES2015 || node.impliedNodeFormat === ts.ModuleKind.CommonJS); + const moduleKind = getEmitModuleKind(compilerOptions); + let create = (hasExportStarsToExportValues || (getESModuleInterop(compilerOptions) && hasImportStarOrImportDefault)) + && moduleKind !== ModuleKind.System + && (moduleKind < ModuleKind.ES2015 || node.impliedNodeFormat === ModuleKind.CommonJS); if (!create) { - const helpers = ts.getEmitHelpers(node); + const helpers = getEmitHelpers(node); if (helpers) { for (const helper of helpers) { if (!helper.scoped) { @@ -585,9 +616,9 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: ts.NodeFac } if (create) { - const parseNode = ts.getOriginalNode(node, ts.isSourceFile); - const emitNode = ts.getOrCreateEmitNode(parseNode); - return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(ts.externalHelpersModuleNameText)); + const parseNode = getOriginalNode(node, isSourceFile); + const emitNode = getOrCreateEmitNode(parseNode); + return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText)); } } } @@ -596,16 +627,16 @@ export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: ts.NodeFac /** * Get the name of that target module from an import or export declaration */ -export function getLocalNameForExternalImport(factory: ts.NodeFactory, node: ts.ImportDeclaration | ts.ExportDeclaration | ts.ImportEqualsDeclaration, sourceFile: ts.SourceFile): ts.Identifier | undefined { - const namespaceDeclaration = ts.getNamespaceDeclarationNode(node); - if (namespaceDeclaration && !ts.isDefaultImport(node) && !ts.isExportNamespaceAsDefaultDeclaration(node)) { +export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined { + const namespaceDeclaration = getNamespaceDeclarationNode(node); + if (namespaceDeclaration && !isDefaultImport(node) && !isExportNamespaceAsDefaultDeclaration(node)) { const name = namespaceDeclaration.name; - return ts.isGeneratedIdentifier(name) ? name : factory.createIdentifier(ts.getSourceTextOfNodeFromSourceFile(sourceFile, name) || ts.idText(name)); + return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name)); } - if (node.kind === ts.SyntaxKind.ImportDeclaration && node.importClause) { + if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) { return factory.getGeneratedNameForNode(node); } - if (node.kind === ts.SyntaxKind.ExportDeclaration && node.moduleSpecifier) { + if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) { return factory.getGeneratedNameForNode(node); } return undefined; @@ -620,9 +651,9 @@ export function getLocalNameForExternalImport(factory: ts.NodeFactory, node: ts. * 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System). * Otherwise, a new StringLiteral node representing the module name will be returned. */ -export function getExternalModuleNameLiteral(factory: ts.NodeFactory, importNode: ts.ImportDeclaration | ts.ExportDeclaration | ts.ImportEqualsDeclaration | ts.ImportCall, sourceFile: ts.SourceFile, host: ts.EmitHost, resolver: ts.EmitResolver, compilerOptions: ts.CompilerOptions) { - const moduleName = ts.getExternalModuleName(importNode); - if (moduleName && ts.isStringLiteral(moduleName)) { +export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration | ImportCall, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) { + const moduleName = getExternalModuleName(importNode); + if (moduleName && isStringLiteral(moduleName)) { return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions) || tryRenameExternalModule(factory, moduleName, sourceFile) || factory.cloneNode(moduleName); @@ -635,7 +666,7 @@ export function getExternalModuleNameLiteral(factory: ts.NodeFactory, importNode * Some bundlers (SystemJS builder) sometimes want to rename dependencies. * Here we check if alternative name was provided for a given moduleName and return it if possible. */ -function tryRenameExternalModule(factory: ts.NodeFactory, moduleName: ts.LiteralExpression, sourceFile: ts.SourceFile) { +function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) { const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text); return rename ? factory.createStringLiteral(rename) : undefined; } @@ -648,20 +679,20 @@ function tryRenameExternalModule(factory: ts.NodeFactory, moduleName: ts.Literal * 2. --out or --outFile is used, making the name relative to the rootDir * Otherwise, a new StringLiteral node representing the module name will be returned. */ -export function tryGetModuleNameFromFile(factory: ts.NodeFactory, file: ts.SourceFile | undefined, host: ts.EmitHost, options: ts.CompilerOptions): ts.StringLiteral | undefined { +export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined { if (!file) { return undefined; } if (file.moduleName) { return factory.createStringLiteral(file.moduleName); } - if (!file.isDeclarationFile && ts.outFile(options)) { - return factory.createStringLiteral(ts.getExternalModuleNameFromPath(host, file.fileName)); + if (!file.isDeclarationFile && outFile(options)) { + return factory.createStringLiteral(getExternalModuleNameFromPath(host, file.fileName)); } return undefined; } -function tryGetModuleNameFromDeclaration(declaration: ts.ImportEqualsDeclaration | ts.ImportDeclaration | ts.ExportDeclaration | ts.ImportCall, host: ts.EmitHost, factory: ts.NodeFactory, resolver: ts.EmitResolver, compilerOptions: ts.CompilerOptions) { +function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ImportCall, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) { return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions); } @@ -669,8 +700,8 @@ function tryGetModuleNameFromDeclaration(declaration: ts.ImportEqualsDeclaration /** * Gets the initializer of an BindingOrAssignmentElement. */ -export function getInitializerOfBindingOrAssignmentElement(bindingElement: ts.BindingOrAssignmentElement): ts.Expression | undefined { - if (ts.isDeclarationBindingElement(bindingElement)) { +export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined { + if (isDeclarationBindingElement(bindingElement)) { // `1` in `let { a = 1 } = ...` // `1` in `let { a: b = 1 } = ...` // `1` in `let { a: {b} = 1 } = ...` @@ -681,31 +712,31 @@ export function getInitializerOfBindingOrAssignmentElement(bindingElement: ts.Bi return bindingElement.initializer; } - if (ts.isPropertyAssignment(bindingElement)) { + if (isPropertyAssignment(bindingElement)) { // `1` in `({ a: b = 1 } = ...)` // `1` in `({ a: {b} = 1 } = ...)` // `1` in `({ a: [b] = 1 } = ...)` const initializer = bindingElement.initializer; - return ts.isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) + return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true) ? initializer.right : undefined; } - if (ts.isShorthandPropertyAssignment(bindingElement)) { + if (isShorthandPropertyAssignment(bindingElement)) { // `1` in `({ a = 1 } = ...)` return bindingElement.objectAssignmentInitializer; } - if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { // `1` in `[a = 1] = ...` // `1` in `[{a} = 1] = ...` // `1` in `[[a] = 1] = ...` return bindingElement.right; } - if (ts.isSpreadElement(bindingElement)) { + if (isSpreadElement(bindingElement)) { // Recovery consistent with existing emit. - return getInitializerOfBindingOrAssignmentElement(bindingElement.expression as ts.BindingOrAssignmentElement); + return getInitializerOfBindingOrAssignmentElement(bindingElement.expression as BindingOrAssignmentElement); } } @@ -713,8 +744,8 @@ export function getInitializerOfBindingOrAssignmentElement(bindingElement: ts.Bi /** * Gets the name of an BindingOrAssignmentElement. */ -export function getTargetOfBindingOrAssignmentElement(bindingElement: ts.BindingOrAssignmentElement): ts.BindingOrAssignmentElementTarget | undefined { - if (ts.isDeclarationBindingElement(bindingElement)) { +export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined { + if (isDeclarationBindingElement(bindingElement)) { // `a` in `let { a } = ...` // `a` in `let { a = 1 } = ...` // `b` in `let { a: b } = ...` @@ -734,9 +765,9 @@ export function getTargetOfBindingOrAssignmentElement(bindingElement: ts.Binding return bindingElement.name; } - if (ts.isObjectLiteralElementLike(bindingElement)) { + if (isObjectLiteralElementLike(bindingElement)) { switch (bindingElement.kind) { - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyAssignment: // `b` in `({ a: b } = ...)` // `b` in `({ a: b = 1 } = ...)` // `{b}` in `({ a: {b} } = ...)` @@ -747,34 +778,34 @@ export function getTargetOfBindingOrAssignmentElement(bindingElement: ts.Binding // `b.c` in `({ a: b.c = 1 } = ...)` // `b[0]` in `({ a: b[0] } = ...)` // `b[0]` in `({ a: b[0] = 1 } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.initializer as ts.BindingOrAssignmentElement); + return getTargetOfBindingOrAssignmentElement(bindingElement.initializer as BindingOrAssignmentElement); - case ts.SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: // `a` in `({ a } = ...)` // `a` in `({ a = 1 } = ...)` return bindingElement.name; - case ts.SyntaxKind.SpreadAssignment: + case SyntaxKind.SpreadAssignment: // `a` in `({ ...a } = ...)` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression as ts.BindingOrAssignmentElement); + return getTargetOfBindingOrAssignmentElement(bindingElement.expression as BindingOrAssignmentElement); } // no target return undefined; } - if (ts.isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { + if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) { // `a` in `[a = 1] = ...` // `{a}` in `[{a} = 1] = ...` // `[a]` in `[[a] = 1] = ...` // `a.b` in `[a.b = 1] = ...` // `a[0]` in `[a[0] = 1] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.left as ts.BindingOrAssignmentElement); + return getTargetOfBindingOrAssignmentElement(bindingElement.left as BindingOrAssignmentElement); } - if (ts.isSpreadElement(bindingElement)) { + if (isSpreadElement(bindingElement)) { // `a` in `[...a] = ...` - return getTargetOfBindingOrAssignmentElement(bindingElement.expression as ts.BindingOrAssignmentElement); + return getTargetOfBindingOrAssignmentElement(bindingElement.expression as BindingOrAssignmentElement); } // `a` in `[a] = ...` @@ -789,15 +820,15 @@ export function getTargetOfBindingOrAssignmentElement(bindingElement: ts.Binding /** * Determines whether an BindingOrAssignmentElement is a rest element. */ -export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: ts.BindingOrAssignmentElement): ts.BindingOrAssignmentElementRestIndicator | undefined { +export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined { switch (bindingElement.kind) { - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.BindingElement: + case SyntaxKind.Parameter: + case SyntaxKind.BindingElement: // `...` in `let [...a] = ...` return bindingElement.dotDotDotToken; - case ts.SyntaxKind.SpreadElement: - case ts.SyntaxKind.SpreadAssignment: + case SyntaxKind.SpreadElement: + case SyntaxKind.SpreadAssignment: // `...` in `[...a] = ...` return bindingElement; } @@ -809,95 +840,95 @@ export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: ts. /** * Gets the property name of a BindingOrAssignmentElement */ -export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: ts.BindingOrAssignmentElement): Exclude | undefined { +export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude | undefined { const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement); - ts.Debug.assert(!!propertyName || ts.isSpreadAssignment(bindingElement), "Invalid property name for binding element."); + Debug.assert(!!propertyName || isSpreadAssignment(bindingElement), "Invalid property name for binding element."); return propertyName; } /** @internal */ -export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: ts.BindingOrAssignmentElement): Exclude | undefined { +export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude | undefined { switch (bindingElement.kind) { - case ts.SyntaxKind.BindingElement: + case SyntaxKind.BindingElement: // `a` in `let { a: b } = ...` // `[a]` in `let { [a]: b } = ...` // `"a"` in `let { "a": b } = ...` // `1` in `let { 1: b } = ...` if (bindingElement.propertyName) { const propertyName = bindingElement.propertyName; - if (ts.isPrivateIdentifier(propertyName)) { - return ts.Debug.failBadSyntaxKind(propertyName); + if (isPrivateIdentifier(propertyName)) { + return Debug.failBadSyntaxKind(propertyName); } - return ts.isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) ? propertyName.expression : propertyName; } break; - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyAssignment: // `a` in `({ a: b } = ...)` // `[a]` in `({ [a]: b } = ...)` // `"a"` in `({ "a": b } = ...)` // `1` in `({ 1: b } = ...)` if (bindingElement.name) { const propertyName = bindingElement.name; - if (ts.isPrivateIdentifier(propertyName)) { - return ts.Debug.failBadSyntaxKind(propertyName); + if (isPrivateIdentifier(propertyName)) { + return Debug.failBadSyntaxKind(propertyName); } - return ts.isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) + return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression) ? propertyName.expression : propertyName; } break; - case ts.SyntaxKind.SpreadAssignment: + case SyntaxKind.SpreadAssignment: // `a` in `({ ...a } = ...)` - if (bindingElement.name && ts.isPrivateIdentifier(bindingElement.name)) { - return ts.Debug.failBadSyntaxKind(bindingElement.name); + if (bindingElement.name && isPrivateIdentifier(bindingElement.name)) { + return Debug.failBadSyntaxKind(bindingElement.name); } return bindingElement.name; } const target = getTargetOfBindingOrAssignmentElement(bindingElement); - if (target && ts.isPropertyName(target)) { + if (target && isPropertyName(target)) { return target; } } -function isStringOrNumericLiteral(node: ts.Node): node is ts.StringLiteral | ts.NumericLiteral { +function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral { const kind = node.kind; - return kind === ts.SyntaxKind.StringLiteral - || kind === ts.SyntaxKind.NumericLiteral; + return kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.NumericLiteral; } /** @internal */ /** * Gets the elements of a BindingOrAssignmentPattern */ -export function getElementsOfBindingOrAssignmentPattern(name: ts.BindingOrAssignmentPattern): readonly ts.BindingOrAssignmentElement[] { +export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] { switch (name.kind) { - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayLiteralExpression: // `a` in `{a}` // `a` in `[a]` - return name.elements as readonly ts.BindingOrAssignmentElement[]; + return name.elements as readonly BindingOrAssignmentElement[]; - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: // `a` in `{a}` - return name.properties as readonly ts.BindingOrAssignmentElement[]; + return name.properties as readonly BindingOrAssignmentElement[]; } } /* @internal */ -export function getJSDocTypeAliasName(fullName: ts.JSDocNamespaceBody | undefined) { +export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) { if (fullName) { let rightNode = fullName; while (true) { - if (ts.isIdentifier(rightNode) || !rightNode.body) { - return ts.isIdentifier(rightNode) ? rightNode : rightNode.name; + if (isIdentifier(rightNode) || !rightNode.body) { + return isIdentifier(rightNode) ? rightNode : rightNode.name; } rightNode = rightNode.body; } @@ -905,177 +936,177 @@ export function getJSDocTypeAliasName(fullName: ts.JSDocNamespaceBody | undefine } /** @internal */ -export function canHaveIllegalType(node: ts.Node): node is ts.HasIllegalType { +export function canHaveIllegalType(node: Node): node is HasIllegalType { const kind = node.kind; - return kind === ts.SyntaxKind.Constructor - || kind === ts.SyntaxKind.SetAccessor; + return kind === SyntaxKind.Constructor + || kind === SyntaxKind.SetAccessor; } /** @internal */ -export function canHaveIllegalTypeParameters(node: ts.Node): node is ts.HasIllegalTypeParameters { +export function canHaveIllegalTypeParameters(node: Node): node is HasIllegalTypeParameters { const kind = node.kind; - return kind === ts.SyntaxKind.Constructor - || kind === ts.SyntaxKind.GetAccessor - || kind === ts.SyntaxKind.SetAccessor; + return kind === SyntaxKind.Constructor + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor; } /** @internal */ -export function canHaveIllegalDecorators(node: ts.Node): node is ts.HasIllegalDecorators { +export function canHaveIllegalDecorators(node: Node): node is HasIllegalDecorators { const kind = node.kind; - return kind === ts.SyntaxKind.PropertyAssignment - || kind === ts.SyntaxKind.ShorthandPropertyAssignment - || kind === ts.SyntaxKind.FunctionDeclaration - || kind === ts.SyntaxKind.Constructor - || kind === ts.SyntaxKind.IndexSignature - || kind === ts.SyntaxKind.ClassStaticBlockDeclaration - || kind === ts.SyntaxKind.MissingDeclaration - || kind === ts.SyntaxKind.VariableStatement - || kind === ts.SyntaxKind.InterfaceDeclaration - || kind === ts.SyntaxKind.TypeAliasDeclaration - || kind === ts.SyntaxKind.EnumDeclaration - || kind === ts.SyntaxKind.ModuleDeclaration - || kind === ts.SyntaxKind.ImportEqualsDeclaration - || kind === ts.SyntaxKind.ImportDeclaration - || kind === ts.SyntaxKind.NamespaceExportDeclaration - || kind === ts.SyntaxKind.ExportDeclaration - || kind === ts.SyntaxKind.ExportAssignment; -} - -/** @internal */ -export function canHaveIllegalModifiers(node: ts.Node): node is ts.HasIllegalModifiers { + return kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.FunctionDeclaration + || kind === SyntaxKind.Constructor + || kind === SyntaxKind.IndexSignature + || kind === SyntaxKind.ClassStaticBlockDeclaration + || kind === SyntaxKind.MissingDeclaration + || kind === SyntaxKind.VariableStatement + || kind === SyntaxKind.InterfaceDeclaration + || kind === SyntaxKind.TypeAliasDeclaration + || kind === SyntaxKind.EnumDeclaration + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.ImportEqualsDeclaration + || kind === SyntaxKind.ImportDeclaration + || kind === SyntaxKind.NamespaceExportDeclaration + || kind === SyntaxKind.ExportDeclaration + || kind === SyntaxKind.ExportAssignment; +} + +/** @internal */ +export function canHaveIllegalModifiers(node: Node): node is HasIllegalModifiers { const kind = node.kind; - return kind === ts.SyntaxKind.ClassStaticBlockDeclaration - || kind === ts.SyntaxKind.PropertyAssignment - || kind === ts.SyntaxKind.ShorthandPropertyAssignment - || kind === ts.SyntaxKind.FunctionType - || kind === ts.SyntaxKind.MissingDeclaration - || kind === ts.SyntaxKind.NamespaceExportDeclaration; + return kind === SyntaxKind.ClassStaticBlockDeclaration + || kind === SyntaxKind.PropertyAssignment + || kind === SyntaxKind.ShorthandPropertyAssignment + || kind === SyntaxKind.FunctionType + || kind === SyntaxKind.MissingDeclaration + || kind === SyntaxKind.NamespaceExportDeclaration; } /** @internal */ -export const isTypeNodeOrTypeParameterDeclaration = ts.or(ts.isTypeNode, ts.isTypeParameterDeclaration) as (node: ts.Node) => node is ts.TypeNode | ts.TypeParameterDeclaration; +export const isTypeNodeOrTypeParameterDeclaration = or(isTypeNode, isTypeParameterDeclaration) as (node: Node) => node is TypeNode | TypeParameterDeclaration; /** @internal */ -export const isQuestionOrExclamationToken = ts.or(ts.isQuestionToken, ts.isExclamationToken) as (node: ts.Node) => node is ts.QuestionToken | ts.ExclamationToken; +export const isQuestionOrExclamationToken = or(isQuestionToken, isExclamationToken) as (node: Node) => node is QuestionToken | ExclamationToken; /** @internal */ -export const isIdentifierOrThisTypeNode = ts.or(ts.isIdentifier, ts.isThisTypeNode) as (node: ts.Node) => node is ts.Identifier | ts.ThisTypeNode; +export const isIdentifierOrThisTypeNode = or(isIdentifier, isThisTypeNode) as (node: Node) => node is Identifier | ThisTypeNode; /** @internal */ -export const isReadonlyKeywordOrPlusOrMinusToken = ts.or(ts.isReadonlyKeyword, ts.isPlusToken, ts.isMinusToken) as (node: ts.Node) => node is ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken; +export const isReadonlyKeywordOrPlusOrMinusToken = or(isReadonlyKeyword, isPlusToken, isMinusToken) as (node: Node) => node is ReadonlyKeyword | PlusToken | MinusToken; /** @internal */ -export const isQuestionOrPlusOrMinusToken = ts.or(ts.isQuestionToken, ts.isPlusToken, ts.isMinusToken) as (node: ts.Node) => node is ts.QuestionToken | ts.PlusToken | ts.MinusToken; +export const isQuestionOrPlusOrMinusToken = or(isQuestionToken, isPlusToken, isMinusToken) as (node: Node) => node is QuestionToken | PlusToken | MinusToken; /** @internal */ -export const isModuleName = ts.or(ts.isIdentifier, ts.isStringLiteral) as (node: ts.Node) => node is ts.ModuleName; +export const isModuleName = or(isIdentifier, isStringLiteral) as (node: Node) => node is ModuleName; /** @internal */ -export function isLiteralTypeLikeExpression(node: ts.Node): node is ts.NullLiteral | ts.BooleanLiteral | ts.LiteralExpression | ts.PrefixUnaryExpression { +export function isLiteralTypeLikeExpression(node: Node): node is NullLiteral | BooleanLiteral | LiteralExpression | PrefixUnaryExpression { const kind = node.kind; - return kind === ts.SyntaxKind.NullKeyword - || kind === ts.SyntaxKind.TrueKeyword - || kind === ts.SyntaxKind.FalseKeyword - || ts.isLiteralExpression(node) - || ts.isPrefixUnaryExpression(node); + return kind === SyntaxKind.NullKeyword + || kind === SyntaxKind.TrueKeyword + || kind === SyntaxKind.FalseKeyword + || isLiteralExpression(node) + || isPrefixUnaryExpression(node); } -function isExponentiationOperator(kind: ts.SyntaxKind): kind is ts.ExponentiationOperator { - return kind === ts.SyntaxKind.AsteriskAsteriskToken; +function isExponentiationOperator(kind: SyntaxKind): kind is ExponentiationOperator { + return kind === SyntaxKind.AsteriskAsteriskToken; } -function isMultiplicativeOperator(kind: ts.SyntaxKind): kind is ts.MultiplicativeOperator { - return kind === ts.SyntaxKind.AsteriskToken - || kind === ts.SyntaxKind.SlashToken - || kind === ts.SyntaxKind.PercentToken; +function isMultiplicativeOperator(kind: SyntaxKind): kind is MultiplicativeOperator { + return kind === SyntaxKind.AsteriskToken + || kind === SyntaxKind.SlashToken + || kind === SyntaxKind.PercentToken; } -function isMultiplicativeOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.MultiplicativeOperatorOrHigher { +function isMultiplicativeOperatorOrHigher(kind: SyntaxKind): kind is MultiplicativeOperatorOrHigher { return isExponentiationOperator(kind) || isMultiplicativeOperator(kind); } -function isAdditiveOperator(kind: ts.SyntaxKind): kind is ts.AdditiveOperator { - return kind === ts.SyntaxKind.PlusToken - || kind === ts.SyntaxKind.MinusToken; +function isAdditiveOperator(kind: SyntaxKind): kind is AdditiveOperator { + return kind === SyntaxKind.PlusToken + || kind === SyntaxKind.MinusToken; } -function isAdditiveOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.AdditiveOperatorOrHigher { +function isAdditiveOperatorOrHigher(kind: SyntaxKind): kind is AdditiveOperatorOrHigher { return isAdditiveOperator(kind) || isMultiplicativeOperatorOrHigher(kind); } -function isShiftOperator(kind: ts.SyntaxKind): kind is ts.ShiftOperator { - return kind === ts.SyntaxKind.LessThanLessThanToken - || kind === ts.SyntaxKind.GreaterThanGreaterThanToken - || kind === ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken; +function isShiftOperator(kind: SyntaxKind): kind is ShiftOperator { + return kind === SyntaxKind.LessThanLessThanToken + || kind === SyntaxKind.GreaterThanGreaterThanToken + || kind === SyntaxKind.GreaterThanGreaterThanGreaterThanToken; } -function isShiftOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.ShiftOperatorOrHigher { +function isShiftOperatorOrHigher(kind: SyntaxKind): kind is ShiftOperatorOrHigher { return isShiftOperator(kind) || isAdditiveOperatorOrHigher(kind); } -function isRelationalOperator(kind: ts.SyntaxKind): kind is ts.RelationalOperator { - return kind === ts.SyntaxKind.LessThanToken - || kind === ts.SyntaxKind.LessThanEqualsToken - || kind === ts.SyntaxKind.GreaterThanToken - || kind === ts.SyntaxKind.GreaterThanEqualsToken - || kind === ts.SyntaxKind.InstanceOfKeyword - || kind === ts.SyntaxKind.InKeyword; +function isRelationalOperator(kind: SyntaxKind): kind is RelationalOperator { + return kind === SyntaxKind.LessThanToken + || kind === SyntaxKind.LessThanEqualsToken + || kind === SyntaxKind.GreaterThanToken + || kind === SyntaxKind.GreaterThanEqualsToken + || kind === SyntaxKind.InstanceOfKeyword + || kind === SyntaxKind.InKeyword; } -function isRelationalOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.RelationalOperatorOrHigher { +function isRelationalOperatorOrHigher(kind: SyntaxKind): kind is RelationalOperatorOrHigher { return isRelationalOperator(kind) || isShiftOperatorOrHigher(kind); } -function isEqualityOperator(kind: ts.SyntaxKind): kind is ts.EqualityOperator { - return kind === ts.SyntaxKind.EqualsEqualsToken - || kind === ts.SyntaxKind.EqualsEqualsEqualsToken - || kind === ts.SyntaxKind.ExclamationEqualsToken - || kind === ts.SyntaxKind.ExclamationEqualsEqualsToken; +function isEqualityOperator(kind: SyntaxKind): kind is EqualityOperator { + return kind === SyntaxKind.EqualsEqualsToken + || kind === SyntaxKind.EqualsEqualsEqualsToken + || kind === SyntaxKind.ExclamationEqualsToken + || kind === SyntaxKind.ExclamationEqualsEqualsToken; } -function isEqualityOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.EqualityOperatorOrHigher { +function isEqualityOperatorOrHigher(kind: SyntaxKind): kind is EqualityOperatorOrHigher { return isEqualityOperator(kind) || isRelationalOperatorOrHigher(kind); } -function isBitwiseOperator(kind: ts.SyntaxKind): kind is ts.BitwiseOperator { - return kind === ts.SyntaxKind.AmpersandToken - || kind === ts.SyntaxKind.BarToken - || kind === ts.SyntaxKind.CaretToken; +function isBitwiseOperator(kind: SyntaxKind): kind is BitwiseOperator { + return kind === SyntaxKind.AmpersandToken + || kind === SyntaxKind.BarToken + || kind === SyntaxKind.CaretToken; } -function isBitwiseOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.BitwiseOperatorOrHigher { +function isBitwiseOperatorOrHigher(kind: SyntaxKind): kind is BitwiseOperatorOrHigher { return isBitwiseOperator(kind) || isEqualityOperatorOrHigher(kind); } // NOTE: The version in utilities includes ExclamationToken, which is not a binary operator. -function isLogicalOperator(kind: ts.SyntaxKind): kind is ts.LogicalOperator { - return kind === ts.SyntaxKind.AmpersandAmpersandToken - || kind === ts.SyntaxKind.BarBarToken; +function isLogicalOperator(kind: SyntaxKind): kind is LogicalOperator { + return kind === SyntaxKind.AmpersandAmpersandToken + || kind === SyntaxKind.BarBarToken; } -function isLogicalOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.LogicalOperatorOrHigher { +function isLogicalOperatorOrHigher(kind: SyntaxKind): kind is LogicalOperatorOrHigher { return isLogicalOperator(kind) || isBitwiseOperatorOrHigher(kind); } -function isAssignmentOperatorOrHigher(kind: ts.SyntaxKind): kind is ts.AssignmentOperatorOrHigher { - return kind === ts.SyntaxKind.QuestionQuestionToken +function isAssignmentOperatorOrHigher(kind: SyntaxKind): kind is AssignmentOperatorOrHigher { + return kind === SyntaxKind.QuestionQuestionToken || isLogicalOperatorOrHigher(kind) - || ts.isAssignmentOperator(kind); + || isAssignmentOperator(kind); } -function isBinaryOperator(kind: ts.SyntaxKind): kind is ts.BinaryOperator { +function isBinaryOperator(kind: SyntaxKind): kind is BinaryOperator { return isAssignmentOperatorOrHigher(kind) - || kind === ts.SyntaxKind.CommaToken; + || kind === SyntaxKind.CommaToken; } /** @internal */ -export function isBinaryOperatorToken(node: ts.Node): node is ts.BinaryOperatorToken { +export function isBinaryOperatorToken(node: Node): node is BinaryOperatorToken { return isBinaryOperator(node.kind); } -type BinaryExpressionState = (machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }, outerState: TOuterState) => number; +type BinaryExpressionState = (machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }, outerState: TOuterState) => number; namespace BinaryExpressionState { /** @@ -1084,9 +1115,9 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function enter(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, outerState: TOuterState): number { + export function enter(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, outerState: TOuterState): number { const prevUserState = stackIndex > 0 ? userStateStack[stackIndex - 1] : undefined; - ts.Debug.assertEqual(stateStack[stackIndex], enter); + Debug.assertEqual(stateStack[stackIndex], enter); userStateStack[stackIndex] = machine.onEnter(nodeStack[stackIndex], prevUserState, outerState); stateStack[stackIndex] = nextState(machine, enter); return stackIndex; @@ -1098,9 +1129,9 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function left(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { - ts.Debug.assertEqual(stateStack[stackIndex], left); - ts.Debug.assertIsDefined(machine.onLeft); + export function left(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { + Debug.assertEqual(stateStack[stackIndex], left); + Debug.assertIsDefined(machine.onLeft); stateStack[stackIndex] = nextState(machine, left); const nextNode = machine.onLeft(nodeStack[stackIndex].left, userStateStack[stackIndex], nodeStack[stackIndex]); if (nextNode) { @@ -1116,9 +1147,9 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function operator(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { - ts.Debug.assertEqual(stateStack[stackIndex], operator); - ts.Debug.assertIsDefined(machine.onOperator); + export function operator(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { + Debug.assertEqual(stateStack[stackIndex], operator); + Debug.assertIsDefined(machine.onOperator); stateStack[stackIndex] = nextState(machine, operator); machine.onOperator(nodeStack[stackIndex].operatorToken, userStateStack[stackIndex], nodeStack[stackIndex]); return stackIndex; @@ -1130,9 +1161,9 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function right(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { - ts.Debug.assertEqual(stateStack[stackIndex], right); - ts.Debug.assertIsDefined(machine.onRight); + export function right(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { + Debug.assertEqual(stateStack[stackIndex], right); + Debug.assertIsDefined(machine.onRight); stateStack[stackIndex] = nextState(machine, right); const nextNode = machine.onRight(nodeStack[stackIndex].right, userStateStack[stackIndex], nodeStack[stackIndex]); if (nextNode) { @@ -1148,8 +1179,8 @@ namespace BinaryExpressionState { * @param frame The current frame * @returns The new frame */ - export function exit(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }, _outerState: TOuterState): number { - ts.Debug.assertEqual(stateStack[stackIndex], exit); + export function exit(machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], resultHolder: { value: TResult }, _outerState: TOuterState): number { + Debug.assertEqual(stateStack[stackIndex], exit); stateStack[stackIndex] = nextState(machine, exit); const result = machine.onExit(nodeStack[stackIndex], userStateStack[stackIndex]); if (stackIndex > 0) { @@ -1169,8 +1200,8 @@ namespace BinaryExpressionState { * Handles a frame that is already done. * @returns The `done` state. */ - export function done(_machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], _nodeStack: ts.BinaryExpression[], _userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { - ts.Debug.assertEqual(stateStack[stackIndex], done); + export function done(_machine: BinaryExpressionStateMachine, stackIndex: number, stateStack: BinaryExpressionState[], _nodeStack: BinaryExpression[], _userStateStack: TState[], _resultHolder: { value: TResult }, _outerState: TOuterState): number { + Debug.assertEqual(stateStack[stackIndex], done); return stackIndex; } @@ -1188,11 +1219,11 @@ namespace BinaryExpressionState { case right: return exit; case exit: return done; case done: return done; - default: ts.Debug.fail("Invalid state"); + default: Debug.fail("Invalid state"); } } - function pushStack(stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: ts.BinaryExpression[], userStateStack: TState[], node: ts.BinaryExpression) { + function pushStack(stackIndex: number, stateStack: BinaryExpressionState[], nodeStack: BinaryExpression[], userStateStack: TState[], node: BinaryExpression) { stackIndex++; stateStack[stackIndex] = enter; nodeStack[stackIndex] = node; @@ -1200,10 +1231,10 @@ namespace BinaryExpressionState { return stackIndex; } - function checkCircularity(stackIndex: number, nodeStack: ts.BinaryExpression[], node: ts.BinaryExpression) { - if (ts.Debug.shouldAssert(ts.AssertionLevel.Aggressive)) { + function checkCircularity(stackIndex: number, nodeStack: BinaryExpression[], node: BinaryExpression) { + if (Debug.shouldAssert(AssertionLevel.Aggressive)) { while (stackIndex >= 0) { - ts.Debug.assert(nodeStack[stackIndex] !== node, "Circular traversal detected."); + Debug.assert(nodeStack[stackIndex] !== node, "Circular traversal detected."); stackIndex--; } } @@ -1215,11 +1246,11 @@ namespace BinaryExpressionState { */ class BinaryExpressionStateMachine { constructor( - readonly onEnter: (node: ts.BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, - readonly onLeft: ((left: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - readonly onOperator: ((operatorToken: ts.BinaryOperatorToken, userState: TState, node: ts.BinaryExpression) => void) | undefined, - readonly onRight: ((right: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - readonly onExit: (node: ts.BinaryExpression, userState: TState) => TResult, + readonly onEnter: (node: BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, + readonly onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + readonly onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined, + readonly onRight: ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + readonly onExit: (node: BinaryExpression, userState: TState) => TResult, readonly foldState: ((userState: TState, result: TResult, side: "left" | "right") => TState) | undefined, ) { } @@ -1236,13 +1267,13 @@ class BinaryExpressionStateMachine { * @returns A function that walks a `BinaryExpression` node using the above callbacks, returning the result of the call to `onExit` from the outermost `BinaryExpression` node. */ export function createBinaryExpressionTrampoline( - onEnter: (node: ts.BinaryExpression, prev: TState | undefined) => TState, - onLeft: ((left: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onOperator: ((operatorToken: ts.BinaryOperatorToken, userState: TState, node: ts.BinaryExpression) => void) | undefined, - onRight: ((right: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onExit: (node: ts.BinaryExpression, userState: TState) => TResult, + onEnter: (node: BinaryExpression, prev: TState | undefined) => TState, + onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined, + onRight: ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onExit: (node: BinaryExpression, userState: TState) => TResult, foldState: ((userState: TState, result: TResult, side: "left" | "right") => TState) | undefined, -): (node: ts.BinaryExpression) => TResult; +): (node: BinaryExpression) => TResult; /** @internal */ /** * Creates a state machine that walks a `BinaryExpression` using the heap to reduce call-stack depth on a large tree. @@ -1254,35 +1285,35 @@ class BinaryExpressionStateMachine { * @returns A function that walks a `BinaryExpression` node using the above callbacks, returning the result of the call to `onExit` from the outermost `BinaryExpression` node. */ export function createBinaryExpressionTrampoline( - onEnter: (node: ts.BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, - onLeft: ((left: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onOperator: ((operatorToken: ts.BinaryOperatorToken, userState: TState, node: ts.BinaryExpression) => void) | undefined, - onRight: ((right: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onExit: (node: ts.BinaryExpression, userState: TState) => TResult, + onEnter: (node: BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, + onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined, + onRight: ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onExit: (node: BinaryExpression, userState: TState) => TResult, foldState: ((userState: TState, result: TResult, side: "left" | "right") => TState) | undefined, -): (node: ts.BinaryExpression, outerState: TOuterState) => TResult; +): (node: BinaryExpression, outerState: TOuterState) => TResult; /** @internal */ export function createBinaryExpressionTrampoline( - onEnter: (node: ts.BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, - onLeft: ((left: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onOperator: ((operatorToken: ts.BinaryOperatorToken, userState: TState, node: ts.BinaryExpression) => void) | undefined, - onRight: ((right: ts.Expression, userState: TState, node: ts.BinaryExpression) => ts.BinaryExpression | void) | undefined, - onExit: (node: ts.BinaryExpression, userState: TState) => TResult, + onEnter: (node: BinaryExpression, prev: TState | undefined, outerState: TOuterState) => TState, + onLeft: ((left: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onOperator: ((operatorToken: BinaryOperatorToken, userState: TState, node: BinaryExpression) => void) | undefined, + onRight: ((right: Expression, userState: TState, node: BinaryExpression) => BinaryExpression | void) | undefined, + onExit: (node: BinaryExpression, userState: TState) => TResult, foldState: ((userState: TState, result: TResult, side: "left" | "right") => TState) | undefined, ) { const machine = new BinaryExpressionStateMachine(onEnter, onLeft, onOperator, onRight, onExit, foldState); return trampoline; - function trampoline(node: ts.BinaryExpression, outerState?: TOuterState) { + function trampoline(node: BinaryExpression, outerState?: TOuterState) { const resultHolder: { value: TResult } = { value: undefined! }; const stateStack: BinaryExpressionState[] = [BinaryExpressionState.enter]; - const nodeStack: ts.BinaryExpression[] = [node]; + const nodeStack: BinaryExpression[] = [node]; const userStateStack: TState[] = [undefined!]; let stackIndex = 0; while (stateStack[stackIndex] !== BinaryExpressionState.done) { stackIndex = stateStack[stackIndex](machine, stackIndex, stateStack, nodeStack, userStateStack, resultHolder, outerState); } - ts.Debug.assertEqual(stackIndex, 0); + Debug.assertEqual(stackIndex, 0); return resultHolder.value; } } @@ -1291,31 +1322,31 @@ export function createBinaryExpressionTrampoline( * If `nodes` is not undefined, creates an empty `NodeArray` that preserves the `pos` and `end` of `nodes`. * @internal */ -export function elideNodes(factory: ts.NodeFactory, nodes: ts.NodeArray): ts.NodeArray; +export function elideNodes(factory: NodeFactory, nodes: NodeArray): NodeArray; /** @internal */ -export function elideNodes(factory: ts.NodeFactory, nodes: ts.NodeArray | undefined): ts.NodeArray | undefined; +export function elideNodes(factory: NodeFactory, nodes: NodeArray | undefined): NodeArray | undefined; /** @internal */ -export function elideNodes(factory: ts.NodeFactory, nodes: ts.NodeArray | undefined): ts.NodeArray | undefined { +export function elideNodes(factory: NodeFactory, nodes: NodeArray | undefined): NodeArray | undefined { if (nodes === undefined) return undefined; if (nodes.length === 0) return nodes; - return ts.setTextRange(factory.createNodeArray([], nodes.hasTrailingComma), nodes); + return setTextRange(factory.createNodeArray([], nodes.hasTrailingComma), nodes); } /** @internal */ /** * Gets the node from which a name should be generated. */ -export function getNodeForGeneratedName(name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) { - if (name.autoGenerateFlags & ts.GeneratedIdentifierFlags.Node) { +export function getNodeForGeneratedName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { + if (name.autoGenerateFlags & GeneratedIdentifierFlags.Node) { const autoGenerateId = name.autoGenerateId; - let node = name as ts.Node; + let node = name as Node; let original = node.original; while (original) { node = original; // if "node" is a different generated name (having a different "autoGenerateId"), use it and stop traversing. - if (ts.isMemberName(node) - && !!(node.autoGenerateFlags! & ts.GeneratedIdentifierFlags.Node) + if (isMemberName(node) + && !!(node.autoGenerateFlags! & GeneratedIdentifierFlags.Node) && node.autoGenerateId !== autoGenerateId) { break; } @@ -1337,24 +1368,24 @@ export function formatGeneratedNamePart(part: string | undefined): string; /** * Formats a prefix or suffix of a generated name. If the part is a {@link GeneratedNamePart}, calls {@link generateName} to format the source node. */ -export function formatGeneratedNamePart(part: string | ts.GeneratedNamePart | undefined, generateName: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string): string; +export function formatGeneratedNamePart(part: string | GeneratedNamePart | undefined, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string; /** @internal */ -export function formatGeneratedNamePart(part: string | ts.GeneratedNamePart | undefined, generateName?: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string): string { +export function formatGeneratedNamePart(part: string | GeneratedNamePart | undefined, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string { return typeof part === "object" ? formatGeneratedName(/*privateName*/ false, part.prefix, part.node, part.suffix, generateName!) : - typeof part === "string" ? part.length > 0 && part.charCodeAt(0) === ts.CharacterCodes.hash ? part.slice(1) : part : + typeof part === "string" ? part.length > 0 && part.charCodeAt(0) === CharacterCodes.hash ? part.slice(1) : part : ""; } -function formatIdentifier(name: string | ts.Identifier | ts.PrivateIdentifier, generateName?: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string) { +function formatIdentifier(name: string | Identifier | PrivateIdentifier, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { return typeof name === "string" ? name : - formatIdentifierWorker(name, ts.Debug.checkDefined(generateName)); + formatIdentifierWorker(name, Debug.checkDefined(generateName)); } -function formatIdentifierWorker(node: ts.Identifier | ts.PrivateIdentifier, generateName: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string) { - return ts.isGeneratedPrivateIdentifier(node) ? generateName(node).slice(1) : - ts.isGeneratedIdentifier(node) ? generateName(node) : - ts.isPrivateIdentifier(node) ? (node.escapedText as string).slice(1) : - ts.idText(node); +function formatIdentifierWorker(node: Identifier | PrivateIdentifier, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { + return isGeneratedPrivateIdentifier(node) ? generateName(node).slice(1) : + isGeneratedIdentifier(node) ? generateName(node) : + isPrivateIdentifier(node) ? (node.escapedText as string).slice(1) : + idText(node); } /** @internal */ @@ -1375,9 +1406,9 @@ export function formatGeneratedName(privateName: boolean, prefix: string | undef * @param suffix The suffix (if any) to include after the base name. * @param generateName Called to format the source node of {@link prefix} when it is a {@link GeneratedNamePart}. */ -export function formatGeneratedName(privateName: boolean, prefix: string | ts.GeneratedNamePart | undefined, baseName: string | ts.Identifier | ts.PrivateIdentifier, suffix: string | ts.GeneratedNamePart | undefined, generateName: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string): string; +export function formatGeneratedName(privateName: boolean, prefix: string | GeneratedNamePart | undefined, baseName: string | Identifier | PrivateIdentifier, suffix: string | GeneratedNamePart | undefined, generateName: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string): string; /** @internal */ -export function formatGeneratedName(privateName: boolean, prefix: string | ts.GeneratedNamePart | undefined, baseName: string | ts.Identifier | ts.PrivateIdentifier, suffix: string | ts.GeneratedNamePart | undefined, generateName?: (name: ts.GeneratedIdentifier | ts.GeneratedPrivateIdentifier) => string) { +export function formatGeneratedName(privateName: boolean, prefix: string | GeneratedNamePart | undefined, baseName: string | Identifier | PrivateIdentifier, suffix: string | GeneratedNamePart | undefined, generateName?: (name: GeneratedIdentifier | GeneratedPrivateIdentifier) => string) { prefix = formatGeneratedNamePart(prefix, generateName!); suffix = formatGeneratedNamePart(suffix, generateName!); baseName = formatIdentifier(baseName, generateName); @@ -1389,7 +1420,7 @@ export function formatGeneratedName(privateName: boolean, prefix: string | ts.Ge /** * Creates a private backing field for an `accessor` {@link PropertyDeclaration}. */ -export function createAccessorPropertyBackingField(factory: ts.NodeFactory, node: ts.PropertyDeclaration, modifiers: ts.ModifiersArray | undefined, initializer: ts.Expression | undefined) { +export function createAccessorPropertyBackingField(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, initializer: Expression | undefined) { return factory.updatePropertyDeclaration( node, modifiers, @@ -1404,7 +1435,7 @@ export function createAccessorPropertyBackingField(factory: ts.NodeFactory, node /** * Creates a {@link GetAccessorDeclaration} that reads from a private backing field. */ -export function createAccessorPropertyGetRedirector(factory: ts.NodeFactory, node: ts.PropertyDeclaration, modifiers: ts.ModifiersArray | undefined, name: ts.PropertyName) { +export function createAccessorPropertyGetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName) { return factory.createGetAccessorDeclaration( modifiers, name, @@ -1425,7 +1456,7 @@ export function createAccessorPropertyGetRedirector(factory: ts.NodeFactory, nod /** * Creates a {@link SetAccessorDeclaration} that writes to a private backing field. */ -export function createAccessorPropertySetRedirector(factory: ts.NodeFactory, node: ts.PropertyDeclaration, modifiers: ts.ModifiersArray | undefined, name: ts.PropertyName) { +export function createAccessorPropertySetRedirector(factory: NodeFactory, node: PropertyDeclaration, modifiers: ModifiersArray | undefined, name: PropertyName) { return factory.createSetAccessorDeclaration( modifiers, name, diff --git a/src/compiler/factory/utilitiesPublic.ts b/src/compiler/factory/utilitiesPublic.ts index 04668f4fa3896..d679f8f34b649 100644 --- a/src/compiler/factory/utilitiesPublic.ts +++ b/src/compiler/factory/utilitiesPublic.ts @@ -1,45 +1,45 @@ -import * as ts from "../_namespaces/ts"; +import { HasDecorators, HasModifiers, Node, setTextRangePosEnd, SyntaxKind, TextRange } from "../_namespaces/ts"; -export function setTextRange(range: T, location: ts.TextRange | undefined): T { - return location ? ts.setTextRangePosEnd(range, location.pos, location.end) : range; +export function setTextRange(range: T, location: TextRange | undefined): T { + return location ? setTextRangePosEnd(range, location.pos, location.end) : range; } -export function canHaveModifiers(node: ts.Node): node is ts.HasModifiers { +export function canHaveModifiers(node: Node): node is HasModifiers { const kind = node.kind; - return kind === ts.SyntaxKind.TypeParameter - || kind === ts.SyntaxKind.Parameter - || kind === ts.SyntaxKind.PropertySignature - || kind === ts.SyntaxKind.PropertyDeclaration - || kind === ts.SyntaxKind.MethodSignature - || kind === ts.SyntaxKind.MethodDeclaration - || kind === ts.SyntaxKind.Constructor - || kind === ts.SyntaxKind.GetAccessor - || kind === ts.SyntaxKind.SetAccessor - || kind === ts.SyntaxKind.IndexSignature - || kind === ts.SyntaxKind.ConstructorType - || kind === ts.SyntaxKind.FunctionExpression - || kind === ts.SyntaxKind.ArrowFunction - || kind === ts.SyntaxKind.ClassExpression - || kind === ts.SyntaxKind.VariableStatement - || kind === ts.SyntaxKind.FunctionDeclaration - || kind === ts.SyntaxKind.ClassDeclaration - || kind === ts.SyntaxKind.InterfaceDeclaration - || kind === ts.SyntaxKind.TypeAliasDeclaration - || kind === ts.SyntaxKind.EnumDeclaration - || kind === ts.SyntaxKind.ModuleDeclaration - || kind === ts.SyntaxKind.ImportEqualsDeclaration - || kind === ts.SyntaxKind.ImportDeclaration - || kind === ts.SyntaxKind.ExportAssignment - || kind === ts.SyntaxKind.ExportDeclaration; + return kind === SyntaxKind.TypeParameter + || kind === SyntaxKind.Parameter + || kind === SyntaxKind.PropertySignature + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.MethodSignature + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.Constructor + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.IndexSignature + || kind === SyntaxKind.ConstructorType + || kind === SyntaxKind.FunctionExpression + || kind === SyntaxKind.ArrowFunction + || kind === SyntaxKind.ClassExpression + || kind === SyntaxKind.VariableStatement + || kind === SyntaxKind.FunctionDeclaration + || kind === SyntaxKind.ClassDeclaration + || kind === SyntaxKind.InterfaceDeclaration + || kind === SyntaxKind.TypeAliasDeclaration + || kind === SyntaxKind.EnumDeclaration + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.ImportEqualsDeclaration + || kind === SyntaxKind.ImportDeclaration + || kind === SyntaxKind.ExportAssignment + || kind === SyntaxKind.ExportDeclaration; } -export function canHaveDecorators(node: ts.Node): node is ts.HasDecorators { +export function canHaveDecorators(node: Node): node is HasDecorators { const kind = node.kind; - return kind === ts.SyntaxKind.Parameter - || kind === ts.SyntaxKind.PropertyDeclaration - || kind === ts.SyntaxKind.MethodDeclaration - || kind === ts.SyntaxKind.GetAccessor - || kind === ts.SyntaxKind.SetAccessor - || kind === ts.SyntaxKind.ClassExpression - || kind === ts.SyntaxKind.ClassDeclaration; + return kind === SyntaxKind.Parameter + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor + || kind === SyntaxKind.ClassExpression + || kind === SyntaxKind.ClassDeclaration; } \ No newline at end of file diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 9dad82ae4315f..5d71e9490452a 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1,24 +1,43 @@ -import * as ts from "./_namespaces/ts"; +import { + append, appendIfUnique, arrayFrom, changeAnyExtension, CharacterCodes, combinePaths, comparePaths, Comparison, + CompilerOptions, contains, containsPath, createCompilerDiagnostic, Debug, Diagnostic, DiagnosticMessage, + DiagnosticReporter, Diagnostics, directoryProbablyExists, directorySeparator, emptyArray, endsWith, + ensureTrailingDirectorySeparator, ESMap, every, Extension, extensionIsTS, fileExtensionIs, fileExtensionIsOneOf, + FileReference, filter, firstDefined, forEach, forEachAncestorDirectory, formatMessage, getBaseFileName, + GetCanonicalFileName, getCommonSourceDirectory, getDirectoryPath, GetEffectiveTypeRootsHost, getEmitModuleKind, + getEmitModuleResolutionKind, getModeForResolutionAtIndex, getNormalizedAbsolutePath, getOwnKeys, getPathComponents, + getPathFromPathComponents, getPathsBasePath, getPossibleOriginalInputExtensionForExtension, + getRelativePathFromDirectory, getRootLength, hasJSFileExtension, hasProperty, hasTrailingDirectorySeparator, + hasTSFileExtension, hostGetCanonicalFileName, isArray, isExternalModuleNameRelative, isRootedDiskPath, isString, + lastOrUndefined, length, Map, MapLike, matchedText, MatchingKeys, matchPatternOrExact, ModuleKind, + ModuleResolutionHost, ModuleResolutionKind, noop, noopPush, normalizePath, normalizeSlashes, + optionsHaveModuleResolutionChanges, PackageId, packageIdToString, ParsedCommandLine, Path, pathIsRelative, Pattern, + patternText, perfLogger, Push, readJson, removeExtension, removeFileExtension, removePrefix, + ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, ResolvedTypeReferenceDirective, + ResolvedTypeReferenceDirectiveWithFailedLookupLocations, some, sort, SourceFile, startsWith, stringContains, + supportedTSExtensionsFlat, toPath, tryExtractTSExtension, tryGetExtensionFromPath, tryParsePatterns, + tryRemoveExtension, version, Version, versionMajorMinor, VersionRange, +} from "./_namespaces/ts"; /* @internal */ -export function trace(host: ts.ModuleResolutionHost, message: ts.DiagnosticMessage, ...args: any[]): void; -export function trace(host: ts.ModuleResolutionHost): void { - host.trace!(ts.formatMessage.apply(undefined, arguments)); +export function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; +export function trace(host: ModuleResolutionHost): void { + host.trace!(formatMessage.apply(undefined, arguments)); } /* @internal */ -export function isTraceEnabled(compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost): boolean { +export function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean { return !!compilerOptions.traceResolution && host.trace !== undefined; } function withPackageId(packageInfo: PackageJsonInfo | undefined, r: PathAndExtension | undefined): Resolved | undefined { - let packageId: ts.PackageId | undefined; + let packageId: PackageId | undefined; if (r && packageInfo) { const packageJsonContent = packageInfo.contents.packageJsonContent as PackageJson; if (typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string") { packageId = { name: packageJsonContent.name, - subModuleName: r.path.slice(packageInfo.packageDirectory.length + ts.directorySeparator.length), + subModuleName: r.path.slice(packageInfo.packageDirectory.length + directorySeparator.length), version: packageJsonContent.version }; } @@ -32,7 +51,7 @@ function noPackageId(r: PathAndExtension | undefined): Resolved | undefined { function removeIgnoredPackageId(r: Resolved | undefined): PathAndExtension | undefined { if (r) { - ts.Debug.assert(r.packageId === undefined); + Debug.assert(r.packageId === undefined); return { path: r.path, ext: r.extension }; } } @@ -40,8 +59,8 @@ function removeIgnoredPackageId(r: Resolved | undefined): PathAndExtension | und /** Result of trying to resolve a module. */ interface Resolved { path: string; - extension: ts.Extension; - packageId: ts.PackageId | undefined; + extension: Extension; + packageId: PackageId | undefined; /** * When the resolved is not created from cache, the value is * - string if it is symbolic link to the resolved `path` @@ -58,7 +77,7 @@ interface Resolved { interface PathAndExtension { path: string; // (Use a different name than `extension` to make sure Resolved isn't assignable to PathAndExtension.) - ext: ts.Extension; + ext: Extension; } /** @@ -76,14 +95,14 @@ enum Extensions { interface PathAndPackageId { readonly fileName: string; - readonly packageId: ts.PackageId | undefined; + readonly packageId: PackageId | undefined; } /** Used with `Extensions.DtsOnly` to extract the path from TypeScript results. */ function resolvedTypeScriptOnly(resolved: Resolved | undefined): PathAndPackageId | undefined { if (!resolved) { return undefined; } - ts.Debug.assert(ts.extensionIsTS(resolved.extension)); + Debug.assert(extensionIsTS(resolved.extension)); return { fileName: resolved.path, packageId: resolved.packageId }; } @@ -92,9 +111,9 @@ function createResolvedModuleWithFailedLookupLocations( isExternalLibraryImport: boolean | undefined, failedLookupLocations: string[], affectingLocations: string[], - diagnostics: ts.Diagnostic[], - resultFromCache: ts.ResolvedModuleWithFailedLookupLocations | undefined -): ts.ResolvedModuleWithFailedLookupLocations { + diagnostics: Diagnostic[], + resultFromCache: ResolvedModuleWithFailedLookupLocations | undefined +): ResolvedModuleWithFailedLookupLocations { if (resultFromCache) { resultFromCache.failedLookupLocations.push(...failedLookupLocations); resultFromCache.affectingLocations.push(...affectingLocations); @@ -110,17 +129,17 @@ function createResolvedModuleWithFailedLookupLocations( /*@internal*/ interface ModuleResolutionState { - host: ts.ModuleResolutionHost; - compilerOptions: ts.CompilerOptions; + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; traceEnabled: boolean; - failedLookupLocations: ts.Push; - affectingLocations: ts.Push; - resultFromCache?: ts.ResolvedModuleWithFailedLookupLocations; + failedLookupLocations: Push; + affectingLocations: Push; + resultFromCache?: ResolvedModuleWithFailedLookupLocations; packageJsonInfoCache: PackageJsonInfoCache | undefined; features: NodeResolutionFeatures; conditions: readonly string[]; requestContainingDirectory: string | undefined; - reportDiagnostic: ts.DiagnosticReporter; + reportDiagnostic: DiagnosticReporter; } /** Just the fields that we use for module resolution. */ @@ -128,7 +147,7 @@ interface ModuleResolutionState { interface PackageJsonPathFields { typings?: string; types?: string; - typesVersions?: ts.MapLike>; + typesVersions?: MapLike>; main?: string; tsconfig?: string; type?: string; @@ -142,12 +161,12 @@ interface PackageJson extends PackageJsonPathFields { version?: string; } -function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; -function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; +function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; +function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; function readPackageJsonField(jsonContent: PackageJson, fieldName: K, typeOfTag: "string" | "object", state: ModuleResolutionState): PackageJson[K] | undefined { - if (!ts.hasProperty(jsonContent, fieldName)) { + if (!hasProperty(jsonContent, fieldName)) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_does_not_have_a_0_field, fieldName); + trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, fieldName); } return; } @@ -155,7 +174,7 @@ function readPackageJsonField(jsonContent: PackageJ if (typeof value !== typeOfTag || value === null) { // eslint-disable-line no-null/no-null if (state.traceEnabled) { // eslint-disable-next-line no-null/no-null - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, typeOfTag, value === null ? "null" : typeof value); + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, typeOfTag, value === null ? "null" : typeof value); } return; } @@ -169,13 +188,13 @@ function readPackageJsonPathField; + paths: MapLike; } function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: ModuleResolutionState): VersionPaths | undefined { @@ -216,8 +235,8 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul if (state.traceEnabled) { for (const key in typesVersions) { - if (ts.hasProperty(typesVersions, key) && !ts.VersionRange.tryParse(key)) { - trace(state.host, ts.Diagnostics.package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range, key); + if (hasProperty(typesVersions, key) && !VersionRange.tryParse(key)) { + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range, key); } } } @@ -225,7 +244,7 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul const result = getPackageJsonTypesVersionsPaths(typesVersions); if (!result) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, ts.versionMajorMinor); + trace(state.host, Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, versionMajorMinor); } return; } @@ -233,7 +252,7 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul const { version: bestVersionKey, paths: bestVersionPaths } = result; if (typeof bestVersionPaths !== "object") { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${bestVersionKey}']`, "object", typeof bestVersionPaths); + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${bestVersionKey}']`, "object", typeof bestVersionPaths); } return; } @@ -241,16 +260,16 @@ function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: Modul return result; } -let typeScriptVersion: ts.Version | undefined; +let typeScriptVersion: Version | undefined; /* @internal */ -export function getPackageJsonTypesVersionsPaths(typesVersions: ts.MapLike>) { - if (!typeScriptVersion) typeScriptVersion = new ts.Version(ts.version); +export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>) { + if (!typeScriptVersion) typeScriptVersion = new Version(version); for (const key in typesVersions) { - if (!ts.hasProperty(typesVersions, key)) continue; + if (!hasProperty(typesVersions, key)) continue; - const keyRange = ts.VersionRange.tryParse(key); + const keyRange = VersionRange.tryParse(key); if (keyRange === undefined) { continue; } @@ -262,14 +281,14 @@ export function getPackageJsonTypesVersionsPaths(typesVersions: ts.MapLike boolean }): string[] | undefined { if (!host.directoryExists) { - return [ts.combinePaths(currentDirectory, nodeModulesAtTypes)]; + return [combinePaths(currentDirectory, nodeModulesAtTypes)]; // And if it doesn't exist, tough. } let typeRoots: string[] | undefined; - ts.forEachAncestorDirectory(ts.normalizePath(currentDirectory), directory => { - const atTypes = ts.combinePaths(directory, nodeModulesAtTypes); + forEachAncestorDirectory(normalizePath(currentDirectory), directory => { + const atTypes = combinePaths(directory, nodeModulesAtTypes); if (host.directoryExists!(atTypes)) { (typeRoots || (typeRoots = [])).push(atTypes); } @@ -300,11 +319,11 @@ function getDefaultTypeRoots(currentDirectory: string, host: { directoryExists?: }); return typeRoots; } -const nodeModulesAtTypes = ts.combinePaths("node_modules", "@types"); +const nodeModulesAtTypes = combinePaths("node_modules", "@types"); -function arePathsEqual(path1: string, path2: string, host: ts.ModuleResolutionHost): boolean { +function arePathsEqual(path1: string, path2: string, host: ModuleResolutionHost): boolean { const useCaseSensitiveFileNames = typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames; - return ts.comparePaths(path1, path2, !useCaseSensitiveFileNames) === ts.Comparison.EqualTo; + return comparePaths(path1, path2, !useCaseSensitiveFileNames) === Comparison.EqualTo; } /** @@ -312,21 +331,21 @@ function arePathsEqual(path1: string, path2: string, host: ts.ModuleResolutionHo * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups * is assumed to be the same as root directory of the project. */ -export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: ts.CompilerOptions, host: ts.ModuleResolutionHost, redirectedReference?: ts.ResolvedProjectReference, cache?: TypeReferenceDirectiveResolutionCache, resolutionMode?: ts.SourceFile["impliedNodeFormat"]): ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations { - ts.Debug.assert(typeof typeReferenceDirectiveName === "string", "Non-string value passed to `ts.resolveTypeReferenceDirective`, likely by a wrapping package working with an outdated `resolveTypeReferenceDirectives` signature. This is probably not a problem in TS itself."); +export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, cache?: TypeReferenceDirectiveResolutionCache, resolutionMode?: SourceFile["impliedNodeFormat"]): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { + Debug.assert(typeof typeReferenceDirectiveName === "string", "Non-string value passed to `ts.resolveTypeReferenceDirective`, likely by a wrapping package working with an outdated `resolveTypeReferenceDirectives` signature. This is probably not a problem in TS itself."); const traceEnabled = isTraceEnabled(options, host); if (redirectedReference) { options = redirectedReference.commandLine.options; } - const containingDirectory = containingFile ? ts.getDirectoryPath(containingFile) : undefined; + const containingDirectory = containingFile ? getDirectoryPath(containingFile) : undefined; const perFolderCache = containingDirectory ? cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference) : undefined; let result = perFolderCache && perFolderCache.get(typeReferenceDirectiveName, /*mode*/ resolutionMode); if (result) { if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1, typeReferenceDirectiveName, containingFile); - if (redirectedReference) trace(host, ts.Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); - trace(host, ts.Diagnostics.Resolution_for_type_reference_directive_0_was_found_in_cache_from_location_1, typeReferenceDirectiveName, containingDirectory); + trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1, typeReferenceDirectiveName, containingFile); + if (redirectedReference) trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); + trace(host, Diagnostics.Resolution_for_type_reference_directive_0_was_found_in_cache_from_location_1, typeReferenceDirectiveName, containingDirectory); traceResult(result); } return result; @@ -336,22 +355,22 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string if (traceEnabled) { if (containingFile === undefined) { if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); + trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_not_set, typeReferenceDirectiveName); } else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); + trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_not_set_root_directory_1, typeReferenceDirectiveName, typeRoots); } } else { if (typeRoots === undefined) { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); + trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_not_set, typeReferenceDirectiveName, containingFile); } else { - trace(host, ts.Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); + trace(host, Diagnostics.Resolving_type_reference_directive_0_containing_file_1_root_directory_2, typeReferenceDirectiveName, containingFile, typeRoots); } } if (redirectedReference) { - trace(host, ts.Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); + trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); } } @@ -365,11 +384,11 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string // in practice, not every cache has the options available to intelligently make the choice to ignore the mode request, and it's unclear how modern "faithful modern // resolution" should be (`node16`? `nodenext`?). As such, witnessing a mode-overriding triple-slash reference in a non-modal module resolution // context should _probably_ be an error - and that should likely be handled by the `Program` (which is what we do). - if (resolutionMode === ts.ModuleKind.ESNext && (ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.NodeNext)) { + if (resolutionMode === ModuleKind.ESNext && (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext)) { features |= NodeResolutionFeatures.EsmMode; } const conditions = features & NodeResolutionFeatures.Exports ? features & NodeResolutionFeatures.EsmMode ? ["node", "import", "types"] : ["node", "require", "types"] : []; - const diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, @@ -389,7 +408,7 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string primary = false; } - let resolvedTypeReferenceDirective: ts.ResolvedTypeReferenceDirective | undefined; + let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined; if (resolved) { const { fileName, packageId } = resolved; const resolvedFileName = options.preserveSymlinks ? fileName : realPath(fileName, host, traceEnabled); @@ -408,15 +427,15 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string if (traceEnabled) traceResult(result); return result; - function traceResult(result: ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { + function traceResult(result: ResolvedTypeReferenceDirectiveWithFailedLookupLocations) { if (!result.resolvedTypeReferenceDirective?.resolvedFileName) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); + trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); } else if (result.resolvedTypeReferenceDirective.packageId) { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, ts.packageIdToString(result.resolvedTypeReferenceDirective.packageId), result.resolvedTypeReferenceDirective.primary); + trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_with_Package_ID_2_primary_Colon_3, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, packageIdToString(result.resolvedTypeReferenceDirective.packageId), result.resolvedTypeReferenceDirective.primary); } else { - trace(host, ts.Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, result.resolvedTypeReferenceDirective.primary); + trace(host, Diagnostics.Type_reference_directive_0_was_successfully_resolved_to_1_primary_Colon_2, typeReferenceDirectiveName, result.resolvedTypeReferenceDirective.resolvedFileName, result.resolvedTypeReferenceDirective.primary); } } @@ -424,14 +443,14 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string // Check primary library paths if (typeRoots && typeRoots.length) { if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); + trace(host, Diagnostics.Resolving_with_primary_search_path_0, typeRoots.join(", ")); } - return ts.firstDefined(typeRoots, typeRoot => { - const candidate = ts.combinePaths(typeRoot, typeReferenceDirectiveName); - const candidateDirectory = ts.getDirectoryPath(candidate); - const directoryExists = ts.directoryProbablyExists(candidateDirectory, host); + return firstDefined(typeRoots, typeRoot => { + const candidate = combinePaths(typeRoot, typeReferenceDirectiveName); + const candidateDirectory = getDirectoryPath(candidate); + const directoryExists = directoryProbablyExists(candidateDirectory, host); if (!directoryExists && traceEnabled) { - trace(host, ts.Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, candidateDirectory); + trace(host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, candidateDirectory); } return resolvedTypeScriptOnly( loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, @@ -440,21 +459,21 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string } else { if (traceEnabled) { - trace(host, ts.Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); + trace(host, Diagnostics.Root_directory_cannot_be_determined_skipping_primary_search_paths); } } } function secondaryLookup(): PathAndPackageId | undefined { - const initialLocationForSecondaryLookup = containingFile && ts.getDirectoryPath(containingFile); + const initialLocationForSecondaryLookup = containingFile && getDirectoryPath(containingFile); if (initialLocationForSecondaryLookup !== undefined) { // check secondary locations if (traceEnabled) { - trace(host, ts.Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); + trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } let result: Resolved | undefined; - if (!ts.isExternalModuleNameRelative(typeReferenceDirectiveName)) { + if (!isExternalModuleNameRelative(typeReferenceDirectiveName)) { const searchResult = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined, /*redirectedReference*/ undefined); result = searchResult && searchResult.value; } @@ -466,15 +485,15 @@ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string } else { if (traceEnabled) { - trace(host, ts.Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); + trace(host, Diagnostics.Containing_file_is_not_specified_and_root_directory_cannot_be_determined_skipping_lookup_in_node_modules_folder); } } } } -function getDefaultNodeResolutionFeatures(options: ts.CompilerOptions) { - return ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.Node16 ? NodeResolutionFeatures.Node16Default : - ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.NodeNext ? NodeResolutionFeatures.NodeNextDefault : +function getDefaultNodeResolutionFeatures(options: CompilerOptions) { + return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 ? NodeResolutionFeatures.Node16Default : + getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext ? NodeResolutionFeatures.NodeNextDefault : NodeResolutionFeatures.None; } @@ -485,16 +504,16 @@ function getDefaultNodeResolutionFeatures(options: ts.CompilerOptions) { export function resolvePackageNameToPackageJson( packageName: string, containingDirectory: string, - options: ts.CompilerOptions, - host: ts.ModuleResolutionHost, + options: CompilerOptions, + host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, ): PackageJsonInfo | undefined { const moduleResolutionState = getTemporaryModuleResolutionState(cache?.getPackageJsonInfoCache(), host, options); - return ts.forEachAncestorDirectory(containingDirectory, ancestorDirectory => { - if (ts.getBaseFileName(ancestorDirectory) !== "node_modules") { - const nodeModulesFolder = ts.combinePaths(ancestorDirectory, "node_modules"); - const candidate = ts.combinePaths(nodeModulesFolder, packageName); + return forEachAncestorDirectory(containingDirectory, ancestorDirectory => { + if (getBaseFileName(ancestorDirectory) !== "node_modules") { + const nodeModulesFolder = combinePaths(ancestorDirectory, "node_modules"); + const candidate = combinePaths(nodeModulesFolder, packageName); return getPackageJsonInfo(candidate, /*onlyRecordFailures*/ false, moduleResolutionState); } }); @@ -508,7 +527,7 @@ export function resolvePackageNameToPackageJson( * More type directives might appear in the program later as a result of loading actual source files; * this list is only the set of defaults that are implicitly included. */ -export function getAutomaticTypeDirectiveNames(options: ts.CompilerOptions, host: ts.ModuleResolutionHost): string[] { +export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[] { // Use explicit type list from tsconfig.json if (options.types) { return options.types; @@ -522,17 +541,17 @@ export function getAutomaticTypeDirectiveNames(options: ts.CompilerOptions, host for (const root of typeRoots) { if (host.directoryExists(root)) { for (const typeDirectivePath of host.getDirectories(root)) { - const normalized = ts.normalizePath(typeDirectivePath); - const packageJsonPath = ts.combinePaths(root, normalized, "package.json"); + const normalized = normalizePath(typeDirectivePath); + const packageJsonPath = combinePaths(root, normalized, "package.json"); // `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types. // See `createNotNeededPackageJSON` in the types-publisher` repo. // eslint-disable-next-line no-null/no-null - const isNotNeededPackage = host.fileExists(packageJsonPath) && (ts.readJson(packageJsonPath, host) as PackageJson).typings === null; + const isNotNeededPackage = host.fileExists(packageJsonPath) && (readJson(packageJsonPath, host) as PackageJson).typings === null; if (!isNotNeededPackage) { - const baseFileName = ts.getBaseFileName(normalized); + const baseFileName = getBaseFileName(normalized); // At this stage, skip results with leading dot. - if (baseFileName.charCodeAt(0) !== ts.CharacterCodes.dot) { + if (baseFileName.charCodeAt(0) !== CharacterCodes.dot) { // Return just the type directive names result.push(baseFileName); } @@ -545,16 +564,16 @@ export function getAutomaticTypeDirectiveNames(options: ts.CompilerOptions, host return result; } -export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { +export interface TypeReferenceDirectiveResolutionCache extends PerDirectoryResolutionCache, PackageJsonInfoCache { /*@internal*/ clearAllExceptPackageJsonInfoCache(): void; } export interface ModeAwareCache { - get(key: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined): T | undefined; - set(key: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined, value: T): this; - delete(key: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined): this; - has(key: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined): boolean; - forEach(cb: (elem: T, key: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined) => void): void; + get(key: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined): T | undefined; + set(key: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined, value: T): this; + delete(key: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined): this; + has(key: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined): boolean; + forEach(cb: (elem: T, key: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined) => void): void; size(): number; } @@ -563,16 +582,16 @@ export interface ModeAwareCache { * This assumes that any module id will have the same resolution for sibling files located in the same folder. */ export interface PerDirectoryResolutionCache { - getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ts.ResolvedProjectReference): ModeAwareCache; + getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference): ModeAwareCache; clear(): void; /** * Updates with the current compilerOptions the cache will operate with. * This updates the redirects map as well if needed so module resolutions are cached if they can across the projects */ - update(options: ts.CompilerOptions): void; + update(options: CompilerOptions): void; } -export interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { +export interface ModuleResolutionCache extends PerDirectoryResolutionCache, NonRelativeModuleNameResolutionCache, PackageJsonInfoCache { getPackageJsonInfoCache(): PackageJsonInfoCache; /*@internal*/ clearAllExceptPackageJsonInfoCache(): void; } @@ -582,36 +601,36 @@ export interface ModuleResolutionCache extends PerDirectoryResolutionCache | undefined; + /*@internal*/ entries(): [Path, PackageJsonInfo | boolean][]; + /*@internal*/ getInternalMap(): ESMap | undefined; clear(): void; } export interface PerModuleNameCache { - get(directory: string): ts.ResolvedModuleWithFailedLookupLocations | undefined; - set(directory: string, result: ts.ResolvedModuleWithFailedLookupLocations): void; + get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined; + set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void; } /*@internal*/ export interface CacheWithRedirects { - getOwnMap: () => ts.ESMap; - redirectsMap: ts.ESMap>; - getOrCreateMapOfCacheRedirects(redirectedReference: ts.ResolvedProjectReference | undefined): ts.ESMap; + getOwnMap: () => ESMap; + redirectsMap: ESMap>; + getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined): ESMap; clear(): void; - setOwnOptions(newOptions: ts.CompilerOptions): void; - setOwnMap(newOwnMap: ts.ESMap): void; + setOwnOptions(newOptions: CompilerOptions): void; + setOwnMap(newOwnMap: ESMap): void; } /*@internal*/ -export function createCacheWithRedirects(options?: ts.CompilerOptions): CacheWithRedirects { - let ownMap: ts.ESMap = new ts.Map(); - const redirectsMap = new ts.Map>(); +export function createCacheWithRedirects(options?: CompilerOptions): CacheWithRedirects { + let ownMap: ESMap = new Map(); + const redirectsMap = new Map>(); return { getOwnMap, redirectsMap, @@ -625,15 +644,15 @@ export function createCacheWithRedirects(options?: ts.CompilerOptions): Cache return ownMap; } - function setOwnOptions(newOptions: ts.CompilerOptions) { + function setOwnOptions(newOptions: CompilerOptions) { options = newOptions; } - function setOwnMap(newOwnMap: ts.ESMap) { + function setOwnMap(newOwnMap: ESMap) { ownMap = newOwnMap; } - function getOrCreateMapOfCacheRedirects(redirectedReference: ts.ResolvedProjectReference | undefined) { + function getOrCreateMapOfCacheRedirects(redirectedReference: ResolvedProjectReference | undefined) { if (!redirectedReference) { return ownMap; } @@ -641,7 +660,7 @@ export function createCacheWithRedirects(options?: ts.CompilerOptions): Cache let redirects = redirectsMap.get(path); if (!redirects) { // Reuse map if redirected reference map uses same resolution - redirects = !options || ts.optionsHaveModuleResolutionChanges(options, redirectedReference.commandLine.options) ? new ts.Map() : ownMap; + redirects = !options || optionsHaveModuleResolutionChanges(options, redirectedReference.commandLine.options) ? new Map() : ownMap; redirectsMap.set(path, redirects); } return redirects; @@ -654,27 +673,27 @@ export function createCacheWithRedirects(options?: ts.CompilerOptions): Cache } function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): PackageJsonInfoCache { - let cache: ts.ESMap | undefined; + let cache: ESMap | undefined; return { getPackageJsonInfo, setPackageJsonInfo, clear, entries, getInternalMap }; function getPackageJsonInfo(packageJsonPath: string) { - return cache?.get(ts.toPath(packageJsonPath, currentDirectory, getCanonicalFileName)); + return cache?.get(toPath(packageJsonPath, currentDirectory, getCanonicalFileName)); } function setPackageJsonInfo(packageJsonPath: string, info: PackageJsonInfo | boolean) { - (cache ||= new ts.Map()).set(ts.toPath(packageJsonPath, currentDirectory, getCanonicalFileName), info); + (cache ||= new Map()).set(toPath(packageJsonPath, currentDirectory, getCanonicalFileName), info); } function clear() { cache = undefined; } function entries() { const iter = cache?.entries(); - return iter ? ts.arrayFrom(iter) : []; + return iter ? arrayFrom(iter) : []; } function getInternalMap() { return cache; } } -function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, redirectedReference: ts.ResolvedProjectReference | undefined, key: string, create: () => T): T { +function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, redirectedReference: ResolvedProjectReference | undefined, key: string, create: () => T): T { const cache = cacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference); let result = cache.get(key); if (!result) { @@ -685,25 +704,25 @@ function getOrCreateCache(cacheWithRedirects: CacheWithRedirects, redirect } function updateRedirectsMap( - options: ts.CompilerOptions, + options: CompilerOptions, directoryToModuleNameMap: CacheWithRedirects>, moduleNameToDirectoryMap?: CacheWithRedirects ) { if (!options.configFile) return; if (directoryToModuleNameMap.redirectsMap.size === 0) { // The own map will be for projectCompilerOptions - ts.Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size === 0); - ts.Debug.assert(directoryToModuleNameMap.getOwnMap().size === 0); - ts.Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.getOwnMap().size === 0); + Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size === 0); + Debug.assert(directoryToModuleNameMap.getOwnMap().size === 0); + Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.getOwnMap().size === 0); directoryToModuleNameMap.redirectsMap.set(options.configFile.path, directoryToModuleNameMap.getOwnMap()); moduleNameToDirectoryMap?.redirectsMap.set(options.configFile.path, moduleNameToDirectoryMap.getOwnMap()); } else { // Set correct own map - ts.Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size > 0); - const ref: ts.ResolvedProjectReference = { + Debug.assert(!moduleNameToDirectoryMap || moduleNameToDirectoryMap.redirectsMap.size > 0); + const ref: ResolvedProjectReference = { sourceFile: options.configFile, - commandLine: { options } as ts.ParsedCommandLine + commandLine: { options } as ParsedCommandLine }; directoryToModuleNameMap.setOwnMap(directoryToModuleNameMap.getOrCreateMapOfCacheRedirects(ref)); moduleNameToDirectoryMap?.setOwnMap(moduleNameToDirectoryMap.getOrCreateMapOfCacheRedirects(ref)); @@ -712,7 +731,7 @@ function updateRedirectsMap( moduleNameToDirectoryMap?.setOwnOptions(options); } -function createPerDirectoryResolutionCache(currentDirectory: string, getCanonicalFileName: ts.GetCanonicalFileName, directoryToModuleNameMap: CacheWithRedirects>): PerDirectoryResolutionCache { +function createPerDirectoryResolutionCache(currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, directoryToModuleNameMap: CacheWithRedirects>): PerDirectoryResolutionCache { return { getOrCreateCacheForDirectory, clear, @@ -723,20 +742,20 @@ function createPerDirectoryResolutionCache(currentDirectory: string, getCanon directoryToModuleNameMap.clear(); } - function update(options: ts.CompilerOptions) { + function update(options: CompilerOptions) { updateRedirectsMap(options, directoryToModuleNameMap); } - function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ts.ResolvedProjectReference) { - const path = ts.toPath(directoryName, currentDirectory, getCanonicalFileName); + function getOrCreateCacheForDirectory(directoryName: string, redirectedReference?: ResolvedProjectReference) { + const path = toPath(directoryName, currentDirectory, getCanonicalFileName); return getOrCreateCache>(directoryToModuleNameMap, redirectedReference, path, () => createModeAwareCache()); } } /* @internal */ export function createModeAwareCache(): ModeAwareCache { - const underlying = new ts.Map(); - const memoizedReverseKeys = new ts.Map(); + const underlying = new Map(); + const memoizedReverseKeys = new Map(); const cache: ModeAwareCache = { get(specifier, mode) { @@ -765,7 +784,7 @@ export function createModeAwareCache(): ModeAwareCache { }; return cache; - function getUnderlyingCacheKey(specifier: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined) { + function getUnderlyingCacheKey(specifier: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined) { const result = mode === undefined ? specifier : `${mode}|${specifier}`; memoizedReverseKeys.set(result, [specifier, mode]); return result; @@ -773,14 +792,14 @@ export function createModeAwareCache(): ModeAwareCache { } /* @internal */ -export function zipToModeAwareCache(file: ts.SourceFile, keys: readonly string[] | readonly ts.FileReference[], values: readonly V[]): ModeAwareCache { - ts.Debug.assert(keys.length === values.length); +export function zipToModeAwareCache(file: SourceFile, keys: readonly string[] | readonly FileReference[], values: readonly V[]): ModeAwareCache { + Debug.assert(keys.length === values.length); const map = createModeAwareCache(); for (let i = 0; i < keys.length; ++i) { const entry = keys[i]; // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. - const name = !ts.isString(entry) ? entry.fileName.toLowerCase() : entry; - const mode = !ts.isString(entry) ? entry.resolutionMode || file.impliedNodeFormat : ts.getModeForResolutionAtIndex(file, i); + const name = !isString(entry) ? entry.fileName.toLowerCase() : entry; + const mode = !isString(entry) ? entry.resolutionMode || file.impliedNodeFormat : getModeForResolutionAtIndex(file, i); map.set(name, mode, values[i]); } return map; @@ -789,21 +808,21 @@ export function zipToModeAwareCache(file: ts.SourceFile, keys: readonly strin export function createModuleResolutionCache( currentDirectory: string, getCanonicalFileName: (s: string) => string, - options?: ts.CompilerOptions + options?: CompilerOptions ): ModuleResolutionCache; /*@internal*/ export function createModuleResolutionCache( currentDirectory: string, - getCanonicalFileName: ts.GetCanonicalFileName, + getCanonicalFileName: GetCanonicalFileName, options: undefined, - directoryToModuleNameMap: CacheWithRedirects>, + directoryToModuleNameMap: CacheWithRedirects>, moduleNameToDirectoryMap: CacheWithRedirects, ): ModuleResolutionCache; export function createModuleResolutionCache( currentDirectory: string, - getCanonicalFileName: ts.GetCanonicalFileName, - options?: ts.CompilerOptions, - directoryToModuleNameMap?: CacheWithRedirects>, + getCanonicalFileName: GetCanonicalFileName, + options?: CompilerOptions, + directoryToModuleNameMap?: CacheWithRedirects>, moduleNameToDirectoryMap?: CacheWithRedirects, ): ModuleResolutionCache { const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options)); @@ -830,22 +849,22 @@ export function createModuleResolutionCache( moduleNameToDirectoryMap!.clear(); } - function update(options: ts.CompilerOptions) { + function update(options: CompilerOptions) { updateRedirectsMap(options, directoryToModuleNameMap!, moduleNameToDirectoryMap); } - function getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined, redirectedReference?: ts.ResolvedProjectReference): PerModuleNameCache { - ts.Debug.assert(!ts.isExternalModuleNameRelative(nonRelativeModuleName)); + function getOrCreateCacheForModuleName(nonRelativeModuleName: string, mode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined, redirectedReference?: ResolvedProjectReference): PerModuleNameCache { + Debug.assert(!isExternalModuleNameRelative(nonRelativeModuleName)); return getOrCreateCache(moduleNameToDirectoryMap!, redirectedReference, mode === undefined ? nonRelativeModuleName : `${mode}|${nonRelativeModuleName}`, createPerModuleNameCache); } function createPerModuleNameCache(): PerModuleNameCache { - const directoryPathMap = new ts.Map(); + const directoryPathMap = new Map(); return { get, set }; - function get(directory: string): ts.ResolvedModuleWithFailedLookupLocations | undefined { - return directoryPathMap.get(ts.toPath(directory, currentDirectory, getCanonicalFileName)); + function get(directory: string): ResolvedModuleWithFailedLookupLocations | undefined { + return directoryPathMap.get(toPath(directory, currentDirectory, getCanonicalFileName)); } /** @@ -859,8 +878,8 @@ export function createModuleResolutionCache( * ] * this means that request for module resolution from file in any of these folder will be immediately found in cache. */ - function set(directory: string, result: ts.ResolvedModuleWithFailedLookupLocations): void { - const path = ts.toPath(directory, currentDirectory, getCanonicalFileName); + function set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void { + const path = toPath(directory, currentDirectory, getCanonicalFileName); // if entry is already in cache do nothing if (directoryPathMap.has(path)) { return; @@ -878,7 +897,7 @@ export function createModuleResolutionCache( const commonPrefix = resolvedFileName && getCommonPrefix(path, resolvedFileName); let current = path; while (current !== commonPrefix) { - const parent = ts.getDirectoryPath(current); + const parent = getDirectoryPath(current); if (parent === current || directoryPathMap.has(parent)) { break; } @@ -887,8 +906,8 @@ export function createModuleResolutionCache( } } - function getCommonPrefix(directory: ts.Path, resolution: string) { - const resolutionDirectory = ts.toPath(ts.getDirectoryPath(resolution), currentDirectory, getCanonicalFileName); + function getCommonPrefix(directory: Path, resolution: string) { + const resolutionDirectory = toPath(getDirectoryPath(resolution), currentDirectory, getCanonicalFileName); // find first position where directory and resolution differs let i = 0; @@ -896,14 +915,14 @@ export function createModuleResolutionCache( while (i < limit && directory.charCodeAt(i) === resolutionDirectory.charCodeAt(i)) { i++; } - if (i === directory.length && (resolutionDirectory.length === i || resolutionDirectory[i] === ts.directorySeparator)) { + if (i === directory.length && (resolutionDirectory.length === i || resolutionDirectory[i] === directorySeparator)) { return directory; } - const rootLength = ts.getRootLength(directory); + const rootLength = getRootLength(directory); if (i < rootLength) { return undefined; } - const sep = directory.lastIndexOf(ts.directorySeparator, i - 1); + const sep = directory.lastIndexOf(directorySeparator, i - 1); if (sep === -1) { return undefined; } @@ -915,23 +934,23 @@ export function createModuleResolutionCache( export function createTypeReferenceDirectiveResolutionCache( currentDirectory: string, getCanonicalFileName: (s: string) => string, - options?: ts.CompilerOptions, + options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache, ): TypeReferenceDirectiveResolutionCache; /*@internal*/ export function createTypeReferenceDirectiveResolutionCache( currentDirectory: string, - getCanonicalFileName: ts.GetCanonicalFileName, + getCanonicalFileName: GetCanonicalFileName, options: undefined, packageJsonInfoCache: PackageJsonInfoCache | undefined, - directoryToModuleNameMap: CacheWithRedirects>, + directoryToModuleNameMap: CacheWithRedirects>, ): TypeReferenceDirectiveResolutionCache; export function createTypeReferenceDirectiveResolutionCache( currentDirectory: string, - getCanonicalFileName: ts.GetCanonicalFileName, - options?: ts.CompilerOptions, + getCanonicalFileName: GetCanonicalFileName, + options?: CompilerOptions, packageJsonInfoCache?: PackageJsonInfoCache | undefined, - directoryToModuleNameMap?: CacheWithRedirects>, + directoryToModuleNameMap?: CacheWithRedirects>, ): TypeReferenceDirectiveResolutionCache { const perDirectoryResolutionCache = createPerDirectoryResolutionCache(currentDirectory, getCanonicalFileName, directoryToModuleNameMap ||= createCacheWithRedirects(options)); packageJsonInfoCache ||= createPackageJsonInfoCache(currentDirectory, getCanonicalFileName); @@ -953,83 +972,83 @@ export function createTypeReferenceDirectiveResolutionCache( } } -export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations | undefined { - const containingDirectory = ts.getDirectoryPath(containingFile); +export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache, mode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations | undefined { + const containingDirectory = getDirectoryPath(containingFile); const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory); if (!perFolderCache) return undefined; return perFolderCache.get(moduleName, mode); } -export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations { +export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (redirectedReference) { compilerOptions = redirectedReference.commandLine.options; } if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); + trace(host, Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); if (redirectedReference) { - trace(host, ts.Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); + trace(host, Diagnostics.Using_compiler_options_of_project_reference_redirect_0, redirectedReference.sourceFile.fileName); } } - const containingDirectory = ts.getDirectoryPath(containingFile); + const containingDirectory = getDirectoryPath(containingFile); const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory, redirectedReference); let result = perFolderCache && perFolderCache.get(moduleName, resolutionMode); if (result) { if (traceEnabled) { - trace(host, ts.Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); + trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); } } else { let moduleResolution = compilerOptions.moduleResolution; if (moduleResolution === undefined) { - switch (ts.getEmitModuleKind(compilerOptions)) { - case ts.ModuleKind.CommonJS: - moduleResolution = ts.ModuleResolutionKind.NodeJs; + switch (getEmitModuleKind(compilerOptions)) { + case ModuleKind.CommonJS: + moduleResolution = ModuleResolutionKind.NodeJs; break; - case ts.ModuleKind.Node16: - moduleResolution = ts.ModuleResolutionKind.Node16; + case ModuleKind.Node16: + moduleResolution = ModuleResolutionKind.Node16; break; - case ts.ModuleKind.NodeNext: - moduleResolution = ts.ModuleResolutionKind.NodeNext; + case ModuleKind.NodeNext: + moduleResolution = ModuleResolutionKind.NodeNext; break; default: - moduleResolution = ts.ModuleResolutionKind.Classic; + moduleResolution = ModuleResolutionKind.Classic; break; } if (traceEnabled) { - trace(host, ts.Diagnostics.Module_resolution_kind_is_not_specified_using_0, ts.ModuleResolutionKind[moduleResolution]); + trace(host, Diagnostics.Module_resolution_kind_is_not_specified_using_0, ModuleResolutionKind[moduleResolution]); } } else { if (traceEnabled) { - trace(host, ts.Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ts.ModuleResolutionKind[moduleResolution]); + trace(host, Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ModuleResolutionKind[moduleResolution]); } } - ts.perfLogger.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/); + perfLogger.logStartResolveModule(moduleName /* , containingFile, ModuleResolutionKind[moduleResolution]*/); switch (moduleResolution) { - case ts.ModuleResolutionKind.Node16: + case ModuleResolutionKind.Node16: result = node16ModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode); break; - case ts.ModuleResolutionKind.NodeNext: + case ModuleResolutionKind.NodeNext: result = nodeNextModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference, resolutionMode); break; - case ts.ModuleResolutionKind.NodeJs: + case ModuleResolutionKind.NodeJs: result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); break; - case ts.ModuleResolutionKind.Classic: + case ModuleResolutionKind.Classic: result = classicNameResolver(moduleName, containingFile, compilerOptions, host, cache, redirectedReference); break; default: - return ts.Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); + return Debug.fail(`Unexpected moduleResolution: ${moduleResolution}`); } - if (result && result.resolvedModule) ts.perfLogger.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); - ts.perfLogger.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null"); + if (result && result.resolvedModule) perfLogger.logInfoEvent(`Module "${moduleName}" resolved to "${result.resolvedModule.resolvedFileName}"`); + perfLogger.logStopResolveModule((result && result.resolvedModule) ? "" + result.resolvedModule.resolvedFileName : "null"); if (perFolderCache) { perFolderCache.set(moduleName, resolutionMode, result); - if (!ts.isExternalModuleNameRelative(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { // put result in per-module name cache cache.getOrCreateCacheForModuleName(moduleName, resolutionMode, redirectedReference).set(containingDirectory, result); } @@ -1039,14 +1058,14 @@ export function resolveModuleName(moduleName: string, containingFile: string, co if (traceEnabled) { if (result.resolvedModule) { if (result.resolvedModule.packageId) { - trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1_with_Package_ID_2, moduleName, result.resolvedModule.resolvedFileName, ts.packageIdToString(result.resolvedModule.packageId)); + trace(host, Diagnostics.Module_name_0_was_successfully_resolved_to_1_with_Package_ID_2, moduleName, result.resolvedModule.resolvedFileName, packageIdToString(result.resolvedModule.packageId)); } else { - trace(host, ts.Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); + trace(host, Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); } } else { - trace(host, ts.Diagnostics.Module_name_0_was_not_resolved, moduleName); + trace(host, Diagnostics.Module_name_0_was_not_resolved, moduleName); } } @@ -1129,7 +1148,7 @@ function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, mo const resolved = tryLoadModuleUsingPathsIfEligible(extensions, moduleName, loader, state); if (resolved) return resolved.value; - if (!ts.isExternalModuleNameRelative(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, state); } else { @@ -1139,15 +1158,15 @@ function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, mo function tryLoadModuleUsingPathsIfEligible(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState) { const { baseUrl, paths, configFile } = state.compilerOptions; - if (paths && !ts.pathIsRelative(moduleName)) { + if (paths && !pathIsRelative(moduleName)) { if (state.traceEnabled) { if (baseUrl) { - trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); + trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); } - trace(state.host, ts.Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); + trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); } - const baseDirectory = ts.getPathsBasePath(state.compilerOptions, state.host)!; // Always defined when 'paths' is defined - const pathPatterns = configFile?.configFileSpecs ? configFile.configFileSpecs.pathPatterns ||= ts.tryParsePatterns(paths) : undefined; + const baseDirectory = getPathsBasePath(state.compilerOptions, state.host)!; // Always defined when 'paths' is defined + const pathPatterns = configFile?.configFileSpecs ? configFile.configFileSpecs.pathPatterns ||= tryParsePatterns(paths) : undefined; return tryLoadModuleUsingPaths(extensions, moduleName, baseDirectory, paths, pathPatterns, loader, /*onlyRecordFailures*/ false, state); } } @@ -1160,10 +1179,10 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); + trace(state.host, Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); } - const candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); let matchedRootDir: string | undefined; let matchedNormalizedPrefix: string | undefined; @@ -1171,16 +1190,16 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, // rootDirs are expected to be absolute // in case of tsconfig.json this will happen automatically - compiler will expand relative names // using location of tsconfig.json as base location - let normalizedRoot = ts.normalizePath(rootDir); - if (!ts.endsWith(normalizedRoot, ts.directorySeparator)) { - normalizedRoot += ts.directorySeparator; + let normalizedRoot = normalizePath(rootDir); + if (!endsWith(normalizedRoot, directorySeparator)) { + normalizedRoot += directorySeparator; } const isLongestMatchingPrefix = - ts.startsWith(candidate, normalizedRoot) && + startsWith(candidate, normalizedRoot) && (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); + trace(state.host, Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); } if (isLongestMatchingPrefix) { @@ -1190,21 +1209,21 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, } if (matchedNormalizedPrefix) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); + trace(state.host, Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); } const suffix = candidate.substr(matchedNormalizedPrefix.length); // first - try to load from a initial location if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); + trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } - const resolvedFileName = loader(extensions, candidate, !ts.directoryProbablyExists(containingDirectory, state.host), state); + const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(containingDirectory, state.host), state); if (resolvedFileName) { return resolvedFileName; } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_other_entries_in_rootDirs); + trace(state.host, Diagnostics.Trying_other_entries_in_rootDirs); } // then try to resolve using remaining entries in rootDirs for (const rootDir of state.compilerOptions.rootDirs) { @@ -1212,18 +1231,18 @@ function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, // skip the initially matched entry continue; } - const candidate = ts.combinePaths(ts.normalizePath(rootDir), suffix); + const candidate = combinePaths(normalizePath(rootDir), suffix); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate); + trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate); } - const baseDirectory = ts.getDirectoryPath(candidate); - const resolvedFileName = loader(extensions, candidate, !ts.directoryProbablyExists(baseDirectory, state.host), state); + const baseDirectory = getDirectoryPath(candidate); + const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(baseDirectory, state.host), state); if (resolvedFileName) { return resolvedFileName; } } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_resolution_using_rootDirs_has_failed); + trace(state.host, Diagnostics.Module_resolution_using_rootDirs_has_failed); } } return undefined; @@ -1235,13 +1254,13 @@ function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, l return undefined; } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); + trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); } - const candidate = ts.normalizePath(ts.combinePaths(baseUrl, moduleName)); + const candidate = normalizePath(combinePaths(baseUrl, moduleName)); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, baseUrl, candidate); + trace(state.host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, baseUrl, candidate); } - return loader(extensions, candidate, !ts.directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + return loader(extensions, candidate, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); } /** @@ -1250,7 +1269,7 @@ function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, l * Throws an error if the module can't be resolved. */ /* @internal */ -export function resolveJSModule(moduleName: string, initialDir: string, host: ts.ModuleResolutionHost): string { +export function resolveJSModule(moduleName: string, initialDir: string, host: ModuleResolutionHost): string { const { resolvedModule, failedLookupLocations } = tryResolveJSModuleWorker(moduleName, initialDir, host); if (!resolvedModule) { throw new Error(`Could not resolve JS module '${moduleName}' starting at '${initialDir}'. Looked in: ${failedLookupLocations.join(", ")}`); @@ -1279,9 +1298,9 @@ enum NodeResolutionFeatures { EsmMode = 1 << 5, } -function node16ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, - host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, - resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations { +function node16ModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, + host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, + resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations { return nodeNextModuleNameResolverWorker( NodeResolutionFeatures.Node16Default, moduleName, @@ -1294,9 +1313,9 @@ function node16ModuleNameResolver(moduleName: string, containingFile: string, co ); } -function nodeNextModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, - host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, - resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations { +function nodeNextModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, + host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, + resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations { return nodeNextModuleNameResolverWorker( NodeResolutionFeatures.NodeNextDefault, moduleName, @@ -1313,11 +1332,11 @@ const jsOnlyExtensions = [Extensions.JavaScript]; const tsExtensions = [Extensions.TypeScript, Extensions.JavaScript]; const tsPlusJsonExtensions = [...tsExtensions, Extensions.Json]; const tsconfigExtensions = [Extensions.TSConfig]; -function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations { - const containingDirectory = ts.getDirectoryPath(containingFile); +function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations { + const containingDirectory = getDirectoryPath(containingFile); // es module file or cjs-like input file, use a variant of the legacy cjs resolver that supports the selected modern features - const esmMode = resolutionMode === ts.ModuleKind.ESNext ? NodeResolutionFeatures.EsmMode : 0; + const esmMode = resolutionMode === ModuleKind.ESNext ? NodeResolutionFeatures.EsmMode : 0; let extensions = compilerOptions.noDtsResolution ? [Extensions.TsOnly, Extensions.JavaScript] : tsExtensions; if (compilerOptions.resolveJsonModule) { extensions = [...extensions, Extensions.Json]; @@ -1325,13 +1344,13 @@ function nodeNextModuleNameResolverWorker(features: NodeResolutionFeatures, modu return nodeModuleNameResolverWorker(features | esmMode, moduleName, containingDirectory, compilerOptions, host, cache, extensions, redirectedReference); } -function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ts.ModuleResolutionHost): ts.ResolvedModuleWithFailedLookupLocations { - return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, initialDir, { moduleResolution: ts.ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, jsOnlyExtensions, /*redirectedReferences*/ undefined); +function tryResolveJSModuleWorker(moduleName: string, initialDir: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { + return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, initialDir, { moduleResolution: ModuleResolutionKind.NodeJs, allowJs: true }, host, /*cache*/ undefined, jsOnlyExtensions, /*redirectedReferences*/ undefined); } -export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference): ts.ResolvedModuleWithFailedLookupLocations; -/* @internal */ export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, lookupConfig?: boolean): ts.ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures -export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ts.ResolvedProjectReference, lookupConfig?: boolean): ts.ResolvedModuleWithFailedLookupLocations { +export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations; +/* @internal */ export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations; // eslint-disable-line @typescript-eslint/unified-signatures +export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache, redirectedReference?: ResolvedProjectReference, lookupConfig?: boolean): ResolvedModuleWithFailedLookupLocations { let extensions; if (lookupConfig) { extensions = tsconfigExtensions; @@ -1344,10 +1363,10 @@ export function nodeModuleNameResolver(moduleName: string, containingFile: strin else { extensions = compilerOptions.resolveJsonModule ? tsPlusJsonExtensions : tsExtensions; } - return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, ts.getDirectoryPath(containingFile), compilerOptions, host, cache, extensions, redirectedReference); + return nodeModuleNameResolverWorker(NodeResolutionFeatures.None, moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, extensions, redirectedReference); } -function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingDirectory: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache: ModuleResolutionCache | undefined, extensions: Extensions[], redirectedReference: ts.ResolvedProjectReference | undefined): ts.ResolvedModuleWithFailedLookupLocations { +function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, extensions: Extensions[], redirectedReference: ResolvedProjectReference | undefined): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; @@ -1359,7 +1378,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa conditions.pop(); } - const diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, @@ -1373,11 +1392,11 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa reportDiagnostic: diag => void diagnostics.push(diag), }; - if (traceEnabled && ts.getEmitModuleResolutionKind(compilerOptions) >= ts.ModuleResolutionKind.Node16 && ts.getEmitModuleResolutionKind(compilerOptions) <= ts.ModuleResolutionKind.NodeNext) { - trace(host, ts.Diagnostics.Resolving_in_0_mode_with_conditions_1, features & NodeResolutionFeatures.EsmMode ? "ESM" : "CJS", conditions.map(c => `'${c}'`).join(", ")); + if (traceEnabled && getEmitModuleResolutionKind(compilerOptions) >= ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) <= ModuleResolutionKind.NodeNext) { + trace(host, Diagnostics.Resolving_in_0_mode_with_conditions_1, features & NodeResolutionFeatures.EsmMode ? "ESM" : "CJS", conditions.map(c => `'${c}'`).join(", ")); } - const result = ts.forEach(extensions, ext => tryResolve(ext)); + const result = forEach(extensions, ext => tryResolve(ext)); return createResolvedModuleWithFailedLookupLocations( result?.value?.resolved, result?.value?.isExternalLibraryImport, @@ -1394,9 +1413,9 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa return toSearchResult({ resolved, isExternalLibraryImport: pathContainsNodeModules(resolved.path) }); } - if (!ts.isExternalModuleNameRelative(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { let resolved: SearchResult | undefined; - if (features & NodeResolutionFeatures.Imports && ts.startsWith(moduleName, "#")) { + if (features & NodeResolutionFeatures.Imports && startsWith(moduleName, "#")) { resolved = loadModuleFromImports(extensions, moduleName, containingDirectory, state, cache, redirectedReference); } if (!resolved && features & NodeResolutionFeatures.SelfName) { @@ -1404,7 +1423,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa } if (!resolved) { if (traceEnabled) { - trace(host, ts.Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); + trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); } resolved = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache, redirectedReference); } @@ -1425,7 +1444,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa const { path: candidate, parts } = normalizePathForCJSResolution(containingDirectory, moduleName); const resolved = nodeLoadModuleByRelativeName(extensions, candidate, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); // Treat explicit "node_modules" import as an external library import. - return resolved && toSearchResult({ resolved, isExternalLibraryImport: ts.contains(parts, "node_modules") }); + return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") }); } } @@ -1437,36 +1456,36 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa // (https://nodejs.org/api/modules.html#all-together), but it seems that module paths ending // in `.` are actually normalized to `./` before proceeding with the resolution algorithm. function normalizePathForCJSResolution(containingDirectory: string, moduleName: string) { - const combined = ts.combinePaths(containingDirectory, moduleName); - const parts = ts.getPathComponents(combined); - const lastPart = ts.lastOrUndefined(parts); - const path = lastPart === "." || lastPart === ".." ? ts.ensureTrailingDirectorySeparator(ts.normalizePath(combined)) : ts.normalizePath(combined); + const combined = combinePaths(containingDirectory, moduleName); + const parts = getPathComponents(combined); + const lastPart = lastOrUndefined(parts); + const path = lastPart === "." || lastPart === ".." ? ensureTrailingDirectorySeparator(normalizePath(combined)) : normalizePath(combined); return { path, parts }; } -function realPath(path: string, host: ts.ModuleResolutionHost, traceEnabled: boolean): string { +function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string { if (!host.realpath) { return path; } - const real = ts.normalizePath(host.realpath(path)); + const real = normalizePath(host.realpath(path)); if (traceEnabled) { - trace(host, ts.Diagnostics.Resolving_real_path_for_0_result_1, path, real); + trace(host, Diagnostics.Resolving_real_path_for_0_result_1, path, real); } - ts.Debug.assert(host.fileExists(real), `${path} linked to nonexistent file ${real}`); + Debug.assert(host.fileExists(real), `${path} linked to nonexistent file ${real}`); return real; } function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1, candidate, Extensions[extensions]); + trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1, candidate, Extensions[extensions]); } - if (!ts.hasTrailingDirectorySeparator(candidate)) { + if (!hasTrailingDirectorySeparator(candidate)) { if (!onlyRecordFailures) { - const parentOfCandidate = ts.getDirectoryPath(candidate); - if (!ts.directoryProbablyExists(parentOfCandidate, state.host)) { + const parentOfCandidate = getDirectoryPath(candidate); + if (!directoryProbablyExists(parentOfCandidate, state.host)) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, parentOfCandidate); + trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, parentOfCandidate); } onlyRecordFailures = true; } @@ -1479,10 +1498,10 @@ function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, } } if (!onlyRecordFailures) { - const candidateExists = ts.directoryProbablyExists(candidate, state.host); + const candidateExists = directoryProbablyExists(candidate, state.host); if (!candidateExists) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, candidate); + trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, candidate); } onlyRecordFailures = true; } @@ -1500,7 +1519,7 @@ function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, export const nodeModulesPathPart = "/node_modules/"; /*@internal*/ export function pathContainsNodeModules(path: string): boolean { - return ts.stringContains(path, nodeModulesPathPart); + return stringContains(path, nodeModulesPathPart); } /** @@ -1515,7 +1534,7 @@ export function pathContainsNodeModules(path: string): boolean { */ /* @internal */ export function parseNodeModuleFromPath(resolved: string): string | undefined { - const path = ts.normalizePath(resolved); + const path = normalizePath(resolved); const idx = path.lastIndexOf(nodeModulesPathPart); if (idx === -1) { return undefined; @@ -1523,14 +1542,14 @@ export function parseNodeModuleFromPath(resolved: string): string | undefined { const indexAfterNodeModules = idx + nodeModulesPathPart.length; let indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterNodeModules); - if (path.charCodeAt(indexAfterNodeModules) === ts.CharacterCodes.at) { + if (path.charCodeAt(indexAfterNodeModules) === CharacterCodes.at) { indexAfterPackageName = moveToNextDirectorySeparatorIfAvailable(path, indexAfterPackageName); } return path.slice(0, indexAfterPackageName); } function moveToNextDirectorySeparatorIfAvailable(path: string, prevSeparatorIndex: number): number { - const nextSeparatorIndex = path.indexOf(ts.directorySeparator, prevSeparatorIndex + 1); + const nextSeparatorIndex = path.indexOf(directorySeparator, prevSeparatorIndex + 1); return nextSeparatorIndex === -1 ? prevSeparatorIndex : nextSeparatorIndex; } @@ -1544,7 +1563,7 @@ function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string */ function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { if (extensions === Extensions.Json || extensions === Extensions.TSConfig) { - const extensionLess = ts.tryRemoveExtension(candidate, ts.Extension.Json); + const extensionLess = tryRemoveExtension(candidate, Extension.Json); const extension = extensionLess ? candidate.substring(extensionLess.length) : ""; return (extensionLess === undefined && extensions === Extensions.Json) ? undefined : tryAddingExtensions(extensionLess || candidate, extensions, extension, onlyRecordFailures, state); } @@ -1564,20 +1583,20 @@ function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecor function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { // If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; // e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" - if (ts.hasJSFileExtension(candidate) || (ts.fileExtensionIs(candidate, ts.Extension.Json) && state.compilerOptions.resolveJsonModule)) { - const extensionless = ts.removeFileExtension(candidate); + if (hasJSFileExtension(candidate) || (fileExtensionIs(candidate, Extension.Json) && state.compilerOptions.resolveJsonModule)) { + const extensionless = removeFileExtension(candidate); const extension = candidate.substring(extensionless.length); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); + trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); } return tryAddingExtensions(extensionless, extensions, extension, onlyRecordFailures, state); } } function loadJSOrExactTSFileName(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { - if ((extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) && ts.fileExtensionIsOneOf(candidate, ts.supportedTSExtensionsFlat)) { + if ((extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) && fileExtensionIsOneOf(candidate, supportedTSExtensionsFlat)) { const result = tryFile(candidate, onlyRecordFailures, state); - return result !== undefined ? { path: candidate, ext: ts.tryExtractTSExtension(candidate) as ts.Extension } : undefined; + return result !== undefined ? { path: candidate, ext: tryExtractTSExtension(candidate) as Extension } : undefined; } return loadModuleFromFileNoImplicitExtensions(extensions, candidate, onlyRecordFailures, state); @@ -1587,67 +1606,67 @@ function loadJSOrExactTSFileName(extensions: Extensions, candidate: string, only function tryAddingExtensions(candidate: string, extensions: Extensions, originalExtension: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { if (!onlyRecordFailures) { // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing - const directory = ts.getDirectoryPath(candidate); + const directory = getDirectoryPath(candidate); if (directory) { - onlyRecordFailures = !ts.directoryProbablyExists(directory, state.host); + onlyRecordFailures = !directoryProbablyExists(directory, state.host); } } switch (extensions) { case Extensions.DtsOnly: switch (originalExtension) { - case ts.Extension.Mjs: - case ts.Extension.Mts: - case ts.Extension.Dmts: - return tryExtension(ts.Extension.Dmts); - case ts.Extension.Cjs: - case ts.Extension.Cts: - case ts.Extension.Dcts: - return tryExtension(ts.Extension.Dcts); - case ts.Extension.Json: - candidate += ts.Extension.Json; - return tryExtension(ts.Extension.Dts); - default: return tryExtension(ts.Extension.Dts); + case Extension.Mjs: + case Extension.Mts: + case Extension.Dmts: + return tryExtension(Extension.Dmts); + case Extension.Cjs: + case Extension.Cts: + case Extension.Dcts: + return tryExtension(Extension.Dcts); + case Extension.Json: + candidate += Extension.Json; + return tryExtension(Extension.Dts); + default: return tryExtension(Extension.Dts); } case Extensions.TypeScript: case Extensions.TsOnly: const useDts = extensions === Extensions.TypeScript; switch (originalExtension) { - case ts.Extension.Mjs: - case ts.Extension.Mts: - case ts.Extension.Dmts: - return tryExtension(ts.Extension.Mts) || (useDts ? tryExtension(ts.Extension.Dmts) : undefined); - case ts.Extension.Cjs: - case ts.Extension.Cts: - case ts.Extension.Dcts: - return tryExtension(ts.Extension.Cts) || (useDts ? tryExtension(ts.Extension.Dcts) : undefined); - case ts.Extension.Json: - candidate += ts.Extension.Json; - return useDts ? tryExtension(ts.Extension.Dts) : undefined; + case Extension.Mjs: + case Extension.Mts: + case Extension.Dmts: + return tryExtension(Extension.Mts) || (useDts ? tryExtension(Extension.Dmts) : undefined); + case Extension.Cjs: + case Extension.Cts: + case Extension.Dcts: + return tryExtension(Extension.Cts) || (useDts ? tryExtension(Extension.Dcts) : undefined); + case Extension.Json: + candidate += Extension.Json; + return useDts ? tryExtension(Extension.Dts) : undefined; default: - return tryExtension(ts.Extension.Ts) || tryExtension(ts.Extension.Tsx) || (useDts ? tryExtension(ts.Extension.Dts) : undefined); + return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || (useDts ? tryExtension(Extension.Dts) : undefined); } case Extensions.JavaScript: switch (originalExtension) { - case ts.Extension.Mjs: - case ts.Extension.Mts: - case ts.Extension.Dmts: - return tryExtension(ts.Extension.Mjs); - case ts.Extension.Cjs: - case ts.Extension.Cts: - case ts.Extension.Dcts: - return tryExtension(ts.Extension.Cjs); - case ts.Extension.Json: - return tryExtension(ts.Extension.Json); + case Extension.Mjs: + case Extension.Mts: + case Extension.Dmts: + return tryExtension(Extension.Mjs); + case Extension.Cjs: + case Extension.Cts: + case Extension.Dcts: + return tryExtension(Extension.Cjs); + case Extension.Json: + return tryExtension(Extension.Json); default: - return tryExtension(ts.Extension.Js) || tryExtension(ts.Extension.Jsx); + return tryExtension(Extension.Js) || tryExtension(Extension.Jsx); } case Extensions.TSConfig: case Extensions.Json: - return tryExtension(ts.Extension.Json); + return tryExtension(Extension.Json); } - function tryExtension(ext: ts.Extension): PathAndExtension | undefined { + function tryExtension(ext: Extension): PathAndExtension | undefined { const path = tryFile(candidate + ext, onlyRecordFailures, state); return path === undefined ? undefined : { path, ext }; } @@ -1659,22 +1678,22 @@ function tryFile(fileName: string, onlyRecordFailures: boolean, state: ModuleRes return tryFileLookup(fileName, onlyRecordFailures, state); } - const ext = ts.tryGetExtensionFromPath(fileName) ?? ""; - const fileNameNoExtension = ext ? ts.removeExtension(fileName, ext) : fileName; - return ts.forEach(state.compilerOptions.moduleSuffixes, suffix => tryFileLookup(fileNameNoExtension + suffix + ext, onlyRecordFailures, state)); + const ext = tryGetExtensionFromPath(fileName) ?? ""; + const fileNameNoExtension = ext ? removeExtension(fileName, ext) : fileName; + return forEach(state.compilerOptions.moduleSuffixes, suffix => tryFileLookup(fileNameNoExtension + suffix + ext, onlyRecordFailures, state)); } function tryFileLookup(fileName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined { if (!onlyRecordFailures) { if (state.host.fileExists(fileName)) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); + trace(state.host, Diagnostics.File_0_exist_use_it_as_a_name_resolution_result, fileName); } return fileName; } else { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_does_not_exist, fileName); + trace(state.host, Diagnostics.File_0_does_not_exist, fileName); } } } @@ -1692,8 +1711,8 @@ function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, /* @internal */ export function getEntrypointsFromPackageJsonInfo( packageJsonInfo: PackageJsonInfo, - options: ts.CompilerOptions, - host: ts.ModuleResolutionHost, + options: CompilerOptions, + host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, resolveJs?: boolean, ): string[] | false { @@ -1716,7 +1735,7 @@ export function getEntrypointsFromPackageJsonInfo( requireState, packageJsonInfo.contents.packageJsonContent, packageJsonInfo.contents.versionPaths); - entrypoints = ts.append(entrypoints, requireResolution?.path); + entrypoints = append(entrypoints, requireResolution?.path); if (features & NodeResolutionFeatures.Exports && packageJsonInfo.contents.packageJsonContent.exports) { for (const conditions of [["node", "import", "types"], ["node", "require", "types"]]) { @@ -1728,7 +1747,7 @@ export function getEntrypointsFromPackageJsonInfo( extensions); if (exportResolutions) { for (const resolution of exportResolutions) { - entrypoints = ts.appendIfUnique(entrypoints, resolution.path); + entrypoints = appendIfUnique(entrypoints, resolution.path); } } } @@ -1744,15 +1763,15 @@ function loadEntrypointsFromExportMap( extensions: Extensions, ): PathAndExtension[] | undefined { let entrypoints: PathAndExtension[] | undefined; - if (ts.isArray(exports)) { + if (isArray(exports)) { for (const target of exports) { loadEntrypointsFromTargetExports(target); } } // eslint-disable-next-line no-null/no-null - else if (typeof exports === "object" && exports !== null && allKeysStartWithDot(exports as ts.MapLike)) { + else if (typeof exports === "object" && exports !== null && allKeysStartWithDot(exports as MapLike)) { for (const key in exports) { - loadEntrypointsFromTargetExports((exports as ts.MapLike)[key]); + loadEntrypointsFromTargetExports((exports as MapLike)[key]); } } else { @@ -1761,16 +1780,16 @@ function loadEntrypointsFromExportMap( return entrypoints; function loadEntrypointsFromTargetExports(target: unknown): boolean | undefined { - if (typeof target === "string" && ts.startsWith(target, "./") && target.indexOf("*") === -1) { - const partsAfterFirst = ts.getPathComponents(target).slice(2); + if (typeof target === "string" && startsWith(target, "./") && target.indexOf("*") === -1) { + const partsAfterFirst = getPathComponents(target).slice(2); if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) { return false; } - const resolvedTarget = ts.combinePaths(scope.packageDirectory, target); - const finalPath = ts.getNormalizedAbsolutePath(resolvedTarget, state.host.getCurrentDirectory?.()); + const resolvedTarget = combinePaths(scope.packageDirectory, target); + const finalPath = getNormalizedAbsolutePath(resolvedTarget, state.host.getCurrentDirectory?.()); const result = loadJSOrExactTSFileName(extensions, finalPath, /*recordOnlyFailures*/ false, state); if (result) { - entrypoints = ts.appendIfUnique(entrypoints, result, (a, b) => a.path === b.path); + entrypoints = appendIfUnique(entrypoints, result, (a, b) => a.path === b.path); return true; } } @@ -1784,9 +1803,9 @@ function loadEntrypointsFromExportMap( } // eslint-disable-next-line no-null/no-null else if (typeof target === "object" && target !== null) { - return ts.forEach(ts.getOwnKeys(target as ts.MapLike), key => { - if (key === "default" || ts.contains(state.conditions, key) || isApplicableVersionedTypesKey(state.conditions, key)) { - loadEntrypointsFromTargetExports((target as ts.MapLike)[key]); + return forEach(getOwnKeys(target as MapLike), key => { + if (key === "default" || contains(state.conditions, key) || isApplicableVersionedTypesKey(state.conditions, key)) { + loadEntrypointsFromTargetExports((target as MapLike)[key]); return true; } }); @@ -1795,18 +1814,18 @@ function loadEntrypointsFromExportMap( } /*@internal*/ -export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ts.ModuleResolutionHost, options: ts.CompilerOptions): ModuleResolutionState { +export function getTemporaryModuleResolutionState(packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleResolutionState { return { host, compilerOptions: options, traceEnabled: isTraceEnabled(options, host), - failedLookupLocations: ts.noopPush, - affectingLocations: ts.noopPush, + failedLookupLocations: noopPush, + affectingLocations: noopPush, packageJsonInfoCache, features: NodeResolutionFeatures.None, - conditions: ts.emptyArray, + conditions: emptyArray, requestContainingDirectory: undefined, - reportDiagnostic: ts.noop + reportDiagnostic: noop }; } @@ -1828,10 +1847,10 @@ export interface PackageJsonInfoContents { */ /*@internal*/ export function getPackageScopeForPath(fileName: string, state: ModuleResolutionState): PackageJsonInfo | undefined { - const parts = ts.getPathComponents(fileName); + const parts = getPathComponents(fileName); parts.pop(); while (parts.length > 0) { - const pkg = getPackageJsonInfo(ts.getPathFromPathComponents(parts), /*onlyRecordFailures*/ false, state); + const pkg = getPackageJsonInfo(getPathFromPathComponents(parts), /*onlyRecordFailures*/ false, state); if (pkg) { return pkg; } @@ -1843,7 +1862,7 @@ export interface PackageJsonInfoContents { /*@internal*/ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined { const { host, traceEnabled } = state; - const packageJsonPath = ts.combinePaths(packageDirectory, "package.json"); + const packageJsonPath = combinePaths(packageDirectory, "package.json"); if (onlyRecordFailures) { state.failedLookupLocations.push(packageJsonPath); return undefined; @@ -1852,23 +1871,23 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: const existing = state.packageJsonInfoCache?.getPackageJsonInfo(packageJsonPath); if (existing !== undefined) { if (typeof existing !== "boolean") { - if (traceEnabled) trace(host, ts.Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath); + if (traceEnabled) trace(host, Diagnostics.File_0_exists_according_to_earlier_cached_lookups, packageJsonPath); state.affectingLocations.push(packageJsonPath); return existing.packageDirectory === packageDirectory ? existing : { packageDirectory, contents: existing.contents }; } else { - if (existing && traceEnabled) trace(host, ts.Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath); + if (existing && traceEnabled) trace(host, Diagnostics.File_0_does_not_exist_according_to_earlier_cached_lookups, packageJsonPath); state.failedLookupLocations.push(packageJsonPath); return undefined; } } - const directoryExists = ts.directoryProbablyExists(packageDirectory, host); + const directoryExists = directoryProbablyExists(packageDirectory, host); if (directoryExists && host.fileExists(packageJsonPath)) { - const packageJsonContent = ts.readJson(packageJsonPath, host) as PackageJson; + const packageJsonContent = readJson(packageJsonPath, host) as PackageJson; if (traceEnabled) { - trace(host, ts.Diagnostics.Found_package_json_at_0, packageJsonPath); + trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath); } const versionPaths = readPackageJsonTypesVersionPaths(packageJsonContent, state); const result: PackageJsonInfo = { packageDirectory, contents: { packageJsonContent, versionPaths, resolvedEntrypoints: undefined } }; @@ -1878,7 +1897,7 @@ export function getPackageJsonInfo(packageDirectory: string, onlyRecordFailures: } else { if (directoryExists && traceEnabled) { - trace(host, ts.Diagnostics.File_0_does_not_exist, packageJsonPath); + trace(host, Diagnostics.File_0_does_not_exist, packageJsonPath); } state.packageJsonInfoCache?.setPackageJsonInfo(packageJsonPath, directoryExists); // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results @@ -1906,7 +1925,7 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st packageFile = readPackageJsonTSConfigField(jsonContent, candidate, state); break; default: - return ts.Debug.assertNever(extensions); + return Debug.assertNever(extensions); } } @@ -1918,7 +1937,7 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st return noPackageId(resolved); } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); + trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); } } @@ -1938,14 +1957,14 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st return result; }; - const onlyRecordFailuresForPackageFile = packageFile ? !ts.directoryProbablyExists(ts.getDirectoryPath(packageFile), state.host) : undefined; - const onlyRecordFailuresForIndex = onlyRecordFailures || !ts.directoryProbablyExists(candidate, state.host); - const indexPath = ts.combinePaths(candidate, extensions === Extensions.TSConfig ? "tsconfig" : "index"); + const onlyRecordFailuresForPackageFile = packageFile ? !directoryProbablyExists(getDirectoryPath(packageFile), state.host) : undefined; + const onlyRecordFailuresForIndex = onlyRecordFailures || !directoryProbablyExists(candidate, state.host); + const indexPath = combinePaths(candidate, extensions === Extensions.TSConfig ? "tsconfig" : "index"); - if (versionPaths && (!packageFile || ts.containsPath(candidate, packageFile))) { - const moduleName = ts.getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false); + if (versionPaths && (!packageFile || containsPath(candidate, packageFile))) { + const moduleName = getRelativePathFromDirectory(candidate, packageFile || indexPath, /*ignoreCase*/ false); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, ts.version, moduleName); + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, moduleName); } const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, /*pathPatterns*/ undefined, loader, onlyRecordFailuresForPackageFile || onlyRecordFailuresForIndex, state); if (result) { @@ -1965,47 +1984,47 @@ function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: st /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ function resolvedIfExtensionMatches(extensions: Extensions, path: string): PathAndExtension | undefined { - const ext = ts.tryGetExtensionFromPath(path); + const ext = tryGetExtensionFromPath(path); return ext !== undefined && extensionIsOk(extensions, ext) ? { path, ext } : undefined; } /** True if `extension` is one of the supported `extensions`. */ -function extensionIsOk(extensions: Extensions, extension: ts.Extension): boolean { +function extensionIsOk(extensions: Extensions, extension: Extension): boolean { switch (extensions) { case Extensions.JavaScript: - return extension === ts.Extension.Js || extension === ts.Extension.Jsx || extension === ts.Extension.Mjs || extension === ts.Extension.Cjs; + return extension === Extension.Js || extension === Extension.Jsx || extension === Extension.Mjs || extension === Extension.Cjs; case Extensions.TSConfig: case Extensions.Json: - return extension === ts.Extension.Json; + return extension === Extension.Json; case Extensions.TypeScript: - return extension === ts.Extension.Ts || extension === ts.Extension.Tsx || extension === ts.Extension.Mts || extension === ts.Extension.Cts || extension === ts.Extension.Dts || extension === ts.Extension.Dmts || extension === ts.Extension.Dcts; + return extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Mts || extension === Extension.Cts || extension === Extension.Dts || extension === Extension.Dmts || extension === Extension.Dcts; case Extensions.TsOnly: - return extension === ts.Extension.Ts || extension === ts.Extension.Tsx || extension === ts.Extension.Mts || extension === ts.Extension.Cts; + return extension === Extension.Ts || extension === Extension.Tsx || extension === Extension.Mts || extension === Extension.Cts; case Extensions.DtsOnly: - return extension === ts.Extension.Dts || extension === ts.Extension.Dmts || extension === ts.Extension.Dcts; + return extension === Extension.Dts || extension === Extension.Dmts || extension === Extension.Dcts; } } /* @internal */ export function parsePackageName(moduleName: string): { packageName: string, rest: string } { - let idx = moduleName.indexOf(ts.directorySeparator); + let idx = moduleName.indexOf(directorySeparator); if (moduleName[0] === "@") { - idx = moduleName.indexOf(ts.directorySeparator, idx + 1); + idx = moduleName.indexOf(directorySeparator, idx + 1); } return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } /* @internal */ -export function allKeysStartWithDot(obj: ts.MapLike) { - return ts.every(ts.getOwnKeys(obj), k => ts.startsWith(k, ".")); +export function allKeysStartWithDot(obj: MapLike) { + return every(getOwnKeys(obj), k => startsWith(k, ".")); } -function noKeyStartsWithDot(obj: ts.MapLike) { - return !ts.some(ts.getOwnKeys(obj), k => ts.startsWith(k, ".")); +function noKeyStartsWithDot(obj: MapLike) { + return !some(getOwnKeys(obj), k => startsWith(k, ".")); } -function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): SearchResult { - const directoryPath = ts.getNormalizedAbsolutePath(ts.combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); +function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { + const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); const scope = getPackageScopeForPath(directoryPath, state); if (!scope || !scope.contents.packageJsonContent.exports) { return undefined; @@ -2013,37 +2032,37 @@ function loadModuleFromSelfNameReference(extensions: Extensions, moduleName: str if (typeof scope.contents.packageJsonContent.name !== "string") { return undefined; } - const parts = ts.getPathComponents(moduleName); // unrooted paths should have `""` as their 0th entry - const nameParts = ts.getPathComponents(scope.contents.packageJsonContent.name); - if (!ts.every(nameParts, (p, i) => parts[i] === p)) { + const parts = getPathComponents(moduleName); // unrooted paths should have `""` as their 0th entry + const nameParts = getPathComponents(scope.contents.packageJsonContent.name); + if (!every(nameParts, (p, i) => parts[i] === p)) { return undefined; } const trailingParts = parts.slice(nameParts.length); - return loadModuleFromExports(scope, extensions, !ts.length(trailingParts) ? "." : `.${ts.directorySeparator}${trailingParts.join(ts.directorySeparator)}`, state, cache, redirectedReference); + return loadModuleFromExports(scope, extensions, !length(trailingParts) ? "." : `.${directorySeparator}${trailingParts.join(directorySeparator)}`, state, cache, redirectedReference); } -function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, subpath: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): SearchResult { +function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, subpath: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { if (!scope.contents.packageJsonContent.exports) { return undefined; } if (subpath === ".") { let mainExport; - if (typeof scope.contents.packageJsonContent.exports === "string" || Array.isArray(scope.contents.packageJsonContent.exports) || (typeof scope.contents.packageJsonContent.exports === "object" && noKeyStartsWithDot(scope.contents.packageJsonContent.exports as ts.MapLike))) { + if (typeof scope.contents.packageJsonContent.exports === "string" || Array.isArray(scope.contents.packageJsonContent.exports) || (typeof scope.contents.packageJsonContent.exports === "object" && noKeyStartsWithDot(scope.contents.packageJsonContent.exports as MapLike))) { mainExport = scope.contents.packageJsonContent.exports; } - else if (ts.hasProperty(scope.contents.packageJsonContent.exports as ts.MapLike, ".")) { - mainExport = (scope.contents.packageJsonContent.exports as ts.MapLike)["."]; + else if (hasProperty(scope.contents.packageJsonContent.exports as MapLike, ".")) { + mainExport = (scope.contents.packageJsonContent.exports as MapLike)["."]; } if (mainExport) { const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, subpath, scope, /*isImports*/ false); return loadModuleFromTargetImportOrExport(mainExport, "", /*pattern*/ false, "."); } } - else if (allKeysStartWithDot(scope.contents.packageJsonContent.exports as ts.MapLike)) { + else if (allKeysStartWithDot(scope.contents.packageJsonContent.exports as MapLike)) { if (typeof scope.contents.packageJsonContent.exports !== "object") { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); + trace(state.host, Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); } return toSearchResult(/*value*/ undefined); } @@ -2054,29 +2073,29 @@ function loadModuleFromExports(scope: PackageJsonInfo, extensions: Extensions, s } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); + trace(state.host, Diagnostics.Export_specifier_0_does_not_exist_in_package_json_scope_at_path_1, subpath, scope.packageDirectory); } return toSearchResult(/*value*/ undefined); } -function loadModuleFromImports(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): SearchResult { - if (moduleName === "#" || ts.startsWith(moduleName, "#/")) { +function loadModuleFromImports(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { + if (moduleName === "#" || startsWith(moduleName, "#/")) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Invalid_import_specifier_0_has_no_possible_resolutions, moduleName); + trace(state.host, Diagnostics.Invalid_import_specifier_0_has_no_possible_resolutions, moduleName); } return toSearchResult(/*value*/ undefined); } - const directoryPath = ts.getNormalizedAbsolutePath(ts.combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); + const directoryPath = getNormalizedAbsolutePath(combinePaths(directory, "dummy"), state.host.getCurrentDirectory?.()); const scope = getPackageScopeForPath(directoryPath, state); if (!scope) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, directoryPath); + trace(state.host, Diagnostics.Directory_0_has_no_containing_package_json_scope_Imports_will_not_resolve, directoryPath); } return toSearchResult(/*value*/ undefined); } if (!scope.contents.packageJsonContent.imports) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_no_imports_defined, scope.packageDirectory); + trace(state.host, Diagnostics.package_json_scope_0_has_no_imports_defined, scope.packageDirectory); } return toSearchResult(/*value*/ undefined); } @@ -2087,7 +2106,7 @@ function loadModuleFromImports(extensions: Extensions, moduleName: string, direc } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Import_specifier_0_does_not_exist_in_package_json_scope_at_path_1, moduleName, scope.packageDirectory); + trace(state.host, Diagnostics.Import_specifier_0_does_not_exist_in_package_json_scope_at_path_1, moduleName, scope.packageDirectory); } return toSearchResult(/*value*/ undefined); } @@ -2111,14 +2130,14 @@ export function comparePatternKeys(a: string, b: string) { return 0; } -function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult | undefined { +function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult | undefined { const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, moduleName, scope, isImports); - if (!ts.endsWith(moduleName, ts.directorySeparator) && moduleName.indexOf("*") === -1 && ts.hasProperty(lookupTable, moduleName)) { + if (!endsWith(moduleName, directorySeparator) && moduleName.indexOf("*") === -1 && hasProperty(lookupTable, moduleName)) { const target = (lookupTable as {[idx: string]: unknown})[moduleName]; return loadModuleFromTargetImportOrExport(target, /*subpath*/ "", /*pattern*/ false, moduleName); } - const expandingKeys = ts.sort(ts.filter(ts.getOwnKeys(lookupTable as ts.MapLike), k => k.indexOf("*") !== -1 || ts.endsWith(k, "/")), comparePatternKeys); + const expandingKeys = sort(filter(getOwnKeys(lookupTable as MapLike), k => k.indexOf("*") !== -1 || endsWith(k, "/")), comparePatternKeys); for (const potentialTarget of expandingKeys) { if (state.features & NodeResolutionFeatures.ExportsPatternTrailers && matchesPatternWithTrailer(potentialTarget, moduleName)) { const target = (lookupTable as {[idx: string]: unknown})[potentialTarget]; @@ -2126,12 +2145,12 @@ function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleRes const subpath = moduleName.substring(potentialTarget.substring(0, starPos).length, moduleName.length - (potentialTarget.length - 1 - starPos)); return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget); } - else if (ts.endsWith(potentialTarget, "*") && ts.startsWith(moduleName, potentialTarget.substring(0, potentialTarget.length - 1))) { + else if (endsWith(potentialTarget, "*") && startsWith(moduleName, potentialTarget.substring(0, potentialTarget.length - 1))) { const target = (lookupTable as {[idx: string]: unknown})[potentialTarget]; const subpath = moduleName.substring(potentialTarget.length - 1); return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ true, potentialTarget); } - else if (ts.startsWith(moduleName, potentialTarget)) { + else if (startsWith(moduleName, potentialTarget)) { const target = (lookupTable as {[idx: string]: unknown})[potentialTarget]; const subpath = moduleName.substring(potentialTarget.length); return loadModuleFromTargetImportOrExport(target, subpath, /*pattern*/ false, potentialTarget); @@ -2139,91 +2158,91 @@ function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleRes } function matchesPatternWithTrailer(target: string, name: string) { - if (ts.endsWith(target, "*")) return false; // handled by next case in loop + if (endsWith(target, "*")) return false; // handled by next case in loop const starPos = target.indexOf("*"); if (starPos === -1) return false; // handled by last case in loop - return ts.startsWith(name, target.substring(0, starPos)) && ts.endsWith(name, target.substring(starPos + 1)); + return startsWith(name, target.substring(0, starPos)) && endsWith(name, target.substring(starPos + 1)); } } /** * Gets the self-recursive function specialized to retrieving the targeted import/export element for the given resolution configuration */ -function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined, moduleName: string, scope: PackageJsonInfo, isImports: boolean) { +function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, scope: PackageJsonInfo, isImports: boolean) { return loadModuleFromTargetImportOrExport; function loadModuleFromTargetImportOrExport(target: unknown, subpath: string, pattern: boolean, key: string): SearchResult | undefined { if (typeof target === "string") { - if (!pattern && subpath.length > 0 && !ts.endsWith(target, "/")) { + if (!pattern && subpath.length > 0 && !endsWith(target, "/")) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } - if (!ts.startsWith(target, "./")) { - if (isImports && !ts.startsWith(target, "../") && !ts.startsWith(target, "/") && !ts.isRootedDiskPath(target)) { + if (!startsWith(target, "./")) { + if (isImports && !startsWith(target, "../") && !startsWith(target, "/") && !isRootedDiskPath(target)) { const combinedLookup = pattern ? target.replace(/\*/g, subpath) : target + subpath; - traceIfEnabled(state, ts.Diagnostics.Using_0_subpath_1_with_target_2, "imports", key, combinedLookup); - traceIfEnabled(state, ts.Diagnostics.Resolving_module_0_from_1, combinedLookup, scope.packageDirectory + "/"); + traceIfEnabled(state, Diagnostics.Using_0_subpath_1_with_target_2, "imports", key, combinedLookup); + traceIfEnabled(state, Diagnostics.Resolving_module_0_from_1, combinedLookup, scope.packageDirectory + "/"); const result = nodeModuleNameResolverWorker(state.features, combinedLookup, scope.packageDirectory + "/", state.compilerOptions, state.host, cache, [extensions], redirectedReference); return toSearchResult(result.resolvedModule ? { path: result.resolvedModule.resolvedFileName, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId, originalPath: result.resolvedModule.originalPath } : undefined); } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } - const parts = ts.pathIsRelative(target) ? ts.getPathComponents(target).slice(1) : ts.getPathComponents(target); + const parts = pathIsRelative(target) ? getPathComponents(target).slice(1) : getPathComponents(target); const partsAfterFirst = parts.slice(1); if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } - const resolvedTarget = ts.combinePaths(scope.packageDirectory, target); + const resolvedTarget = combinePaths(scope.packageDirectory, target); // TODO: Assert that `resolvedTarget` is actually within the package directory? That's what the spec says.... but I'm not sure we need // to be in the business of validating everyone's import and export map correctness. - const subpathParts = ts.getPathComponents(subpath); + const subpathParts = getPathComponents(subpath); if (subpathParts.indexOf("..") >= 0 || subpathParts.indexOf(".") >= 0 || subpathParts.indexOf("node_modules") >= 0) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } if (state.traceEnabled) { trace(state.host, - ts.Diagnostics.Using_0_subpath_1_with_target_2, + Diagnostics.Using_0_subpath_1_with_target_2, isImports ? "imports" : "exports", key, pattern ? target.replace(/\*/g, subpath) : target + subpath); } const finalPath = toAbsolutePath(pattern ? resolvedTarget.replace(/\*/g, subpath) : resolvedTarget + subpath); - const inputLink = tryLoadInputFileForPath(finalPath, subpath, ts.combinePaths(scope.packageDirectory, "package.json"), isImports); + const inputLink = tryLoadInputFileForPath(finalPath, subpath, combinePaths(scope.packageDirectory, "package.json"), isImports); if (inputLink) return inputLink; return toSearchResult(withPackageId(scope, loadJSOrExactTSFileName(extensions, finalPath, /*onlyRecordFailures*/ false, state))); } else if (typeof target === "object" && target !== null) { // eslint-disable-line no-null/no-null if (!Array.isArray(target)) { - for (const condition of ts.getOwnKeys(target as ts.MapLike)) { + for (const condition of getOwnKeys(target as MapLike)) { if (condition === "default" || state.conditions.indexOf(condition) >= 0 || isApplicableVersionedTypesKey(state.conditions, condition)) { - traceIfEnabled(state, ts.Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition); - const subTarget = (target as ts.MapLike)[condition]; + traceIfEnabled(state, Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition); + const subTarget = (target as MapLike)[condition]; const result = loadModuleFromTargetImportOrExport(subTarget, subpath, pattern, key); if (result) { return result; } } else { - traceIfEnabled(state, ts.Diagnostics.Saw_non_matching_condition_0, condition); + traceIfEnabled(state, Diagnostics.Saw_non_matching_condition_0, condition); } } return undefined; } else { - if (!ts.length(target)) { + if (!length(target)) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } @@ -2237,12 +2256,12 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo } else if (target === null) { // eslint-disable-line no-null/no-null if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_explicitly_maps_specifier_1_to_null, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_explicitly_maps_specifier_1_to_null, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); } if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); + trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName); } return toSearchResult(/*value*/ undefined); @@ -2250,11 +2269,11 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo function toAbsolutePath(path: string | undefined): string | undefined; function toAbsolutePath(path: string | undefined): string | undefined { if (path === undefined) return path; - return ts.getNormalizedAbsolutePath(path, state.host.getCurrentDirectory?.()); + return getNormalizedAbsolutePath(path, state.host.getCurrentDirectory?.()); } function combineDirectoryPath(root: string, dir: string) { - return ts.ensureTrailingDirectorySeparator(ts.combinePaths(root, dir)); + return ensureTrailingDirectorySeparator(combinePaths(root, dir)); } function useCaseSensitiveFileNames() { @@ -2272,18 +2291,18 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo if ((extensions === Extensions.TypeScript || extensions === Extensions.JavaScript || extensions === Extensions.Json) && (state.compilerOptions.declarationDir || state.compilerOptions.outDir) && finalPath.indexOf("/node_modules/") === -1 - && (state.compilerOptions.configFile ? ts.containsPath(scope.packageDirectory, toAbsolutePath(state.compilerOptions.configFile.fileName), !useCaseSensitiveFileNames()) : true) + && (state.compilerOptions.configFile ? containsPath(scope.packageDirectory, toAbsolutePath(state.compilerOptions.configFile.fileName), !useCaseSensitiveFileNames()) : true) ) { // So that all means we'll only try these guesses for files outside `node_modules` in a directory where the `package.json` and `tsconfig.json` are siblings. // Even with all that, we still don't know if the root of the output file structure will be (relative to the package file) // `.`, `./src` or any other deeper directory structure. (If project references are used, it's definitely `.` by fiat, so that should be pretty common.) - const getCanonicalFileName = ts.hostGetCanonicalFileName({ useCaseSensitiveFileNames }); + const getCanonicalFileName = hostGetCanonicalFileName({ useCaseSensitiveFileNames }); const commonSourceDirGuesses: string[] = []; // A `rootDir` compiler option strongly indicates the root location // A `composite` project is using project references and has it's common src dir set to `.`, so it shouldn't need to check any other locations if (state.compilerOptions.rootDir || (state.compilerOptions.composite && state.compilerOptions.configFilePath)) { - const commonDir = toAbsolutePath(ts.getCommonSourceDirectory(state.compilerOptions, () => [], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); + const commonDir = toAbsolutePath(getCommonSourceDirectory(state.compilerOptions, () => [], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); commonSourceDirGuesses.push(commonDir); } else if (state.requestContainingDirectory) { @@ -2301,7 +2320,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo // But we do have more context! Just a tiny bit more! We're resolving an import _for some other input file_! And that input file, too // must be inside the common source directory! So we propagate that tidbit of info all the way to here via state.requestContainingDirectory - const requestingFile = toAbsolutePath(ts.combinePaths(state.requestContainingDirectory, "index.ts")); + const requestingFile = toAbsolutePath(combinePaths(state.requestContainingDirectory, "index.ts")); // And we can try every folder above the common folder for the request folder and the config/package base directory // This technically can be wrong - we may load ./src/index.ts when ./src/sub/index.ts was right because we don't // know if only `./src/sub` files were loaded by the program; but this has the best chance to be right of just about anything @@ -2309,23 +2328,23 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo // be a file outside of `./src/sub` in the program (the file we resolved to), making us de-facto right. So this fallback lookup // logic may influence what files are pulled in by self-names, which in turn influences the output path shape, but it's all // internally consistent so the paths should be stable so long as we prefer the "most general" (meaning: top-most-level directory) possible results first. - const commonDir = toAbsolutePath(ts.getCommonSourceDirectory(state.compilerOptions, () => [requestingFile, toAbsolutePath(packagePath)], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); + const commonDir = toAbsolutePath(getCommonSourceDirectory(state.compilerOptions, () => [requestingFile, toAbsolutePath(packagePath)], state.host.getCurrentDirectory?.() || "", getCanonicalFileName)); commonSourceDirGuesses.push(commonDir); - let fragment = ts.ensureTrailingDirectorySeparator(commonDir); + let fragment = ensureTrailingDirectorySeparator(commonDir); while (fragment && fragment.length > 1) { - const parts = ts.getPathComponents(fragment); + const parts = getPathComponents(fragment); parts.pop(); // remove a directory - const commonDir = ts.getPathFromPathComponents(parts); + const commonDir = getPathFromPathComponents(parts); commonSourceDirGuesses.unshift(commonDir); - fragment = ts.ensureTrailingDirectorySeparator(commonDir); + fragment = ensureTrailingDirectorySeparator(commonDir); } } if (commonSourceDirGuesses.length > 1) { - state.reportDiagnostic(ts.createCompilerDiagnostic( + state.reportDiagnostic(createCompilerDiagnostic( isImports - ? ts.Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_import_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate - : ts.Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_export_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate, + ? Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_import_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate + : Diagnostics.The_project_root_is_ambiguous_but_is_required_to_resolve_export_map_entry_0_in_file_1_Supply_the_rootDir_compiler_option_to_disambiguate, entry === "" ? "." : entry, // replace empty string with `.` - the reverse of the operation done when entries are built - so main entrypoint errors don't look weird packagePath )); @@ -2333,18 +2352,18 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo for (const commonSourceDirGuess of commonSourceDirGuesses) { const candidateDirectories = getOutputDirectoriesForBaseDirectory(commonSourceDirGuess); for (const candidateDir of candidateDirectories) { - if (ts.containsPath(candidateDir, finalPath, !useCaseSensitiveFileNames())) { + if (containsPath(candidateDir, finalPath, !useCaseSensitiveFileNames())) { // The matched export is looking up something in either the out declaration or js dir, now map the written path back into the source dir and source extension const pathFragment = finalPath.slice(candidateDir.length + 1); // +1 to also remove directory seperator - const possibleInputBase = ts.combinePaths(commonSourceDirGuess, pathFragment); - const jsAndDtsExtensions = [ts.Extension.Mjs, ts.Extension.Cjs, ts.Extension.Js, ts.Extension.Json, ts.Extension.Dmts, ts.Extension.Dcts, ts.Extension.Dts]; + const possibleInputBase = combinePaths(commonSourceDirGuess, pathFragment); + const jsAndDtsExtensions = [Extension.Mjs, Extension.Cjs, Extension.Js, Extension.Json, Extension.Dmts, Extension.Dcts, Extension.Dts]; for (const ext of jsAndDtsExtensions) { - if (ts.fileExtensionIs(possibleInputBase, ext)) { - const inputExts = ts.getPossibleOriginalInputExtensionForExtension(possibleInputBase); + if (fileExtensionIs(possibleInputBase, ext)) { + const inputExts = getPossibleOriginalInputExtensionForExtension(possibleInputBase); for (const possibleExt of inputExts) { - const possibleInputWithInputExtension = ts.changeAnyExtension(possibleInputBase, possibleExt, ext, !useCaseSensitiveFileNames()); - if ((extensions === Extensions.TypeScript && ts.hasJSFileExtension(possibleInputWithInputExtension)) || - (extensions === Extensions.JavaScript && ts.hasTSFileExtension(possibleInputWithInputExtension))) { + const possibleInputWithInputExtension = changeAnyExtension(possibleInputBase, possibleExt, ext, !useCaseSensitiveFileNames()); + if ((extensions === Extensions.TypeScript && hasJSFileExtension(possibleInputWithInputExtension)) || + (extensions === Extensions.JavaScript && hasTSFileExtension(possibleInputWithInputExtension))) { continue; } if (state.host.fileExists(possibleInputWithInputExtension)) { @@ -2379,13 +2398,13 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo /* @internal */ export function isApplicableVersionedTypesKey(conditions: readonly string[], key: string) { if (conditions.indexOf("types") === -1) return false; // only apply versioned types conditions if the types condition is applied - if (!ts.startsWith(key, "types@")) return false; - const range = ts.VersionRange.tryParse(key.substring("types@".length)); + if (!startsWith(key, "types@")) return false; + const range = VersionRange.tryParse(key.substring("types@".length)); if (!range) return false; - return range.test(ts.version); + return range.test(version); } -function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): SearchResult { +function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { return loadModuleFromNearestNodeModulesDirectoryWorker(extensions, moduleName, directory, state, /*typesScopeOnly*/ false, cache, redirectedReference); } @@ -2394,10 +2413,10 @@ function loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName: string, return loadModuleFromNearestNodeModulesDirectoryWorker(Extensions.DtsOnly, moduleName, directory, state, /*typesScopeOnly*/ true, /*cache*/ undefined, /*redirectedReference*/ undefined); } -function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): SearchResult { - const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, state.features === 0 ? undefined : state.features & NodeResolutionFeatures.EsmMode ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS, redirectedReference); - return ts.forEachAncestorDirectory(ts.normalizeSlashes(directory), ancestorDirectory => { - if (ts.getBaseFileName(ancestorDirectory) !== "node_modules") { +function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): SearchResult { + const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, state.features === 0 ? undefined : state.features & NodeResolutionFeatures.EsmMode ? ModuleKind.ESNext : ModuleKind.CommonJS, redirectedReference); + return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { + if (getBaseFileName(ancestorDirectory) !== "node_modules") { const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, ancestorDirectory, state); if (resolutionFromCache) { return resolutionFromCache; @@ -2407,11 +2426,11 @@ function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, }); } -function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): Resolved | undefined { - const nodeModulesFolder = ts.combinePaths(directory, "node_modules"); - const nodeModulesFolderExists = ts.directoryProbablyExists(nodeModulesFolder, state.host); +function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): Resolved | undefined { + const nodeModulesFolder = combinePaths(directory, "node_modules"); + const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); if (!nodeModulesFolderExists && state.traceEnabled) { - trace(state.host, ts.Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesFolder); + trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesFolder); } const packageResult = typesScopeOnly ? undefined : loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, state, cache, redirectedReference); @@ -2419,11 +2438,11 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod return packageResult; } if (extensions === Extensions.TypeScript || extensions === Extensions.DtsOnly) { - const nodeModulesAtTypes = ts.combinePaths(nodeModulesFolder, "@types"); + const nodeModulesAtTypes = combinePaths(nodeModulesFolder, "@types"); let nodeModulesAtTypesExists = nodeModulesFolderExists; - if (nodeModulesFolderExists && !ts.directoryProbablyExists(nodeModulesAtTypes, state.host)) { + if (nodeModulesFolderExists && !directoryProbablyExists(nodeModulesAtTypes, state.host)) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesAtTypes); + trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesAtTypes); } nodeModulesAtTypesExists = false; } @@ -2431,8 +2450,8 @@ function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, mod } } -function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ts.ResolvedProjectReference | undefined): Resolved | undefined { - const candidate = ts.normalizePath(ts.combinePaths(nodeModulesDirectory, moduleName)); +function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined): Resolved | undefined { + const candidate = normalizePath(combinePaths(nodeModulesDirectory, moduleName)); // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. let packageInfo = getPackageJsonInfo(candidate, !nodeModulesDirectoryExists, state); @@ -2475,26 +2494,26 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu ) { // EsmMode disables index lookup in `loadNodeModuleFromDirectoryWorker` generally, however non-relative package resolutions still assume // a default `index.js` entrypoint if no `main` or `exports` are present - pathAndExtension = loadModuleFromFile(extensions, ts.combinePaths(candidate, "index.js"), onlyRecordFailures, state); + pathAndExtension = loadModuleFromFile(extensions, combinePaths(candidate, "index.js"), onlyRecordFailures, state); } return withPackageId(packageInfo, pathAndExtension); }; const { packageName, rest } = parsePackageName(moduleName); - const packageDirectory = ts.combinePaths(nodeModulesDirectory, packageName); + const packageDirectory = combinePaths(nodeModulesDirectory, packageName); if (rest !== "") { // Previous `packageInfo` may have been from a nested package.json; ensure we have the one from the package root now. packageInfo = getPackageJsonInfo(packageDirectory, !nodeModulesDirectoryExists, state); } // package exports are higher priority than file/directory/typesVersions lookups and (and, if there's exports present, blocks them) if (packageInfo && packageInfo.contents.packageJsonContent.exports && state.features & NodeResolutionFeatures.Exports) { - return loadModuleFromExports(packageInfo, extensions, ts.combinePaths(".", rest), state, cache, redirectedReference)?.value; + return loadModuleFromExports(packageInfo, extensions, combinePaths(".", rest), state, cache, redirectedReference)?.value; } if (rest !== "" && packageInfo && packageInfo.contents.versionPaths) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, packageInfo.contents.versionPaths.version, ts.version, rest); + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, packageInfo.contents.versionPaths.version, version, rest); } - const packageDirectoryExists = nodeModulesDirectoryExists && ts.directoryProbablyExists(packageDirectory, state.host); + const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host); const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, packageInfo.contents.versionPaths.paths, /*pathPatterns*/ undefined, loader, !packageDirectoryExists, state); if (fromPaths) { return fromPaths.value; @@ -2504,31 +2523,31 @@ function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, modu return loader(extensions, candidate, !nodeModulesDirectoryExists, state); } -function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, baseDirectory: string, paths: ts.MapLike, pathPatterns: readonly (string | ts.Pattern)[] | undefined, loader: ResolutionKindSpecificLoader, onlyRecordFailures: boolean, state: ModuleResolutionState): SearchResult { - pathPatterns ||= ts.tryParsePatterns(paths); - const matchedPattern = ts.matchPatternOrExact(pathPatterns, moduleName); +function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, baseDirectory: string, paths: MapLike, pathPatterns: readonly (string | Pattern)[] | undefined, loader: ResolutionKindSpecificLoader, onlyRecordFailures: boolean, state: ModuleResolutionState): SearchResult { + pathPatterns ||= tryParsePatterns(paths); + const matchedPattern = matchPatternOrExact(pathPatterns, moduleName); if (matchedPattern) { - const matchedStar = ts.isString(matchedPattern) ? undefined : ts.matchedText(matchedPattern, moduleName); - const matchedPatternText = ts.isString(matchedPattern) ? matchedPattern : ts.patternText(matchedPattern); + const matchedStar = isString(matchedPattern) ? undefined : matchedText(matchedPattern, moduleName); + const matchedPatternText = isString(matchedPattern) ? matchedPattern : patternText(matchedPattern); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); } - const resolved = ts.forEach(paths[matchedPatternText], subst => { + const resolved = forEach(paths[matchedPatternText], subst => { const path = matchedStar ? subst.replace("*", matchedStar) : subst; // When baseUrl is not specified, the command line parser resolves relative paths to the config file location. - const candidate = ts.normalizePath(ts.combinePaths(baseDirectory, path)); + const candidate = normalizePath(combinePaths(baseDirectory, path)); if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); + trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); } // A path mapping may have an extension, in contrast to an import, which should omit it. - const extension = ts.tryGetExtensionFromPath(subst); + const extension = tryGetExtensionFromPath(subst); if (extension !== undefined) { const path = tryFile(candidate, onlyRecordFailures, state); if (path !== undefined) { return noPackageId({ path, ext: extension }); } } - return loader(extensions, candidate, onlyRecordFailures || !ts.directoryProbablyExists(ts.getDirectoryPath(candidate), state.host), state); + return loader(extensions, candidate, onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); }); return { value: resolved }; } @@ -2541,7 +2560,7 @@ const mangledScopedPackageSeparator = "__"; function mangleScopedPackageNameWithTrace(packageName: string, state: ModuleResolutionState): string { const mangled = mangleScopedPackageName(packageName); if (state.traceEnabled && mangled !== packageName) { - trace(state.host, ts.Diagnostics.Scoped_package_detected_looking_in_0, mangled); + trace(state.host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); } return mangled; } @@ -2553,8 +2572,8 @@ export function getTypesPackageName(packageName: string): string { /* @internal */ export function mangleScopedPackageName(packageName: string): string { - if (ts.startsWith(packageName, "@")) { - const replaceSlash = packageName.replace(ts.directorySeparator, mangledScopedPackageSeparator); + if (startsWith(packageName, "@")) { + const replaceSlash = packageName.replace(directorySeparator, mangledScopedPackageSeparator); if (replaceSlash !== packageName) { return replaceSlash.slice(1); // Take off the "@" } @@ -2564,7 +2583,7 @@ export function mangleScopedPackageName(packageName: string): string { /* @internal */ export function getPackageNameFromTypesPackageName(mangledName: string): string { - const withoutAtTypePrefix = ts.removePrefix(mangledName, "@types/"); + const withoutAtTypePrefix = removePrefix(mangledName, "@types/"); if (withoutAtTypePrefix !== mangledName) { return unmangleScopedPackageName(withoutAtTypePrefix); } @@ -2573,8 +2592,8 @@ export function getPackageNameFromTypesPackageName(mangledName: string): string /* @internal */ export function unmangleScopedPackageName(typesPackageName: string): string { - return ts.stringContains(typesPackageName, mangledScopedPackageSeparator) ? - "@" + typesPackageName.replace(mangledScopedPackageSeparator, ts.directorySeparator) : + return stringContains(typesPackageName, mangledScopedPackageSeparator) ? + "@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) : typesPackageName; } @@ -2582,19 +2601,19 @@ function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefin const result = cache && cache.get(containingDirectory); if (result) { if (state.traceEnabled) { - trace(state.host, ts.Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); + trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); } state.resultFromCache = result; return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, originalPath: result.resolvedModule.originalPath || true, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } }; } } -export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ts.ResolvedProjectReference): ts.ResolvedModuleWithFailedLookupLocations { +export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache, redirectedReference?: ResolvedProjectReference): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; const affectingLocations: string[] = []; - const containingDirectory = ts.getDirectoryPath(containingFile); - const diagnostics: ts.Diagnostic[] = []; + const containingDirectory = getDirectoryPath(containingFile); + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, @@ -2624,15 +2643,15 @@ export function classicNameResolver(moduleName: string, containingFile: string, return { value: resolvedUsingSettings }; } - if (!ts.isExternalModuleNameRelative(moduleName)) { + if (!isExternalModuleNameRelative(moduleName)) { const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName, /*mode*/ undefined, redirectedReference); // Climb up parent directories looking for a module. - const resolved = ts.forEachAncestorDirectory(containingDirectory, directory => { + const resolved = forEachAncestorDirectory(containingDirectory, directory => { const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, state); if (resolutionFromCache) { return resolutionFromCache; } - const searchName = ts.normalizePath(ts.combinePaths(directory, moduleName)); + const searchName = normalizePath(combinePaths(directory, moduleName)); return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, /*onlyRecordFailures*/ false, state)); }); if (resolved) { @@ -2644,7 +2663,7 @@ export function classicNameResolver(moduleName: string, containingFile: string, } } else { - const candidate = ts.normalizePath(ts.combinePaths(containingDirectory, moduleName)); + const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, /*onlyRecordFailures*/ false, state)); } } @@ -2655,14 +2674,14 @@ export function classicNameResolver(moduleName: string, containingFile: string, * This is the minumum code needed to expose that functionality; the rest is in the host. */ /* @internal */ -export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, globalCache: string, packageJsonInfoCache: PackageJsonInfoCache): ts.ResolvedModuleWithFailedLookupLocations { +export function loadModuleFromGlobalCache(moduleName: string, projectName: string | undefined, compilerOptions: CompilerOptions, host: ModuleResolutionHost, globalCache: string, packageJsonInfoCache: PackageJsonInfoCache): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); if (traceEnabled) { - trace(host, ts.Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); + trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); } const failedLookupLocations: string[] = []; const affectingLocations: string[] = []; - const diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; const state: ModuleResolutionState = { compilerOptions, host, @@ -2705,7 +2724,7 @@ function toSearchResult(value: T | undefined): SearchResult { return value !== undefined ? { value } : undefined; } -function traceIfEnabled(state: ModuleResolutionState, diagnostic: ts.DiagnosticMessage, ...args: string[]) { +function traceIfEnabled(state: ModuleResolutionState, diagnostic: DiagnosticMessage, ...args: string[]) { if (state.traceEnabled) { trace(state.host, diagnostic, ...args); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 56d03a007fdfe..27075cf9e4577 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -1,4 +1,23 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, allKeysStartWithDot, AmbientModuleDeclaration, append, arrayFrom, CharacterCodes, combinePaths, + compareBooleans, compareNumberOfDirectorySeparators, comparePaths, Comparison, CompilerOptions, containsIgnoredPath, + containsPath, createGetCanonicalFileName, Debug, directorySeparator, emptyArray, endsWith, + ensurePathIsNonModuleName, ensureTrailingDirectorySeparator, every, ExportAssignment, Extension, extensionFromPath, + fileExtensionIsOneOf, FileIncludeKind, firstDefined, flatMap, flatten, forEach, forEachAncestorDirectory, + GetCanonicalFileName, getDirectoryPath, getEmitModuleResolutionKind, getImpliedNodeFormatForFile, + getModeForResolutionAtIndex, getModuleNameStringLiteralAt, getNodeModulePathParts, getNormalizedAbsolutePath, + getOwnKeys, getPackageJsonTypesVersionsPaths, getPackageNameFromTypesPackageName, getPathsBasePath, + getRelativePathFromDirectory, getRelativePathToDirectoryOrUrl, getSourceFileOfModule, getSupportedExtensions, + getTextOfIdentifierOrLiteral, hasJSFileExtension, hasTSFileExtension, hostGetCanonicalFileName, Identifier, + isAmbientModule, isApplicableVersionedTypesKey, isExternalModuleAugmentation, isExternalModuleNameRelative, + isModuleBlock, isModuleDeclaration, isNonGlobalAmbientModule, isRootedDiskPath, isSourceFile, isString, JsxEmit, + map, Map, mapDefined, MapLike, matchPatternOrExact, min, ModuleDeclaration, ModuleKind, ModulePath, + ModuleResolutionHost, ModuleResolutionKind, ModuleSpecifierCache, ModuleSpecifierOptions, + ModuleSpecifierResolutionHost, NodeFlags, NodeModulePathParts, normalizePath, Path, pathContainsNodeModules, + pathIsBareSpecifier, pathIsRelative, PropertyAccessExpression, removeFileExtension, removeSuffix, resolvePath, + ScriptKind, some, SourceFile, startsWith, startsWithDirectory, stringContains, StringLiteral, Symbol, SymbolFlags, + toPath, tryGetExtensionFromPath, tryParsePatterns, TypeChecker, UserPreferences, +} from "./_namespaces/ts"; // Used by importFixes, getEditsForFileRename, and declaration emit to synthesize import module specifiers. @@ -12,7 +31,7 @@ interface Preferences { readonly ending: Ending; } -function getPreferences(host: ts.ModuleSpecifierResolutionHost, { importModuleSpecifierPreference, importModuleSpecifierEnding }: ts.UserPreferences, compilerOptions: ts.CompilerOptions, importingSourceFile: ts.SourceFile): Preferences { +function getPreferences(host: ModuleSpecifierResolutionHost, { importModuleSpecifierPreference, importModuleSpecifierEnding }: UserPreferences, compilerOptions: CompilerOptions, importingSourceFile: SourceFile): Preferences { return { relativePreference: importModuleSpecifierPreference === "relative" ? RelativePreference.Relative : @@ -27,32 +46,32 @@ function getPreferences(host: ts.ModuleSpecifierResolutionHost, { importModuleSp case "index": return Ending.Index; case "js": return Ending.JsExtension; default: return usesJsExtensionOnImports(importingSourceFile) || isFormatRequiringExtensions(compilerOptions, importingSourceFile.path, host) ? Ending.JsExtension - : ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeJs ? Ending.Index : Ending.Minimal; + : getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs ? Ending.Index : Ending.Minimal; } } } -function getPreferencesForUpdate(compilerOptions: ts.CompilerOptions, oldImportSpecifier: string, importingSourceFileName: ts.Path, host: ts.ModuleSpecifierResolutionHost): Preferences { +function getPreferencesForUpdate(compilerOptions: CompilerOptions, oldImportSpecifier: string, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Preferences { return { - relativePreference: ts.isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative, - ending: ts.hasJSFileExtension(oldImportSpecifier) || isFormatRequiringExtensions(compilerOptions, importingSourceFileName, host) ? + relativePreference: isExternalModuleNameRelative(oldImportSpecifier) ? RelativePreference.Relative : RelativePreference.NonRelative, + ending: hasJSFileExtension(oldImportSpecifier) || isFormatRequiringExtensions(compilerOptions, importingSourceFileName, host) ? Ending.JsExtension : - ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeJs || ts.endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal, + getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeJs || endsWith(oldImportSpecifier, "index") ? Ending.Index : Ending.Minimal, }; } -function isFormatRequiringExtensions(compilerOptions: ts.CompilerOptions, importingSourceFileName: ts.Path, host: ts.ModuleSpecifierResolutionHost) { - if (ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.Node16 - && ts.getEmitModuleResolutionKind(compilerOptions) !== ts.ModuleResolutionKind.NodeNext) { +function isFormatRequiringExtensions(compilerOptions: CompilerOptions, importingSourceFileName: Path, host: ModuleSpecifierResolutionHost) { + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 + && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { return false; } - return ts.getImpliedNodeFormatForFile(importingSourceFileName, host.getPackageJsonInfoCache?.(), getModuleResolutionHost(host), compilerOptions) !== ts.ModuleKind.CommonJS; + return getImpliedNodeFormatForFile(importingSourceFileName, host.getPackageJsonInfoCache?.(), getModuleResolutionHost(host), compilerOptions) !== ModuleKind.CommonJS; } -function getModuleResolutionHost(host: ts.ModuleSpecifierResolutionHost): ts.ModuleResolutionHost { +function getModuleResolutionHost(host: ModuleSpecifierResolutionHost): ModuleResolutionHost { return { fileExists: host.fileExists, - readFile: ts.Debug.checkDefined(host.readFile), + readFile: Debug.checkDefined(host.readFile), directoryExists: host.directoryExists, getCurrentDirectory: host.getCurrentDirectory, realpath: host.realpath, @@ -66,13 +85,13 @@ function getModuleResolutionHost(host: ts.ModuleSpecifierResolutionHost): ts.Mod // `impliedNodeFormat` and to detect certain preferences from existing import module specifiers. /** @internal */ export function updateModuleSpecifier( - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - importingSourceFileName: ts.Path, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + importingSourceFileName: Path, toFileName: string, - host: ts.ModuleSpecifierResolutionHost, + host: ModuleSpecifierResolutionHost, oldImportSpecifier: string, - options: ts.ModuleSpecifierOptions = {}, + options: ModuleSpecifierOptions = {}, ): string | undefined { const res = getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferencesForUpdate(compilerOptions, oldImportSpecifier, importingSourceFileName, host), {}, options); if (res === oldImportSpecifier) return undefined; @@ -87,54 +106,54 @@ export function updateModuleSpecifier( // specifiers. /** @internal */ export function getModuleSpecifier( - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - importingSourceFileName: ts.Path, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + importingSourceFileName: Path, toFileName: string, - host: ts.ModuleSpecifierResolutionHost, - options: ts.ModuleSpecifierOptions = {}, + host: ModuleSpecifierResolutionHost, + options: ModuleSpecifierOptions = {}, ): string { return getModuleSpecifierWorker(compilerOptions, importingSourceFile, importingSourceFileName, toFileName, host, getPreferences(host, {}, compilerOptions, importingSourceFile), {}, options); } /** @internal */ export function getNodeModulesPackageName( - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, nodeModulesFileName: string, - host: ts.ModuleSpecifierResolutionHost, - preferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + host: ModuleSpecifierResolutionHost, + preferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ): string | undefined { const info = getInfo(importingSourceFile.path, host); const modulePaths = getAllModulePaths(importingSourceFile.path, nodeModulesFileName, host, preferences, options); - return ts.firstDefined(modulePaths, + return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, preferences, /*packageNameOnly*/ true, options.overrideImportMode)); } function getModuleSpecifierWorker( - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - importingSourceFileName: ts.Path, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + importingSourceFileName: Path, toFileName: string, - host: ts.ModuleSpecifierResolutionHost, + host: ModuleSpecifierResolutionHost, preferences: Preferences, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {} + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {} ): string { const info = getInfo(importingSourceFileName, host); const modulePaths = getAllModulePaths(importingSourceFileName, toFileName, host, userPreferences, options); - return ts.firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) || + return firstDefined(modulePaths, modulePath => tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode)) || getLocalModuleSpecifier(toFileName, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences); } /** @internal */ export function tryGetModuleSpecifiersFromCache( - moduleSymbol: ts.Symbol, - importingSourceFile: ts.SourceFile, - host: ts.ModuleSpecifierResolutionHost, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + moduleSymbol: Symbol, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ): readonly string[] | undefined { return tryGetModuleSpecifiersFromCacheWorker( moduleSymbol, @@ -145,15 +164,15 @@ export function tryGetModuleSpecifiersFromCache( } function tryGetModuleSpecifiersFromCacheWorker( - moduleSymbol: ts.Symbol, - importingSourceFile: ts.SourceFile, - host: ts.ModuleSpecifierResolutionHost, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, -): readonly [specifiers?: readonly string[], moduleFile?: ts.SourceFile, modulePaths?: readonly ts.ModulePath[], cache?: ts.ModuleSpecifierCache] { - const moduleSourceFile = ts.getSourceFileOfModule(moduleSymbol); + moduleSymbol: Symbol, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {}, +): readonly [specifiers?: readonly string[], moduleFile?: SourceFile, modulePaths?: readonly ModulePath[], cache?: ModuleSpecifierCache] { + const moduleSourceFile = getSourceFileOfModule(moduleSymbol); if (!moduleSourceFile) { - return ts.emptyArray as []; + return emptyArray as []; } const cache = host.getModuleSpecifierCache?.(); @@ -164,13 +183,13 @@ function tryGetModuleSpecifiersFromCacheWorker( /** @internal */ /** Returns an import for each symlink and for the realpath. */ export function getModuleSpecifiers( - moduleSymbol: ts.Symbol, - checker: ts.TypeChecker, - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - host: ts.ModuleSpecifierResolutionHost, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + moduleSymbol: Symbol, + checker: TypeChecker, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ): readonly string[] { return getModuleSpecifiersWithCacheInfo( moduleSymbol, @@ -185,13 +204,13 @@ export function getModuleSpecifiers( /** @internal */ export function getModuleSpecifiersWithCacheInfo( - moduleSymbol: ts.Symbol, - checker: ts.TypeChecker, - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - host: ts.ModuleSpecifierResolutionHost, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + moduleSymbol: Symbol, + checker: TypeChecker, + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ): { moduleSpecifiers: readonly string[], computedWithoutCache: boolean } { let computedWithoutCache = false; const ambient = tryGetModuleNameFromAmbientModule(moduleSymbol, checker); @@ -206,7 +225,7 @@ export function getModuleSpecifiersWithCacheInfo( options ); if (specifiers) return { moduleSpecifiers: specifiers, computedWithoutCache }; - if (!moduleSourceFile) return { moduleSpecifiers: ts.emptyArray, computedWithoutCache }; + if (!moduleSourceFile) return { moduleSpecifiers: emptyArray, computedWithoutCache }; computedWithoutCache = true; modulePaths ||= getAllModulePathsWorker(importingSourceFile.path, moduleSourceFile.originalFileName, host); @@ -216,25 +235,25 @@ export function getModuleSpecifiersWithCacheInfo( } function computeModuleSpecifiers( - modulePaths: readonly ts.ModulePath[], - compilerOptions: ts.CompilerOptions, - importingSourceFile: ts.SourceFile, - host: ts.ModuleSpecifierResolutionHost, - userPreferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + modulePaths: readonly ModulePath[], + compilerOptions: CompilerOptions, + importingSourceFile: SourceFile, + host: ModuleSpecifierResolutionHost, + userPreferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ): readonly string[] { const info = getInfo(importingSourceFile.path, host); const preferences = getPreferences(host, userPreferences, compilerOptions, importingSourceFile); - const existingSpecifier = ts.forEach(modulePaths, modulePath => ts.forEach( - host.getFileIncludeReasons().get(ts.toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)), + const existingSpecifier = forEach(modulePaths, modulePath => forEach( + host.getFileIncludeReasons().get(toPath(modulePath.path, host.getCurrentDirectory(), info.getCanonicalFileName)), reason => { - if (reason.kind !== ts.FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined; + if (reason.kind !== FileIncludeKind.Import || reason.file !== importingSourceFile.path) return undefined; // If the candidate import mode doesn't match the mode we're generating for, don't consider it // TODO: maybe useful to keep around as an alternative option for certain contexts where the mode is overridable - if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== ts.getModeForResolutionAtIndex(importingSourceFile, reason.index)) return undefined; - const specifier = ts.getModuleNameStringLiteralAt(importingSourceFile, reason.index).text; + if (importingSourceFile.impliedNodeFormat && importingSourceFile.impliedNodeFormat !== getModeForResolutionAtIndex(importingSourceFile, reason.index)) return undefined; + const specifier = getModuleNameStringLiteralAt(importingSourceFile, reason.index).text; // If the preference is for non relative and the module specifier is relative, ignore it - return preferences.relativePreference !== RelativePreference.NonRelative || !ts.pathIsRelative(specifier) ? + return preferences.relativePreference !== RelativePreference.NonRelative || !pathIsRelative(specifier) ? specifier : undefined; } @@ -244,7 +263,7 @@ function computeModuleSpecifiers( return moduleSpecifiers; } - const importedFileIsInNodeModules = ts.some(modulePaths, p => p.isInNodeModules); + const importedFileIsInNodeModules = some(modulePaths, p => p.isInNodeModules); // Module specifier priority: // 1. "Bare package specifiers" (e.g. "@foo/bar") resulting from a path through node_modules to a package.json's "types" entry @@ -256,7 +275,7 @@ function computeModuleSpecifiers( let relativeSpecifiers: string[] | undefined; for (const modulePath of modulePaths) { const specifier = tryGetModuleNameAsNodeModule(modulePath, info, importingSourceFile, host, compilerOptions, userPreferences, /*packageNameOnly*/ undefined, options.overrideImportMode); - nodeModulesSpecifiers = ts.append(nodeModulesSpecifiers, specifier); + nodeModulesSpecifiers = append(nodeModulesSpecifiers, specifier); if (specifier && modulePath.isRedirect) { // If we got a specifier for a redirect, it was a bare package specifier (e.g. "@foo/bar", // not "@foo/bar/path/to/file"). No other specifier will be this good, so stop looking. @@ -265,8 +284,8 @@ function computeModuleSpecifiers( if (!specifier && !modulePath.isRedirect) { const local = getLocalModuleSpecifier(modulePath.path, info, compilerOptions, host, options.overrideImportMode || importingSourceFile.impliedNodeFormat, preferences); - if (ts.pathIsBareSpecifier(local)) { - pathsSpecifiers = ts.append(pathsSpecifiers, local); + if (pathIsBareSpecifier(local)) { + pathsSpecifiers = append(pathsSpecifiers, local); } else if (!importedFileIsInNodeModules || modulePath.isInNodeModules) { // Why this extra conditional, not just an `else`? If some path to the file contained @@ -278,38 +297,38 @@ function computeModuleSpecifiers( // in a monorepo is probably not portable. So, the module specifier we actually go with will be // the relative path through node_modules, so that the declaration emitter can produce a // portability error. (See declarationEmitReexportedSymlinkReference3) - relativeSpecifiers = ts.append(relativeSpecifiers, local); + relativeSpecifiers = append(relativeSpecifiers, local); } } } return pathsSpecifiers?.length ? pathsSpecifiers : nodeModulesSpecifiers?.length ? nodeModulesSpecifiers : - ts.Debug.checkDefined(relativeSpecifiers); + Debug.checkDefined(relativeSpecifiers); } interface Info { - readonly getCanonicalFileName: ts.GetCanonicalFileName; - readonly importingSourceFileName: ts.Path - readonly sourceDirectory: ts.Path; + readonly getCanonicalFileName: GetCanonicalFileName; + readonly importingSourceFileName: Path + readonly sourceDirectory: Path; } // importingSourceFileName is separate because getEditsForFileRename may need to specify an updated path -function getInfo(importingSourceFileName: ts.Path, host: ts.ModuleSpecifierResolutionHost): Info { - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true); - const sourceDirectory = ts.getDirectoryPath(importingSourceFileName); +function getInfo(importingSourceFileName: Path, host: ModuleSpecifierResolutionHost): Info { + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : true); + const sourceDirectory = getDirectoryPath(importingSourceFileName); return { getCanonicalFileName, importingSourceFileName, sourceDirectory }; } -function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: ts.CompilerOptions, host: ts.ModuleSpecifierResolutionHost, importMode: ts.SourceFile["impliedNodeFormat"], { ending, relativePreference }: Preferences): string { +function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOptions: CompilerOptions, host: ModuleSpecifierResolutionHost, importMode: SourceFile["impliedNodeFormat"], { ending, relativePreference }: Preferences): string { const { baseUrl, paths, rootDirs } = compilerOptions; const { sourceDirectory, getCanonicalFileName } = info; const relativePath = rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName, ending, compilerOptions) || - removeExtensionAndIndexPostFix(ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions); + removeExtensionAndIndexPostFix(ensurePathIsNonModuleName(getRelativePathFromDirectory(sourceDirectory, moduleFileName, getCanonicalFileName)), ending, compilerOptions); if (!baseUrl && !paths || relativePreference === RelativePreference.Relative) { return relativePath; } - const baseDirectory = ts.getNormalizedAbsolutePath(ts.getPathsBasePath(compilerOptions, host) || baseUrl!, host.getCurrentDirectory()); + const baseDirectory = getNormalizedAbsolutePath(getPathsBasePath(compilerOptions, host) || baseUrl!, host.getCurrentDirectory()); const relativeToBaseUrl = getRelativePathIfInDirectory(moduleFileName, baseDirectory, getCanonicalFileName); if (!relativeToBaseUrl) { return relativePath; @@ -327,11 +346,11 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt if (relativePreference === RelativePreference.ExternalNonRelative) { const projectDirectory = compilerOptions.configFilePath ? - ts.toPath(ts.getDirectoryPath(compilerOptions.configFilePath), host.getCurrentDirectory(), info.getCanonicalFileName) : + toPath(getDirectoryPath(compilerOptions.configFilePath), host.getCurrentDirectory(), info.getCanonicalFileName) : info.getCanonicalFileName(host.getCurrentDirectory()); - const modulePath = ts.toPath(moduleFileName, projectDirectory, getCanonicalFileName); - const sourceIsInternal = ts.startsWith(sourceDirectory, projectDirectory); - const targetIsInternal = ts.startsWith(modulePath, projectDirectory); + const modulePath = toPath(moduleFileName, projectDirectory, getCanonicalFileName); + const sourceIsInternal = startsWith(sourceDirectory, projectDirectory); + const targetIsInternal = startsWith(modulePath, projectDirectory); if (sourceIsInternal && !targetIsInternal || !sourceIsInternal && targetIsInternal) { // 1. The import path crosses the boundary of the tsconfig.json-containing directory. // @@ -344,7 +363,7 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt return nonRelative; } - const nearestTargetPackageJson = getNearestAncestorDirectoryWithPackageJson(host, ts.getDirectoryPath(modulePath)); + const nearestTargetPackageJson = getNearestAncestorDirectoryWithPackageJson(host, getDirectoryPath(modulePath)); const nearestSourcePackageJson = getNearestAncestorDirectoryWithPackageJson(host, sourceDirectory); if (nearestSourcePackageJson !== nearestTargetPackageJson) { // 2. The importing and imported files are part of different packages. @@ -362,7 +381,7 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt return relativePath; } - if (relativePreference !== RelativePreference.Shortest) ts.Debug.assertNever(relativePreference); + if (relativePreference !== RelativePreference.Shortest) Debug.assertNever(relativePreference); // Prefer a relative import over a baseUrl import if it has fewer components. return isPathRelativeToParent(nonRelative) || countPathComponents(relativePath) < countPathComponents(nonRelative) ? relativePath : nonRelative; @@ -371,26 +390,26 @@ function getLocalModuleSpecifier(moduleFileName: string, info: Info, compilerOpt /** @internal */ export function countPathComponents(path: string): number { let count = 0; - for (let i = ts.startsWith(path, "./") ? 2 : 0; i < path.length; i++) { - if (path.charCodeAt(i) === ts.CharacterCodes.slash) count++; + for (let i = startsWith(path, "./") ? 2 : 0; i < path.length; i++) { + if (path.charCodeAt(i) === CharacterCodes.slash) count++; } return count; } -function usesJsExtensionOnImports({ imports }: ts.SourceFile): boolean { - return ts.firstDefined(imports, ({ text }) => ts.pathIsRelative(text) ? ts.hasJSFileExtension(text) : undefined) || false; +function usesJsExtensionOnImports({ imports }: SourceFile): boolean { + return firstDefined(imports, ({ text }) => pathIsRelative(text) ? hasJSFileExtension(text) : undefined) || false; } -function comparePathsByRedirectAndNumberOfDirectorySeparators(a: ts.ModulePath, b: ts.ModulePath) { - return ts.compareBooleans(b.isRedirect, a.isRedirect) || ts.compareNumberOfDirectorySeparators(a.path, b.path); +function comparePathsByRedirectAndNumberOfDirectorySeparators(a: ModulePath, b: ModulePath) { + return compareBooleans(b.isRedirect, a.isRedirect) || compareNumberOfDirectorySeparators(a.path, b.path); } -function getNearestAncestorDirectoryWithPackageJson(host: ts.ModuleSpecifierResolutionHost, fileName: string) { +function getNearestAncestorDirectoryWithPackageJson(host: ModuleSpecifierResolutionHost, fileName: string) { if (host.getNearestAncestorDirectoryWithPackageJson) { return host.getNearestAncestorDirectoryWithPackageJson(fileName); } - return !!ts.forEachAncestorDirectory(fileName, directory => { - return host.fileExists(ts.combinePaths(directory, "package.json")) ? true : undefined; + return !!forEachAncestorDirectory(fileName, directory => { + return host.fileExists(combinePaths(directory, "package.json")) ? true : undefined; }); } @@ -398,45 +417,45 @@ function getNearestAncestorDirectoryWithPackageJson(host: ts.ModuleSpecifierReso export function forEachFileNameOfModule( importingFileName: string, importedFileName: string, - host: ts.ModuleSpecifierResolutionHost, + host: ModuleSpecifierResolutionHost, preferSymlinks: boolean, cb: (fileName: string, isRedirect: boolean) => T | undefined ): T | undefined { - const getCanonicalFileName = ts.hostGetCanonicalFileName(host); + const getCanonicalFileName = hostGetCanonicalFileName(host); const cwd = host.getCurrentDirectory(); const referenceRedirect = host.isSourceOfProjectReferenceRedirect(importedFileName) ? host.getProjectReferenceRedirect(importedFileName) : undefined; - const importedPath = ts.toPath(importedFileName, cwd, getCanonicalFileName); - const redirects = host.redirectTargetsMap.get(importedPath) || ts.emptyArray; - const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : ts.emptyArray), importedFileName, ...redirects]; - const targets = importedFileNames.map(f => ts.getNormalizedAbsolutePath(f, cwd)); - let shouldFilterIgnoredPaths = !ts.every(targets, ts.containsIgnoredPath); + const importedPath = toPath(importedFileName, cwd, getCanonicalFileName); + const redirects = host.redirectTargetsMap.get(importedPath) || emptyArray; + const importedFileNames = [...(referenceRedirect ? [referenceRedirect] : emptyArray), importedFileName, ...redirects]; + const targets = importedFileNames.map(f => getNormalizedAbsolutePath(f, cwd)); + let shouldFilterIgnoredPaths = !every(targets, containsIgnoredPath); if (!preferSymlinks) { // Symlinks inside ignored paths are already filtered out of the symlink cache, // so we only need to remove them from the realpath filenames. - const result = ts.forEach(targets, p => !(shouldFilterIgnoredPaths && ts.containsIgnoredPath(p)) && cb(p, referenceRedirect === p)); + const result = forEach(targets, p => !(shouldFilterIgnoredPaths && containsIgnoredPath(p)) && cb(p, referenceRedirect === p)); if (result) return result; } const symlinkedDirectories = host.getSymlinkCache?.().getSymlinkedDirectoriesByRealpath(); - const fullImportedFileName = ts.getNormalizedAbsolutePath(importedFileName, cwd); - const result = symlinkedDirectories && ts.forEachAncestorDirectory(ts.getDirectoryPath(fullImportedFileName), realPathDirectory => { - const symlinkDirectories = symlinkedDirectories.get(ts.ensureTrailingDirectorySeparator(ts.toPath(realPathDirectory, cwd, getCanonicalFileName))); + const fullImportedFileName = getNormalizedAbsolutePath(importedFileName, cwd); + const result = symlinkedDirectories && forEachAncestorDirectory(getDirectoryPath(fullImportedFileName), realPathDirectory => { + const symlinkDirectories = symlinkedDirectories.get(ensureTrailingDirectorySeparator(toPath(realPathDirectory, cwd, getCanonicalFileName))); if (!symlinkDirectories) return undefined; // Continue to ancestor directory // Don't want to a package to globally import from itself (importNameCodeFix_symlink_own_package.ts) - if (ts.startsWithDirectory(importingFileName, realPathDirectory, getCanonicalFileName)) { + if (startsWithDirectory(importingFileName, realPathDirectory, getCanonicalFileName)) { return false; // Stop search, each ancestor directory will also hit this condition } - return ts.forEach(targets, target => { - if (!ts.startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) { + return forEach(targets, target => { + if (!startsWithDirectory(target, realPathDirectory, getCanonicalFileName)) { return; } - const relative = ts.getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName); + const relative = getRelativePathFromDirectory(realPathDirectory, target, getCanonicalFileName); for (const symlinkDirectory of symlinkDirectories) { - const option = ts.resolvePath(symlinkDirectory, relative); + const option = resolvePath(symlinkDirectory, relative); const result = cb(option, target === referenceRedirect); shouldFilterIgnoredPaths = true; // We found a non-ignored path in symlinks, so we can reject ignored-path realpaths if (result) return result; @@ -444,7 +463,7 @@ export function forEachFileNameOfModule( }); }); return result || (preferSymlinks - ? ts.forEach(targets, p => shouldFilterIgnoredPaths && ts.containsIgnoredPath(p) ? undefined : cb(p, p === referenceRedirect)) + ? forEach(targets, p => shouldFilterIgnoredPaths && containsIgnoredPath(p) ? undefined : cb(p, p === referenceRedirect)) : undefined); } @@ -453,13 +472,13 @@ export function forEachFileNameOfModule( * Symlinks will be returned first so they are preferred over the real path. */ function getAllModulePaths( - importingFilePath: ts.Path, + importingFilePath: Path, importedFileName: string, - host: ts.ModuleSpecifierResolutionHost, - preferences: ts.UserPreferences, - options: ts.ModuleSpecifierOptions = {}, + host: ModuleSpecifierResolutionHost, + preferences: UserPreferences, + options: ModuleSpecifierOptions = {}, ) { - const importedFilePath = ts.toPath(importedFileName, host.getCurrentDirectory(), ts.hostGetCanonicalFileName(host)); + const importedFilePath = toPath(importedFileName, host.getCurrentDirectory(), hostGetCanonicalFileName(host)); const cache = host.getModuleSpecifierCache?.(); if (cache) { const cached = cache.get(importingFilePath, importedFilePath, preferences, options); @@ -472,9 +491,9 @@ function getAllModulePaths( return modulePaths; } -function getAllModulePathsWorker(importingFileName: ts.Path, importedFileName: string, host: ts.ModuleSpecifierResolutionHost): readonly ts.ModulePath[] { - const getCanonicalFileName = ts.hostGetCanonicalFileName(host); - const allFileNames = new ts.Map(); +function getAllModulePathsWorker(importingFileName: Path, importedFileName: string, host: ModuleSpecifierResolutionHost): readonly ModulePath[] { + const getCanonicalFileName = hostGetCanonicalFileName(host); + const allFileNames = new Map(); let importedFileFromNodeModules = false; forEachFileNameOfModule( importingFileName, @@ -482,7 +501,7 @@ function getAllModulePathsWorker(importingFileName: ts.Path, importedFileName: s host, /*preferSymlinks*/ true, (path, isRedirect) => { - const isInNodeModules = ts.pathContainsNodeModules(path); + const isInNodeModules = pathContainsNodeModules(path); allFileNames.set(path, { path: getCanonicalFileName(path), isRedirect, isInNodeModules }); importedFileFromNodeModules = importedFileFromNodeModules || isInNodeModules; // don't return value, so we collect everything @@ -490,15 +509,15 @@ function getAllModulePathsWorker(importingFileName: ts.Path, importedFileName: s ); // Sort by paths closest to importing file Name directory - const sortedPaths: ts.ModulePath[] = []; + const sortedPaths: ModulePath[] = []; for ( - let directory = ts.getDirectoryPath(importingFileName); + let directory = getDirectoryPath(importingFileName); allFileNames.size !== 0; ) { - const directoryStart = ts.ensureTrailingDirectorySeparator(directory); - let pathsInDirectory: ts.ModulePath[] | undefined; + const directoryStart = ensureTrailingDirectorySeparator(directory); + let pathsInDirectory: ModulePath[] | undefined; allFileNames.forEach(({ path, isRedirect, isInNodeModules }, fileName) => { - if (ts.startsWith(path, directoryStart)) { + if (startsWith(path, directoryStart)) { (pathsInDirectory ||= []).push({ path: fileName, isRedirect, isInNodeModules }); allFileNames.delete(fileName); } @@ -509,12 +528,12 @@ function getAllModulePathsWorker(importingFileName: ts.Path, importedFileName: s } sortedPaths.push(...pathsInDirectory); } - const newDirectory = ts.getDirectoryPath(directory); + const newDirectory = getDirectoryPath(directory); if (newDirectory === directory) break; directory = newDirectory; } if (allFileNames.size) { - const remainingPaths = ts.arrayFrom(allFileNames.values()); + const remainingPaths = arrayFrom(allFileNames.values()); if (remainingPaths.length > 1) remainingPaths.sort(comparePathsByRedirectAndNumberOfDirectorySeparators); sortedPaths.push(...remainingPaths); } @@ -522,10 +541,10 @@ function getAllModulePathsWorker(importingFileName: ts.Path, importedFileName: s return sortedPaths; } -function tryGetModuleNameFromAmbientModule(moduleSymbol: ts.Symbol, checker: ts.TypeChecker): string | undefined { +function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol, checker: TypeChecker): string | undefined { const decl = moduleSymbol.declarations?.find( - d => ts.isNonGlobalAmbientModule(d) && (!ts.isExternalModuleAugmentation(d) || !ts.isExternalModuleNameRelative(ts.getTextOfIdentifierOrLiteral(d.name))) - ) as (ts.ModuleDeclaration & { name: ts.StringLiteral }) | undefined; + d => isNonGlobalAmbientModule(d) && (!isExternalModuleAugmentation(d) || !isExternalModuleNameRelative(getTextOfIdentifierOrLiteral(d.name))) + ) as (ModuleDeclaration & { name: StringLiteral }) | undefined; if (decl) { return decl.name.text; } @@ -540,49 +559,49 @@ function tryGetModuleNameFromAmbientModule(moduleSymbol: ts.Symbol, checker: ts. * } */ // `import {c} from "m";` is valid, in which case, `moduleSymbol` is "ns", but the module name should be "m" - const ambientModuleDeclareCandidates = ts.mapDefined(moduleSymbol.declarations, + const ambientModuleDeclareCandidates = mapDefined(moduleSymbol.declarations, d => { - if (!ts.isModuleDeclaration(d)) return; + if (!isModuleDeclaration(d)) return; const topNamespace = getTopNamespace(d); if (!(topNamespace?.parent?.parent - && ts.isModuleBlock(topNamespace.parent) && ts.isAmbientModule(topNamespace.parent.parent) && ts.isSourceFile(topNamespace.parent.parent.parent))) return; - const exportAssignment = ((topNamespace.parent.parent.symbol.exports?.get("export=" as ts.__String)?.valueDeclaration as ts.ExportAssignment)?.expression as ts.PropertyAccessExpression | ts.Identifier); + && isModuleBlock(topNamespace.parent) && isAmbientModule(topNamespace.parent.parent) && isSourceFile(topNamespace.parent.parent.parent))) return; + const exportAssignment = ((topNamespace.parent.parent.symbol.exports?.get("export=" as __String)?.valueDeclaration as ExportAssignment)?.expression as PropertyAccessExpression | Identifier); if (!exportAssignment) return; const exportSymbol = checker.getSymbolAtLocation(exportAssignment); if (!exportSymbol) return; - const originalExportSymbol = exportSymbol?.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) : exportSymbol; + const originalExportSymbol = exportSymbol?.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(exportSymbol) : exportSymbol; if (originalExportSymbol === d.symbol) return topNamespace.parent.parent; - function getTopNamespace(namespaceDeclaration: ts.ModuleDeclaration) { - while (namespaceDeclaration.flags & ts.NodeFlags.NestedNamespace) { - namespaceDeclaration = namespaceDeclaration.parent as ts.ModuleDeclaration; + function getTopNamespace(namespaceDeclaration: ModuleDeclaration) { + while (namespaceDeclaration.flags & NodeFlags.NestedNamespace) { + namespaceDeclaration = namespaceDeclaration.parent as ModuleDeclaration; } return namespaceDeclaration; } } ); - const ambientModuleDeclare = ambientModuleDeclareCandidates[0] as (ts.AmbientModuleDeclaration & { name: ts.StringLiteral }) | undefined; + const ambientModuleDeclare = ambientModuleDeclareCandidates[0] as (AmbientModuleDeclaration & { name: StringLiteral }) | undefined; if (ambientModuleDeclare) { return ambientModuleDeclare.name.text; } } -function getAllowedEndings(preferredEnding: Ending, compilerOptions: ts.CompilerOptions, importMode: ts.SourceFile["impliedNodeFormat"]) { - if (ts.getEmitModuleResolutionKind(compilerOptions) >= ts.ModuleResolutionKind.Node16 && importMode === ts.ModuleKind.ESNext) { +function getAllowedEndings(preferredEnding: Ending, compilerOptions: CompilerOptions, importMode: SourceFile["impliedNodeFormat"]) { + if (getEmitModuleResolutionKind(compilerOptions) >= ModuleResolutionKind.Node16 && importMode === ModuleKind.ESNext) { return [Ending.JsExtension]; } switch (preferredEnding) { case Ending.JsExtension: return [Ending.JsExtension, Ending.Minimal, Ending.Index]; case Ending.Index: return [Ending.Index, Ending.Minimal, Ending.JsExtension]; case Ending.Minimal: return [Ending.Minimal, Ending.Index, Ending.JsExtension]; - default: ts.Debug.assertNever(preferredEnding); + default: Debug.assertNever(preferredEnding); } } -function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike, allowedEndings: Ending[], host: ts.ModuleSpecifierResolutionHost, compilerOptions: ts.CompilerOptions): string | undefined { +function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: MapLike, allowedEndings: Ending[], host: ModuleSpecifierResolutionHost, compilerOptions: CompilerOptions): string | undefined { for (const key in paths) { for (const patternText of paths[key]) { - const pattern = ts.normalizePath(patternText); + const pattern = normalizePath(patternText); const indexOfStar = pattern.indexOf("*"); // In module resolution, if `pattern` itself has an extension, a file with that extension is looked up directly, // meaning a '.ts' or '.d.ts' extension is allowed to resolve. This is distinct from the case where a '*' substitution @@ -624,7 +643,7 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike< ending, value: removeExtensionAndIndexPostFix(relativeToBaseUrl, ending, compilerOptions) })); - if (ts.tryGetExtensionFromPath(pattern)) { + if (tryGetExtensionFromPath(pattern)) { candidates.push({ ending: undefined, value: relativeToBaseUrl }); } @@ -633,8 +652,8 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike< const suffix = pattern.substring(indexOfStar + 1); for (const { ending, value } of candidates) { if (value.length >= prefix.length + suffix.length && - ts.startsWith(value, prefix) && - ts.endsWith(value, suffix) && + startsWith(value, prefix) && + endsWith(value, suffix) && validateEnding({ ending, value }) ) { const matchedStar = value.substring(prefix.length, value.length - suffix.length); @@ -643,8 +662,8 @@ function tryGetModuleNameFromPaths(relativeToBaseUrl: string, paths: ts.MapLike< } } else if ( - ts.some(candidates, c => c.ending !== Ending.Minimal && pattern === c.value) || - ts.some(candidates, c => c.ending === Ending.Minimal && pattern === c.value && validateEnding(c)) + some(candidates, c => c.ending !== Ending.Minimal && pattern === c.value) || + some(candidates, c => c.ending === Ending.Minimal && pattern === c.value && validateEnding(c)) ) { return key; } @@ -669,31 +688,31 @@ const enum MatchingMode { Pattern } -function tryGetModuleNameFromExports(options: ts.CompilerOptions, targetFilePath: string, packageDirectory: string, packageName: string, exports: unknown, conditions: string[], mode = MatchingMode.Exact): { moduleFileToTry: string } | undefined { +function tryGetModuleNameFromExports(options: CompilerOptions, targetFilePath: string, packageDirectory: string, packageName: string, exports: unknown, conditions: string[], mode = MatchingMode.Exact): { moduleFileToTry: string } | undefined { if (typeof exports === "string") { - const pathOrPattern = ts.getNormalizedAbsolutePath(ts.combinePaths(packageDirectory, exports), /*currentDirectory*/ undefined); - const extensionSwappedTarget = ts.hasTSFileExtension(targetFilePath) ? ts.removeFileExtension(targetFilePath) + tryGetJSExtensionForFile(targetFilePath, options) : undefined; + const pathOrPattern = getNormalizedAbsolutePath(combinePaths(packageDirectory, exports), /*currentDirectory*/ undefined); + const extensionSwappedTarget = hasTSFileExtension(targetFilePath) ? removeFileExtension(targetFilePath) + tryGetJSExtensionForFile(targetFilePath, options) : undefined; switch (mode) { case MatchingMode.Exact: - if (ts.comparePaths(targetFilePath, pathOrPattern) === ts.Comparison.EqualTo || (extensionSwappedTarget && ts.comparePaths(extensionSwappedTarget, pathOrPattern) === ts.Comparison.EqualTo)) { + if (comparePaths(targetFilePath, pathOrPattern) === Comparison.EqualTo || (extensionSwappedTarget && comparePaths(extensionSwappedTarget, pathOrPattern) === Comparison.EqualTo)) { return { moduleFileToTry: packageName }; } break; case MatchingMode.Directory: - if (ts.containsPath(pathOrPattern, targetFilePath)) { - const fragment = ts.getRelativePathFromDirectory(pathOrPattern, targetFilePath, /*ignoreCase*/ false); - return { moduleFileToTry: ts.getNormalizedAbsolutePath(ts.combinePaths(ts.combinePaths(packageName, exports), fragment), /*currentDirectory*/ undefined) }; + if (containsPath(pathOrPattern, targetFilePath)) { + const fragment = getRelativePathFromDirectory(pathOrPattern, targetFilePath, /*ignoreCase*/ false); + return { moduleFileToTry: getNormalizedAbsolutePath(combinePaths(combinePaths(packageName, exports), fragment), /*currentDirectory*/ undefined) }; } break; case MatchingMode.Pattern: const starPos = pathOrPattern.indexOf("*"); const leadingSlice = pathOrPattern.slice(0, starPos); const trailingSlice = pathOrPattern.slice(starPos + 1); - if (ts.startsWith(targetFilePath, leadingSlice) && ts.endsWith(targetFilePath, trailingSlice)) { + if (startsWith(targetFilePath, leadingSlice) && endsWith(targetFilePath, trailingSlice)) { const starReplacement = targetFilePath.slice(leadingSlice.length, targetFilePath.length - trailingSlice.length); return { moduleFileToTry: packageName.replace("*", starReplacement) }; } - if (extensionSwappedTarget && ts.startsWith(extensionSwappedTarget, leadingSlice) && ts.endsWith(extensionSwappedTarget, trailingSlice)) { + if (extensionSwappedTarget && startsWith(extensionSwappedTarget, leadingSlice) && endsWith(extensionSwappedTarget, trailingSlice)) { const starReplacement = extensionSwappedTarget.slice(leadingSlice.length, extensionSwappedTarget.length - trailingSlice.length); return { moduleFileToTry: packageName.replace("*", starReplacement) }; } @@ -701,28 +720,28 @@ function tryGetModuleNameFromExports(options: ts.CompilerOptions, targetFilePath } } else if (Array.isArray(exports)) { - return ts.forEach(exports, e => tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, e, conditions)); + return forEach(exports, e => tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, e, conditions)); } else if (typeof exports === "object" && exports !== null) { // eslint-disable-line no-null/no-null - if (ts.allKeysStartWithDot(exports as ts.MapLike)) { + if (allKeysStartWithDot(exports as MapLike)) { // sub-mappings // 3 cases: // * directory mappings (legacyish, key ends with / (technically allows index/extension resolution under cjs mode)) // * pattern mappings (contains a *) // * exact mappings (no *, does not end with /) - return ts.forEach(ts.getOwnKeys(exports as ts.MapLike), k => { - const subPackageName = ts.getNormalizedAbsolutePath(ts.combinePaths(packageName, k), /*currentDirectory*/ undefined); - const mode = ts.endsWith(k, "/") ? MatchingMode.Directory - : ts.stringContains(k, "*") ? MatchingMode.Pattern + return forEach(getOwnKeys(exports as MapLike), k => { + const subPackageName = getNormalizedAbsolutePath(combinePaths(packageName, k), /*currentDirectory*/ undefined); + const mode = endsWith(k, "/") ? MatchingMode.Directory + : stringContains(k, "*") ? MatchingMode.Pattern : MatchingMode.Exact; - return tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, subPackageName, (exports as ts.MapLike)[k], conditions, mode); + return tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, subPackageName, (exports as MapLike)[k], conditions, mode); }); } else { // conditional mapping - for (const key of ts.getOwnKeys(exports as ts.MapLike)) { - if (key === "default" || conditions.indexOf(key) >= 0 || ts.isApplicableVersionedTypesKey(conditions, key)) { - const subTarget = (exports as ts.MapLike)[key]; + for (const key of getOwnKeys(exports as MapLike)) { + if (key === "default" || conditions.indexOf(key) >= 0 || isApplicableVersionedTypesKey(conditions, key)) { + const subTarget = (exports as MapLike)[key]; const result = tryGetModuleNameFromExports(options, targetFilePath, packageDirectory, packageName, subTarget, conditions); if (result) { return result; @@ -734,31 +753,31 @@ function tryGetModuleNameFromExports(options: ts.CompilerOptions, targetFilePath return undefined; } -function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, ending: Ending, compilerOptions: ts.CompilerOptions): string | undefined { +function tryGetModuleNameFromRootDirs(rootDirs: readonly string[], moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string, ending: Ending, compilerOptions: CompilerOptions): string | undefined { const normalizedTargetPaths = getPathsRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName); if (normalizedTargetPaths === undefined) { return undefined; } const normalizedSourcePaths = getPathsRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName); - const relativePaths = ts.flatMap(normalizedSourcePaths, sourcePath => { - return ts.map(normalizedTargetPaths, targetPath => ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(sourcePath, targetPath, getCanonicalFileName))); + const relativePaths = flatMap(normalizedSourcePaths, sourcePath => { + return map(normalizedTargetPaths, targetPath => ensurePathIsNonModuleName(getRelativePathFromDirectory(sourcePath, targetPath, getCanonicalFileName))); }); - const shortest = ts.min(relativePaths, ts.compareNumberOfDirectorySeparators); + const shortest = min(relativePaths, compareNumberOfDirectorySeparators); if (!shortest) { return undefined; } - return ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs ? removeExtensionAndIndexPostFix(shortest, ending, compilerOptions) - : ts.removeFileExtension(shortest); + : removeFileExtension(shortest); } -function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: ts.SourceFile , host: ts.ModuleSpecifierResolutionHost, options: ts.CompilerOptions, userPreferences: ts.UserPreferences, packageNameOnly?: boolean, overrideMode?: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS): string | undefined { +function tryGetModuleNameAsNodeModule({ path, isRedirect }: ModulePath, { getCanonicalFileName, sourceDirectory }: Info, importingSourceFile: SourceFile , host: ModuleSpecifierResolutionHost, options: CompilerOptions, userPreferences: UserPreferences, packageNameOnly?: boolean, overrideMode?: ModuleKind.ESNext | ModuleKind.CommonJS): string | undefined { if (!host.fileExists || !host.readFile) { return undefined; } - const parts: ts.NodeModulePathParts = ts.getNodeModulePathParts(path)!; + const parts: NodeModulePathParts = getNodeModulePathParts(path)!; if (!parts) { return undefined; } @@ -774,7 +793,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get while (true) { // If the module could be imported by a directory name, use that directory's name const { moduleFileToTry, packageRootPath, blockedByExports, verbatimFromExports } = tryDirectoryWithPackageJson(packageRootIndex); - if (ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.Classic) { + if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Classic) { if (blockedByExports) { return undefined; // File is under this package.json, but is not publicly exported - there's no way to name it via `node_modules` resolution } @@ -790,7 +809,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get if (!moduleFileName) moduleFileName = moduleFileToTry; // try with next level of directory - packageRootIndex = path.indexOf(ts.directorySeparator, packageRootIndex + 1); + packageRootIndex = path.indexOf(directorySeparator, packageRootIndex + 1); if (packageRootIndex === -1) { moduleSpecifier = removeExtensionAndIndexPostFix(moduleFileName, preferences.ending, options, host); break; @@ -806,34 +825,34 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get // Get a path that's relative to node_modules or the importing file's path // if node_modules folder is in this folder or any of its parent folders, no need to keep it. const pathToTopLevelNodeModules = getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)); - if (!(ts.startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && ts.startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { + if (!(startsWith(sourceDirectory, pathToTopLevelNodeModules) || globalTypingsCacheLocation && startsWith(getCanonicalFileName(globalTypingsCacheLocation), pathToTopLevelNodeModules))) { return undefined; } // If the module was found in @types, get the actual Node package name const nodeModulesDirectoryName = moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1); - const packageName = ts.getPackageNameFromTypesPackageName(nodeModulesDirectoryName); + const packageName = getPackageNameFromTypesPackageName(nodeModulesDirectoryName); // For classic resolution, only allow importing from node_modules/@types, not other node_modules - return ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.Classic && packageName === nodeModulesDirectoryName ? undefined : packageName; + return getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic && packageName === nodeModulesDirectoryName ? undefined : packageName; function tryDirectoryWithPackageJson(packageRootIndex: number): { moduleFileToTry: string, packageRootPath?: string, blockedByExports?: true, verbatimFromExports?: true } { const packageRootPath = path.substring(0, packageRootIndex); - const packageJsonPath = ts.combinePaths(packageRootPath, "package.json"); + const packageJsonPath = combinePaths(packageRootPath, "package.json"); let moduleFileToTry = path; let maybeBlockedByTypesVersions = false; const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath); if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) { const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!); const importMode = overrideMode || importingSourceFile.impliedNodeFormat; - if (ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.Node16 || ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.NodeNext) { - const conditions = ["node", importMode === ts.ModuleKind.ESNext ? "import" : "require", "types"]; + if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) { + const conditions = ["node", importMode === ModuleKind.ESNext ? "import" : "require", "types"]; const fromExports = packageJsonContent.exports && typeof packageJsonContent.name === "string" - ? tryGetModuleNameFromExports(options, path, packageRootPath, ts.getPackageNameFromTypesPackageName(packageJsonContent.name), packageJsonContent.exports, conditions) + ? tryGetModuleNameFromExports(options, path, packageRootPath, getPackageNameFromTypesPackageName(packageJsonContent.name), packageJsonContent.exports, conditions) : undefined; if (fromExports) { - const withJsExtension = !ts.hasTSFileExtension(fromExports.moduleFileToTry) + const withJsExtension = !hasTSFileExtension(fromExports.moduleFileToTry) ? fromExports - : { moduleFileToTry: ts.removeFileExtension(fromExports.moduleFileToTry) + tryGetJSExtensionForFile(fromExports.moduleFileToTry, options) }; + : { moduleFileToTry: removeFileExtension(fromExports.moduleFileToTry) + tryGetJSExtensionForFile(fromExports.moduleFileToTry, options) }; return { ...withJsExtension, verbatimFromExports: true }; } if (packageJsonContent.exports) { @@ -841,7 +860,7 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get } } const versionPaths = packageJsonContent.typesVersions - ? ts.getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions) + ? getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions) : undefined; if (versionPaths) { const subModuleName = path.slice(packageRootPath.length + 1); @@ -856,20 +875,20 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get maybeBlockedByTypesVersions = true; } else { - moduleFileToTry = ts.combinePaths(packageRootPath, fromPaths); + moduleFileToTry = combinePaths(packageRootPath, fromPaths); } } // If the file is the main module, it can be imported by the package name const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main || "index.js"; - if (ts.isString(mainFileRelative) && !(maybeBlockedByTypesVersions && ts.matchPatternOrExact(ts.tryParsePatterns(versionPaths!.paths), mainFileRelative))) { + if (isString(mainFileRelative) && !(maybeBlockedByTypesVersions && matchPatternOrExact(tryParsePatterns(versionPaths!.paths), mainFileRelative))) { // The 'main' file is also subject to mapping through typesVersions, and we couldn't come up with a path // explicitly through typesVersions, so if it matches a key in typesVersions now, it's not reachable. // (The only way this can happen is if some file in a package that's not resolvable from outside the // package got pulled into the program anyway, e.g. transitively through a file that *is* reachable. It // happens very easily in fourslash tests though, since every test file listed gets included. See // importNameCodeFix_typesVersions.ts for an example.) - const mainExportFile = ts.toPath(mainFileRelative, packageRootPath, getCanonicalFileName); - if (ts.removeFileExtension(mainExportFile) === ts.removeFileExtension(getCanonicalFileName(moduleFileToTry))) { + const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); + if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(moduleFileToTry))) { // ^ An arbitrary removal of file extension for this comparison is almost certainly wrong return { packageRootPath, moduleFileToTry }; } @@ -886,10 +905,10 @@ function tryGetModuleNameAsNodeModule({ path, isRedirect }: ts.ModulePath, { get } } -function tryGetAnyFileFromPath(host: ts.ModuleSpecifierResolutionHost, path: string) { +function tryGetAnyFileFromPath(host: ModuleSpecifierResolutionHost, path: string) { if (!host.fileExists) return; // We check all js, `node` and `json` extensions in addition to TS, since node module resolution would also choose those over the directory - const extensions = ts.flatten(ts.getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: ts.ScriptKind.JSON }])); + const extensions = flatten(getSupportedExtensions({ allowJs: true }, [{ extension: "node", isMixedContent: false }, { extension: "json", isMixedContent: false, scriptKind: ScriptKind.JSON }])); for (const e of extensions) { const fullPath = path + e; if (host.fileExists(fullPath)) { @@ -898,21 +917,21 @@ function tryGetAnyFileFromPath(host: ts.ModuleSpecifierResolutionHost, path: str } } -function getPathsRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: ts.GetCanonicalFileName): string[] | undefined { - return ts.mapDefined(rootDirs, rootDir => { +function getPathsRelativeToRootDirs(path: string, rootDirs: readonly string[], getCanonicalFileName: GetCanonicalFileName): string[] | undefined { + return mapDefined(rootDirs, rootDir => { const relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName); return relativePath !== undefined && isPathRelativeToParent(relativePath) ? undefined : relativePath; }); } -function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: ts.CompilerOptions, host?: ts.ModuleSpecifierResolutionHost): string { - if (ts.fileExtensionIsOneOf(fileName, [ts.Extension.Json, ts.Extension.Mjs, ts.Extension.Cjs])) return fileName; - const noExtension = ts.removeFileExtension(fileName); +function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, options: CompilerOptions, host?: ModuleSpecifierResolutionHost): string { + if (fileExtensionIsOneOf(fileName, [Extension.Json, Extension.Mjs, Extension.Cjs])) return fileName; + const noExtension = removeFileExtension(fileName); if (fileName === noExtension) return fileName; - if (ts.fileExtensionIsOneOf(fileName, [ts.Extension.Dmts, ts.Extension.Mts, ts.Extension.Dcts, ts.Extension.Cts])) return noExtension + getJSExtensionForFile(fileName, options); + if (fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Dcts, Extension.Cts])) return noExtension + getJSExtensionForFile(fileName, options); switch (ending) { case Ending.Minimal: - const withoutIndex = ts.removeSuffix(noExtension, "/index"); + const withoutIndex = removeSuffix(noExtension, "/index"); if (host && withoutIndex !== noExtension && tryGetAnyFileFromPath(host, withoutIndex)) { // Can't remove index if there's a file by the same name as the directory. // Probably more callers should pass `host` so we can determine this? @@ -924,45 +943,45 @@ function removeExtensionAndIndexPostFix(fileName: string, ending: Ending, option case Ending.JsExtension: return noExtension + getJSExtensionForFile(fileName, options); default: - return ts.Debug.assertNever(ending); + return Debug.assertNever(ending); } } -function getJSExtensionForFile(fileName: string, options: ts.CompilerOptions): ts.Extension { - return tryGetJSExtensionForFile(fileName, options) ?? ts.Debug.fail(`Extension ${ts.extensionFromPath(fileName)} is unsupported:: FileName:: ${fileName}`); +function getJSExtensionForFile(fileName: string, options: CompilerOptions): Extension { + return tryGetJSExtensionForFile(fileName, options) ?? Debug.fail(`Extension ${extensionFromPath(fileName)} is unsupported:: FileName:: ${fileName}`); } /** @internal */ -export function tryGetJSExtensionForFile(fileName: string, options: ts.CompilerOptions): ts.Extension | undefined { - const ext = ts.tryGetExtensionFromPath(fileName); +export function tryGetJSExtensionForFile(fileName: string, options: CompilerOptions): Extension | undefined { + const ext = tryGetExtensionFromPath(fileName); switch (ext) { - case ts.Extension.Ts: - case ts.Extension.Dts: - return ts.Extension.Js; - case ts.Extension.Tsx: - return options.jsx === ts.JsxEmit.Preserve ? ts.Extension.Jsx : ts.Extension.Js; - case ts.Extension.Js: - case ts.Extension.Jsx: - case ts.Extension.Json: + case Extension.Ts: + case Extension.Dts: + return Extension.Js; + case Extension.Tsx: + return options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js; + case Extension.Js: + case Extension.Jsx: + case Extension.Json: return ext; - case ts.Extension.Dmts: - case ts.Extension.Mts: - case ts.Extension.Mjs: - return ts.Extension.Mjs; - case ts.Extension.Dcts: - case ts.Extension.Cts: - case ts.Extension.Cjs: - return ts.Extension.Cjs; + case Extension.Dmts: + case Extension.Mts: + case Extension.Mjs: + return Extension.Mjs; + case Extension.Dcts: + case Extension.Cts: + case Extension.Cjs: + return Extension.Cjs; default: return undefined; } } -function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: ts.GetCanonicalFileName): string | undefined { - const relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); - return ts.isRootedDiskPath(relativePath) ? undefined : relativePath; +function getRelativePathIfInDirectory(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName): string | undefined { + const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false); + return isRootedDiskPath(relativePath) ? undefined : relativePath; } function isPathRelativeToParent(path: string): boolean { - return ts.startsWith(path, ".."); + return startsWith(path, ".."); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 327c6301fc4f7..2701742cf3f2a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,4 +1,70 @@ import * as ts from "./_namespaces/ts"; +import { + AccessorDeclaration, addRange, addRelatedInfo, AmdDependency, append, ArrayBindingElement, ArrayBindingPattern, + ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, AsExpression, AssertClause, AssertEntry, AssertionLevel, + AsteriskToken, attachFileToDiagnostics, AwaitExpression, BaseNodeFactory, BinaryExpression, BinaryOperatorToken, + BindingElement, BindingName, BindingPattern, Block, BooleanLiteral, BreakOrContinueStatement, BreakStatement, + CallExpression, CallSignatureDeclaration, canHaveModifiers, CaseBlock, CaseClause, CaseOrDefaultClause, CatchClause, + CharacterCodes, CheckJsDirective, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, + ClassStaticBlockDeclaration, CommaListExpression, CommentDirective, commentPragmas, CommentRange, + ComputedPropertyName, concatenate, ConditionalExpression, ConditionalTypeNode, ConstructorDeclaration, + ConstructorTypeNode, ConstructSignatureDeclaration, containsParseError, ContinueStatement, convertToObjectWorker, + createDetachedDiagnostic, createNodeFactory, createScanner, createTextChangeRange, createTextSpanFromBounds, Debug, + Decorator, DefaultClause, DeleteExpression, Diagnostic, DiagnosticMessage, Diagnostics, + DiagnosticWithDetachedLocation, DoStatement, DotDotDotToken, ElementAccessExpression, emptyArray, emptyMap, + EndOfFileToken, ensureScriptKind, EntityName, EnumDeclaration, EnumMember, ESMap, ExclamationToken, + ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, ExpressionStatement, ExpressionWithTypeArguments, + ExternalModuleReference, fileExtensionIsOneOf, FileReference, findIndex, forEach, ForEachChildNodes, + ForInOrOfStatement, ForInStatement, ForOfStatement, ForStatement, FunctionDeclaration, FunctionExpression, + FunctionOrConstructorTypeNode, FunctionTypeNode, GetAccessorDeclaration, getBinaryOperatorPrecedence, getFullWidth, + getJSDocCommentRanges, getLanguageVariant, getLastChild, getLeadingCommentRanges, getSpellingSuggestion, + getTextOfNodeFromSourceText, HasJSDoc, hasJSDocNodes, HasModifiers, HeritageClause, Identifier, idText, IfStatement, + ImportClause, ImportDeclaration, ImportEqualsDeclaration, ImportOrExportSpecifier, ImportSpecifier, + ImportTypeAssertionContainer, ImportTypeNode, IndexedAccessTypeNode, IndexSignatureDeclaration, InferTypeNode, + InterfaceDeclaration, IntersectionTypeNode, isArray, isAssignmentOperator, isAsyncModifier, isClassMemberModifier, + isExportAssignment, isExportDeclaration, isExportModifier, isExpressionWithTypeArguments, isExternalModuleReference, + isFunctionTypeNode, isIdentifierText, isImportDeclaration, isImportEqualsDeclaration, isJSDocFunctionType, + isJSDocNullableType, isJSDocReturnTag, isJSDocTypeTag, isJsxOpeningElement, isJsxOpeningFragment, isKeyword, + isLeftHandSideExpression, isLiteralKind, isMetaProperty, isModifierKind, isNonNullExpression, isPrivateIdentifier, + isSetAccessorDeclaration, isStringOrNumericLiteralLike, isTaggedTemplateExpression, isTemplateLiteralKind, + isTypeReferenceNode, IterationStatement, JSDoc, JSDocAllType, JSDocAugmentsTag, JSDocAuthorTag, JSDocCallbackTag, + JSDocClassTag, JSDocComment, JSDocContainer, JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocImplementsTag, JSDocLink, JSDocLinkCode, JSDocLinkPlain, JSDocMemberName, JSDocNameReference, + JSDocNamespaceDeclaration, JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, JSDocOverrideTag, + JSDocParameterTag, JSDocPrivateTag, JSDocPropertyLikeTag, JSDocPropertyTag, JSDocProtectedTag, JSDocPublicTag, + JSDocReadonlyTag, JSDocReturnTag, JSDocSeeTag, JSDocSignature, JSDocSyntaxKind, JSDocTag, JSDocTemplateTag, + JSDocText, JSDocThisTag, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeLiteral, JSDocTypeTag, JSDocUnknownTag, + JSDocUnknownType, JSDocVariadicType, JsonMinusNumericLiteral, JsonObjectExpressionStatement, JsonSourceFile, + JsxAttribute, JsxAttributes, JsxAttributeValue, JsxChild, JsxClosingElement, JsxClosingFragment, JsxElement, + JsxExpression, JsxFragment, JsxOpeningElement, JsxOpeningFragment, JsxOpeningLikeElement, JsxSelfClosingElement, + JsxSpreadAttribute, JsxTagNameExpression, JsxTagNamePropertyAccess, JsxText, JsxTokenSyntaxKind, LabeledStatement, + LanguageVariant, lastOrUndefined, LeftHandSideExpression, LiteralExpression, LiteralLikeNode, LiteralTypeNode, map, + Map, mapDefined, MappedTypeNode, MemberExpression, MetaProperty, MethodDeclaration, MethodSignature, MinusToken, + MissingDeclaration, Modifier, ModifierFlags, ModifierLike, ModifiersArray, modifiersToFlags, ModuleBlock, + ModuleDeclaration, ModuleKind, Mutable, NamedExportBindings, NamedExports, NamedImports, NamedImportsOrExports, + NamedTupleMember, NamespaceDeclaration, NamespaceExport, NamespaceExportDeclaration, NamespaceImport, NewExpression, + Node, NodeArray, NodeFactoryFlags, NodeFlags, nodeIsMissing, nodeIsPresent, NonNullExpression, noop, normalizePath, + NoSubstitutionTemplateLiteral, NullLiteral, NumericLiteral, objectAllocator, ObjectBindingPattern, + ObjectLiteralElementLike, ObjectLiteralExpression, OperatorPrecedence, OptionalTypeNode, PackageJsonInfo, + ParameterDeclaration, ParenthesizedExpression, ParenthesizedTypeNode, PartiallyEmittedExpression, perfLogger, + PlusToken, PostfixUnaryExpression, PostfixUnaryOperator, PragmaDefinition, PragmaKindFlags, PragmaMap, + PragmaPseudoMap, PragmaPseudoMapEntry, PrefixUnaryExpression, PrefixUnaryOperator, PrimaryExpression, + PrivateIdentifier, PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyAssignment, + PropertyDeclaration, PropertyName, PropertySignature, QualifiedName, QuestionDotToken, QuestionToken, + ReadonlyKeyword, ReadonlyPragmaMap, ReadonlyTextRange, RestTypeNode, ReturnStatement, SatisfiesExpression, + ScriptKind, ScriptTarget, Set, SetAccessorDeclaration, setParent, setParentRecursive, setTextRange, setTextRangePos, + setTextRangePosEnd, setTextRangePosWidth, ShorthandPropertyAssignment, skipTrivia, some, SourceFile, + SpreadAssignment, SpreadElement, startsWith, Statement, StringLiteral, supportedDeclarationExtensions, + SwitchStatement, SyntaxKind, TaggedTemplateExpression, TemplateExpression, TemplateHead, TemplateLiteralToken, + TemplateLiteralTypeNode, TemplateLiteralTypeSpan, TemplateMiddle, TemplateSpan, TemplateTail, TextChangeRange, + textChangeRangeIsUnchanged, textChangeRangeNewSpan, TextRange, textSpanEnd, textToKeywordObj, ThisExpression, + ThisTypeNode, ThrowStatement, toArray, Token, TokenFlags, tokenIsIdentifierOrKeyword, + tokenIsIdentifierOrKeywordOrGreaterThan, tokenToString, tracing, TransformFlags, trimString, TryStatement, + TupleTypeNode, TypeAliasDeclaration, TypeAssertion, TypeElement, TypeLiteralNode, TypeNode, TypeOfExpression, + TypeOperatorNode, TypeParameterDeclaration, TypePredicateNode, TypeQueryNode, TypeReferenceNode, UnaryExpression, + UnionOrIntersectionTypeNode, UnionTypeNode, UpdateExpression, VariableDeclaration, VariableDeclarationList, + VariableStatement, VoidExpression, WhileStatement, WithStatement, YieldExpression, +} from "./_namespaces/ts"; const enum SignatureFlags { None = 0, @@ -15,32 +81,32 @@ const enum SpeculationKind { Reparse } -let NodeConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; -let TokenConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; -let IdentifierConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; -let PrivateIdentifierConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; -let SourceFileConstructor: new (kind: ts.SyntaxKind, pos?: number, end?: number) => ts.Node; +let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; +let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node; /** * NOTE: You should not use this, it is only exported to support `createNode` in `~/src/deprecatedCompat/deprecations.ts`. */ /* @internal */ -export const parseBaseNodeFactory: ts.BaseNodeFactory = { - createBaseSourceFileNode: kind => new (SourceFileConstructor || (SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor()))(kind, -1, -1), - createBaseIdentifierNode: kind => new (IdentifierConstructor || (IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor()))(kind, -1, -1), - createBasePrivateIdentifierNode: kind => new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = ts.objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1), - createBaseTokenNode: kind => new (TokenConstructor || (TokenConstructor = ts.objectAllocator.getTokenConstructor()))(kind, -1, -1), - createBaseNode: kind => new (NodeConstructor || (NodeConstructor = ts.objectAllocator.getNodeConstructor()))(kind, -1, -1), +export const parseBaseNodeFactory: BaseNodeFactory = { + createBaseSourceFileNode: kind => new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, -1, -1), + createBaseIdentifierNode: kind => new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, -1, -1), + createBasePrivateIdentifierNode: kind => new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1), + createBaseTokenNode: kind => new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, -1, -1), + createBaseNode: kind => new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, -1, -1), }; /* @internal */ -export const parseNodeFactory = ts.createNodeFactory(ts.NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory); +export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory); -function visitNode(cbNode: (node: ts.Node) => T, node: ts.Node | undefined): T | undefined { +function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { return node && cbNode(node); } -function visitNodes(cbNode: (node: ts.Node) => T, cbNodes: ((node: ts.NodeArray) => T | undefined) | undefined, nodes: ts.NodeArray | undefined): T | undefined { +function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray) => T | undefined) | undefined, nodes: NodeArray | undefined): T | undefined { if (nodes) { if (cbNodes) { return cbNodes(nodes); @@ -56,61 +122,61 @@ function visitNodes(cbNode: (node: ts.Node) => T, cbNodes: ((node: ts.NodeArr /*@internal*/ export function isJSDocLikeText(text: string, start: number) { - return text.charCodeAt(start + 1) === ts.CharacterCodes.asterisk && - text.charCodeAt(start + 2) === ts.CharacterCodes.asterisk && - text.charCodeAt(start + 3) !== ts.CharacterCodes.slash; + return text.charCodeAt(start + 1) === CharacterCodes.asterisk && + text.charCodeAt(start + 2) === CharacterCodes.asterisk && + text.charCodeAt(start + 3) !== CharacterCodes.slash; } /*@internal*/ -export function isFileProbablyExternalModule(sourceFile: ts.SourceFile) { +export function isFileProbablyExternalModule(sourceFile: SourceFile) { // Try to use the first top-level import/export when available, then // fall back to looking for an 'import.meta' somewhere in the tree if necessary. - return ts.forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || + return forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) || getImportMetaIfNecessary(sourceFile); } -function isAnExternalModuleIndicatorNode(node: ts.Node) { - return ts.canHaveModifiers(node) && hasModifierOfKind(node, ts.SyntaxKind.ExportKeyword) - || ts.isImportEqualsDeclaration(node) && ts.isExternalModuleReference(node.moduleReference) - || ts.isImportDeclaration(node) - || ts.isExportAssignment(node) - || ts.isExportDeclaration(node) ? node : undefined; +function isAnExternalModuleIndicatorNode(node: Node) { + return canHaveModifiers(node) && hasModifierOfKind(node, SyntaxKind.ExportKeyword) + || isImportEqualsDeclaration(node) && isExternalModuleReference(node.moduleReference) + || isImportDeclaration(node) + || isExportAssignment(node) + || isExportDeclaration(node) ? node : undefined; } -function getImportMetaIfNecessary(sourceFile: ts.SourceFile) { - return sourceFile.flags & ts.NodeFlags.PossiblyContainsImportMeta ? +function getImportMetaIfNecessary(sourceFile: SourceFile) { + return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ? walkTreeForImportMeta(sourceFile) : undefined; } -function walkTreeForImportMeta(node: ts.Node): ts.Node | undefined { +function walkTreeForImportMeta(node: Node): Node | undefined { return isImportMeta(node) ? node : forEachChild(node, walkTreeForImportMeta); } /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */ -function hasModifierOfKind(node: ts.HasModifiers, kind: ts.SyntaxKind) { - return ts.some(node.modifiers, m => m.kind === kind); +function hasModifierOfKind(node: HasModifiers, kind: SyntaxKind) { + return some(node.modifiers, m => m.kind === kind); } -function isImportMeta(node: ts.Node): boolean { - return ts.isMetaProperty(node) && node.keywordToken === ts.SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; +function isImportMeta(node: Node): boolean { + return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; } -type ForEachChildFunction = (node: TNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined) => T | undefined; -type ForEachChildTable = { [TNode in ts.ForEachChildNodes as TNode["kind"]]: ForEachChildFunction }; +type ForEachChildFunction = (node: TNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined) => T | undefined; +type ForEachChildTable = { [TNode in ForEachChildNodes as TNode["kind"]]: ForEachChildFunction }; const forEachChildTable: ForEachChildTable = { - [ts.SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node: ts.QualifiedName, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node: QualifiedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.left) || visitNode(cbNode, node.right); }, - [ts.SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node: ts.TypeParameterDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node: TypeParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.constraint) || visitNode(cbNode, node.default) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node: ts.ShorthandPropertyAssignment, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node: ShorthandPropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -119,10 +185,10 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.equalsToken) || visitNode(cbNode, node.objectAssignmentInitializer); }, - [ts.SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node: ts.SpreadAssignment, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node: SpreadAssignment, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.Parameter]: function forEachChildInParameter(node: ts.ParameterDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.Parameter]: function forEachChildInParameter(node: ParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || @@ -130,7 +196,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node: ts.PropertyDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node: PropertyDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || @@ -138,14 +204,14 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node: ts.PropertySignature, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node: PropertySignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node: ts.PropertyAssignment, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node: PropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -153,40 +219,40 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node: ts.VariableDeclaration, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node: VariableDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name) || visitNode(cbNode, node.exclamationToken) || visitNode(cbNode, node.type) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.BindingElement]: function forEachChildInBindingElement(node: ts.BindingElement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.BindingElement]: function forEachChildInBindingElement(node: BindingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node: ts.IndexSignatureDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node: IndexSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node: ts.ConstructorTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node: ConstructorTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.FunctionType]: function forEachChildInFunctionType(node: ts.FunctionTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.FunctionType]: function forEachChildInFunctionType(node: FunctionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature, - [ts.SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature, - [ts.SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node: ts.MethodDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature, + [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature, + [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node: MethodDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || @@ -197,7 +263,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node: ts.MethodSignature, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node: MethodSignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || @@ -205,7 +271,7 @@ const forEachChildTable: ForEachChildTable = { visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.Constructor]: function forEachChildInConstructor(node: ts.ConstructorDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.Constructor]: function forEachChildInConstructor(node: ConstructorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -214,7 +280,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node: ts.GetAccessorDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node: GetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || @@ -222,7 +288,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node: ts.SetAccessorDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node: SetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || @@ -230,7 +296,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node: ts.FunctionDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node: FunctionDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || @@ -240,7 +306,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node: ts.FunctionExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node: FunctionExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.name) || @@ -249,7 +315,7 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node: ts.ArrowFunction, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node: ArrowFunction, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || @@ -257,60 +323,60 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.equalsGreaterThanToken) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.TypeReference]: function forEachChildInTypeReference(node: ts.TypeReferenceNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeReference]: function forEachChildInTypeReference(node: TypeReferenceNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.typeName) || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [ts.SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node: ts.TypePredicateNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node: TypePredicateNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.assertsModifier) || visitNode(cbNode, node.parameterName) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node: ts.TypeQueryNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node: TypeQueryNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.exprName) || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [ts.SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node: ts.TypeLiteralNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node: TypeLiteralNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.members); }, - [ts.SyntaxKind.ArrayType]: function forEachChildInArrayType(node: ts.ArrayTypeNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ArrayType]: function forEachChildInArrayType(node: ArrayTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.elementType); }, - [ts.SyntaxKind.TupleType]: function forEachChildInTupleType(node: ts.TupleTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TupleType]: function forEachChildInTupleType(node: TupleTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [ts.SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType, - [ts.SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType, - [ts.SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node: ts.ConditionalTypeNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType, + [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType, + [SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node: ConditionalTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.checkType) || visitNode(cbNode, node.extendsType) || visitNode(cbNode, node.trueType) || visitNode(cbNode, node.falseType); }, - [ts.SyntaxKind.InferType]: function forEachChildInInferType(node: ts.InferTypeNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.InferType]: function forEachChildInInferType(node: InferTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.typeParameter); }, - [ts.SyntaxKind.ImportType]: function forEachChildInImportType(node: ts.ImportTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportType]: function forEachChildInImportType(node: ImportTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.argument) || visitNode(cbNode, node.assertions) || visitNode(cbNode, node.qualifier) || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [ts.SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node: ts.ImportTypeAssertionContainer, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node: ImportTypeAssertionContainer, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.assertClause); }, - [ts.SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator, - [ts.SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator, - [ts.SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node: ts.IndexedAccessTypeNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator, + [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator, + [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node: IndexedAccessTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.objectType) || visitNode(cbNode, node.indexType); }, - [ts.SyntaxKind.MappedType]: function forEachChildInMappedType(node: ts.MappedTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MappedType]: function forEachChildInMappedType(node: MappedTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.readonlyToken) || visitNode(cbNode, node.typeParameter) || visitNode(cbNode, node.nameType) || @@ -318,190 +384,190 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.type) || visitNodes(cbNode, cbNodes, node.members); }, - [ts.SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: ts.LiteralTypeNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.literal); }, - [ts.SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: ts.NamedTupleMember, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.name) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern, - [ts.SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern, - [ts.SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node: ts.ArrayLiteralExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern, + [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern, + [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node: ArrayLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [ts.SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node: ts.ObjectLiteralExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node: ObjectLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.properties); }, - [ts.SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node: ts.PropertyAccessExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node: PropertyAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.questionDotToken) || visitNode(cbNode, node.name); }, - [ts.SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node: ts.ElementAccessExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node: ElementAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.questionDotToken) || visitNode(cbNode, node.argumentExpression); }, - [ts.SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression, - [ts.SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression, - [ts.SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node: ts.TaggedTemplateExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression, + [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression, + [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node: TaggedTemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tag) || visitNode(cbNode, node.questionDotToken) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.template); }, - [ts.SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node: ts.TypeAssertion, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node: TypeAssertion, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.type) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node: ts.ParenthesizedExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node: ParenthesizedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node: ts.DeleteExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node: DeleteExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node: ts.TypeOfExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node: TypeOfExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node: ts.VoidExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node: VoidExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node: ts.PrefixUnaryExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node: PrefixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.operand); }, - [ts.SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node: ts.YieldExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node: YieldExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.asteriskToken) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node: ts.AwaitExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node: AwaitExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node: ts.PostfixUnaryExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node: PostfixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.operand); }, - [ts.SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node: ts.BinaryExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node: BinaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.left) || visitNode(cbNode, node.operatorToken) || visitNode(cbNode, node.right); }, - [ts.SyntaxKind.AsExpression]: function forEachChildInAsExpression(node: ts.AsExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AsExpression]: function forEachChildInAsExpression(node: AsExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node: ts.NonNullExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: ts.SatisfiesExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: ts.MetaProperty, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); }, - [ts.SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node: ts.ConditionalExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node: ConditionalExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.condition) || visitNode(cbNode, node.questionToken) || visitNode(cbNode, node.whenTrue) || visitNode(cbNode, node.colonToken) || visitNode(cbNode, node.whenFalse); }, - [ts.SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node: ts.SpreadElement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node: SpreadElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.Block]: forEachChildInBlock, - [ts.SyntaxKind.ModuleBlock]: forEachChildInBlock, - [ts.SyntaxKind.SourceFile]: function forEachChildInSourceFile(node: ts.SourceFile, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.Block]: forEachChildInBlock, + [SyntaxKind.ModuleBlock]: forEachChildInBlock, + [SyntaxKind.SourceFile]: function forEachChildInSourceFile(node: SourceFile, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.statements) || visitNode(cbNode, node.endOfFileToken); }, - [ts.SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node: ts.VariableStatement, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node: VariableStatement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.declarationList); }, - [ts.SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node: ts.VariableDeclarationList, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node: VariableDeclarationList, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.declarations); }, - [ts.SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node: ts.ExpressionStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node: ExpressionStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.IfStatement]: function forEachChildInIfStatement(node: ts.IfStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.IfStatement]: function forEachChildInIfStatement(node: IfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.thenStatement) || visitNode(cbNode, node.elseStatement); }, - [ts.SyntaxKind.DoStatement]: function forEachChildInDoStatement(node: ts.DoStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.DoStatement]: function forEachChildInDoStatement(node: DoStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.statement) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node: ts.WhileStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node: WhileStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.ForStatement]: function forEachChildInForStatement(node: ts.ForStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ForStatement]: function forEachChildInForStatement(node: ForStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.condition) || visitNode(cbNode, node.incrementor) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node: ts.ForInStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node: ForInStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node: ts.ForOfStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node: ForOfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.awaitModifier) || visitNode(cbNode, node.initializer) || visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement, - [ts.SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement, - [ts.SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node: ts.ReturnStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement, + [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement, + [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node: ReturnStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.WithStatement]: function forEachChildInWithStatement(node: ts.WithStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.WithStatement]: function forEachChildInWithStatement(node: WithStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node: ts.SwitchStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node: SwitchStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.caseBlock); }, - [ts.SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node: ts.CaseBlock, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node: CaseBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.clauses); }, - [ts.SyntaxKind.CaseClause]: function forEachChildInCaseClause(node: ts.CaseClause, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CaseClause]: function forEachChildInCaseClause(node: CaseClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.statements); }, - [ts.SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node: ts.DefaultClause, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node: DefaultClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.statements); }, - [ts.SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node: ts.LabeledStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node: LabeledStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.label) || visitNode(cbNode, node.statement); }, - [ts.SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node: ts.ThrowStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node: ThrowStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.TryStatement]: function forEachChildInTryStatement(node: ts.TryStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TryStatement]: function forEachChildInTryStatement(node: TryStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tryBlock) || visitNode(cbNode, node.catchClause) || visitNode(cbNode, node.finallyBlock); }, - [ts.SyntaxKind.CatchClause]: function forEachChildInCatchClause(node: ts.CatchClause, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CatchClause]: function forEachChildInCatchClause(node: CatchClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.variableDeclaration) || visitNode(cbNode, node.block); }, - [ts.SyntaxKind.Decorator]: function forEachChildInDecorator(node: ts.Decorator, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.Decorator]: function forEachChildInDecorator(node: Decorator, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression, - [ts.SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression, - [ts.SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node: ts.InterfaceDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression, + [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression, + [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node: InterfaceDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || @@ -509,197 +575,197 @@ const forEachChildTable: ForEachChildTable = { visitNodes(cbNode, cbNodes, node.heritageClauses) || visitNodes(cbNode, cbNodes, node.members); }, - [ts.SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node: ts.TypeAliasDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node: TypeAliasDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node: ts.EnumDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node: EnumDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.members); }, - [ts.SyntaxKind.EnumMember]: function forEachChildInEnumMember(node: ts.EnumMember, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.EnumMember]: function forEachChildInEnumMember(node: EnumMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node: ts.ModuleDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.body); }, - [ts.SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node: ts.ImportEqualsDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node: ImportEqualsDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNode(cbNode, node.moduleReference); }, - [ts.SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node: ts.ImportDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node: ImportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.importClause) || visitNode(cbNode, node.moduleSpecifier) || visitNode(cbNode, node.assertClause); }, - [ts.SyntaxKind.ImportClause]: function forEachChildInImportClause(node: ts.ImportClause, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportClause]: function forEachChildInImportClause(node: ImportClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name) || visitNode(cbNode, node.namedBindings); }, - [ts.SyntaxKind.AssertClause]: function forEachChildInAssertClause(node: ts.AssertClause, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AssertClause]: function forEachChildInAssertClause(node: AssertClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [ts.SyntaxKind.AssertEntry]: function forEachChildInAssertEntry(node: ts.AssertEntry, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.AssertEntry]: function forEachChildInAssertEntry(node: AssertEntry, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name) || visitNode(cbNode, node.value); }, - [ts.SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node: NamespaceExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNode(cbNode, node.name); }, - [ts.SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node: ts.NamespaceImport, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node: NamespaceImport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); }, - [ts.SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node: ts.NamespaceExport, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node: NamespaceExport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); }, - [ts.SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports, - [ts.SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports, - [ts.SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node: ts.ExportDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports, + [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports, + [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node: ExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.exportClause) || visitNode(cbNode, node.moduleSpecifier) || visitNode(cbNode, node.assertClause); }, - [ts.SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier, - [ts.SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier, - [ts.SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node: ts.ExportAssignment, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier, + [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier, + [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node: ExportAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node: ts.TemplateExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node: TemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans); }, - [ts.SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node: ts.TemplateSpan, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node: TemplateSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNode(cbNode, node.literal); }, - [ts.SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node: ts.TemplateLiteralTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node: TemplateLiteralTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.head) || visitNodes(cbNode, cbNodes, node.templateSpans); }, - [ts.SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node: ts.TemplateLiteralTypeSpan, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.type) || visitNode(cbNode, node.literal); }, - [ts.SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node: ts.ComputedPropertyName, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node: ComputedPropertyName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node: ts.HeritageClause, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node: HeritageClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.types); }, - [ts.SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node: ts.ExpressionWithTypeArguments, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node: ExpressionWithTypeArguments, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || visitNodes(cbNode, cbNodes, node.typeArguments); }, - [ts.SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node: ts.ExternalModuleReference, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node: ExternalModuleReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node: ts.MissingDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node: MissingDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.illegalDecorators) || visitNodes(cbNode, cbNodes, node.modifiers); }, - [ts.SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node: ts.CommaListExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node: CommaListExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); }, - [ts.SyntaxKind.JsxElement]: function forEachChildInJsxElement(node: ts.JsxElement, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxElement]: function forEachChildInJsxElement(node: JsxElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.openingElement) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingElement); }, - [ts.SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node: ts.JsxFragment, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node: JsxFragment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.openingFragment) || visitNodes(cbNode, cbNodes, node.children) || visitNode(cbNode, node.closingFragment); }, - [ts.SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement, - [ts.SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement, - [ts.SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node: ts.JsxAttributes, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement, + [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement, + [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node: JsxAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.properties); }, - [ts.SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node: ts.JsxAttribute, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node: JsxAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name) || visitNode(cbNode, node.initializer); }, - [ts.SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node: ts.JsxSpreadAttribute, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node: JsxSpreadAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node: ts.JsxExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node: JsxExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.dotDotDotToken) || visitNode(cbNode, node.expression); }, - [ts.SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node: ts.JsxClosingElement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node: JsxClosingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName); }, - [ts.SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [ts.SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node: ts.JSDocFunctionType, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node: JSDocFunctionType, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: ts.JSDoc, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: JSDoc, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) || visitNodes(cbNode, cbNodes, node.tags); }, - [ts.SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: ts.JSDocSeeTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: JSDocSeeTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.name) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: ts.JSDocNameReference, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: JSDocNameReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); }, - [ts.SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node: ts.JSDocMemberName, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node: JSDocMemberName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.left) || visitNode(cbNode, node.right); }, - [ts.SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag, - [ts.SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, - [ts.SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: ts.JSDocAuthorTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag, + [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, + [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: JSDocAuthorTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: ts.JSDocImplementsTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: JSDocImplementsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.class) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: ts.JSDocAugmentsTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: JSDocAugmentsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.class) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: ts.JSDocTemplateTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: JSDocTemplateTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.constraint) || visitNodes(cbNode, cbNodes, node.typeParameters) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: ts.JSDocTypedefTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: JSDocTypedefTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (node.typeExpression && - node.typeExpression.kind === ts.SyntaxKind.JSDocTypeExpression + node.typeExpression.kind === SyntaxKind.JSDocTypeExpression ? visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.fullName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) @@ -707,75 +773,75 @@ const forEachChildTable: ForEachChildTable = { visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))); }, - [ts.SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: ts.JSDocCallbackTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { + [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: JSDocCallbackTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.fullName) || visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); }, - [ts.SyntaxKind.JSDocReturnTag]: forEachChildInJSDocReturnTag, - [ts.SyntaxKind.JSDocTypeTag]: forEachChildInJSDocReturnTag, - [ts.SyntaxKind.JSDocThisTag]: forEachChildInJSDocReturnTag, - [ts.SyntaxKind.JSDocEnumTag]: forEachChildInJSDocReturnTag, - [ts.SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node: ts.JSDocSignature, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { - return ts.forEach(node.typeParameters, cbNode) || - ts.forEach(node.parameters, cbNode) || + [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocReturnTag, + [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocReturnTag, + [SyntaxKind.JSDocThisTag]: forEachChildInJSDocReturnTag, + [SyntaxKind.JSDocEnumTag]: forEachChildInJSDocReturnTag, + [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node: JSDocSignature, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return forEach(node.typeParameters, cbNode) || + forEach(node.parameters, cbNode) || visitNode(cbNode, node.type); }, - [ts.SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain, - [ts.SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain, - [ts.SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain, - [ts.SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node: ts.JSDocTypeLiteral, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { - return ts.forEach(node.jsDocPropertyTags, cbNode); + [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node: JSDocTypeLiteral, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return forEach(node.jsDocPropertyTags, cbNode); }, - [ts.SyntaxKind.JSDocTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, - [ts.SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, + [SyntaxKind.JSDocTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, + [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, }; // shared -function forEachChildInCallOrConstructSignature(node: ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInCallOrConstructSignature(node: CallSignatureDeclaration | ConstructSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.typeParameters) || visitNodes(cbNode, cbNodes, node.parameters) || visitNode(cbNode, node.type); } -function forEachChildInUnionOrIntersectionType(node: ts.UnionTypeNode | ts.IntersectionTypeNode, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInUnionOrIntersectionType(node: UnionTypeNode | IntersectionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.types); } -function forEachChildInParenthesizedTypeOrTypeOperator(node: ts.ParenthesizedTypeNode | ts.TypeOperatorNode, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInParenthesizedTypeOrTypeOperator(node: ParenthesizedTypeNode | TypeOperatorNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.type); } -function forEachChildInObjectOrArrayBindingPattern(node: ts.BindingPattern, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInObjectOrArrayBindingPattern(node: BindingPattern, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); } -function forEachChildInCallOrNewExpression(node: ts.CallExpression | ts.NewExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInCallOrNewExpression(node: CallExpression | NewExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression) || // TODO: should we separate these branches out? - visitNode(cbNode, (node as ts.CallExpression).questionDotToken) || + visitNode(cbNode, (node as CallExpression).questionDotToken) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNodes(cbNode, cbNodes, node.arguments); } -function forEachChildInBlock(node: ts.Block | ts.ModuleBlock, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInBlock(node: Block | ModuleBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.statements); } -function forEachChildInContinueOrBreakStatement(node: ts.ContinueStatement | ts.BreakStatement, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInContinueOrBreakStatement(node: ContinueStatement | BreakStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.label); } -function forEachChildInClassDeclarationOrExpression(node: ts.ClassDeclaration | ts.ClassExpression, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.name) || visitNodes(cbNode, cbNodes, node.typeParameters) || @@ -783,26 +849,26 @@ function forEachChildInClassDeclarationOrExpression(node: ts.ClassDeclaration visitNodes(cbNode, cbNodes, node.members); } -function forEachChildInNamedImportsOrExports(node: ts.NamedImports | ts.NamedExports, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInNamedImportsOrExports(node: NamedImports | NamedExports, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNodes(cbNode, cbNodes, node.elements); } -function forEachChildInImportOrExportSpecifier(node: ts.ImportSpecifier | ts.ExportSpecifier, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInImportOrExportSpecifier(node: ImportSpecifier | ExportSpecifier, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.propertyName) || visitNode(cbNode, node.name); } -function forEachChildInJsxOpeningOrSelfClosingElement(node: ts.JsxOpeningLikeElement, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInJsxOpeningOrSelfClosingElement(node: JsxOpeningLikeElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNodes(cbNode, cbNodes, node.typeArguments) || visitNode(cbNode, node.attributes); } -function forEachChildInOptionalRestOrJSDocParameterModifier(node: ts.OptionalTypeNode | ts.RestTypeNode | ts.JSDocTypeExpression | ts.JSDocNullableType | ts.JSDocNonNullableType | ts.JSDocOptionalType | ts.JSDocVariadicType, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInOptionalRestOrJSDocParameterModifier(node: OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocNullableType | JSDocNonNullableType | JSDocOptionalType | JSDocVariadicType, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.type); } -function forEachChildInJSDocParameterOrPropertyTag(node: ts.JSDocParameterTag | ts.JSDocPropertyTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocParameterOrPropertyTag(node: JSDocParameterTag | JSDocPropertyTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (node.isNameFirst ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression) @@ -810,22 +876,22 @@ function forEachChildInJSDocParameterOrPropertyTag(node: ts.JSDocParameterTag (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInJSDocReturnTag(node: ts.JSDocReturnTag | ts.JSDocTypeTag | ts.JSDocThisTag | ts.JSDocEnumTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocReturnTag(node: JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || visitNode(cbNode, node.typeExpression) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInJSDocLinkCodeOrPlain(node: ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.name); } -function forEachChildInJSDocTag(node: ts.JSDocUnknownTag | ts.JSDocClassTag | ts.JSDocPublicTag | ts.JSDocPrivateTag | ts.JSDocProtectedTag | ts.JSDocReadonlyTag | ts.JSDocDeprecatedTag | ts.JSDocOverrideTag, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } -function forEachChildInPartiallyEmittedExpression(node: ts.PartiallyEmittedExpression, cbNode: (node: ts.Node) => T | undefined, _cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { +function forEachChildInPartiallyEmittedExpression(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.expression); } @@ -842,11 +908,11 @@ function forEachChildInPartiallyEmittedExpression(node: ts.PartiallyEmittedEx * @remarks `forEachChild` must visit the children of a node in the order * that they appear in the source code. The language service depends on this property to locate nodes by position. */ -export function forEachChild(node: ts.Node, cbNode: (node: ts.Node) => T | undefined, cbNodes?: (nodes: ts.NodeArray) => T | undefined): T | undefined { - if (node === undefined || node.kind <= ts.SyntaxKind.LastToken) { +export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + if (node === undefined || node.kind <= SyntaxKind.LastToken) { return; } - const fn = (forEachChildTable as Record>)[node.kind]; + const fn = (forEachChildTable as Record>)[node.kind]; return fn === undefined ? undefined : fn(node, cbNode, cbNodes); } @@ -864,16 +930,16 @@ export function forEachChild(node: ts.Node, cbNode: (node: ts.Node) => T | un * @remarks Unlike `forEachChild`, `forEachChildRecursively` handles recursively invoking the traversal on each child node found, * and while doing so, handles traversing the structure without relying on the callstack to encode the tree structure. */ -export function forEachChildRecursively(rootNode: ts.Node, cbNode: (node: ts.Node, parent: ts.Node) => T | "skip" | undefined, cbNodes?: (nodes: ts.NodeArray, parent: ts.Node) => T | "skip" | undefined): T | undefined { - const queue: (ts.Node | ts.NodeArray)[] = gatherPossibleChildren(rootNode); - const parents: ts.Node[] = []; // tracks parent references for elements in queue +export function forEachChildRecursively(rootNode: Node, cbNode: (node: Node, parent: Node) => T | "skip" | undefined, cbNodes?: (nodes: NodeArray, parent: Node) => T | "skip" | undefined): T | undefined { + const queue: (Node | NodeArray)[] = gatherPossibleChildren(rootNode); + const parents: Node[] = []; // tracks parent references for elements in queue while (parents.length < queue.length) { parents.push(rootNode); } while (queue.length !== 0) { const current = queue.pop()!; const parent = parents.pop()!; - if (ts.isArray(current)) { + if (isArray(current)) { if (cbNodes) { const res = cbNodes(current, parent); if (res) { @@ -892,7 +958,7 @@ export function forEachChildRecursively(rootNode: ts.Node, cbNode: (node: ts. if (res === "skip") continue; return res; } - if (current.kind >= ts.SyntaxKind.FirstNode) { + if (current.kind >= SyntaxKind.FirstNode) { // add children in reverse order to the queue, so popping gives the first child for (const child of gatherPossibleChildren(current)) { queue.push(child); @@ -903,68 +969,68 @@ export function forEachChildRecursively(rootNode: ts.Node, cbNode: (node: ts. } } -function gatherPossibleChildren(node: ts.Node) { - const children: (ts.Node | ts.NodeArray)[] = []; +function gatherPossibleChildren(node: Node) { + const children: (Node | NodeArray)[] = []; forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal return children; - function addWorkItem(n: ts.Node | ts.NodeArray) { + function addWorkItem(n: Node | NodeArray) { children.unshift(n); } } export interface CreateSourceFileOptions { - languageVersion: ts.ScriptTarget; + languageVersion: ScriptTarget; /** * Controls the format the file is detected as - this can be derived from only the path * and files on disk, but needs to be done with a module resolution cache in scope to be performant. * This is usually `undefined` for compilations that do not have `moduleResolution` values of `node16` or `nodenext`. */ - impliedNodeFormat?: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS; + impliedNodeFormat?: ModuleKind.ESNext | ModuleKind.CommonJS; /** * Controls how module-y-ness is set for the given file. Usually the result of calling * `getSetExternalModuleIndicator` on a valid `CompilerOptions` object. If not present, the default * check specified by `isFileProbablyExternalModule` will be used to set the field. */ - setExternalModuleIndicator?: (file: ts.SourceFile) => void; + setExternalModuleIndicator?: (file: SourceFile) => void; /*@internal*/ packageJsonLocations?: readonly string[]; - /*@internal*/ packageJsonScope?: ts.PackageJsonInfo; + /*@internal*/ packageJsonScope?: PackageJsonInfo; } -function setExternalModuleIndicator(sourceFile: ts.SourceFile) { +function setExternalModuleIndicator(sourceFile: SourceFile) { sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile); } -export function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ts.ScriptTarget | CreateSourceFileOptions, setParentNodes = false, scriptKind?: ts.ScriptKind): ts.SourceFile { - ts.tracing?.push(ts.tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); +export function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { + tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); ts.performance.mark("beforeParse"); - let result: ts.SourceFile; + let result: SourceFile; - ts.perfLogger.logStartParseSourceFile(fileName); + perfLogger.logStartParseSourceFile(fileName); const { languageVersion, setExternalModuleIndicator: overrideSetExternalModuleIndicator, impliedNodeFormat: format } = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions : ({ languageVersion: languageVersionOrOptions } as CreateSourceFileOptions); - if (languageVersion === ts.ScriptTarget.JSON) { - result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ts.ScriptKind.JSON, ts.noop); + if (languageVersion === ScriptTarget.JSON) { + result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON, noop); } else { - const setIndicator = format === undefined ? overrideSetExternalModuleIndicator : (file: ts.SourceFile) => { + const setIndicator = format === undefined ? overrideSetExternalModuleIndicator : (file: SourceFile) => { file.impliedNodeFormat = format; return (overrideSetExternalModuleIndicator || setExternalModuleIndicator)(file); }; result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind, setIndicator); } - ts.perfLogger.logStopParseSourceFile(); + perfLogger.logStopParseSourceFile(); ts.performance.mark("afterParse"); ts.performance.measure("Parse", "beforeParse", "afterParse"); - ts.tracing?.pop(); + tracing?.pop(); return result; } -export function parseIsolatedEntityName(text: string, languageVersion: ts.ScriptTarget): ts.EntityName | undefined { +export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined { return Parser.parseIsolatedEntityName(text, languageVersion); } @@ -973,12 +1039,12 @@ export function parseIsolatedEntityName(text: string, languageVersion: ts.Script * @param fileName * @param sourceText */ -export function parseJsonText(fileName: string, sourceText: string): ts.JsonSourceFile { +export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile { return Parser.parseJsonText(fileName, sourceText); } // See also `isExternalOrCommonJsModule` in utilities.ts -export function isExternalModule(file: ts.SourceFile): boolean { +export function isExternalModule(file: SourceFile): boolean { return file.externalModuleIndicator !== undefined; } @@ -991,11 +1057,11 @@ export function isExternalModule(file: ts.SourceFile): boolean { // from this SourceFile that are being held onto may change as a result (including // becoming detached from any SourceFile). It is recommended that this SourceFile not // be used once 'update' is called on it. -export function updateSourceFile(sourceFile: ts.SourceFile, newText: string, textChangeRange: ts.TextChangeRange, aggressiveChecks = false): ts.SourceFile { +export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false): SourceFile { const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. // We will manually port the flag to the new source file. - (newSourceFile as ts.Mutable).flags |= (sourceFile.flags & ts.NodeFlags.PermanentlySetIncrementalFlags); + (newSourceFile as Mutable).flags |= (sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags); return newSourceFile; } @@ -1023,25 +1089,25 @@ export function parseJSDocTypeExpressionForTests(content: string, start?: number namespace Parser { // Share a single scanner across all calls to parse a source file. This helps speed things // up by avoiding the cost of creating/compiling scanners over and over again. - const scanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ true); + const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); - const disallowInAndDecoratorContext = ts.NodeFlags.DisallowInContext | ts.NodeFlags.DecoratorContext; + const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; // capture constructors in 'initializeState' to avoid null checks - let NodeConstructor: new (kind: ts.SyntaxKind, pos: number, end: number) => ts.Node; - let TokenConstructor: new (kind: ts.SyntaxKind, pos: number, end: number) => ts.Node; - let IdentifierConstructor: new (kind: ts.SyntaxKind, pos: number, end: number) => ts.Node; - let PrivateIdentifierConstructor: new (kind: ts.SyntaxKind, pos: number, end: number) => ts.Node; - let SourceFileConstructor: new (kind: ts.SyntaxKind, pos: number, end: number) => ts.Node; + let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; + let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - function countNode(node: ts.Node) { + function countNode(node: Node) { nodeCount++; return node; } // Rather than using `createBaseNodeFactory` here, we establish a `BaseNodeFactory` that closes over the // constructors above, which are reset each time `initializeState` is called. - const baseNodeFactory: ts.BaseNodeFactory = { + const baseNodeFactory: BaseNodeFactory = { createBaseSourceFileNode: kind => countNode(new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0)), createBaseIdentifierNode: kind => countNode(new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)), createBasePrivateIdentifierNode: kind => countNode(new PrivateIdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)), @@ -1049,27 +1115,27 @@ namespace Parser { createBaseNode: kind => countNode(new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0)) }; - const factory = ts.createNodeFactory(ts.NodeFactoryFlags.NoParenthesizerRules | ts.NodeFactoryFlags.NoNodeConverters | ts.NodeFactoryFlags.NoOriginalNode, baseNodeFactory); + const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory); let fileName: string; - let sourceFlags: ts.NodeFlags; + let sourceFlags: NodeFlags; let sourceText: string; - let languageVersion: ts.ScriptTarget; - let scriptKind: ts.ScriptKind; - let languageVariant: ts.LanguageVariant; - let parseDiagnostics: ts.DiagnosticWithDetachedLocation[]; - let jsDocDiagnostics: ts.DiagnosticWithDetachedLocation[]; + let languageVersion: ScriptTarget; + let scriptKind: ScriptKind; + let languageVariant: LanguageVariant; + let parseDiagnostics: DiagnosticWithDetachedLocation[]; + let jsDocDiagnostics: DiagnosticWithDetachedLocation[]; let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; - let currentToken: ts.SyntaxKind; + let currentToken: SyntaxKind; let nodeCount: number; - let identifiers: ts.ESMap; - let privateIdentifiers: ts.ESMap; + let identifiers: ESMap; + let privateIdentifiers: ESMap; let identifierCount: number; let parsingContext: ParsingContext; - let notParenthesizedArrow: ts.Set | undefined; + let notParenthesizedArrow: Set | undefined; // Flags that dictate what parsing context we're in. For example: // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is @@ -1117,7 +1183,7 @@ namespace Parser { // Note: it should not be necessary to save/restore these flags during speculative/lookahead // parsing. These context flags are naturally stored and restored through normal recursive // descent parsing and unwinding. - let contextFlags: ts.NodeFlags; + let contextFlags: NodeFlags; // Indicates whether we are currently parsing top-level statements. let topLevel = true; @@ -1151,17 +1217,17 @@ namespace Parser { // attached to the EOF token. let parseErrorBeforeNextFinishedNode = false; - export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ts.ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ts.ScriptKind, setExternalModuleIndicatorOverride?: (file: ts.SourceFile) => void): ts.SourceFile { - scriptKind = ts.ensureScriptKind(fileName, scriptKind); - if (scriptKind === ts.ScriptKind.JSON) { + export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind, setExternalModuleIndicatorOverride?: (file: SourceFile) => void): SourceFile { + scriptKind = ensureScriptKind(fileName, scriptKind); + if (scriptKind === ScriptKind.JSON) { const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); - ts.convertToObjectWorker(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); - result.referencedFiles = ts.emptyArray; - result.typeReferenceDirectives = ts.emptyArray; - result.libReferenceDirectives = ts.emptyArray; - result.amdDependencies = ts.emptyArray; + convertToObjectWorker(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); + result.referencedFiles = emptyArray; + result.typeReferenceDirectives = emptyArray; + result.libReferenceDirectives = emptyArray; + result.amdDependencies = emptyArray; result.hasNoDefaultLib = false; - result.pragmas = ts.emptyMap as ts.ReadonlyPragmaMap; + result.pragmas = emptyMap as ReadonlyPragmaMap; return result; } @@ -1174,56 +1240,56 @@ namespace Parser { return result; } - export function parseIsolatedEntityName(content: string, languageVersion: ts.ScriptTarget): ts.EntityName | undefined { + export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined { // Choice of `isDeclarationFile` should be arbitrary - initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ts.ScriptKind.JS); + initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); // Prime the scanner. nextToken(); const entityName = parseEntityName(/*allowReservedWords*/ true); - const isInvalid = token() === ts.SyntaxKind.EndOfFileToken && !parseDiagnostics.length; + const isInvalid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length; clearState(); return isInvalid ? entityName : undefined; } - export function parseJsonText(fileName: string, sourceText: string, languageVersion: ts.ScriptTarget = ts.ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): ts.JsonSourceFile { - initializeState(fileName, sourceText, languageVersion, syntaxCursor, ts.ScriptKind.JSON); + export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { + initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); sourceFlags = contextFlags; // Prime the scanner. nextToken(); const pos = getNodePos(); let statements, endOfFileToken; - if (token() === ts.SyntaxKind.EndOfFileToken) { + if (token() === SyntaxKind.EndOfFileToken) { statements = createNodeArray([], pos, pos); - endOfFileToken = parseTokenNode(); + endOfFileToken = parseTokenNode(); } else { // Loop and synthesize an ArrayLiteralExpression if there are more than // one top-level expressions to ensure all input text is consumed. - let expressions: ts.Expression[] | ts.Expression | undefined; - while (token() !== ts.SyntaxKind.EndOfFileToken) { + let expressions: Expression[] | Expression | undefined; + while (token() !== SyntaxKind.EndOfFileToken) { let expression; switch (token()) { - case ts.SyntaxKind.OpenBracketToken: + case SyntaxKind.OpenBracketToken: expression = parseArrayLiteralExpression(); break; - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: - expression = parseTokenNode(); + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + expression = parseTokenNode(); break; - case ts.SyntaxKind.MinusToken: - if (lookAhead(() => nextToken() === ts.SyntaxKind.NumericLiteral && nextToken() !== ts.SyntaxKind.ColonToken)) { - expression = parsePrefixUnaryExpression() as ts.JsonMinusNumericLiteral; + case SyntaxKind.MinusToken: + if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) { + expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; } else { expression = parseObjectLiteralExpression(); } break; - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.StringLiteral: - if (lookAhead(() => nextToken() !== ts.SyntaxKind.ColonToken)) { - expression = parseLiteralNode() as ts.StringLiteral | ts.NumericLiteral; + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) { + expression = parseLiteralNode() as StringLiteral | NumericLiteral; break; } // falls through @@ -1233,7 +1299,7 @@ namespace Parser { } // Error recovery: collect multiple top-level expressions - if (expressions && ts.isArray(expressions)) { + if (expressions && isArray(expressions)) { expressions.push(expression); } else if (expressions) { @@ -1241,21 +1307,21 @@ namespace Parser { } else { expressions = expression; - if (token() !== ts.SyntaxKind.EndOfFileToken) { - parseErrorAtCurrentToken(ts.Diagnostics.Unexpected_token); + if (token() !== SyntaxKind.EndOfFileToken) { + parseErrorAtCurrentToken(Diagnostics.Unexpected_token); } } } - const expression = ts.isArray(expressions) ? finishNode(factory.createArrayLiteralExpression(expressions), pos) : ts.Debug.checkDefined(expressions); - const statement = factory.createExpressionStatement(expression) as ts.JsonObjectExpressionStatement; + const expression = isArray(expressions) ? finishNode(factory.createArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions); + const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement; finishNode(statement, pos); statements = createNodeArray([statement], pos); - endOfFileToken = parseExpectedToken(ts.SyntaxKind.EndOfFileToken, ts.Diagnostics.Unexpected_token); + endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); } // Set source file so that errors will be reported with this file name - const sourceFile = createSourceFile(fileName, ts.ScriptTarget.ES2015, ts.ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags, ts.noop); + const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags, noop); if (setParentNodes) { fixupParentReferences(sourceFile); @@ -1264,49 +1330,49 @@ namespace Parser { sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = ts.attachFileToDiagnostics(parseDiagnostics, sourceFile); + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = ts.attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); } - const result = sourceFile as ts.JsonSourceFile; + const result = sourceFile as JsonSourceFile; clearState(); return result; } - function initializeState(_fileName: string, _sourceText: string, _languageVersion: ts.ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ts.ScriptKind) { - NodeConstructor = ts.objectAllocator.getNodeConstructor(); - TokenConstructor = ts.objectAllocator.getTokenConstructor(); - IdentifierConstructor = ts.objectAllocator.getIdentifierConstructor(); - PrivateIdentifierConstructor = ts.objectAllocator.getPrivateIdentifierConstructor(); - SourceFileConstructor = ts.objectAllocator.getSourceFileConstructor(); + function initializeState(_fileName: string, _sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) { + NodeConstructor = objectAllocator.getNodeConstructor(); + TokenConstructor = objectAllocator.getTokenConstructor(); + IdentifierConstructor = objectAllocator.getIdentifierConstructor(); + PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor(); + SourceFileConstructor = objectAllocator.getSourceFileConstructor(); - fileName = ts.normalizePath(_fileName); + fileName = normalizePath(_fileName); sourceText = _sourceText; languageVersion = _languageVersion; syntaxCursor = _syntaxCursor; scriptKind = _scriptKind; - languageVariant = ts.getLanguageVariant(_scriptKind); + languageVariant = getLanguageVariant(_scriptKind); parseDiagnostics = []; parsingContext = 0; - identifiers = new ts.Map(); - privateIdentifiers = new ts.Map(); + identifiers = new Map(); + privateIdentifiers = new Map(); identifierCount = 0; nodeCount = 0; sourceFlags = 0; topLevel = true; switch (scriptKind) { - case ts.ScriptKind.JS: - case ts.ScriptKind.JSX: - contextFlags = ts.NodeFlags.JavaScriptFile; + case ScriptKind.JS: + case ScriptKind.JSX: + contextFlags = NodeFlags.JavaScriptFile; break; - case ts.ScriptKind.JSON: - contextFlags = ts.NodeFlags.JavaScriptFile | ts.NodeFlags.JsonFile; + case ScriptKind.JSON: + contextFlags = NodeFlags.JavaScriptFile | NodeFlags.JsonFile; break; default: - contextFlags = ts.NodeFlags.None; + contextFlags = NodeFlags.None; break; } parseErrorBeforeNextFinishedNode = false; @@ -1339,10 +1405,10 @@ namespace Parser { topLevel = true; } - function parseSourceFileWorker(languageVersion: ts.ScriptTarget, setParentNodes: boolean, scriptKind: ts.ScriptKind, setExternalModuleIndicator: (file: ts.SourceFile) => void): ts.SourceFile { + function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, setExternalModuleIndicator: (file: SourceFile) => void): SourceFile { const isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { - contextFlags |= ts.NodeFlags.Ambient; + contextFlags |= NodeFlags.Ambient; } sourceFlags = contextFlags; @@ -1351,8 +1417,8 @@ namespace Parser { nextToken(); const statements = parseList(ParsingContext.SourceElements, parseStatement); - ts.Debug.assert(token() === ts.SyntaxKind.EndOfFileToken); - const endOfFileToken = addJSDocComment(parseTokenNode()); + Debug.assert(token() === SyntaxKind.EndOfFileToken); + const endOfFileToken = addJSDocComment(parseTokenNode()); const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken, sourceFlags, setExternalModuleIndicator); @@ -1364,9 +1430,9 @@ namespace Parser { sourceFile.nodeCount = nodeCount; sourceFile.identifierCount = identifierCount; sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = ts.attachFileToDiagnostics(parseDiagnostics, sourceFile); + sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = ts.attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); } if (setParentNodes) { @@ -1375,33 +1441,33 @@ namespace Parser { return sourceFile; - function reportPragmaDiagnostic(pos: number, end: number, diagnostic: ts.DiagnosticMessage) { - parseDiagnostics.push(ts.createDetachedDiagnostic(fileName, pos, end, diagnostic)); + function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) { + parseDiagnostics.push(createDetachedDiagnostic(fileName, pos, end, diagnostic)); } } - function withJSDoc(node: T, hasJSDoc: boolean): T { + function withJSDoc(node: T, hasJSDoc: boolean): T { return hasJSDoc ? addJSDocComment(node) : node; } let hasDeprecatedTag = false; - function addJSDocComment(node: T): T { - ts.Debug.assert(!node.jsDoc); // Should only be called once per node - const jsDoc = ts.mapDefined(ts.getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); + function addJSDocComment(node: T): T { + Debug.assert(!node.jsDoc); // Should only be called once per node + const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); if (jsDoc.length) node.jsDoc = jsDoc; if (hasDeprecatedTag) { hasDeprecatedTag = false; - (node as ts.Mutable).flags |= ts.NodeFlags.Deprecated; + (node as Mutable).flags |= NodeFlags.Deprecated; } return node; } - function reparseTopLevelAwait(sourceFile: ts.SourceFile) { + function reparseTopLevelAwait(sourceFile: SourceFile) { const savedSyntaxCursor = syntaxCursor; const baseSyntaxCursor = IncrementalParser.createSyntaxCursor(sourceFile); syntaxCursor = { currentNode }; - const statements: ts.Statement[] = []; + const statements: Statement[] = []; const savedParseDiagnostics = parseDiagnostics; parseDiagnostics = []; @@ -1412,24 +1478,24 @@ namespace Parser { // append all statements between pos and start const prevStatement = sourceFile.statements[pos]; const nextStatement = sourceFile.statements[start]; - ts.addRange(statements, sourceFile.statements, pos, start); + addRange(statements, sourceFile.statements, pos, start); pos = findNextStatementWithoutAwait(sourceFile.statements, start); // append all diagnostics associated with the copied range - const diagnosticStart = ts.findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); - const diagnosticEnd = diagnosticStart >= 0 ? ts.findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1; + const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); + const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1; if (diagnosticStart >= 0) { - ts.addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : undefined); + addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : undefined); } // reparse all statements between start and pos. We skip existing diagnostics for the same range and allow the parser to generate new ones. speculationHelper(() => { const savedContextFlags = contextFlags; - contextFlags |= ts.NodeFlags.AwaitContext; + contextFlags |= NodeFlags.AwaitContext; scanner.setTextPos(nextStatement.pos); nextToken(); - while (token() !== ts.SyntaxKind.EndOfFileToken) { + while (token() !== SyntaxKind.EndOfFileToken) { const startPos = scanner.getStartPos(); const statement = parseListElement(ParsingContext.SourceElements, parseStatement); statements.push(statement); @@ -1460,24 +1526,24 @@ namespace Parser { // append all statements between pos and the end of the list if (pos >= 0) { const prevStatement = sourceFile.statements[pos]; - ts.addRange(statements, sourceFile.statements, pos); + addRange(statements, sourceFile.statements, pos); // append all diagnostics associated with the copied range - const diagnosticStart = ts.findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); + const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); if (diagnosticStart >= 0) { - ts.addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart); + addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart); } } syntaxCursor = savedSyntaxCursor; - return factory.updateSourceFile(sourceFile, ts.setTextRange(factory.createNodeArray(statements), sourceFile.statements)); + return factory.updateSourceFile(sourceFile, setTextRange(factory.createNodeArray(statements), sourceFile.statements)); - function containsPossibleTopLevelAwait(node: ts.Node) { - return !(node.flags & ts.NodeFlags.AwaitContext) - && !!(node.transformFlags & ts.TransformFlags.ContainsPossibleTopLevelAwait); + function containsPossibleTopLevelAwait(node: Node) { + return !(node.flags & NodeFlags.AwaitContext) + && !!(node.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait); } - function findNextStatementWithAwait(statements: ts.NodeArray, start: number) { + function findNextStatementWithAwait(statements: NodeArray, start: number) { for (let i = start; i < statements.length; i++) { if (containsPossibleTopLevelAwait(statements[i])) { return i; @@ -1486,7 +1552,7 @@ namespace Parser { return -1; } - function findNextStatementWithoutAwait(statements: ts.NodeArray, start: number) { + function findNextStatementWithoutAwait(statements: NodeArray, start: number) { for (let i = start; i < statements.length; i++) { if (!containsPossibleTopLevelAwait(statements[i])) { return i; @@ -1505,44 +1571,44 @@ namespace Parser { } - export function fixupParentReferences(rootNode: ts.Node) { + export function fixupParentReferences(rootNode: Node) { // normally parent references are set during binding. However, for clients that only need // a syntax tree, and no semantic features, then the binding process is an unnecessary // overhead. This functions allows us to set all the parents, without all the expense of // binding. - ts.setParentRecursive(rootNode, /*incremental*/ true); + setParentRecursive(rootNode, /*incremental*/ true); } function createSourceFile( fileName: string, - languageVersion: ts.ScriptTarget, - scriptKind: ts.ScriptKind, + languageVersion: ScriptTarget, + scriptKind: ScriptKind, isDeclarationFile: boolean, - statements: readonly ts.Statement[], - endOfFileToken: ts.EndOfFileToken, - flags: ts.NodeFlags, - setExternalModuleIndicator: (sourceFile: ts.SourceFile) => void): ts.SourceFile { + statements: readonly Statement[], + endOfFileToken: EndOfFileToken, + flags: NodeFlags, + setExternalModuleIndicator: (sourceFile: SourceFile) => void): SourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags); - ts.setTextRangePosWidth(sourceFile, 0, sourceText.length); + setTextRangePosWidth(sourceFile, 0, sourceText.length); setFields(sourceFile); // If we parsed this as an external module, it may contain top-level await - if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & ts.TransformFlags.ContainsPossibleTopLevelAwait) { + if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) { sourceFile = reparseTopLevelAwait(sourceFile); setFields(sourceFile); } return sourceFile; - function setFields(sourceFile: ts.SourceFile) { + function setFields(sourceFile: SourceFile) { sourceFile.text = sourceText; sourceFile.bindDiagnostics = []; sourceFile.bindSuggestionDiagnostics = undefined; sourceFile.languageVersion = languageVersion; sourceFile.fileName = fileName; - sourceFile.languageVariant = ts.getLanguageVariant(scriptKind); + sourceFile.languageVariant = getLanguageVariant(scriptKind); sourceFile.isDeclarationFile = isDeclarationFile; sourceFile.scriptKind = scriptKind; @@ -1551,7 +1617,7 @@ namespace Parser { } } - function setContextFlag(val: boolean, flag: ts.NodeFlags) { + function setContextFlag(val: boolean, flag: NodeFlags) { if (val) { contextFlags |= flag; } @@ -1561,22 +1627,22 @@ namespace Parser { } function setDisallowInContext(val: boolean) { - setContextFlag(val, ts.NodeFlags.DisallowInContext); + setContextFlag(val, NodeFlags.DisallowInContext); } function setYieldContext(val: boolean) { - setContextFlag(val, ts.NodeFlags.YieldContext); + setContextFlag(val, NodeFlags.YieldContext); } function setDecoratorContext(val: boolean) { - setContextFlag(val, ts.NodeFlags.DecoratorContext); + setContextFlag(val, NodeFlags.DecoratorContext); } function setAwaitContext(val: boolean) { - setContextFlag(val, ts.NodeFlags.AwaitContext); + setContextFlag(val, NodeFlags.AwaitContext); } - function doOutsideOfContext(context: ts.NodeFlags, func: () => T): T { + function doOutsideOfContext(context: NodeFlags, func: () => T): T { // contextFlagsToClear will contain only the context flags that are // currently set that we need to temporarily clear // We don't just blindly reset to the previous flags to ensure @@ -1597,7 +1663,7 @@ namespace Parser { return func(); } - function doInsideOfContext(context: ts.NodeFlags, func: () => T): T { + function doInsideOfContext(context: NodeFlags, func: () => T): T { // contextFlagsToSet will contain only the context flags that // are not currently set that we need to temporarily enable. // We don't just blindly reset to the previous flags to ensure @@ -1619,79 +1685,79 @@ namespace Parser { } function allowInAnd(func: () => T): T { - return doOutsideOfContext(ts.NodeFlags.DisallowInContext, func); + return doOutsideOfContext(NodeFlags.DisallowInContext, func); } function disallowInAnd(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.DisallowInContext, func); + return doInsideOfContext(NodeFlags.DisallowInContext, func); } function allowConditionalTypesAnd(func: () => T): T { - return doOutsideOfContext(ts.NodeFlags.DisallowConditionalTypesContext, func); + return doOutsideOfContext(NodeFlags.DisallowConditionalTypesContext, func); } function disallowConditionalTypesAnd(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.DisallowConditionalTypesContext, func); + return doInsideOfContext(NodeFlags.DisallowConditionalTypesContext, func); } function doInYieldContext(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.YieldContext, func); + return doInsideOfContext(NodeFlags.YieldContext, func); } function doInDecoratorContext(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.DecoratorContext, func); + return doInsideOfContext(NodeFlags.DecoratorContext, func); } function doInAwaitContext(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.AwaitContext, func); + return doInsideOfContext(NodeFlags.AwaitContext, func); } function doOutsideOfAwaitContext(func: () => T): T { - return doOutsideOfContext(ts.NodeFlags.AwaitContext, func); + return doOutsideOfContext(NodeFlags.AwaitContext, func); } function doInYieldAndAwaitContext(func: () => T): T { - return doInsideOfContext(ts.NodeFlags.YieldContext | ts.NodeFlags.AwaitContext, func); + return doInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func); } function doOutsideOfYieldAndAwaitContext(func: () => T): T { - return doOutsideOfContext(ts.NodeFlags.YieldContext | ts.NodeFlags.AwaitContext, func); + return doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func); } - function inContext(flags: ts.NodeFlags) { + function inContext(flags: NodeFlags) { return (contextFlags & flags) !== 0; } function inYieldContext() { - return inContext(ts.NodeFlags.YieldContext); + return inContext(NodeFlags.YieldContext); } function inDisallowInContext() { - return inContext(ts.NodeFlags.DisallowInContext); + return inContext(NodeFlags.DisallowInContext); } function inDisallowConditionalTypesContext() { - return inContext(ts.NodeFlags.DisallowConditionalTypesContext); + return inContext(NodeFlags.DisallowConditionalTypesContext); } function inDecoratorContext() { - return inContext(ts.NodeFlags.DecoratorContext); + return inContext(NodeFlags.DecoratorContext); } function inAwaitContext() { - return inContext(ts.NodeFlags.AwaitContext); + return inContext(NodeFlags.AwaitContext); } - function parseErrorAtCurrentToken(message: ts.DiagnosticMessage, arg0?: any): ts.DiagnosticWithDetachedLocation | undefined { + function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined { return parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg0); } - function parseErrorAtPosition(start: number, length: number, message: ts.DiagnosticMessage, arg0?: any): ts.DiagnosticWithDetachedLocation | undefined { + function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined { // Don't report another error if it would just be at the same position as the last error. - const lastError = ts.lastOrUndefined(parseDiagnostics); - let result: ts.DiagnosticWithDetachedLocation | undefined; + const lastError = lastOrUndefined(parseDiagnostics); + let result: DiagnosticWithDetachedLocation | undefined; if (!lastError || start !== lastError.start) { - result = ts.createDetachedDiagnostic(fileName, start, length, message, arg0); + result = createDetachedDiagnostic(fileName, start, length, message, arg0); parseDiagnostics.push(result); } @@ -1701,15 +1767,15 @@ namespace Parser { return result; } - function parseErrorAt(start: number, end: number, message: ts.DiagnosticMessage, arg0?: any): ts.DiagnosticWithDetachedLocation | undefined { + function parseErrorAt(start: number, end: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined { return parseErrorAtPosition(start, end - start, message, arg0); } - function parseErrorAtRange(range: ts.TextRange, message: ts.DiagnosticMessage, arg0?: any): void { + function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, arg0?: any): void { parseErrorAt(range.pos, range.end, message, arg0); } - function scanError(message: ts.DiagnosticMessage, length: number): void { + function scanError(message: DiagnosticMessage, length: number): void { parseErrorAtPosition(scanner.getTextPos(), length, message); } @@ -1727,7 +1793,7 @@ namespace Parser { // token (e.g. a call to nextToken() changes the current token but the checker doesn't // reason about this side effect). Mainstream VMs inline simple functions like this, so // there is no performance penalty. - function token(): ts.SyntaxKind { + function token(): SyntaxKind { return currentToken; } @@ -1740,52 +1806,52 @@ namespace Parser { return func(); } - function nextToken(): ts.SyntaxKind { + function nextToken(): SyntaxKind { // if the keyword had an escape - if (ts.isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) { + if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) { // issue a parse error for the escape - parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), ts.Diagnostics.Keywords_cannot_contain_escape_characters); + parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), Diagnostics.Keywords_cannot_contain_escape_characters); } return nextTokenWithoutCheck(); } - function nextTokenJSDoc(): ts.JSDocSyntaxKind { + function nextTokenJSDoc(): JSDocSyntaxKind { return currentToken = scanner.scanJsDocToken(); } - function reScanGreaterToken(): ts.SyntaxKind { + function reScanGreaterToken(): SyntaxKind { return currentToken = scanner.reScanGreaterToken(); } - function reScanSlashToken(): ts.SyntaxKind { + function reScanSlashToken(): SyntaxKind { return currentToken = scanner.reScanSlashToken(); } - function reScanTemplateToken(isTaggedTemplate: boolean): ts.SyntaxKind { + function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind { return currentToken = scanner.reScanTemplateToken(isTaggedTemplate); } - function reScanTemplateHeadOrNoSubstitutionTemplate(): ts.SyntaxKind { + function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind { return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate(); } - function reScanLessThanToken(): ts.SyntaxKind { + function reScanLessThanToken(): SyntaxKind { return currentToken = scanner.reScanLessThanToken(); } - function reScanHashToken(): ts.SyntaxKind { + function reScanHashToken(): SyntaxKind { return currentToken = scanner.reScanHashToken(); } - function scanJsxIdentifier(): ts.SyntaxKind { + function scanJsxIdentifier(): SyntaxKind { return currentToken = scanner.scanJsxIdentifier(); } - function scanJsxText(): ts.SyntaxKind { + function scanJsxText(): SyntaxKind { return currentToken = scanner.scanJsxToken(); } - function scanJsxAttributeValue(): ts.SyntaxKind { + function scanJsxAttributeValue(): SyntaxKind { return currentToken = scanner.scanJsxAttributeValue(); } @@ -1809,7 +1875,7 @@ namespace Parser { ? scanner.lookAhead(callback) : scanner.tryScan(callback); - ts.Debug.assert(saveContextFlags === contextFlags); + Debug.assert(saveContextFlags === contextFlags); // If our callback returned something 'falsy' or we're just looking ahead, // then unconditionally restore us to where we were. @@ -1842,36 +1908,36 @@ namespace Parser { } function isBindingIdentifier(): boolean { - if (token() === ts.SyntaxKind.Identifier) { + if (token() === SyntaxKind.Identifier) { return true; } // `let await`/`let yield` in [Yield] or [Await] are allowed here and disallowed in the binder. - return token() > ts.SyntaxKind.LastReservedWord; + return token() > SyntaxKind.LastReservedWord; } // Ignore strict mode flag because we will report an error in type checker instead. function isIdentifier(): boolean { - if (token() === ts.SyntaxKind.Identifier) { + if (token() === SyntaxKind.Identifier) { return true; } // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is // considered a keyword and is not an identifier. - if (token() === ts.SyntaxKind.YieldKeyword && inYieldContext()) { + if (token() === SyntaxKind.YieldKeyword && inYieldContext()) { return false; } // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is // considered a keyword and is not an identifier. - if (token() === ts.SyntaxKind.AwaitKeyword && inAwaitContext()) { + if (token() === SyntaxKind.AwaitKeyword && inAwaitContext()) { return false; } - return token() > ts.SyntaxKind.LastReservedWord; + return token() > SyntaxKind.LastReservedWord; } - function parseExpected(kind: ts.SyntaxKind, diagnosticMessage?: ts.DiagnosticMessage, shouldAdvance = true): boolean { + function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean { if (token() === kind) { if (shouldAdvance) { nextToken(); @@ -1884,12 +1950,12 @@ namespace Parser { parseErrorAtCurrentToken(diagnosticMessage); } else { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind)); } return false; } - const viableKeywordSuggestions = Object.keys(ts.textToKeywordObj).filter(keyword => keyword.length > 2); + const viableKeywordSuggestions = Object.keys(textToKeywordObj).filter(keyword => keyword.length > 2); /** * Provides a better error message than the generic "';' expected" if possible for @@ -1897,30 +1963,30 @@ namespace Parser { * * @param node Node preceding the expected semicolon location. */ - function parseErrorForMissingSemicolonAfter(node: ts.Expression | ts.PropertyName): void { + function parseErrorForMissingSemicolonAfter(node: Expression | PropertyName): void { // Tagged template literals are sometimes used in places where only simple strings are allowed, i.e.: // module `M1` { // ^^^^^^^^^^^ This block is parsed as a template literal like module`M1`. - if (ts.isTaggedTemplateExpression(node)) { - parseErrorAt(ts.skipTrivia(sourceText, node.template.pos), node.template.end, ts.Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings); + if (isTaggedTemplateExpression(node)) { + parseErrorAt(skipTrivia(sourceText, node.template.pos), node.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings); return; } // Otherwise, if this isn't a well-known keyword-like identifier, give the generic fallback message. - const expressionText = ts.isIdentifier(node) ? ts.idText(node) : undefined; - if (!expressionText || !ts.isIdentifierText(expressionText, languageVersion)) { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.SemicolonToken)); + const expressionText = ts.isIdentifier(node) ? idText(node) : undefined; + if (!expressionText || !isIdentifierText(expressionText, languageVersion)) { + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken)); return; } - const pos = ts.skipTrivia(sourceText, node.pos); + const pos = skipTrivia(sourceText, node.pos); // Some known keywords are likely signs of syntax being used improperly. switch (expressionText) { case "const": case "let": case "var": - parseErrorAt(pos, node.end, ts.Diagnostics.Variable_declaration_not_allowed_at_this_location); + parseErrorAt(pos, node.end, Diagnostics.Variable_declaration_not_allowed_at_this_location); return; case "declare": @@ -1928,37 +1994,37 @@ namespace Parser { return; case "interface": - parseErrorForInvalidName(ts.Diagnostics.Interface_name_cannot_be_0, ts.Diagnostics.Interface_must_be_given_a_name, ts.SyntaxKind.OpenBraceToken); + parseErrorForInvalidName(Diagnostics.Interface_name_cannot_be_0, Diagnostics.Interface_must_be_given_a_name, SyntaxKind.OpenBraceToken); return; case "is": - parseErrorAt(pos, scanner.getTextPos(), ts.Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); + parseErrorAt(pos, scanner.getTextPos(), Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods); return; case "module": case "namespace": - parseErrorForInvalidName(ts.Diagnostics.Namespace_name_cannot_be_0, ts.Diagnostics.Namespace_must_be_given_a_name, ts.SyntaxKind.OpenBraceToken); + parseErrorForInvalidName(Diagnostics.Namespace_name_cannot_be_0, Diagnostics.Namespace_must_be_given_a_name, SyntaxKind.OpenBraceToken); return; case "type": - parseErrorForInvalidName(ts.Diagnostics.Type_alias_name_cannot_be_0, ts.Diagnostics.Type_alias_must_be_given_a_name, ts.SyntaxKind.EqualsToken); + parseErrorForInvalidName(Diagnostics.Type_alias_name_cannot_be_0, Diagnostics.Type_alias_must_be_given_a_name, SyntaxKind.EqualsToken); return; } // The user alternatively might have misspelled or forgotten to add a space after a common keyword. - const suggestion = ts.getSpellingSuggestion(expressionText, viableKeywordSuggestions, n => n) ?? getSpaceSuggestion(expressionText); + const suggestion = getSpellingSuggestion(expressionText, viableKeywordSuggestions, n => n) ?? getSpaceSuggestion(expressionText); if (suggestion) { - parseErrorAt(pos, node.end, ts.Diagnostics.Unknown_keyword_or_identifier_Did_you_mean_0, suggestion); + parseErrorAt(pos, node.end, Diagnostics.Unknown_keyword_or_identifier_Did_you_mean_0, suggestion); return; } // Unknown tokens are handled with their own errors in the scanner - if (token() === ts.SyntaxKind.Unknown) { + if (token() === SyntaxKind.Unknown) { return; } // Otherwise, we know this some kind of unknown word, not just a missing expected semicolon. - parseErrorAt(pos, node.end, ts.Diagnostics.Unexpected_keyword_or_identifier); + parseErrorAt(pos, node.end, Diagnostics.Unexpected_keyword_or_identifier); } /** @@ -1968,7 +2034,7 @@ namespace Parser { * @param nameDiagnostic Diagnostic to report for all other cases. * @param tokenIfBlankName Current token if the name was invalid for being blank (not provided / skipped). */ - function parseErrorForInvalidName(nameDiagnostic: ts.DiagnosticMessage, blankDiagnostic: ts.DiagnosticMessage, tokenIfBlankName: ts.SyntaxKind) { + function parseErrorForInvalidName(nameDiagnostic: DiagnosticMessage, blankDiagnostic: DiagnosticMessage, tokenIfBlankName: SyntaxKind) { if (token() === tokenIfBlankName) { parseErrorAtCurrentToken(blankDiagnostic); } @@ -1979,7 +2045,7 @@ namespace Parser { function getSpaceSuggestion(expressionText: string) { for (const keyword of viableKeywordSuggestions) { - if (expressionText.length > keyword.length + 2 && ts.startsWith(expressionText, keyword)) { + if (expressionText.length > keyword.length + 2 && startsWith(expressionText, keyword)) { return `${keyword} ${expressionText.slice(keyword.length)}`; } } @@ -1987,24 +2053,24 @@ namespace Parser { return undefined; } - function parseSemicolonAfterPropertyName(name: ts.PropertyName, type: ts.TypeNode | undefined, initializer: ts.Expression | undefined) { - if (token() === ts.SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) { - parseErrorAtCurrentToken(ts.Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations); + function parseSemicolonAfterPropertyName(name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) { + if (token() === SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) { + parseErrorAtCurrentToken(Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations); return; } - if (token() === ts.SyntaxKind.OpenParenToken) { - parseErrorAtCurrentToken(ts.Diagnostics.Cannot_start_a_function_call_in_a_type_annotation); + if (token() === SyntaxKind.OpenParenToken) { + parseErrorAtCurrentToken(Diagnostics.Cannot_start_a_function_call_in_a_type_annotation); nextToken(); return; } if (type && !canParseSemicolon()) { if (initializer) { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.SemicolonToken)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken)); } else { - parseErrorAtCurrentToken(ts.Diagnostics.Expected_for_property_initializer); + parseErrorAtCurrentToken(Diagnostics.Expected_for_property_initializer); } return; } @@ -2014,40 +2080,40 @@ namespace Parser { } if (initializer) { - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.SemicolonToken)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken)); return; } parseErrorForMissingSemicolonAfter(name); } - function parseExpectedJSDoc(kind: ts.JSDocSyntaxKind) { + function parseExpectedJSDoc(kind: JSDocSyntaxKind) { if (token() === kind) { nextTokenJSDoc(); return true; } - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(kind)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind)); return false; } - function parseExpectedMatchingBrackets(openKind: ts.SyntaxKind, closeKind: ts.SyntaxKind, openParsed: boolean, openPosition: number) { + function parseExpectedMatchingBrackets(openKind: SyntaxKind, closeKind: SyntaxKind, openParsed: boolean, openPosition: number) { if (token() === closeKind) { nextToken(); return; } - const lastError = parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(closeKind)); + const lastError = parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(closeKind)); if (!openParsed) { return; } if (lastError) { - ts.addRelatedInfo( + addRelatedInfo( lastError, - ts.createDetachedDiagnostic(fileName, openPosition, 1, ts.Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, ts.tokenToString(openKind), ts.tokenToString(closeKind)) + createDetachedDiagnostic(fileName, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind)) ); } } - function parseOptional(t: ts.SyntaxKind): boolean { + function parseOptional(t: SyntaxKind): boolean { if (token() === t) { nextToken(); return true; @@ -2055,42 +2121,42 @@ namespace Parser { return false; } - function parseOptionalToken(t: TKind): ts.Token; - function parseOptionalToken(t: ts.SyntaxKind): ts.Node | undefined { + function parseOptionalToken(t: TKind): Token; + function parseOptionalToken(t: SyntaxKind): Node | undefined { if (token() === t) { return parseTokenNode(); } return undefined; } - function parseOptionalTokenJSDoc(t: TKind): ts.Token; - function parseOptionalTokenJSDoc(t: ts.JSDocSyntaxKind): ts.Node | undefined { + function parseOptionalTokenJSDoc(t: TKind): Token; + function parseOptionalTokenJSDoc(t: JSDocSyntaxKind): Node | undefined { if (token() === t) { return parseTokenNodeJSDoc(); } return undefined; } - function parseExpectedToken(t: TKind, diagnosticMessage?: ts.DiagnosticMessage, arg0?: any): ts.Token; - function parseExpectedToken(t: ts.SyntaxKind, diagnosticMessage?: ts.DiagnosticMessage, arg0?: any): ts.Node { + function parseExpectedToken(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Token; + function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Node { return parseOptionalToken(t) || - createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || ts.Diagnostics._0_expected, arg0 || ts.tokenToString(t)); + createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t)); } - function parseExpectedTokenJSDoc(t: TKind): ts.Token; - function parseExpectedTokenJSDoc(t: ts.JSDocSyntaxKind): ts.Node { + function parseExpectedTokenJSDoc(t: TKind): Token; + function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): Node { return parseOptionalTokenJSDoc(t) || - createMissingNode(t, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(t)); + createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t)); } - function parseTokenNode(): T { + function parseTokenNode(): T { const pos = getNodePos(); const kind = token(); nextToken(); return finishNode(factory.createToken(kind), pos) as T; } - function parseTokenNodeJSDoc(): T { + function parseTokenNodeJSDoc(): T { const pos = getNodePos(); const kind = token(); nextTokenJSDoc(); @@ -2099,12 +2165,12 @@ namespace Parser { function canParseSemicolon() { // If there's a real semicolon, then we can always parse it out. - if (token() === ts.SyntaxKind.SemicolonToken) { + if (token() === SyntaxKind.SemicolonToken) { return true; } // We can parse out an optional semicolon in ASI cases in the following cases. - return token() === ts.SyntaxKind.CloseBraceToken || token() === ts.SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak(); + return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak(); } function tryParseSemicolon() { @@ -2112,7 +2178,7 @@ namespace Parser { return false; } - if (token() === ts.SyntaxKind.SemicolonToken) { + if (token() === SyntaxKind.SemicolonToken) { // consume the semicolon if it was explicitly provided. nextToken(); } @@ -2121,19 +2187,19 @@ namespace Parser { } function parseSemicolon(): boolean { - return tryParseSemicolon() || parseExpected(ts.SyntaxKind.SemicolonToken); + return tryParseSemicolon() || parseExpected(SyntaxKind.SemicolonToken); } - function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): ts.NodeArray { + function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray { const array = factory.createNodeArray(elements, hasTrailingComma); - ts.setTextRangePosEnd(array, pos, end ?? scanner.getStartPos()); + setTextRangePosEnd(array, pos, end ?? scanner.getStartPos()); return array; } - function finishNode(node: T, pos: number, end?: number): T { - ts.setTextRangePosEnd(node, pos, end ?? scanner.getStartPos()); + function finishNode(node: T, pos: number, end?: number): T { + setTextRangePosEnd(node, pos, end ?? scanner.getStartPos()); if (contextFlags) { - (node as ts.Mutable).flags |= contextFlags; + (node as Mutable).flags |= contextFlags; } // Keep track on the node if we encountered an error while parsing it. If we did, then @@ -2141,15 +2207,15 @@ namespace Parser { // flag so that we don't mark any subsequent nodes. if (parseErrorBeforeNextFinishedNode) { parseErrorBeforeNextFinishedNode = false; - (node as ts.Mutable).flags |= ts.NodeFlags.ThisNodeHasError; + (node as Mutable).flags |= NodeFlags.ThisNodeHasError; } return node; } - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: ts.DiagnosticMessage, arg0?: any): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: ts.DiagnosticMessage, arg0?: any): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: ts.DiagnosticMessage, arg0?: any): T { + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, arg0?: any): T; + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T; + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T { if (reportAtCurrentPosition) { parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0); } @@ -2159,11 +2225,11 @@ namespace Parser { const pos = getNodePos(); const result = - kind === ts.SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) : - ts.isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) : - kind === ts.SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) : - kind === ts.SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) : - kind === ts.SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : + kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) : + isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) : + kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) : + kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) : + kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : factory.createToken(kind); return finishNode(result, pos) as T; } @@ -2179,7 +2245,7 @@ namespace Parser { // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for // each identifier in order to reduce memory consumption. - function createIdentifier(isIdentifier: boolean, diagnosticMessage?: ts.DiagnosticMessage, privateIdentifierDiagnosticMessage?: ts.DiagnosticMessage): ts.Identifier { + function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { if (isIdentifier) { identifierCount++; const pos = getNodePos(); @@ -2191,83 +2257,83 @@ namespace Parser { return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind, hasExtendedUnicodeEscape), pos); } - if (token() === ts.SyntaxKind.PrivateIdentifier) { - parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); + if (token() === SyntaxKind.PrivateIdentifier) { + parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies); return createIdentifier(/*isIdentifier*/ true); } - if (token() === ts.SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === ts.SyntaxKind.Identifier)) { + if (token() === SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier)) { // Scanner has already recorded an 'Invalid character' error, so no need to add another from the parser. return createIdentifier(/*isIdentifier*/ true); } identifierCount++; // Only for end of file because the error gets reported incorrectly on embedded script tags. - const reportAtCurrentPosition = token() === ts.SyntaxKind.EndOfFileToken; + const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken; const isReservedWord = scanner.isReservedWord(); const msgArg = scanner.getTokenText(); const defaultMessage = isReservedWord ? - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : - ts.Diagnostics.Identifier_expected; + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : + Diagnostics.Identifier_expected; - return createMissingNode(ts.SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg); + return createMissingNode(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg); } - function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: ts.DiagnosticMessage) { + function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) { return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage); } - function parseIdentifier(diagnosticMessage?: ts.DiagnosticMessage, privateIdentifierDiagnosticMessage?: ts.DiagnosticMessage): ts.Identifier { + function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage); } - function parseIdentifierName(diagnosticMessage?: ts.DiagnosticMessage): ts.Identifier { - return createIdentifier(ts.tokenIsIdentifierOrKeyword(token()), diagnosticMessage); + function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier { + return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage); } function isLiteralPropertyName(): boolean { - return ts.tokenIsIdentifierOrKeyword(token()) || - token() === ts.SyntaxKind.StringLiteral || - token() === ts.SyntaxKind.NumericLiteral; + return tokenIsIdentifierOrKeyword(token()) || + token() === SyntaxKind.StringLiteral || + token() === SyntaxKind.NumericLiteral; } function isAssertionKey(): boolean { - return ts.tokenIsIdentifierOrKeyword(token()) || - token() === ts.SyntaxKind.StringLiteral; + return tokenIsIdentifierOrKeyword(token()) || + token() === SyntaxKind.StringLiteral; } - function parsePropertyNameWorker(allowComputedPropertyNames: boolean): ts.PropertyName { - if (token() === ts.SyntaxKind.StringLiteral || token() === ts.SyntaxKind.NumericLiteral) { - const node = parseLiteralNode() as ts.StringLiteral | ts.NumericLiteral; + function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { + if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) { + const node = parseLiteralNode() as StringLiteral | NumericLiteral; node.text = internIdentifier(node.text); return node; } - if (allowComputedPropertyNames && token() === ts.SyntaxKind.OpenBracketToken) { + if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { return parseComputedPropertyName(); } - if (token() === ts.SyntaxKind.PrivateIdentifier) { + if (token() === SyntaxKind.PrivateIdentifier) { return parsePrivateIdentifier(); } return parseIdentifierName(); } - function parsePropertyName(): ts.PropertyName { + function parsePropertyName(): PropertyName { return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } - function parseComputedPropertyName(): ts.ComputedPropertyName { + function parseComputedPropertyName(): ComputedPropertyName { // PropertyName [Yield]: // LiteralPropertyName // ComputedPropertyName[?Yield] const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBracketToken); + parseExpected(SyntaxKind.OpenBracketToken); // We parse any expression (including a comma expression). But the grammar // says that only an assignment expression is allowed, so the grammar checker // will error if it sees a comma expression. const expression = allowInAnd(parseExpression); - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); return finishNode(factory.createComputedPropertyName(expression), pos); } @@ -2279,14 +2345,14 @@ namespace Parser { return privateIdentifier; } - function parsePrivateIdentifier(): ts.PrivateIdentifier { + function parsePrivateIdentifier(): PrivateIdentifier { const pos = getNodePos(); const node = factory.createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenValue())); nextToken(); return finishNode(node, pos); } - function parseContextualModifier(t: ts.SyntaxKind): boolean { + function parseContextualModifier(t: SyntaxKind): boolean { return token() === t && tryParse(nextTokenCanFollowModifier); } @@ -2300,24 +2366,24 @@ namespace Parser { function nextTokenCanFollowModifier() { switch (token()) { - case ts.SyntaxKind.ConstKeyword: + case SyntaxKind.ConstKeyword: // 'const' is only a modifier if followed by 'enum'. - return nextToken() === ts.SyntaxKind.EnumKeyword; - case ts.SyntaxKind.ExportKeyword: + return nextToken() === SyntaxKind.EnumKeyword; + case SyntaxKind.ExportKeyword: nextToken(); - if (token() === ts.SyntaxKind.DefaultKeyword) { + if (token() === SyntaxKind.DefaultKeyword) { return lookAhead(nextTokenCanFollowDefaultKeyword); } - if (token() === ts.SyntaxKind.TypeKeyword) { + if (token() === SyntaxKind.TypeKeyword) { return lookAhead(nextTokenCanFollowExportModifier); } return canFollowExportModifier(); - case ts.SyntaxKind.DefaultKeyword: + case SyntaxKind.DefaultKeyword: return nextTokenCanFollowDefaultKeyword(); - case ts.SyntaxKind.AccessorKeyword: - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.GetKeyword: - case ts.SyntaxKind.SetKeyword: + case SyntaxKind.AccessorKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: nextToken(); return canFollowModifier(); default: @@ -2326,9 +2392,9 @@ namespace Parser { } function canFollowExportModifier(): boolean { - return token() !== ts.SyntaxKind.AsteriskToken - && token() !== ts.SyntaxKind.AsKeyword - && token() !== ts.SyntaxKind.OpenBraceToken + return token() !== SyntaxKind.AsteriskToken + && token() !== SyntaxKind.AsKeyword + && token() !== SyntaxKind.OpenBraceToken && canFollowModifier(); } @@ -2338,23 +2404,23 @@ namespace Parser { } function parseAnyContextualModifier(): boolean { - return ts.isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); + return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier); } function canFollowModifier(): boolean { - return token() === ts.SyntaxKind.OpenBracketToken - || token() === ts.SyntaxKind.OpenBraceToken - || token() === ts.SyntaxKind.AsteriskToken - || token() === ts.SyntaxKind.DotDotDotToken + return token() === SyntaxKind.OpenBracketToken + || token() === SyntaxKind.OpenBraceToken + || token() === SyntaxKind.AsteriskToken + || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName(); } function nextTokenCanFollowDefaultKeyword(): boolean { nextToken(); - return token() === ts.SyntaxKind.ClassKeyword || token() === ts.SyntaxKind.FunctionKeyword || - token() === ts.SyntaxKind.InterfaceKeyword || - (token() === ts.SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || - (token() === ts.SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); + return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword || + token() === SyntaxKind.InterfaceKeyword || + (token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) || + (token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine)); } // True if positioned at the start of a list element @@ -2374,9 +2440,9 @@ namespace Parser { // we're parsing. For example, if we have a semicolon in the middle of a class, then // we really don't want to assume the class is over and we're on a statement in the // outer module. We just want to consume and move on. - return !(token() === ts.SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement(); + return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement(); case ParsingContext.SwitchClauses: - return token() === ts.SyntaxKind.CaseKeyword || token() === ts.SyntaxKind.DefaultKeyword; + return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword; case ParsingContext.TypeMembers: return lookAhead(isTypeMemberStart); case ParsingContext.ClassMembers: @@ -2384,17 +2450,17 @@ namespace Parser { // not in error recovery. If we're in error recovery, we don't want an errant // semicolon to be treated as a class member (since they're almost always used // for statements. - return lookAhead(isClassMemberStart) || (token() === ts.SyntaxKind.SemicolonToken && !inErrorRecovery); + return lookAhead(isClassMemberStart) || (token() === SyntaxKind.SemicolonToken && !inErrorRecovery); case ParsingContext.EnumMembers: // Include open bracket computed properties. This technically also lets in indexers, // which would be a candidate for improved error reporting. - return token() === ts.SyntaxKind.OpenBracketToken || isLiteralPropertyName(); + return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName(); case ParsingContext.ObjectLiteralMembers: switch (token()) { - case ts.SyntaxKind.OpenBracketToken: - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.DotDotDotToken: - case ts.SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`) + case SyntaxKind.OpenBracketToken: + case SyntaxKind.AsteriskToken: + case SyntaxKind.DotDotDotToken: + case SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`) return true; default: return isLiteralPropertyName(); @@ -2402,13 +2468,13 @@ namespace Parser { case ParsingContext.RestProperties: return isLiteralPropertyName(); case ParsingContext.ObjectBindingElements: - return token() === ts.SyntaxKind.OpenBracketToken || token() === ts.SyntaxKind.DotDotDotToken || isLiteralPropertyName(); + return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName(); case ParsingContext.AssertEntries: return isAssertionKey(); case ParsingContext.HeritageClauseElement: // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{` // That way we won't consume the body of a class in its heritage clause. - if (token() === ts.SyntaxKind.OpenBraceToken) { + if (token() === SyntaxKind.OpenBraceToken) { return lookAhead(isValidHeritageClauseObjectLiteral); } @@ -2424,41 +2490,41 @@ namespace Parser { case ParsingContext.VariableDeclarations: return isBindingIdentifierOrPrivateIdentifierOrPattern(); case ParsingContext.ArrayBindingElements: - return token() === ts.SyntaxKind.CommaToken || token() === ts.SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern(); + return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern(); case ParsingContext.TypeParameters: - return token() === ts.SyntaxKind.InKeyword || isIdentifier(); + return token() === SyntaxKind.InKeyword || isIdentifier(); case ParsingContext.ArrayLiteralMembers: switch (token()) { - case ts.SyntaxKind.CommaToken: - case ts.SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`) + case SyntaxKind.CommaToken: + case SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`) return true; } // falls through case ParsingContext.ArgumentExpressions: - return token() === ts.SyntaxKind.DotDotDotToken || isStartOfExpression(); + return token() === SyntaxKind.DotDotDotToken || isStartOfExpression(); case ParsingContext.Parameters: return isStartOfParameter(/*isJSDocParameter*/ false); case ParsingContext.JSDocParameters: return isStartOfParameter(/*isJSDocParameter*/ true); case ParsingContext.TypeArguments: case ParsingContext.TupleElementTypes: - return token() === ts.SyntaxKind.CommaToken || isStartOfType(); + return token() === SyntaxKind.CommaToken || isStartOfType(); case ParsingContext.HeritageClauses: return isHeritageClause(); case ParsingContext.ImportOrExportSpecifiers: - return ts.tokenIsIdentifierOrKeyword(token()); + return tokenIsIdentifierOrKeyword(token()); case ParsingContext.JsxAttributes: - return ts.tokenIsIdentifierOrKeyword(token()) || token() === ts.SyntaxKind.OpenBraceToken; + return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken; case ParsingContext.JsxChildren: return true; } - return ts.Debug.fail("Non-exhaustive case in 'isListElement'."); + return Debug.fail("Non-exhaustive case in 'isListElement'."); } function isValidHeritageClauseObjectLiteral() { - ts.Debug.assert(token() === ts.SyntaxKind.OpenBraceToken); - if (nextToken() === ts.SyntaxKind.CloseBraceToken) { + Debug.assert(token() === SyntaxKind.OpenBraceToken); + if (nextToken() === SyntaxKind.CloseBraceToken) { // if we see "extends {}" then only treat the {} as what we're extending (and not // the class body) if we have: // @@ -2468,7 +2534,7 @@ namespace Parser { // extends {} implements const next = nextToken(); - return next === ts.SyntaxKind.CommaToken || next === ts.SyntaxKind.OpenBraceToken || next === ts.SyntaxKind.ExtendsKeyword || next === ts.SyntaxKind.ImplementsKeyword; + return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword; } return true; @@ -2481,17 +2547,17 @@ namespace Parser { function nextTokenIsIdentifierOrKeyword() { nextToken(); - return ts.tokenIsIdentifierOrKeyword(token()); + return tokenIsIdentifierOrKeyword(token()); } function nextTokenIsIdentifierOrKeywordOrGreaterThan() { nextToken(); - return ts.tokenIsIdentifierOrKeywordOrGreaterThan(token()); + return tokenIsIdentifierOrKeywordOrGreaterThan(token()); } function isHeritageClauseExtendsOrImplementsKeyword(): boolean { - if (token() === ts.SyntaxKind.ImplementsKeyword || - token() === ts.SyntaxKind.ExtendsKeyword) { + if (token() === SyntaxKind.ImplementsKeyword || + token() === SyntaxKind.ExtendsKeyword) { return lookAhead(nextTokenIsStartOfExpression); } @@ -2511,7 +2577,7 @@ namespace Parser { // True if positioned at a list terminator function isListTerminator(kind: ParsingContext): boolean { - if (token() === ts.SyntaxKind.EndOfFileToken) { + if (token() === SyntaxKind.EndOfFileToken) { // Being at the end of the file ends all lists. return true; } @@ -2526,37 +2592,37 @@ namespace Parser { case ParsingContext.ObjectBindingElements: case ParsingContext.ImportOrExportSpecifiers: case ParsingContext.AssertEntries: - return token() === ts.SyntaxKind.CloseBraceToken; + return token() === SyntaxKind.CloseBraceToken; case ParsingContext.SwitchClauseStatements: - return token() === ts.SyntaxKind.CloseBraceToken || token() === ts.SyntaxKind.CaseKeyword || token() === ts.SyntaxKind.DefaultKeyword; + return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword; case ParsingContext.HeritageClauseElement: - return token() === ts.SyntaxKind.OpenBraceToken || token() === ts.SyntaxKind.ExtendsKeyword || token() === ts.SyntaxKind.ImplementsKeyword; + return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; case ParsingContext.VariableDeclarations: return isVariableDeclaratorListTerminator(); case ParsingContext.TypeParameters: // Tokens other than '>' are here for better error recovery - return token() === ts.SyntaxKind.GreaterThanToken || token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.OpenBraceToken || token() === ts.SyntaxKind.ExtendsKeyword || token() === ts.SyntaxKind.ImplementsKeyword; + return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; case ParsingContext.ArgumentExpressions: // Tokens other than ')' are here for better error recovery - return token() === ts.SyntaxKind.CloseParenToken || token() === ts.SyntaxKind.SemicolonToken; + return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken; case ParsingContext.ArrayLiteralMembers: case ParsingContext.TupleElementTypes: case ParsingContext.ArrayBindingElements: - return token() === ts.SyntaxKind.CloseBracketToken; + return token() === SyntaxKind.CloseBracketToken; case ParsingContext.JSDocParameters: case ParsingContext.Parameters: case ParsingContext.RestProperties: // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery - return token() === ts.SyntaxKind.CloseParenToken || token() === ts.SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/; + return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/; case ParsingContext.TypeArguments: // All other tokens should cause the type-argument to terminate except comma token - return token() !== ts.SyntaxKind.CommaToken; + return token() !== SyntaxKind.CommaToken; case ParsingContext.HeritageClauses: - return token() === ts.SyntaxKind.OpenBraceToken || token() === ts.SyntaxKind.CloseBraceToken; + return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken; case ParsingContext.JsxAttributes: - return token() === ts.SyntaxKind.GreaterThanToken || token() === ts.SyntaxKind.SlashToken; + return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken; case ParsingContext.JsxChildren: - return token() === ts.SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash); + return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash); default: return false; } @@ -2579,7 +2645,7 @@ namespace Parser { // For better error recovery, if we see an '=>' then we just stop immediately. We've got an // arrow function here and it's going to be very unlikely that we'll resynchronize and get // another variable declaration. - if (token() === ts.SyntaxKind.EqualsGreaterThanToken) { + if (token() === SyntaxKind.EqualsGreaterThanToken) { return true; } @@ -2601,7 +2667,7 @@ namespace Parser { } // Parses a list of elements - function parseList(kind: ParsingContext, parseElement: () => T): ts.NodeArray { + function parseList(kind: ParsingContext, parseElement: () => T): NodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const list = []; @@ -2623,7 +2689,7 @@ namespace Parser { return createNodeArray(list, listPos); } - function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { + function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { const node = currentNode(parsingContext); if (node) { return consumeNode(node) as T; @@ -2632,7 +2698,7 @@ namespace Parser { return parseElement(); } - function currentNode(parsingContext: ParsingContext, pos?: number): ts.Node | undefined { + function currentNode(parsingContext: ParsingContext, pos?: number): Node | undefined { // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse. // // If there is an outstanding parse error that we've encountered, but not attached to @@ -2652,7 +2718,7 @@ namespace Parser { // Can't reuse a node that intersected the change range. // Can't reuse a node that contains a parse error. This is necessary so that we // produce the same set of errors again. - if (ts.nodeIsMissing(node) || node.intersectsChange || ts.containsParseError(node)) { + if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) { return undefined; } @@ -2667,7 +2733,7 @@ namespace Parser { // differently depending on what mode it is in. // // This also applies to all our other context flags as well. - const nodeContextFlags = node.flags & ts.NodeFlags.ContextFlags; + const nodeContextFlags = node.flags & NodeFlags.ContextFlags; if (nodeContextFlags !== contextFlags) { return undefined; } @@ -2678,15 +2744,15 @@ namespace Parser { return undefined; } - if ((node as ts.JSDocContainer).jsDocCache) { + if ((node as JSDocContainer).jsDocCache) { // jsDocCache may include tags from parent nodes, which might have been modified. - (node as ts.JSDocContainer).jsDocCache = undefined; + (node as JSDocContainer).jsDocCache = undefined; } return node; } - function consumeNode(node: ts.Node) { + function consumeNode(node: Node) { // Move the scanner so it is after the node we just consumed. scanner.setTextPos(node.end); nextToken(); @@ -2710,7 +2776,7 @@ namespace Parser { return false; } - function canReuseNode(node: ts.Node, parsingContext: ParsingContext): boolean { + function canReuseNode(node: Node, parsingContext: ParsingContext): boolean { switch (parsingContext) { case ParsingContext.ClassMembers: return isReusableClassMember(node); @@ -2789,23 +2855,23 @@ namespace Parser { return false; } - function isReusableClassMember(node: ts.Node) { + function isReusableClassMember(node: Node) { if (node) { switch (node.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.SemicolonClassElement: + case SyntaxKind.Constructor: + case SyntaxKind.IndexSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.SemicolonClassElement: return true; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: // Method declarations are not necessarily reusable. An object-literal // may have a method calls "constructor(...)" and we must reparse that // into an actual .ConstructorDeclaration. - const methodDeclaration = node as ts.MethodDeclaration; - const nameIsConstructor = methodDeclaration.name.kind === ts.SyntaxKind.Identifier && - methodDeclaration.name.originalKeywordKind === ts.SyntaxKind.ConstructorKeyword; + const methodDeclaration = node as MethodDeclaration; + const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && + methodDeclaration.name.originalKeywordKind === SyntaxKind.ConstructorKeyword; return !nameIsConstructor; } @@ -2814,11 +2880,11 @@ namespace Parser { return false; } - function isReusableSwitchClause(node: ts.Node) { + function isReusableSwitchClause(node: Node) { if (node) { switch (node.kind) { - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: return true; } } @@ -2826,38 +2892,38 @@ namespace Parser { return false; } - function isReusableStatement(node: ts.Node) { + function isReusableStatement(node: Node) { if (node) { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.ExpressionStatement: - case ts.SyntaxKind.ThrowStatement: - case ts.SyntaxKind.ReturnStatement: - case ts.SyntaxKind.SwitchStatement: - case ts.SyntaxKind.BreakStatement: - case ts.SyntaxKind.ContinueStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.WithStatement: - case ts.SyntaxKind.EmptyStatement: - case ts.SyntaxKind.TryStatement: - case ts.SyntaxKind.LabeledStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.DebuggerStatement: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.Block: + case SyntaxKind.IfStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.EmptyStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: return true; } } @@ -2865,18 +2931,18 @@ namespace Parser { return false; } - function isReusableEnumMember(node: ts.Node) { - return node.kind === ts.SyntaxKind.EnumMember; + function isReusableEnumMember(node: Node) { + return node.kind === SyntaxKind.EnumMember; } - function isReusableTypeMember(node: ts.Node) { + function isReusableTypeMember(node: Node) { if (node) { switch (node.kind) { - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.PropertySignature: + case SyntaxKind.CallSignature: return true; } } @@ -2884,8 +2950,8 @@ namespace Parser { return false; } - function isReusableVariableDeclaration(node: ts.Node) { - if (node.kind !== ts.SyntaxKind.VariableDeclaration) { + function isReusableVariableDeclaration(node: Node) { + if (node.kind !== SyntaxKind.VariableDeclaration) { return false; } @@ -2903,17 +2969,17 @@ namespace Parser { // // In order to prevent this, we do not allow a variable declarator to be reused if it // has an initializer. - const variableDeclarator = node as ts.VariableDeclaration; + const variableDeclarator = node as VariableDeclaration; return variableDeclarator.initializer === undefined; } - function isReusableParameter(node: ts.Node) { - if (node.kind !== ts.SyntaxKind.Parameter) { + function isReusableParameter(node: Node) { + if (node.kind !== SyntaxKind.Parameter) { return false; } // See the comment in isReusableVariableDeclaration for why we do this. - const parameter = node as ts.ParameterDeclaration; + const parameter = node as ParameterDeclaration; return parameter.initializer === undefined; } @@ -2931,48 +2997,48 @@ namespace Parser { function parsingContextErrors(context: ParsingContext) { switch (context) { case ParsingContext.SourceElements: - return token() === ts.SyntaxKind.DefaultKeyword - ? parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.ExportKeyword)) - : parseErrorAtCurrentToken(ts.Diagnostics.Declaration_or_statement_expected); - case ParsingContext.BlockStatements: return parseErrorAtCurrentToken(ts.Diagnostics.Declaration_or_statement_expected); - case ParsingContext.SwitchClauses: return parseErrorAtCurrentToken(ts.Diagnostics.case_or_default_expected); - case ParsingContext.SwitchClauseStatements: return parseErrorAtCurrentToken(ts.Diagnostics.Statement_expected); + return token() === SyntaxKind.DefaultKeyword + ? parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ExportKeyword)) + : parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected); + case ParsingContext.BlockStatements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected); + case ParsingContext.SwitchClauses: return parseErrorAtCurrentToken(Diagnostics.case_or_default_expected); + case ParsingContext.SwitchClauseStatements: return parseErrorAtCurrentToken(Diagnostics.Statement_expected); case ParsingContext.RestProperties: // fallthrough - case ParsingContext.TypeMembers: return parseErrorAtCurrentToken(ts.Diagnostics.Property_or_signature_expected); - case ParsingContext.ClassMembers: return parseErrorAtCurrentToken(ts.Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected); - case ParsingContext.EnumMembers: return parseErrorAtCurrentToken(ts.Diagnostics.Enum_member_expected); - case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(ts.Diagnostics.Expression_expected); + case ParsingContext.TypeMembers: return parseErrorAtCurrentToken(Diagnostics.Property_or_signature_expected); + case ParsingContext.ClassMembers: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected); + case ParsingContext.EnumMembers: return parseErrorAtCurrentToken(Diagnostics.Enum_member_expected); + case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics.Expression_expected); case ParsingContext.VariableDeclarations: - return ts.isKeyword(token()) - ? parseErrorAtCurrentToken(ts.Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, ts.tokenToString(token())) - : parseErrorAtCurrentToken(ts.Diagnostics.Variable_declaration_expected); - case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(ts.Diagnostics.Property_destructuring_pattern_expected); - case ParsingContext.ArrayBindingElements: return parseErrorAtCurrentToken(ts.Diagnostics.Array_element_destructuring_pattern_expected); - case ParsingContext.ArgumentExpressions: return parseErrorAtCurrentToken(ts.Diagnostics.Argument_expression_expected); - case ParsingContext.ObjectLiteralMembers: return parseErrorAtCurrentToken(ts.Diagnostics.Property_assignment_expected); - case ParsingContext.ArrayLiteralMembers: return parseErrorAtCurrentToken(ts.Diagnostics.Expression_or_comma_expected); - case ParsingContext.JSDocParameters: return parseErrorAtCurrentToken(ts.Diagnostics.Parameter_declaration_expected); + return isKeyword(token()) + ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token())) + : parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected); + case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected); + case ParsingContext.ArrayBindingElements: return parseErrorAtCurrentToken(Diagnostics.Array_element_destructuring_pattern_expected); + case ParsingContext.ArgumentExpressions: return parseErrorAtCurrentToken(Diagnostics.Argument_expression_expected); + case ParsingContext.ObjectLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Property_assignment_expected); + case ParsingContext.ArrayLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Expression_or_comma_expected); + case ParsingContext.JSDocParameters: return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected); case ParsingContext.Parameters: - return ts.isKeyword(token()) - ? parseErrorAtCurrentToken(ts.Diagnostics._0_is_not_allowed_as_a_parameter_name, ts.tokenToString(token())) - : parseErrorAtCurrentToken(ts.Diagnostics.Parameter_declaration_expected); - case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(ts.Diagnostics.Type_parameter_declaration_expected); - case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(ts.Diagnostics.Type_argument_expected); - case ParsingContext.TupleElementTypes: return parseErrorAtCurrentToken(ts.Diagnostics.Type_expected); - case ParsingContext.HeritageClauses: return parseErrorAtCurrentToken(ts.Diagnostics.Unexpected_token_expected); - case ParsingContext.ImportOrExportSpecifiers: return parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); - case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); - case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(ts.Diagnostics.Identifier_expected); - case ParsingContext.AssertEntries: return parseErrorAtCurrentToken(ts.Diagnostics.Identifier_or_string_literal_expected); // AssertionKey. - case ParsingContext.Count: return ts.Debug.fail("ParsingContext.Count used as a context"); // Not a real context, only a marker. - default: ts.Debug.assertNever(context); + return isKeyword(token()) + ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token())) + : parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected); + case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected); + case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected); + case ParsingContext.TupleElementTypes: return parseErrorAtCurrentToken(Diagnostics.Type_expected); + case ParsingContext.HeritageClauses: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_expected); + case ParsingContext.ImportOrExportSpecifiers: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected); + case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected); + case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected); + case ParsingContext.AssertEntries: return parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected); // AssertionKey. + case ParsingContext.Count: return Debug.fail("ParsingContext.Count used as a context"); // Not a real context, only a marker. + default: Debug.assertNever(context); } } // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): ts.NodeArray; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): ts.NodeArray> | undefined; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): ts.NodeArray> | undefined { + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const list: NonNullable[] = []; @@ -2990,7 +3056,7 @@ namespace Parser { list.push(result); commaStart = scanner.getTokenPos(); - if (parseOptional(ts.SyntaxKind.CommaToken)) { + if (parseOptional(SyntaxKind.CommaToken)) { // No need to check for a zero length node since we know we parsed a comma continue; } @@ -3002,14 +3068,14 @@ namespace Parser { // We didn't get a comma, and the list wasn't terminated, explicitly parse // out a comma so we give a good error message. - parseExpected(ts.SyntaxKind.CommaToken, getExpectedCommaDiagnostic(kind)); + parseExpected(SyntaxKind.CommaToken, getExpectedCommaDiagnostic(kind)); // If the token was a semicolon, and the caller allows that, then skip it and // continue. This ensures we get back on track and don't result in tons of // parse errors. For example, this can happen when people do things like use // a semicolon to delimit object literal members. Note: we'll have already // reported an error when we called parseExpected above. - if (considerSemicolonAsDelimiter && token() === ts.SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { + if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) { nextToken(); } if (startPos === scanner.getStartPos()) { @@ -3042,24 +3108,24 @@ namespace Parser { } function getExpectedCommaDiagnostic(kind: ParsingContext) { - return kind === ParsingContext.EnumMembers ? ts.Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined; + return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined; } - interface MissingList extends ts.NodeArray { + interface MissingList extends NodeArray { isMissingList: true; } - function createMissingList(): MissingList { + function createMissingList(): MissingList { const list = createNodeArray([], getNodePos()) as MissingList; list.isMissingList = true; return list; } - function isMissingList(arr: ts.NodeArray): boolean { - return !!(arr as MissingList).isMissingList; + function isMissingList(arr: NodeArray): boolean { + return !!(arr as MissingList).isMissingList; } - function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: ts.SyntaxKind, close: ts.SyntaxKind): ts.NodeArray { + function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray { if (parseExpected(open)) { const result = parseDelimitedList(kind, parseElement); parseExpected(close); @@ -3069,12 +3135,12 @@ namespace Parser { return createMissingList(); } - function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: ts.DiagnosticMessage): ts.EntityName { + function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { const pos = getNodePos(); - let entity: ts.EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); + let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); let dotPos = getNodePos(); - while (parseOptional(ts.SyntaxKind.DotToken)) { - if (token() === ts.SyntaxKind.LessThanToken) { + while (parseOptional(SyntaxKind.DotToken)) { + if (token() === SyntaxKind.LessThanToken) { // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting entity.jsdocDotPos = dotPos; break; @@ -3083,7 +3149,7 @@ namespace Parser { entity = finishNode( factory.createQualifiedName( entity, - parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as ts.Identifier + parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as Identifier ), pos ); @@ -3091,11 +3157,11 @@ namespace Parser { return entity; } - function createQualifiedName(entity: ts.EntityName, name: ts.Identifier): ts.QualifiedName { + function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName { return finishNode(factory.createQualifiedName(entity, name), entity.pos); } - function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean): ts.Identifier | ts.PrivateIdentifier { + function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean): Identifier | PrivateIdentifier { // Technically a keyword is valid here as all identifiers and keywords are identifier names. // However, often we'll encounter this in error situations when the identifier or keyword // is actually starting another valid construct. @@ -3115,20 +3181,20 @@ namespace Parser { // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword". // In the first case though, ASI will not take effect because there is not a // line terminator after the identifier or keyword. - if (scanner.hasPrecedingLineBreak() && ts.tokenIsIdentifierOrKeyword(token())) { + if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) { const matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); if (matchesPattern) { // Report that we need an identifier. However, report it right after the dot, // and not on the next token. This is because the next token might actually // be an identifier and the error would be quite confusing. - return createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); } } - if (token() === ts.SyntaxKind.PrivateIdentifier) { + if (token() === SyntaxKind.PrivateIdentifier) { const node = parsePrivateIdentifier(); - return allowPrivateIdentifiers ? node : createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Identifier_expected); + return allowPrivateIdentifiers ? node : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); } return allowIdentifierNames ? parseIdentifierName() : parseIdentifier(); @@ -3137,16 +3203,16 @@ namespace Parser { function parseTemplateSpans(isTaggedTemplate: boolean) { const pos = getNodePos(); const list = []; - let node: ts.TemplateSpan; + let node: TemplateSpan; do { node = parseTemplateSpan(isTaggedTemplate); list.push(node); } - while (node.literal.kind === ts.SyntaxKind.TemplateMiddle); + while (node.literal.kind === SyntaxKind.TemplateMiddle); return createNodeArray(list, pos); } - function parseTemplateExpression(isTaggedTemplate: boolean): ts.TemplateExpression { + function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression { const pos = getNodePos(); return finishNode( factory.createTemplateExpression( @@ -3157,7 +3223,7 @@ namespace Parser { ); } - function parseTemplateType(): ts.TemplateLiteralTypeNode { + function parseTemplateType(): TemplateLiteralTypeNode { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralType( @@ -3171,16 +3237,16 @@ namespace Parser { function parseTemplateTypeSpans() { const pos = getNodePos(); const list = []; - let node: ts.TemplateLiteralTypeSpan; + let node: TemplateLiteralTypeSpan; do { node = parseTemplateTypeSpan(); list.push(node); } - while (node.literal.kind === ts.SyntaxKind.TemplateMiddle); + while (node.literal.kind === SyntaxKind.TemplateMiddle); return createNodeArray(list, pos); } - function parseTemplateTypeSpan(): ts.TemplateLiteralTypeSpan { + function parseTemplateTypeSpan(): TemplateLiteralTypeSpan { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralTypeSpan( @@ -3192,17 +3258,17 @@ namespace Parser { } function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean) { - if (token() === ts.SyntaxKind.CloseBraceToken) { + if (token() === SyntaxKind.CloseBraceToken) { reScanTemplateToken(isTaggedTemplate); return parseTemplateMiddleOrTemplateTail(); } else { // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly? - return parseExpectedToken(ts.SyntaxKind.TemplateTail, ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.CloseBraceToken)) as ts.TemplateTail; + return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)) as TemplateTail; } } - function parseTemplateSpan(isTaggedTemplate: boolean): ts.TemplateSpan { + function parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan { const pos = getNodePos(); return finishNode( factory.createTemplateSpan( @@ -3213,45 +3279,45 @@ namespace Parser { ); } - function parseLiteralNode(): ts.LiteralExpression { - return parseLiteralLikeNode(token()) as ts.LiteralExpression; + function parseLiteralNode(): LiteralExpression { + return parseLiteralLikeNode(token()) as LiteralExpression; } - function parseTemplateHead(isTaggedTemplate: boolean): ts.TemplateHead { + function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead { if (isTaggedTemplate) { reScanTemplateHeadOrNoSubstitutionTemplate(); } const fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === ts.SyntaxKind.TemplateHead, "Template head has wrong token kind"); - return fragment as ts.TemplateHead; + Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); + return fragment as TemplateHead; } - function parseTemplateMiddleOrTemplateTail(): ts.TemplateMiddle | ts.TemplateTail { + function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail { const fragment = parseLiteralLikeNode(token()); - ts.Debug.assert(fragment.kind === ts.SyntaxKind.TemplateMiddle || fragment.kind === ts.SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); - return fragment as ts.TemplateMiddle | ts.TemplateTail; + Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); + return fragment as TemplateMiddle | TemplateTail; } - function getTemplateLiteralRawText(kind: ts.TemplateLiteralToken["kind"]) { - const isLast = kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral || kind === ts.SyntaxKind.TemplateTail; + function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) { + const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail; const tokenText = scanner.getTokenText(); return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); } - function parseLiteralLikeNode(kind: ts.SyntaxKind): ts.LiteralLikeNode { + function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { const pos = getNodePos(); const node = - ts.isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & ts.TokenFlags.TemplateLiteralLikeFlags) : + isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) : // Octal literals are not allowed in strict mode or ES5 // Note that theoretically the following condition would hold true literals like 009, // which is not octal. But because of how the scanner separates the tokens, we would // never get a token like this. Instead, we would get 00 and 9 as two separate tokens. // We also do not need to check for negatives because any prefix operator would be part of a // parent unary expression. - kind === ts.SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : - kind === ts.SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : - ts.isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) : - ts.Debug.fail(); + kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) : + kind === SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) : + isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) : + Debug.fail(); if (scanner.hasExtendedUnicodeEscape()) { node.hasExtendedUnicodeEscape = true; @@ -3268,16 +3334,16 @@ namespace Parser { // TYPES function parseEntityNameOfTypeReference() { - return parseEntityName(/*allowReservedWords*/ true, ts.Diagnostics.Type_expected); + return parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected); } function parseTypeArgumentsOfTypeReference() { - if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === ts.SyntaxKind.LessThanToken) { - return parseBracketedList(ParsingContext.TypeArguments, parseType, ts.SyntaxKind.LessThanToken, ts.SyntaxKind.GreaterThanToken); + if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) { + return parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); } } - function parseTypeReference(): ts.TypeReferenceNode { + function parseTypeReference(): TypeReferenceNode { const pos = getNodePos(); return finishNode( factory.createTypeReferenceNode( @@ -3289,46 +3355,46 @@ namespace Parser { } // If true, we should abort parsing an error function. - function typeHasArrowFunctionBlockingParseError(node: ts.TypeNode): boolean { + function typeHasArrowFunctionBlockingParseError(node: TypeNode): boolean { switch (node.kind) { - case ts.SyntaxKind.TypeReference: - return ts.nodeIsMissing((node as ts.TypeReferenceNode).typeName); - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: { - const { parameters, type } = node as ts.FunctionOrConstructorTypeNode; + case SyntaxKind.TypeReference: + return nodeIsMissing((node as TypeReferenceNode).typeName); + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: { + const { parameters, type } = node as FunctionOrConstructorTypeNode; return isMissingList(parameters) || typeHasArrowFunctionBlockingParseError(type); } - case ts.SyntaxKind.ParenthesizedType: - return typeHasArrowFunctionBlockingParseError((node as ts.ParenthesizedTypeNode).type); + case SyntaxKind.ParenthesizedType: + return typeHasArrowFunctionBlockingParseError((node as ParenthesizedTypeNode).type); default: return false; } } - function parseThisTypePredicate(lhs: ts.ThisTypeNode): ts.TypePredicateNode { + function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode { nextToken(); return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, lhs, parseType()), lhs.pos); } - function parseThisTypeNode(): ts.ThisTypeNode { + function parseThisTypeNode(): ThisTypeNode { const pos = getNodePos(); nextToken(); return finishNode(factory.createThisTypeNode(), pos); } - function parseJSDocAllType(): ts.JSDocAllType | ts.JSDocOptionalType { + function parseJSDocAllType(): JSDocAllType | JSDocOptionalType { const pos = getNodePos(); nextToken(); return finishNode(factory.createJSDocAllType(), pos); } - function parseJSDocNonNullableType(): ts.TypeNode { + function parseJSDocNonNullableType(): TypeNode { const pos = getNodePos(); nextToken(); return finishNode(factory.createJSDocNonNullableType(parseNonArrayType(), /*postfix*/ false), pos); } - function parseJSDocUnknownOrNullableType(): ts.JSDocUnknownType | ts.JSDocNullableType { + function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { const pos = getNodePos(); // skip the ? nextToken(); @@ -3343,12 +3409,12 @@ namespace Parser { // Foo // Foo(?= // (?| - if (token() === ts.SyntaxKind.CommaToken || - token() === ts.SyntaxKind.CloseBraceToken || - token() === ts.SyntaxKind.CloseParenToken || - token() === ts.SyntaxKind.GreaterThanToken || - token() === ts.SyntaxKind.EqualsToken || - token() === ts.SyntaxKind.BarToken) { + if (token() === SyntaxKind.CommaToken || + token() === SyntaxKind.CloseBraceToken || + token() === SyntaxKind.CloseParenToken || + token() === SyntaxKind.GreaterThanToken || + token() === SyntaxKind.EqualsToken || + token() === SyntaxKind.BarToken) { return finishNode(factory.createJSDocUnknownType(), pos); } else { @@ -3356,24 +3422,24 @@ namespace Parser { } } - function parseJSDocFunctionType(): ts.JSDocFunctionType | ts.TypeReferenceNode { + function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); if (lookAhead(nextTokenIsOpenParen)) { nextToken(); const parameters = parseParameters(SignatureFlags.Type | SignatureFlags.JSDoc); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); return withJSDoc(finishNode(factory.createJSDocFunctionType(parameters, type), pos), hasJSDoc); } return finishNode(factory.createTypeReferenceNode(parseIdentifierName(), /*typeArguments*/ undefined), pos); } - function parseJSDocParameter(): ts.ParameterDeclaration { + function parseJSDocParameter(): ParameterDeclaration { const pos = getNodePos(); - let name: ts.Identifier | undefined; - if (token() === ts.SyntaxKind.ThisKeyword || token() === ts.SyntaxKind.NewKeyword) { + let name: Identifier | undefined; + if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) { name = parseIdentifierName(); - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.ColonToken); } return finishNode( factory.createParameterDeclaration( @@ -3389,18 +3455,18 @@ namespace Parser { ); } - function parseJSDocType(): ts.TypeNode { + function parseJSDocType(): TypeNode { scanner.setInJSDocType(true); const pos = getNodePos(); - if (parseOptional(ts.SyntaxKind.ModuleKeyword)) { + if (parseOptional(SyntaxKind.ModuleKeyword)) { // TODO(rbuckton): We never set the type for a JSDocNamepathType. What should we put here? const moduleTag = factory.createJSDocNamepathType(/*type*/ undefined!); terminate: while (true) { switch (token()) { - case ts.SyntaxKind.CloseBraceToken: - case ts.SyntaxKind.EndOfFileToken: - case ts.SyntaxKind.CommaToken: - case ts.SyntaxKind.WhitespaceTrivia: + case SyntaxKind.CloseBraceToken: + case SyntaxKind.EndOfFileToken: + case SyntaxKind.CommaToken: + case SyntaxKind.WhitespaceTrivia: break terminate; default: nextTokenJSDoc(); @@ -3411,35 +3477,35 @@ namespace Parser { return finishNode(moduleTag, pos); } - const hasDotDotDot = parseOptional(ts.SyntaxKind.DotDotDotToken); + const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken); let type = parseTypeOrTypePredicate(); scanner.setInJSDocType(false); if (hasDotDotDot) { type = finishNode(factory.createJSDocVariadicType(type), pos); } - if (token() === ts.SyntaxKind.EqualsToken) { + if (token() === SyntaxKind.EqualsToken) { nextToken(); return finishNode(factory.createJSDocOptionalType(type), pos); } return type; } - function parseTypeQuery(): ts.TypeQueryNode { + function parseTypeQuery(): TypeQueryNode { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.TypeOfKeyword); + parseExpected(SyntaxKind.TypeOfKeyword); const entityName = parseEntityName(/*allowReservedWords*/ true); // Make sure we perform ASI to prevent parsing the next line's type arguments as part of an instantiation expression. const typeArguments = !scanner.hasPrecedingLineBreak() ? tryParseTypeArguments() : undefined; return finishNode(factory.createTypeQueryNode(entityName, typeArguments), pos); } - function parseTypeParameter(): ts.TypeParameterDeclaration { + function parseTypeParameter(): TypeParameterDeclaration { const pos = getNodePos(); const modifiers = parseModifiers(); const name = parseIdentifier(); - let constraint: ts.TypeNode | undefined; - let expression: ts.Expression | undefined; - if (parseOptional(ts.SyntaxKind.ExtendsKeyword)) { + let constraint: TypeNode | undefined; + let expression: Expression | undefined; + if (parseOptional(SyntaxKind.ExtendsKeyword)) { // It's not uncommon for people to write improper constraints to a generic. If the // user writes a constraint that is an expression and not an actual type, then parse // it out as an expression (so we can recover well), but report that a type is needed @@ -3459,31 +3525,31 @@ namespace Parser { } } - const defaultType = parseOptional(ts.SyntaxKind.EqualsToken) ? parseType() : undefined; + const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined; const node = factory.createTypeParameterDeclaration(modifiers, name, constraint, defaultType); node.expression = expression; return finishNode(node, pos); } - function parseTypeParameters(): ts.NodeArray | undefined { - if (token() === ts.SyntaxKind.LessThanToken) { - return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, ts.SyntaxKind.LessThanToken, ts.SyntaxKind.GreaterThanToken); + function parseTypeParameters(): NodeArray | undefined { + if (token() === SyntaxKind.LessThanToken) { + return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); } } function isStartOfParameter(isJSDocParameter: boolean): boolean { - return token() === ts.SyntaxKind.DotDotDotToken || + return token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern() || - ts.isModifierKind(token()) || - token() === ts.SyntaxKind.AtToken || + isModifierKind(token()) || + token() === SyntaxKind.AtToken || isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); } - function parseNameOfParameter(modifiers: ts.NodeArray | undefined) { + function parseNameOfParameter(modifiers: NodeArray | undefined) { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] - const name = parseIdentifierOrPattern(ts.Diagnostics.Private_identifiers_cannot_be_used_as_parameters); - if (ts.getFullWidth(name) === 0 && !ts.some(modifiers) && ts.isModifierKind(token())) { + const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters); + if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) { // in cases like // 'use strict' // function foo(static) @@ -3501,20 +3567,20 @@ namespace Parser { // Be permissive about await and yield by calling isBindingIdentifier instead of isIdentifier; disallowing // them during a speculative parse leads to many more follow-on errors than allowing the function to parse then later // complaining about the use of the keywords. - return isBindingIdentifier() || token() === ts.SyntaxKind.OpenBracketToken || token() === ts.SyntaxKind.OpenBraceToken; + return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken; } - function parseParameter(inOuterAwaitContext: boolean): ts.ParameterDeclaration { + function parseParameter(inOuterAwaitContext: boolean): ParameterDeclaration { return parseParameterWorker(inOuterAwaitContext); } - function parseParameterForSpeculation(inOuterAwaitContext: boolean): ts.ParameterDeclaration | undefined { + function parseParameterForSpeculation(inOuterAwaitContext: boolean): ParameterDeclaration | undefined { return parseParameterWorker(inOuterAwaitContext, /*allowAmbiguity*/ false); } - function parseParameterWorker(inOuterAwaitContext: boolean): ts.ParameterDeclaration; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ts.ParameterDeclaration | undefined; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ts.ParameterDeclaration | undefined { + function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration; + function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ParameterDeclaration | undefined; + function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ParameterDeclaration | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -3524,7 +3590,7 @@ namespace Parser { // Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context. const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : doOutsideOfAwaitContext(parseDecorators); - if (token() === ts.SyntaxKind.ThisKeyword) { + if (token() === SyntaxKind.ThisKeyword) { const node = factory.createParameterDeclaration( decorators, /*dotDotDotToken*/ undefined, @@ -3535,7 +3601,7 @@ namespace Parser { ); if (decorators) { - parseErrorAtRange(decorators[0], ts.Diagnostics.Decorators_may_not_be_applied_to_this_parameters); + parseErrorAtRange(decorators[0], Diagnostics.Decorators_may_not_be_applied_to_this_parameters); } return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -3545,7 +3611,7 @@ namespace Parser { topLevel = false; const modifiers = combineDecoratorsAndModifiers(decorators, parseModifiers()); - const dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); if (!allowAmbiguity && !isParameterNameStart()) { return undefined; @@ -3557,7 +3623,7 @@ namespace Parser { modifiers, dotDotDotToken, parseNameOfParameter(modifiers), - parseOptionalToken(ts.SyntaxKind.QuestionToken), + parseOptionalToken(SyntaxKind.QuestionToken), parseTypeAnnotation(), parseInitializer() ), @@ -3569,34 +3635,34 @@ namespace Parser { return node; } - function parseReturnType(returnToken: ts.SyntaxKind.EqualsGreaterThanToken, isType: boolean): ts.TypeNode; - function parseReturnType(returnToken: ts.SyntaxKind.ColonToken | ts.SyntaxKind.EqualsGreaterThanToken, isType: boolean): ts.TypeNode | undefined; - function parseReturnType(returnToken: ts.SyntaxKind.ColonToken | ts.SyntaxKind.EqualsGreaterThanToken, isType: boolean) { + function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode; + function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined; + function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) { if (shouldParseReturnType(returnToken, isType)) { return allowConditionalTypesAnd(parseTypeOrTypePredicate); } } - function shouldParseReturnType(returnToken: ts.SyntaxKind.ColonToken | ts.SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean { - if (returnToken === ts.SyntaxKind.EqualsGreaterThanToken) { + function shouldParseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean { + if (returnToken === SyntaxKind.EqualsGreaterThanToken) { parseExpected(returnToken); return true; } - else if (parseOptional(ts.SyntaxKind.ColonToken)) { + else if (parseOptional(SyntaxKind.ColonToken)) { return true; } - else if (isType && token() === ts.SyntaxKind.EqualsGreaterThanToken) { + else if (isType && token() === SyntaxKind.EqualsGreaterThanToken) { // This is easy to get backward, especially in type contexts, so parse the type anyway - parseErrorAtCurrentToken(ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.ColonToken)); + parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)); nextToken(); return true; } return false; } - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): ts.NodeArray; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): ts.NodeArray | undefined; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): ts.NodeArray | undefined { + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): NodeArray; + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): NodeArray | undefined; + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): NodeArray | undefined { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -3626,7 +3692,7 @@ namespace Parser { return parameters; } - function parseParameters(flags: SignatureFlags): ts.NodeArray { + function parseParameters(flags: SignatureFlags): NodeArray { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -3640,19 +3706,19 @@ namespace Parser { // // SingleNameBinding [Yield,Await]: // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt - if (!parseExpected(ts.SyntaxKind.OpenParenToken)) { - return createMissingList(); + if (!parseExpected(SyntaxKind.OpenParenToken)) { + return createMissingList(); } const parameters = parseParametersWorker(flags, /*allowAmbiguity*/ true); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); return parameters; } function parseTypeMemberSemicolon() { // We allow type members to be separated by commas or (possibly ASI) semicolons. // First check if it was a comma. If so, we're done with the member. - if (parseOptional(ts.SyntaxKind.CommaToken)) { + if (parseOptional(SyntaxKind.CommaToken)) { return; } @@ -3660,25 +3726,25 @@ namespace Parser { parseSemicolon(); } - function parseSignatureMember(kind: ts.SyntaxKind.CallSignature | ts.SyntaxKind.ConstructSignature): ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration { + function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - if (kind === ts.SyntaxKind.ConstructSignature) { - parseExpected(ts.SyntaxKind.NewKeyword); + if (kind === SyntaxKind.ConstructSignature) { + parseExpected(SyntaxKind.NewKeyword); } const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.Type); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ true); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true); parseTypeMemberSemicolon(); - const node = kind === ts.SyntaxKind.CallSignature + const node = kind === SyntaxKind.CallSignature ? factory.createCallSignature(typeParameters, parameters, type) : factory.createConstructSignature(typeParameters, parameters, type); return withJSDoc(finishNode(node, pos), hasJSDoc); } function isIndexSignature(): boolean { - return token() === ts.SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature); + return token() === SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature); } function isUnambiguouslyIndexSignature() { @@ -3699,11 +3765,11 @@ namespace Parser { // [] // nextToken(); - if (token() === ts.SyntaxKind.DotDotDotToken || token() === ts.SyntaxKind.CloseBracketToken) { + if (token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.CloseBracketToken) { return true; } - if (ts.isModifierKind(token())) { + if (isModifierKind(token())) { nextToken(); if (isIdentifier()) { return true; @@ -3720,41 +3786,41 @@ namespace Parser { // A colon signifies a well formed indexer // A comma should be a badly formed indexer because comma expressions are not allowed // in computed properties. - if (token() === ts.SyntaxKind.ColonToken || token() === ts.SyntaxKind.CommaToken) { + if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken) { return true; } // Question mark could be an indexer with an optional property, // or it could be a conditional expression in a computed property. - if (token() !== ts.SyntaxKind.QuestionToken) { + if (token() !== SyntaxKind.QuestionToken) { return false; } // If any of the following tokens are after the question mark, it cannot // be a conditional expression, so treat it as an indexer. nextToken(); - return token() === ts.SyntaxKind.ColonToken || token() === ts.SyntaxKind.CommaToken || token() === ts.SyntaxKind.CloseBracketToken; + return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken; } - function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.IndexSignatureDeclaration { - const parameters = parseBracketedList(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.CloseBracketToken); + function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): IndexSignatureDeclaration { + const parameters = parseBracketedList(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); const type = parseTypeAnnotation(); parseTypeMemberSemicolon(); const node = factory.createIndexSignature(modifiers, parameters, type); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: ts.NodeArray | undefined): ts.PropertySignature | ts.MethodSignature { + function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): PropertySignature | MethodSignature { const name = parsePropertyName(); - const questionToken = parseOptionalToken(ts.SyntaxKind.QuestionToken); - let node: ts.PropertySignature | ts.MethodSignature; - if (token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken) { + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + let node: PropertySignature | MethodSignature; + if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { // Method signatures don't exist in expression contexts. So they have neither // [Yield] nor [Await] const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.Type); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ true); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true); node = factory.createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type); } else { @@ -3763,7 +3829,7 @@ namespace Parser { // Although type literal properties cannot not have initializers, we attempt // to parse an initializer so we can report in the checker that an interface // property or type literal property cannot have an initializer. - if (token() === ts.SyntaxKind.EqualsToken) (node as ts.Mutable).initializer = parseInitializer(); + if (token() === SyntaxKind.EqualsToken) (node as Mutable).initializer = parseInitializer(); } parseTypeMemberSemicolon(); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -3771,20 +3837,20 @@ namespace Parser { function isTypeMemberStart(): boolean { // Return true if we have the start of a signature member - if (token() === ts.SyntaxKind.OpenParenToken || - token() === ts.SyntaxKind.LessThanToken || - token() === ts.SyntaxKind.GetKeyword || - token() === ts.SyntaxKind.SetKeyword) { + if (token() === SyntaxKind.OpenParenToken || + token() === SyntaxKind.LessThanToken || + token() === SyntaxKind.GetKeyword || + token() === SyntaxKind.SetKeyword) { return true; } let idToken = false; // Eat up all modifiers, but hold on to the last one in case it is actually an identifier - while (ts.isModifierKind(token())) { + while (isModifierKind(token())) { idToken = true; nextToken(); } // Index signatures and computed property names are type members - if (token() === ts.SyntaxKind.OpenBracketToken) { + if (token() === SyntaxKind.OpenBracketToken) { return true; } // Try to get the first property-like token following all modifiers @@ -3795,32 +3861,32 @@ namespace Parser { // If we were able to get any potential identifier, check that it is // the start of a member declaration if (idToken) { - return token() === ts.SyntaxKind.OpenParenToken || - token() === ts.SyntaxKind.LessThanToken || - token() === ts.SyntaxKind.QuestionToken || - token() === ts.SyntaxKind.ColonToken || - token() === ts.SyntaxKind.CommaToken || + return token() === SyntaxKind.OpenParenToken || + token() === SyntaxKind.LessThanToken || + token() === SyntaxKind.QuestionToken || + token() === SyntaxKind.ColonToken || + token() === SyntaxKind.CommaToken || canParseSemicolon(); } return false; } - function parseTypeMember(): ts.TypeElement { - if (token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken) { - return parseSignatureMember(ts.SyntaxKind.CallSignature); + function parseTypeMember(): TypeElement { + if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { + return parseSignatureMember(SyntaxKind.CallSignature); } - if (token() === ts.SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { - return parseSignatureMember(ts.SyntaxKind.ConstructSignature); + if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) { + return parseSignatureMember(SyntaxKind.ConstructSignature); } const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(); - if (parseContextualModifier(ts.SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, ts.SyntaxKind.GetAccessor, SignatureFlags.Type); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.GetAccessor, SignatureFlags.Type); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, ts.SyntaxKind.SetAccessor, SignatureFlags.Type); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.SetAccessor, SignatureFlags.Type); } if (isIndexSignature()) { @@ -3831,36 +3897,36 @@ namespace Parser { function nextTokenIsOpenParenOrLessThan() { nextToken(); - return token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken; + return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken; } function nextTokenIsDot() { - return nextToken() === ts.SyntaxKind.DotToken; + return nextToken() === SyntaxKind.DotToken; } function nextTokenIsOpenParenOrLessThanOrDot() { switch (nextToken()) { - case ts.SyntaxKind.OpenParenToken: - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.DotToken: + case SyntaxKind.OpenParenToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.DotToken: return true; } return false; } - function parseTypeLiteral(): ts.TypeLiteralNode { + function parseTypeLiteral(): TypeLiteralNode { const pos = getNodePos(); return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos); } - function parseObjectTypeMembers(): ts.NodeArray { - let members: ts.NodeArray; - if (parseExpected(ts.SyntaxKind.OpenBraceToken)) { + function parseObjectTypeMembers(): NodeArray { + let members: NodeArray; + if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, parseTypeMember); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } return members; @@ -3868,85 +3934,85 @@ namespace Parser { function isStartOfMappedType() { nextToken(); - if (token() === ts.SyntaxKind.PlusToken || token() === ts.SyntaxKind.MinusToken) { - return nextToken() === ts.SyntaxKind.ReadonlyKeyword; + if (token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { + return nextToken() === SyntaxKind.ReadonlyKeyword; } - if (token() === ts.SyntaxKind.ReadonlyKeyword) { + if (token() === SyntaxKind.ReadonlyKeyword) { nextToken(); } - return token() === ts.SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === ts.SyntaxKind.InKeyword; + return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword; } function parseMappedTypeParameter() { const pos = getNodePos(); const name = parseIdentifierName(); - parseExpected(ts.SyntaxKind.InKeyword); + parseExpected(SyntaxKind.InKeyword); const type = parseType(); return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, type, /*defaultType*/ undefined), pos); } function parseMappedType() { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBraceToken); - let readonlyToken: ts.ReadonlyKeyword | ts.PlusToken | ts.MinusToken | undefined; - if (token() === ts.SyntaxKind.ReadonlyKeyword || token() === ts.SyntaxKind.PlusToken || token() === ts.SyntaxKind.MinusToken) { - readonlyToken = parseTokenNode(); - if (readonlyToken.kind !== ts.SyntaxKind.ReadonlyKeyword) { - parseExpected(ts.SyntaxKind.ReadonlyKeyword); + parseExpected(SyntaxKind.OpenBraceToken); + let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; + if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { + readonlyToken = parseTokenNode(); + if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { + parseExpected(SyntaxKind.ReadonlyKeyword); } } - parseExpected(ts.SyntaxKind.OpenBracketToken); + parseExpected(SyntaxKind.OpenBracketToken); const typeParameter = parseMappedTypeParameter(); - const nameType = parseOptional(ts.SyntaxKind.AsKeyword) ? parseType() : undefined; - parseExpected(ts.SyntaxKind.CloseBracketToken); - let questionToken: ts.QuestionToken | ts.PlusToken | ts.MinusToken | undefined; - if (token() === ts.SyntaxKind.QuestionToken || token() === ts.SyntaxKind.PlusToken || token() === ts.SyntaxKind.MinusToken) { - questionToken = parseTokenNode(); - if (questionToken.kind !== ts.SyntaxKind.QuestionToken) { - parseExpected(ts.SyntaxKind.QuestionToken); + const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined; + parseExpected(SyntaxKind.CloseBracketToken); + let questionToken: QuestionToken | PlusToken | MinusToken | undefined; + if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { + questionToken = parseTokenNode(); + if (questionToken.kind !== SyntaxKind.QuestionToken) { + parseExpected(SyntaxKind.QuestionToken); } } const type = parseTypeAnnotation(); parseSemicolon(); const members = parseList(ParsingContext.TypeMembers, parseTypeMember); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), pos); } function parseTupleElementType() { const pos = getNodePos(); - if (parseOptional(ts.SyntaxKind.DotDotDotToken)) { + if (parseOptional(SyntaxKind.DotDotDotToken)) { return finishNode(factory.createRestTypeNode(parseType()), pos); } const type = parseType(); - if (ts.isJSDocNullableType(type) && type.pos === type.type.pos) { + if (isJSDocNullableType(type) && type.pos === type.type.pos) { const node = factory.createOptionalTypeNode(type.type); - ts.setTextRange(node, type); - (node as ts.Mutable).flags = type.flags; + setTextRange(node, type); + (node as Mutable).flags = type.flags; return node; } return type; } function isNextTokenColonOrQuestionColon() { - return nextToken() === ts.SyntaxKind.ColonToken || (token() === ts.SyntaxKind.QuestionToken && nextToken() === ts.SyntaxKind.ColonToken); + return nextToken() === SyntaxKind.ColonToken || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken); } function isTupleElementName() { - if (token() === ts.SyntaxKind.DotDotDotToken) { - return ts.tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon(); + if (token() === SyntaxKind.DotDotDotToken) { + return tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon(); } - return ts.tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon(); + return tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon(); } function parseTupleElementNameOrTupleElementType() { if (lookAhead(isTupleElementName)) { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - const dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const name = parseIdentifierName(); - const questionToken = parseOptionalToken(ts.SyntaxKind.QuestionToken); - parseExpected(ts.SyntaxKind.ColonToken); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + parseExpected(SyntaxKind.ColonToken); const type = parseTupleElementType(); const node = factory.createNamedTupleMember(dotDotDotToken, name, questionToken, type); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -3954,181 +4020,181 @@ namespace Parser { return parseTupleElementType(); } - function parseTupleType(): ts.TupleTypeNode { + function parseTupleType(): TupleTypeNode { const pos = getNodePos(); return finishNode( factory.createTupleTypeNode( - parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.CloseBracketToken) + parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken) ), pos ); } - function parseParenthesizedType(): ts.TypeNode { + function parseParenthesizedType(): TypeNode { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.OpenParenToken); const type = parseType(); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); return finishNode(factory.createParenthesizedType(type), pos); } - function parseModifiersForConstructorType(): ts.NodeArray | undefined { - let modifiers: ts.NodeArray | undefined; - if (token() === ts.SyntaxKind.AbstractKeyword) { + function parseModifiersForConstructorType(): NodeArray | undefined { + let modifiers: NodeArray | undefined; + if (token() === SyntaxKind.AbstractKeyword) { const pos = getNodePos(); nextToken(); - const modifier = finishNode(factory.createToken(ts.SyntaxKind.AbstractKeyword), pos); - modifiers = createNodeArray([modifier], pos); + const modifier = finishNode(factory.createToken(SyntaxKind.AbstractKeyword), pos); + modifiers = createNodeArray([modifier], pos); } return modifiers; } - function parseFunctionOrConstructorType(): ts.TypeNode { + function parseFunctionOrConstructorType(): TypeNode { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForConstructorType(); - const isConstructorType = parseOptional(ts.SyntaxKind.NewKeyword); + const isConstructorType = parseOptional(SyntaxKind.NewKeyword); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.Type); - const type = parseReturnType(ts.SyntaxKind.EqualsGreaterThanToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.EqualsGreaterThanToken, /*isType*/ false); const node = isConstructorType ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, type) : factory.createFunctionTypeNode(typeParameters, parameters, type); - if (!isConstructorType) (node as ts.Mutable).modifiers = modifiers; + if (!isConstructorType) (node as Mutable).modifiers = modifiers; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseKeywordAndNoDot(): ts.TypeNode | undefined { - const node = parseTokenNode(); - return token() === ts.SyntaxKind.DotToken ? undefined : node; + function parseKeywordAndNoDot(): TypeNode | undefined { + const node = parseTokenNode(); + return token() === SyntaxKind.DotToken ? undefined : node; } - function parseLiteralTypeNode(negative?: boolean): ts.LiteralTypeNode { + function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { const pos = getNodePos(); if (negative) { nextToken(); } - let expression: ts.BooleanLiteral | ts.NullLiteral | ts.LiteralExpression | ts.PrefixUnaryExpression = - token() === ts.SyntaxKind.TrueKeyword || token() === ts.SyntaxKind.FalseKeyword || token() === ts.SyntaxKind.NullKeyword ? - parseTokenNode() : - parseLiteralLikeNode(token()) as ts.LiteralExpression; + let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = + token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? + parseTokenNode() : + parseLiteralLikeNode(token()) as LiteralExpression; if (negative) { - expression = finishNode(factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, expression), pos); + expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos); } return finishNode(factory.createLiteralTypeNode(expression), pos); } function isStartOfTypeOfImportType() { nextToken(); - return token() === ts.SyntaxKind.ImportKeyword; + return token() === SyntaxKind.ImportKeyword; } - function parseImportTypeAssertions(): ts.ImportTypeAssertionContainer { + function parseImportTypeAssertions(): ImportTypeAssertionContainer { const pos = getNodePos(); const openBracePosition = scanner.getTokenPos(); - parseExpected(ts.SyntaxKind.OpenBraceToken); + parseExpected(SyntaxKind.OpenBraceToken); const multiLine = scanner.hasPrecedingLineBreak(); - parseExpected(ts.SyntaxKind.AssertKeyword); - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.AssertKeyword); + parseExpected(SyntaxKind.ColonToken); const clause = parseAssertClause(/*skipAssertKeyword*/ true); - if (!parseExpected(ts.SyntaxKind.CloseBraceToken)) { - const lastError = ts.lastOrUndefined(parseDiagnostics); - if (lastError && lastError.code === ts.Diagnostics._0_expected.code) { - ts.addRelatedInfo( + if (!parseExpected(SyntaxKind.CloseBraceToken)) { + const lastError = lastOrUndefined(parseDiagnostics); + if (lastError && lastError.code === Diagnostics._0_expected.code) { + addRelatedInfo( lastError, - ts.createDetachedDiagnostic(fileName, openBracePosition, 1, ts.Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") + createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") ); } } return finishNode(factory.createImportTypeAssertionContainer(clause, multiLine), pos); } - function parseImportType(): ts.ImportTypeNode { - sourceFlags |= ts.NodeFlags.PossiblyContainsDynamicImport; + function parseImportType(): ImportTypeNode { + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; const pos = getNodePos(); - const isTypeOf = parseOptional(ts.SyntaxKind.TypeOfKeyword); - parseExpected(ts.SyntaxKind.ImportKeyword); - parseExpected(ts.SyntaxKind.OpenParenToken); + const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword); + parseExpected(SyntaxKind.ImportKeyword); + parseExpected(SyntaxKind.OpenParenToken); const type = parseType(); - let assertions: ts.ImportTypeAssertionContainer | undefined; - if (parseOptional(ts.SyntaxKind.CommaToken)) { + let assertions: ImportTypeAssertionContainer | undefined; + if (parseOptional(SyntaxKind.CommaToken)) { assertions = parseImportTypeAssertions(); } - parseExpected(ts.SyntaxKind.CloseParenToken); - const qualifier = parseOptional(ts.SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : undefined; + parseExpected(SyntaxKind.CloseParenToken); + const qualifier = parseOptional(SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : undefined; const typeArguments = parseTypeArgumentsOfTypeReference(); return finishNode(factory.createImportTypeNode(type, assertions, qualifier, typeArguments, isTypeOf), pos); } function nextTokenIsNumericOrBigIntLiteral() { nextToken(); - return token() === ts.SyntaxKind.NumericLiteral || token() === ts.SyntaxKind.BigIntLiteral; + return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral; } - function parseNonArrayType(): ts.TypeNode { + function parseNonArrayType(): TypeNode { switch (token()) { - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.UnknownKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.UndefinedKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.ObjectKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.UnknownKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ObjectKeyword: // If these are followed by a dot, then parse these out as a dotted type reference instead. return tryParse(parseKeywordAndNoDot) || parseTypeReference(); - case ts.SyntaxKind.AsteriskEqualsToken: + case SyntaxKind.AsteriskEqualsToken: // If there is '*=', treat it as * followed by postfix = scanner.reScanAsteriskEqualsToken(); // falls through - case ts.SyntaxKind.AsteriskToken: + case SyntaxKind.AsteriskToken: return parseJSDocAllType(); - case ts.SyntaxKind.QuestionQuestionToken: + case SyntaxKind.QuestionQuestionToken: // If there is '??', treat it as prefix-'?' in JSDoc type. scanner.reScanQuestionToken(); // falls through - case ts.SyntaxKind.QuestionToken: + case SyntaxKind.QuestionToken: return parseJSDocUnknownOrNullableType(); - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: return parseJSDocFunctionType(); - case ts.SyntaxKind.ExclamationToken: + case SyntaxKind.ExclamationToken: return parseJSDocNonNullableType(); - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: return parseLiteralTypeNode(); - case ts.SyntaxKind.MinusToken: + case SyntaxKind.MinusToken: return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); - case ts.SyntaxKind.VoidKeyword: - return parseTokenNode(); - case ts.SyntaxKind.ThisKeyword: { + case SyntaxKind.VoidKeyword: + return parseTokenNode(); + case SyntaxKind.ThisKeyword: { const thisKeyword = parseThisTypeNode(); - if (token() === ts.SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { + if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { return parseThisTypePredicate(thisKeyword); } else { return thisKeyword; } } - case ts.SyntaxKind.TypeOfKeyword: + case SyntaxKind.TypeOfKeyword: return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery(); - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral(); - case ts.SyntaxKind.OpenBracketToken: + case SyntaxKind.OpenBracketToken: return parseTupleType(); - case ts.SyntaxKind.OpenParenToken: + case SyntaxKind.OpenParenToken: return parseParenthesizedType(); - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: return parseImportType(); - case ts.SyntaxKind.AssertsKeyword: + case SyntaxKind.AssertsKeyword: return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference(); - case ts.SyntaxKind.TemplateHead: + case SyntaxKind.TemplateHead: return parseTemplateType(); default: return parseTypeReference(); @@ -4137,48 +4203,48 @@ namespace Parser { function isStartOfType(inStartOfParameter?: boolean): boolean { switch (token()) { - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.UnknownKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.ReadonlyKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.UniqueKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.UndefinedKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.TypeOfKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.OpenBraceToken: - case ts.SyntaxKind.OpenBracketToken: - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.AmpersandToken: - case ts.SyntaxKind.NewKeyword: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.ObjectKeyword: - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.QuestionToken: - case ts.SyntaxKind.ExclamationToken: - case ts.SyntaxKind.DotDotDotToken: - case ts.SyntaxKind.InferKeyword: - case ts.SyntaxKind.ImportKeyword: - case ts.SyntaxKind.AssertsKeyword: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TemplateHead: + case SyntaxKind.AnyKeyword: + case SyntaxKind.UnknownKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.UniqueKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBracketToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.BarToken: + case SyntaxKind.AmpersandToken: + case SyntaxKind.NewKeyword: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.AsteriskToken: + case SyntaxKind.QuestionToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.DotDotDotToken: + case SyntaxKind.InferKeyword: + case SyntaxKind.ImportKeyword: + case SyntaxKind.AssertsKeyword: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: return true; - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: return !inStartOfParameter; - case ts.SyntaxKind.MinusToken: + case SyntaxKind.MinusToken: return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral); - case ts.SyntaxKind.OpenParenToken: + case SyntaxKind.OpenParenToken: // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier, // or something that starts a type. We don't want to consider things like '(1)' a type. return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType); @@ -4189,19 +4255,19 @@ namespace Parser { function isStartOfParenthesizedOrFunctionType() { nextToken(); - return token() === ts.SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType(); + return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType(); } - function parsePostfixTypeOrHigher(): ts.TypeNode { + function parsePostfixTypeOrHigher(): TypeNode { const pos = getNodePos(); let type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak()) { switch (token()) { - case ts.SyntaxKind.ExclamationToken: + case SyntaxKind.ExclamationToken: nextToken(); type = finishNode(factory.createJSDocNonNullableType(type, /*postfix*/ true), pos); break; - case ts.SyntaxKind.QuestionToken: + case SyntaxKind.QuestionToken: // If next token is start of a type we have a conditional type if (lookAhead(nextTokenIsStartOfType)) { return type; @@ -4209,15 +4275,15 @@ namespace Parser { nextToken(); type = finishNode(factory.createJSDocNullableType(type, /*postfix*/ true), pos); break; - case ts.SyntaxKind.OpenBracketToken: - parseExpected(ts.SyntaxKind.OpenBracketToken); + case SyntaxKind.OpenBracketToken: + parseExpected(SyntaxKind.OpenBracketToken); if (isStartOfType()) { const indexType = parseType(); - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); type = finishNode(factory.createIndexedAccessTypeNode(type, indexType), pos); } else { - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); type = finishNode(factory.createArrayTypeNode(type), pos); } break; @@ -4228,22 +4294,22 @@ namespace Parser { return type; } - function parseTypeOperator(operator: ts.SyntaxKind.KeyOfKeyword | ts.SyntaxKind.UniqueKeyword | ts.SyntaxKind.ReadonlyKeyword) { + function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) { const pos = getNodePos(); parseExpected(operator); return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos); } function tryParseConstraintOfInferType() { - if (parseOptional(ts.SyntaxKind.ExtendsKeyword)) { + if (parseOptional(SyntaxKind.ExtendsKeyword)) { const constraint = disallowConditionalTypesAnd(parseType); - if (inDisallowConditionalTypesContext() || token() !== ts.SyntaxKind.QuestionToken) { + if (inDisallowConditionalTypesContext() || token() !== SyntaxKind.QuestionToken) { return constraint; } } } - function parseTypeParameterOfInferType(): ts.TypeParameterDeclaration { + function parseTypeParameterOfInferType(): TypeParameterDeclaration { const pos = getNodePos(); const name = parseIdentifier(); const constraint = tryParse(tryParseConstraintOfInferType); @@ -4251,20 +4317,20 @@ namespace Parser { return finishNode(node, pos); } - function parseInferType(): ts.InferTypeNode { + function parseInferType(): InferTypeNode { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.InferKeyword); + parseExpected(SyntaxKind.InferKeyword); return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos); } - function parseTypeOperatorOrHigher(): ts.TypeNode { + function parseTypeOperatorOrHigher(): TypeNode { const operator = token(); switch (operator) { - case ts.SyntaxKind.KeyOfKeyword: - case ts.SyntaxKind.UniqueKeyword: - case ts.SyntaxKind.ReadonlyKeyword: + case SyntaxKind.KeyOfKeyword: + case SyntaxKind.UniqueKeyword: + case SyntaxKind.ReadonlyKeyword: return parseTypeOperator(operator); - case ts.SyntaxKind.InferKeyword: + case SyntaxKind.InferKeyword: return parseInferType(); } return allowConditionalTypesAnd(parsePostfixTypeOrHigher); @@ -4272,22 +4338,22 @@ namespace Parser { function parseFunctionOrConstructorTypeToError( isInUnionType: boolean - ): ts.TypeNode | undefined { + ): TypeNode | undefined { // the function type and constructor type shorthand notation // are not allowed directly in unions and intersections, but we'll // try to parse them gracefully and issue a helpful message. if (isStartOfFunctionTypeOrConstructorType()) { const type = parseFunctionOrConstructorType(); - let diagnostic: ts.DiagnosticMessage; - if (ts.isFunctionTypeNode(type)) { + let diagnostic: DiagnosticMessage; + if (isFunctionTypeNode(type)) { diagnostic = isInUnionType - ? ts.Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type - : ts.Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type; + ? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type + : Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type; } else { diagnostic = isInUnionType - ? ts.Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type - : ts.Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type; + ? Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type + : Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type; } parseErrorAtRange(type, diagnostic); @@ -4297,12 +4363,12 @@ namespace Parser { } function parseUnionOrIntersectionType( - operator: ts.SyntaxKind.BarToken | ts.SyntaxKind.AmpersandToken, - parseConstituentType: () => ts.TypeNode, - createTypeNode: (types: ts.NodeArray) => ts.UnionOrIntersectionTypeNode - ): ts.TypeNode { + operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken, + parseConstituentType: () => TypeNode, + createTypeNode: (types: NodeArray) => UnionOrIntersectionTypeNode + ): TypeNode { const pos = getNodePos(); - const isUnionType = operator === ts.SyntaxKind.BarToken; + const isUnionType = operator === SyntaxKind.BarToken; const hasLeadingOperator = parseOptional(operator); let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType(); @@ -4316,40 +4382,40 @@ namespace Parser { return type; } - function parseIntersectionTypeOrHigher(): ts.TypeNode { - return parseUnionOrIntersectionType(ts.SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode); + function parseIntersectionTypeOrHigher(): TypeNode { + return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode); } - function parseUnionTypeOrHigher(): ts.TypeNode { - return parseUnionOrIntersectionType(ts.SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode); + function parseUnionTypeOrHigher(): TypeNode { + return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode); } function nextTokenIsNewKeyword(): boolean { nextToken(); - return token() === ts.SyntaxKind.NewKeyword; + return token() === SyntaxKind.NewKeyword; } function isStartOfFunctionTypeOrConstructorType(): boolean { - if (token() === ts.SyntaxKind.LessThanToken) { + if (token() === SyntaxKind.LessThanToken) { return true; } - if (token() === ts.SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) { + if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) { return true; } - return token() === ts.SyntaxKind.NewKeyword || - token() === ts.SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword); + return token() === SyntaxKind.NewKeyword || + token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword); } function skipParameterStart(): boolean { - if (ts.isModifierKind(token())) { + if (isModifierKind(token())) { // Skip modifiers parseModifiers(); } - if (isIdentifier() || token() === ts.SyntaxKind.ThisKeyword) { + if (isIdentifier() || token() === SyntaxKind.ThisKeyword) { nextToken(); return true; } - if (token() === ts.SyntaxKind.OpenBracketToken || token() === ts.SyntaxKind.OpenBraceToken) { + if (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken) { // Return true if we can parse an array or object binding pattern with no errors const previousErrorCount = parseDiagnostics.length; parseIdentifierOrPattern(); @@ -4360,7 +4426,7 @@ namespace Parser { function isUnambiguouslyStartOfFunctionType() { nextToken(); - if (token() === ts.SyntaxKind.CloseParenToken || token() === ts.SyntaxKind.DotDotDotToken) { + if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) { // ( ) // ( ... return true; @@ -4368,17 +4434,17 @@ namespace Parser { if (skipParameterStart()) { // We successfully skipped modifiers (if any) and an identifier or binding pattern, // now see if we have something that indicates a parameter declaration - if (token() === ts.SyntaxKind.ColonToken || token() === ts.SyntaxKind.CommaToken || - token() === ts.SyntaxKind.QuestionToken || token() === ts.SyntaxKind.EqualsToken) { + if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || + token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken) { // ( xxx : // ( xxx , // ( xxx ? // ( xxx = return true; } - if (token() === ts.SyntaxKind.CloseParenToken) { + if (token() === SyntaxKind.CloseParenToken) { nextToken(); - if (token() === ts.SyntaxKind.EqualsGreaterThanToken) { + if (token() === SyntaxKind.EqualsGreaterThanToken) { // ( xxx ) => return true; } @@ -4387,7 +4453,7 @@ namespace Parser { return false; } - function parseTypeOrTypePredicate(): ts.TypeNode { + function parseTypeOrTypePredicate(): TypeNode { const pos = getNodePos(); const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); const type = parseType(); @@ -4401,23 +4467,23 @@ namespace Parser { function parseTypePredicatePrefix() { const id = parseIdentifier(); - if (token() === ts.SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { + if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { nextToken(); return id; } } - function parseAssertsTypePredicate(): ts.TypeNode { + function parseAssertsTypePredicate(): TypeNode { const pos = getNodePos(); - const assertsModifier = parseExpectedToken(ts.SyntaxKind.AssertsKeyword); - const parameterName = token() === ts.SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier(); - const type = parseOptional(ts.SyntaxKind.IsKeyword) ? parseType() : undefined; + const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword); + const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier(); + const type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined; return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos); } - function parseType(): ts.TypeNode { - if (contextFlags & ts.NodeFlags.TypeExcludesFlags) { - return doOutsideOfContext(ts.NodeFlags.TypeExcludesFlags, parseType); + function parseType(): TypeNode { + if (contextFlags & NodeFlags.TypeExcludesFlags) { + return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType); } if (isStartOfFunctionTypeOrConstructorType()) { @@ -4425,46 +4491,46 @@ namespace Parser { } const pos = getNodePos(); const type = parseUnionTypeOrHigher(); - if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(ts.SyntaxKind.ExtendsKeyword)) { + if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) { // The type following 'extends' is not permitted to be another conditional type const extendsType = disallowConditionalTypesAnd(parseType); - parseExpected(ts.SyntaxKind.QuestionToken); + parseExpected(SyntaxKind.QuestionToken); const trueType = allowConditionalTypesAnd(parseType); - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.ColonToken); const falseType = allowConditionalTypesAnd(parseType); return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos); } return type; } - function parseTypeAnnotation(): ts.TypeNode | undefined { - return parseOptional(ts.SyntaxKind.ColonToken) ? parseType() : undefined; + function parseTypeAnnotation(): TypeNode | undefined { + return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined; } // EXPRESSIONS function isStartOfLeftHandSideExpression(): boolean { switch (token()) { - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.SuperKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TemplateHead: - case ts.SyntaxKind.OpenParenToken: - case ts.SyntaxKind.OpenBracketToken: - case ts.SyntaxKind.OpenBraceToken: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.ClassKeyword: - case ts.SyntaxKind.NewKeyword: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.SlashEqualsToken: - case ts.SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateHead: + case SyntaxKind.OpenParenToken: + case SyntaxKind.OpenBracketToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.NewKeyword: + case SyntaxKind.SlashToken: + case SyntaxKind.SlashEqualsToken: + case SyntaxKind.Identifier: return true; - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: return lookAhead(nextTokenIsOpenParenOrLessThanOrDot); default: return isIdentifier(); @@ -4477,19 +4543,19 @@ namespace Parser { } switch (token()) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.TildeToken: - case ts.SyntaxKind.ExclamationToken: - case ts.SyntaxKind.DeleteKeyword: - case ts.SyntaxKind.TypeOfKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.PlusPlusToken: - case ts.SyntaxKind.MinusMinusToken: - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.AwaitKeyword: - case ts.SyntaxKind.YieldKeyword: - case ts.SyntaxKind.PrivateIdentifier: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.DeleteKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.PlusPlusToken: + case SyntaxKind.MinusMinusToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.AwaitKeyword: + case SyntaxKind.YieldKeyword: + case SyntaxKind.PrivateIdentifier: // Yield/await always starts an expression. Either it is an identifier (in which case // it is definitely an expression). Or it's a keyword (either because we're in // a generator or async function, or in strict mode (or both)) and it started a yield or await expression. @@ -4509,14 +4575,14 @@ namespace Parser { function isStartOfExpressionStatement(): boolean { // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement. - return token() !== ts.SyntaxKind.OpenBraceToken && - token() !== ts.SyntaxKind.FunctionKeyword && - token() !== ts.SyntaxKind.ClassKeyword && - token() !== ts.SyntaxKind.AtToken && + return token() !== SyntaxKind.OpenBraceToken && + token() !== SyntaxKind.FunctionKeyword && + token() !== SyntaxKind.ClassKeyword && + token() !== SyntaxKind.AtToken && isStartOfExpression(); } - function parseExpression(): ts.Expression { + function parseExpression(): Expression { // Expression[in]: // AssignmentExpression[in] // Expression[in] , AssignmentExpression[in] @@ -4529,8 +4595,8 @@ namespace Parser { const pos = getNodePos(); let expr = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); - let operatorToken: ts.BinaryOperatorToken; - while ((operatorToken = parseOptionalToken(ts.SyntaxKind.CommaToken))) { + let operatorToken: BinaryOperatorToken; + while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true), pos); } @@ -4540,11 +4606,11 @@ namespace Parser { return expr; } - function parseInitializer(): ts.Expression | undefined { - return parseOptional(ts.SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined; + function parseInitializer(): Expression | undefined { + return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined; } - function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): ts.Expression { + function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): Expression { // AssignmentExpression[in,yield]: // 1) ConditionalExpression[?in,?yield] // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] @@ -4587,13 +4653,13 @@ namespace Parser { // binary expression here, so we pass in the 'lowest' precedence here so that it matches // and consumes anything. const pos = getNodePos(); - const expr = parseBinaryExpressionOrHigher(ts.OperatorPrecedence.Lowest); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. - if (expr.kind === ts.SyntaxKind.Identifier && token() === ts.SyntaxKind.EqualsGreaterThanToken) { - return parseSimpleArrowFunctionExpression(pos, expr as ts.Identifier, allowReturnTypeInArrowFunction, /*asyncModifier*/ undefined); + if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { + return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, /*asyncModifier*/ undefined); } // Now see if we might be in cases '2' or '3'. @@ -4602,7 +4668,7 @@ namespace Parser { // // Note: we call reScanGreaterToken so that we get an appropriately merged token // for cases like `> > =` becoming `>>=` - if (ts.isLeftHandSideExpression(expr) && ts.isAssignmentOperator(reScanGreaterToken())) { + if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos); } @@ -4611,7 +4677,7 @@ namespace Parser { } function isYieldExpression(): boolean { - if (token() === ts.SyntaxKind.YieldKeyword) { + if (token() === SyntaxKind.YieldKeyword) { // If we have a 'yield' keyword, and this is a context where yield expressions are // allowed, then definitely parse out a yield expression. if (inYieldContext()) { @@ -4643,7 +4709,7 @@ namespace Parser { return !scanner.hasPrecedingLineBreak() && isIdentifier(); } - function parseYieldExpression(): ts.YieldExpression { + function parseYieldExpression(): YieldExpression { const pos = getNodePos(); // YieldExpression[In] : @@ -4653,10 +4719,10 @@ namespace Parser { nextToken(); if (!scanner.hasPrecedingLineBreak() && - (token() === ts.SyntaxKind.AsteriskToken || isStartOfExpression())) { + (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) { return finishNode( factory.createYieldExpression( - parseOptionalToken(ts.SyntaxKind.AsteriskToken), + parseOptionalToken(SyntaxKind.AsteriskToken), parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) ), pos @@ -4669,8 +4735,8 @@ namespace Parser { } } - function parseSimpleArrowFunctionExpression(pos: number, identifier: ts.Identifier, allowReturnTypeInArrowFunction: boolean, asyncModifier?: ts.NodeArray | undefined): ts.ArrowFunction { - ts.Debug.assert(token() === ts.SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); + function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, allowReturnTypeInArrowFunction: boolean, asyncModifier?: NodeArray | undefined): ArrowFunction { + Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); const parameter = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, @@ -4681,14 +4747,14 @@ namespace Parser { ); finishNode(parameter, identifier.pos); - const parameters = createNodeArray([parameter], parameter.pos, parameter.end); - const equalsGreaterThanToken = parseExpectedToken(ts.SyntaxKind.EqualsGreaterThanToken); + const parameters = createNodeArray([parameter], parameter.pos, parameter.end); + const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier, allowReturnTypeInArrowFunction); const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body); return addJSDocComment(finishNode(node, pos)); } - function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ts.Expression | undefined { + function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): Expression | undefined { const triState = isParenthesizedArrowFunctionExpression(); if (triState === Tristate.False) { // It's definitely not a parenthesized arrow function expression. @@ -4709,11 +4775,11 @@ namespace Parser { // Unknown -> There *might* be a parenthesized arrow function here. // Speculatively look ahead to be sure, and rollback if not. function isParenthesizedArrowFunctionExpression(): Tristate { - if (token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken || token() === ts.SyntaxKind.AsyncKeyword) { + if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) { return lookAhead(isParenthesizedArrowFunctionExpressionWorker); } - if (token() === ts.SyntaxKind.EqualsGreaterThanToken) { + if (token() === SyntaxKind.EqualsGreaterThanToken) { // ERROR RECOVERY TWEAK: // If we see a standalone => try to parse it as an arrow function expression as that's // likely what the user intended to write. @@ -4724,12 +4790,12 @@ namespace Parser { } function isParenthesizedArrowFunctionExpressionWorker() { - if (token() === ts.SyntaxKind.AsyncKeyword) { + if (token() === SyntaxKind.AsyncKeyword) { nextToken(); if (scanner.hasPrecedingLineBreak()) { return Tristate.False; } - if (token() !== ts.SyntaxKind.OpenParenToken && token() !== ts.SyntaxKind.LessThanToken) { + if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.LessThanToken) { return Tristate.False; } } @@ -4737,17 +4803,17 @@ namespace Parser { const first = token(); const second = nextToken(); - if (first === ts.SyntaxKind.OpenParenToken) { - if (second === ts.SyntaxKind.CloseParenToken) { + if (first === SyntaxKind.OpenParenToken) { + if (second === SyntaxKind.CloseParenToken) { // Simple cases: "() =>", "(): ", and "() {". // This is an arrow function with no parameters. // The last one is not actually an arrow function, // but this is probably what the user intended. const third = nextToken(); switch (third) { - case ts.SyntaxKind.EqualsGreaterThanToken: - case ts.SyntaxKind.ColonToken: - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.ColonToken: + case SyntaxKind.OpenBraceToken: return Tristate.True; default: return Tristate.False; @@ -4760,21 +4826,21 @@ namespace Parser { // ({ x }) => { } // ([ x ]) // ({ x }) - if (second === ts.SyntaxKind.OpenBracketToken || second === ts.SyntaxKind.OpenBraceToken) { + if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) { return Tristate.Unknown; } // Simple case: "(..." // This is an arrow function with a rest parameter. - if (second === ts.SyntaxKind.DotDotDotToken) { + if (second === SyntaxKind.DotDotDotToken) { return Tristate.True; } // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This // isn't actually allowed, but we want to treat it as a lambda so we can provide // a good error message. - if (ts.isModifierKind(second) && second !== ts.SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) { - if (nextToken() === ts.SyntaxKind.AsKeyword) { + if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) { + if (nextToken() === SyntaxKind.AsKeyword) { // https://github.com/microsoft/TypeScript/issues/44466 return Tristate.False; } @@ -4784,26 +4850,26 @@ namespace Parser { // If we had "(" followed by something that's not an identifier, // then this definitely doesn't look like a lambda. "this" is not // valid, but we want to parse it and then give a semantic error. - if (!isIdentifier() && second !== ts.SyntaxKind.ThisKeyword) { + if (!isIdentifier() && second !== SyntaxKind.ThisKeyword) { return Tristate.False; } switch (nextToken()) { - case ts.SyntaxKind.ColonToken: + case SyntaxKind.ColonToken: // If we have something like "(a:", then we must have a // type-annotated parameter in an arrow function expression. return Tristate.True; - case ts.SyntaxKind.QuestionToken: + case SyntaxKind.QuestionToken: nextToken(); // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda. - if (token() === ts.SyntaxKind.ColonToken || token() === ts.SyntaxKind.CommaToken || token() === ts.SyntaxKind.EqualsToken || token() === ts.SyntaxKind.CloseParenToken) { + if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) { return Tristate.True; } // Otherwise it is definitely not a lambda. return Tristate.False; - case ts.SyntaxKind.CommaToken: - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.CloseParenToken: + case SyntaxKind.CommaToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.CloseParenToken: // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function return Tristate.Unknown; } @@ -4811,7 +4877,7 @@ namespace Parser { return Tristate.False; } else { - ts.Debug.assert(first === ts.SyntaxKind.LessThanToken); + Debug.assert(first === SyntaxKind.LessThanToken); // If we have "<" not followed by an identifier, // then this definitely is not an arrow function. @@ -4820,20 +4886,20 @@ namespace Parser { } // JSX overrides - if (languageVariant === ts.LanguageVariant.JSX) { + if (languageVariant === LanguageVariant.JSX) { const isArrowFunctionInJsx = lookAhead(() => { const third = nextToken(); - if (third === ts.SyntaxKind.ExtendsKeyword) { + if (third === SyntaxKind.ExtendsKeyword) { const fourth = nextToken(); switch (fourth) { - case ts.SyntaxKind.EqualsToken: - case ts.SyntaxKind.GreaterThanToken: + case SyntaxKind.EqualsToken: + case SyntaxKind.GreaterThanToken: return false; default: return true; } } - else if (third === ts.SyntaxKind.CommaToken || third === ts.SyntaxKind.EqualsToken) { + else if (third === SyntaxKind.CommaToken || third === SyntaxKind.EqualsToken) { return true; } return false; @@ -4851,7 +4917,7 @@ namespace Parser { } } - function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ts.ArrowFunction | undefined { + function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { const tokenPos = scanner.getTokenPos(); if (notParenthesizedArrow?.has(tokenPos)) { return undefined; @@ -4859,20 +4925,20 @@ namespace Parser { const result = parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ false, allowReturnTypeInArrowFunction); if (!result) { - (notParenthesizedArrow || (notParenthesizedArrow = new ts.Set())).add(tokenPos); + (notParenthesizedArrow || (notParenthesizedArrow = new Set())).add(tokenPos); } return result; } - function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ts.ArrowFunction | undefined { + function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { // We do a check here so that we won't be doing unnecessarily call to "lookAhead" - if (token() === ts.SyntaxKind.AsyncKeyword) { + if (token() === SyntaxKind.AsyncKeyword) { if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) { const pos = getNodePos(); const asyncModifier = parseModifiersForArrowFunction(); - const expr = parseBinaryExpressionOrHigher(ts.OperatorPrecedence.Lowest); - return parseSimpleArrowFunctionExpression(pos, expr as ts.Identifier, allowReturnTypeInArrowFunction, asyncModifier); + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); + return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, asyncModifier); } } return undefined; @@ -4882,16 +4948,16 @@ namespace Parser { // AsyncArrowFunctionExpression: // 1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In] // 2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In] - if (token() === ts.SyntaxKind.AsyncKeyword) { + if (token() === SyntaxKind.AsyncKeyword) { nextToken(); // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher" - if (scanner.hasPrecedingLineBreak() || token() === ts.SyntaxKind.EqualsGreaterThanToken) { + if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) { return Tristate.False; } // Check for un-parenthesized AsyncArrowFunction - const expr = parseBinaryExpressionOrHigher(ts.OperatorPrecedence.Lowest); - if (!scanner.hasPrecedingLineBreak() && expr.kind === ts.SyntaxKind.Identifier && token() === ts.SyntaxKind.EqualsGreaterThanToken) { + const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); + if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { return Tristate.True; } } @@ -4899,11 +4965,11 @@ namespace Parser { return Tristate.False; } - function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): ts.ArrowFunction | undefined { + function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForArrowFunction(); - const isAsync = ts.some(modifiers, ts.isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -4913,12 +4979,12 @@ namespace Parser { // close paren. const typeParameters = parseTypeParameters(); - let parameters: ts.NodeArray; - if (!parseExpected(ts.SyntaxKind.OpenParenToken)) { + let parameters: NodeArray; + if (!parseExpected(SyntaxKind.OpenParenToken)) { if (!allowAmbiguity) { return undefined; } - parameters = createMissingList(); + parameters = createMissingList(); } else { if (!allowAmbiguity) { @@ -4931,13 +4997,13 @@ namespace Parser { else { parameters = parseParametersWorker(isAsync, allowAmbiguity); } - if (!parseExpected(ts.SyntaxKind.CloseParenToken) && !allowAmbiguity) { + if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) { return undefined; } } - const hasReturnColon = token() === ts.SyntaxKind.ColonToken; - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const hasReturnColon = token() === SyntaxKind.ColonToken; + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) { return undefined; } @@ -4954,12 +5020,12 @@ namespace Parser { // So we need just a bit of lookahead to ensure that it can only be a signature. let unwrappedType = type; - while (unwrappedType?.kind === ts.SyntaxKind.ParenthesizedType) { - unwrappedType = (unwrappedType as ts.ParenthesizedTypeNode).type; // Skip parens if need be + while (unwrappedType?.kind === SyntaxKind.ParenthesizedType) { + unwrappedType = (unwrappedType as ParenthesizedTypeNode).type; // Skip parens if need be } - const hasJSDocFunctionType = unwrappedType && ts.isJSDocFunctionType(unwrappedType); - if (!allowAmbiguity && token() !== ts.SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== ts.SyntaxKind.OpenBraceToken)) { + const hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType); + if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) { // Returning undefined here will cause our caller to rewind to where we started from. return undefined; } @@ -4967,9 +5033,9 @@ namespace Parser { // If we have an arrow, then try to parse the body. Even if not, try to parse if we // have an opening brace, just in case we're in an error state. const lastToken = token(); - const equalsGreaterThanToken = parseExpectedToken(ts.SyntaxKind.EqualsGreaterThanToken); - const body = (lastToken === ts.SyntaxKind.EqualsGreaterThanToken || lastToken === ts.SyntaxKind.OpenBraceToken) - ? parseArrowFunctionExpressionBody(ts.some(modifiers, ts.isAsyncModifier), allowReturnTypeInArrowFunction) + const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); + const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) + ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier), allowReturnTypeInArrowFunction) : parseIdentifier(); // Given: @@ -4993,7 +5059,7 @@ namespace Parser { // Then allow the arrow function, and treat the second colon as terminating // the conditional expression. It's okay to do this because this code would // be a syntax error in JavaScript (as the second colon shouldn't be there). - if (token() !== ts.SyntaxKind.ColonToken) { + if (token() !== SyntaxKind.ColonToken) { return undefined; } } @@ -5002,14 +5068,14 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): ts.Block | ts.Expression { - if (token() === ts.SyntaxKind.OpenBraceToken) { + function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): Block | Expression { + if (token() === SyntaxKind.OpenBraceToken) { return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None); } - if (token() !== ts.SyntaxKind.SemicolonToken && - token() !== ts.SyntaxKind.FunctionKeyword && - token() !== ts.SyntaxKind.ClassKeyword && + if (token() !== SyntaxKind.SemicolonToken && + token() !== SyntaxKind.FunctionKeyword && + token() !== SyntaxKind.ClassKeyword && isStartOfStatement() && !isStartOfExpressionStatement()) { // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations) @@ -5038,9 +5104,9 @@ namespace Parser { return node; } - function parseConditionalExpressionRest(leftOperand: ts.Expression, pos: number, allowReturnTypeInArrowFunction: boolean): ts.Expression { + function parseConditionalExpressionRest(leftOperand: Expression, pos: number, allowReturnTypeInArrowFunction: boolean): Expression { // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. - const questionToken = parseOptionalToken(ts.SyntaxKind.QuestionToken); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (!questionToken) { return leftOperand; } @@ -5053,32 +5119,32 @@ namespace Parser { leftOperand, questionToken, doOutsideOfContext(disallowInAndDecoratorContext, () => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ false)), - colonToken = parseExpectedToken(ts.SyntaxKind.ColonToken), - ts.nodeIsPresent(colonToken) + colonToken = parseExpectedToken(SyntaxKind.ColonToken), + nodeIsPresent(colonToken) ? parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction) - : createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, ts.Diagnostics._0_expected, ts.tokenToString(ts.SyntaxKind.ColonToken)) + : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)) ), pos ); } - function parseBinaryExpressionOrHigher(precedence: ts.OperatorPrecedence): ts.Expression { + function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): Expression { const pos = getNodePos(); const leftOperand = parseUnaryExpressionOrHigher(); return parseBinaryExpressionRest(precedence, leftOperand, pos); } - function isInOrOfKeyword(t: ts.SyntaxKind) { - return t === ts.SyntaxKind.InKeyword || t === ts.SyntaxKind.OfKeyword; + function isInOrOfKeyword(t: SyntaxKind) { + return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword; } - function parseBinaryExpressionRest(precedence: ts.OperatorPrecedence, leftOperand: ts.Expression, pos: number): ts.Expression { + function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression, pos: number): Expression { while (true) { // We either have a binary operator here, or we're finished. We call // reScanGreaterToken so that we merge token sequences like > and = into >= reScanGreaterToken(); - const newPrecedence = ts.getBinaryOperatorPrecedence(token()); + const newPrecedence = getBinaryOperatorPrecedence(token()); // Check the precedence to see if we should "take" this operator // - For left associative operator (all operator but **), consume the operator, @@ -5101,7 +5167,7 @@ namespace Parser { // ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand // a ** b - c // ^token; leftOperand = b. Return b to the caller as a rightOperand - const consumeCurrentOperator = token() === ts.SyntaxKind.AsteriskAsteriskToken ? + const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ? newPrecedence >= precedence : newPrecedence > precedence; @@ -5109,11 +5175,11 @@ namespace Parser { break; } - if (token() === ts.SyntaxKind.InKeyword && inDisallowInContext()) { + if (token() === SyntaxKind.InKeyword && inDisallowInContext()) { break; } - if (token() === ts.SyntaxKind.AsKeyword || token() === ts.SyntaxKind.SatisfiesKeyword) { + if (token() === SyntaxKind.AsKeyword || token() === SyntaxKind.SatisfiesKeyword) { // Make sure we *do* perform ASI for constructs like this: // var x = foo // as (Bar) @@ -5125,7 +5191,7 @@ namespace Parser { else { const keywordKind = token(); nextToken(); - leftOperand = keywordKind === ts.SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) : + leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) : makeAsExpression(leftOperand, parseType()); } } @@ -5138,28 +5204,28 @@ namespace Parser { } function isBinaryOperator() { - if (inDisallowInContext() && token() === ts.SyntaxKind.InKeyword) { + if (inDisallowInContext() && token() === SyntaxKind.InKeyword) { return false; } - return ts.getBinaryOperatorPrecedence(token()) > 0; + return getBinaryOperatorPrecedence(token()) > 0; } - function makeSatisfiesExpression(left: ts.Expression, right: ts.TypeNode): ts.SatisfiesExpression { + function makeSatisfiesExpression(left: Expression, right: TypeNode): SatisfiesExpression { return finishNode(factory.createSatisfiesExpression(left, right), left.pos); } - function makeBinaryExpression(left: ts.Expression, operatorToken: ts.BinaryOperatorToken, right: ts.Expression, pos: number): ts.BinaryExpression { + function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression { return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos); } - function makeAsExpression(left: ts.Expression, right: ts.TypeNode): ts.AsExpression { + function makeAsExpression(left: Expression, right: TypeNode): AsExpression { return finishNode(factory.createAsExpression(left, right), left.pos); } function parsePrefixUnaryExpression() { const pos = getNodePos(); - return finishNode(factory.createPrefixUnaryExpression(token() as ts.PrefixUnaryOperator, nextTokenAnd(parseSimpleUnaryExpression)), pos); + return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseSimpleUnaryExpression)), pos); } function parseDeleteExpression() { @@ -5178,7 +5244,7 @@ namespace Parser { } function isAwaitExpression(): boolean { - if (token() === ts.SyntaxKind.AwaitKeyword) { + if (token() === SyntaxKind.AwaitKeyword) { if (inAwaitContext()) { return true; } @@ -5203,7 +5269,7 @@ namespace Parser { * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] * */ - function parseUnaryExpressionOrHigher(): ts.UnaryExpression | ts.BinaryExpression { + function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression { /** * ES7 UpdateExpression: * 1) LeftHandSideExpression[?Yield] @@ -5215,8 +5281,8 @@ namespace Parser { if (isUpdateExpression()) { const pos = getNodePos(); const updateExpression = parseUpdateExpression(); - return token() === ts.SyntaxKind.AsteriskAsteriskToken ? - parseBinaryExpressionRest(ts.getBinaryOperatorPrecedence(token()), updateExpression, pos) as ts.BinaryExpression : + return token() === SyntaxKind.AsteriskAsteriskToken ? + parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression : updateExpression; } @@ -5233,14 +5299,14 @@ namespace Parser { */ const unaryOperator = token(); const simpleUnaryExpression = parseSimpleUnaryExpression(); - if (token() === ts.SyntaxKind.AsteriskAsteriskToken) { - const pos = ts.skipTrivia(sourceText, simpleUnaryExpression.pos); + if (token() === SyntaxKind.AsteriskAsteriskToken) { + const pos = skipTrivia(sourceText, simpleUnaryExpression.pos); const { end } = simpleUnaryExpression; - if (simpleUnaryExpression.kind === ts.SyntaxKind.TypeAssertionExpression) { - parseErrorAt(pos, end, ts.Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); + if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) { + parseErrorAt(pos, end, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses); } else { - parseErrorAt(pos, end, ts.Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, ts.tokenToString(unaryOperator)); + parseErrorAt(pos, end, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator)); } } return simpleUnaryExpression; @@ -5260,25 +5326,25 @@ namespace Parser { * 8) ! UnaryExpression[?yield] * 9) [+Await] await UnaryExpression[?yield] */ - function parseSimpleUnaryExpression(): ts.UnaryExpression { + function parseSimpleUnaryExpression(): UnaryExpression { switch (token()) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.TildeToken: - case ts.SyntaxKind.ExclamationToken: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: return parsePrefixUnaryExpression(); - case ts.SyntaxKind.DeleteKeyword: + case SyntaxKind.DeleteKeyword: return parseDeleteExpression(); - case ts.SyntaxKind.TypeOfKeyword: + case SyntaxKind.TypeOfKeyword: return parseTypeOfExpression(); - case ts.SyntaxKind.VoidKeyword: + case SyntaxKind.VoidKeyword: return parseVoidExpression(); - case ts.SyntaxKind.LessThanToken: + case SyntaxKind.LessThanToken: // This is modified UnaryExpression grammar in TypeScript // UnaryExpression (modified): // < type > UnaryExpression return parseTypeAssertion(); - case ts.SyntaxKind.AwaitKeyword: + case SyntaxKind.AwaitKeyword: if (isAwaitExpression()) { return parseAwaitExpression(); } @@ -5302,18 +5368,18 @@ namespace Parser { // This function is called inside parseUnaryExpression to decide // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly switch (token()) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.TildeToken: - case ts.SyntaxKind.ExclamationToken: - case ts.SyntaxKind.DeleteKeyword: - case ts.SyntaxKind.TypeOfKeyword: - case ts.SyntaxKind.VoidKeyword: - case ts.SyntaxKind.AwaitKeyword: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: + case SyntaxKind.TildeToken: + case SyntaxKind.ExclamationToken: + case SyntaxKind.DeleteKeyword: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.VoidKeyword: + case SyntaxKind.AwaitKeyword: return false; - case ts.SyntaxKind.LessThanToken: + case SyntaxKind.LessThanToken: // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression - if (languageVariant !== ts.LanguageVariant.JSX) { + if (languageVariant !== LanguageVariant.JSX) { return false; } // We are in JSX context and the token is part of JSXElement. @@ -5334,21 +5400,21 @@ namespace Parser { * 5) --LeftHandSideExpression[?yield] * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression */ - function parseUpdateExpression(): ts.UpdateExpression { - if (token() === ts.SyntaxKind.PlusPlusToken || token() === ts.SyntaxKind.MinusMinusToken) { + function parseUpdateExpression(): UpdateExpression { + if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) { const pos = getNodePos(); - return finishNode(factory.createPrefixUnaryExpression(token() as ts.PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); + return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); } - else if (languageVariant === ts.LanguageVariant.JSX && token() === ts.SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { + else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) { // JSXElement is part of primaryExpression return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } const expression = parseLeftHandSideExpressionOrHigher(); - ts.Debug.assert(ts.isLeftHandSideExpression(expression)); - if ((token() === ts.SyntaxKind.PlusPlusToken || token() === ts.SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { - const operator = token() as ts.PostfixUnaryOperator; + Debug.assert(isLeftHandSideExpression(expression)); + if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { + const operator = token() as PostfixUnaryOperator; nextToken(); return finishNode(factory.createPostfixUnaryExpression(expression, operator), expression.pos); } @@ -5356,7 +5422,7 @@ namespace Parser { return expression; } - function parseLeftHandSideExpressionOrHigher(): ts.LeftHandSideExpression { + function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression { // Original Ecma: // LeftHandSideExpression: See 11.2 // NewExpression @@ -5389,30 +5455,30 @@ namespace Parser { // 3)we have a MemberExpression which either completes the LeftHandSideExpression, // or starts the beginning of the first four CallExpression productions. const pos = getNodePos(); - let expression: ts.MemberExpression; - if (token() === ts.SyntaxKind.ImportKeyword) { + let expression: MemberExpression; + if (token() === SyntaxKind.ImportKeyword) { if (lookAhead(nextTokenIsOpenParenOrLessThan)) { // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" // For example: // var foo3 = require("subfolder // import * as foo1 from "module-from-node // We want this import to be a statement rather than import call expression - sourceFlags |= ts.NodeFlags.PossiblyContainsDynamicImport; - expression = parseTokenNode(); + sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; + expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { // This is an 'import.*' metaproperty (i.e. 'import.meta') nextToken(); // advance past the 'import' nextToken(); // advance past the dot - expression = finishNode(factory.createMetaProperty(ts.SyntaxKind.ImportKeyword, parseIdentifierName()), pos); - sourceFlags |= ts.NodeFlags.PossiblyContainsImportMeta; + expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos); + sourceFlags |= NodeFlags.PossiblyContainsImportMeta; } else { expression = parseMemberExpressionOrHigher(); } } else { - expression = token() === ts.SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); + expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher(); } // Now, we *may* be complete. However, we might have consumed the start of a @@ -5421,7 +5487,7 @@ namespace Parser { return parseCallExpressionRest(pos, expression); } - function parseMemberExpressionOrHigher(): ts.MemberExpression { + function parseMemberExpressionOrHigher(): MemberExpression { // Note: to make our lives simpler, we decompose the NewExpression productions and // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. // like so: @@ -5474,41 +5540,41 @@ namespace Parser { return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); } - function parseSuperExpression(): ts.MemberExpression { + function parseSuperExpression(): MemberExpression { const pos = getNodePos(); - let expression = parseTokenNode(); - if (token() === ts.SyntaxKind.LessThanToken) { + let expression = parseTokenNode(); + if (token() === SyntaxKind.LessThanToken) { const startPos = getNodePos(); const typeArguments = tryParse(parseTypeArgumentsInExpression); if (typeArguments !== undefined) { - parseErrorAt(startPos, getNodePos(), ts.Diagnostics.super_may_not_use_type_arguments); + parseErrorAt(startPos, getNodePos(), Diagnostics.super_may_not_use_type_arguments); if (!isTemplateStartOfTaggedTemplate()) { expression = factory.createExpressionWithTypeArguments(expression, typeArguments); } } } - if (token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.DotToken || token() === ts.SyntaxKind.OpenBracketToken) { + if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) { return expression; } // If we have seen "super" it must be followed by '(' or '.'. // If it wasn't then just try to parse out a '.' and report an error. - parseExpectedToken(ts.SyntaxKind.DotToken, ts.Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); + parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access); // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic return finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true)), pos); } - function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: ts.JsxOpeningElement | ts.JsxOpeningFragment): ts.JsxElement | ts.JsxSelfClosingElement | ts.JsxFragment { + function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: JsxOpeningElement | JsxOpeningFragment): JsxElement | JsxSelfClosingElement | JsxFragment { const pos = getNodePos(); const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); - let result: ts.JsxElement | ts.JsxSelfClosingElement | ts.JsxFragment; - if (opening.kind === ts.SyntaxKind.JsxOpeningElement) { + let result: JsxElement | JsxSelfClosingElement | JsxFragment; + if (opening.kind === SyntaxKind.JsxOpeningElement) { let children = parseJsxChildren(opening); - let closingElement: ts.JsxClosingElement; + let closingElement: JsxClosingElement; - const lastChild: ts.JsxChild | undefined = children[children.length - 1]; - if (lastChild?.kind === ts.SyntaxKind.JsxElement + const lastChild: JsxChild | undefined = children[children.length - 1]; + if (lastChild?.kind === SyntaxKind.JsxElement && !tagNamesAreEquivalent(lastChild.openingElement.tagName, lastChild.closingElement.tagName) && tagNamesAreEquivalent(opening.tagName, lastChild.closingElement.tagName)) { // when an unclosed JsxOpeningElement incorrectly parses its parent's JsxClosingElement, @@ -5528,23 +5594,23 @@ namespace Parser { else { closingElement = parseJsxClosingElement(opening, inExpressionContext); if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) { - if (openingTag && ts.isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) { + if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) { // opening incorrectly matched with its parent's closing -- put error on opening - parseErrorAtRange(opening.tagName, ts.Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, ts.getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange(opening.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName)); } else { // other opening/closing mismatches -- put error on closing - parseErrorAtRange(closingElement.tagName, ts.Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, ts.getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange(closingElement.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName)); } } } result = finishNode(factory.createJsxElement(opening, children, closingElement), pos); } - else if (opening.kind === ts.SyntaxKind.JsxOpeningFragment) { + else if (opening.kind === SyntaxKind.JsxOpeningFragment) { result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos); } else { - ts.Debug.assert(opening.kind === ts.SyntaxKind.JsxSelfClosingElement); + Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement); // Nothing else to do for self-closing elements result = opening; } @@ -5556,59 +5622,59 @@ namespace Parser { // does less damage and we can report a better error. // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios // of one sort or another. - if (inExpressionContext && token() === ts.SyntaxKind.LessThanToken) { + if (inExpressionContext && token() === SyntaxKind.LessThanToken) { const topBadPos = typeof topInvalidNodePosition === "undefined" ? result.pos : topInvalidNodePosition; const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos)); if (invalidElement) { - const operatorToken = createMissingNode(ts.SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); - ts.setTextRangePosWidth(operatorToken, invalidElement.pos, 0); - parseErrorAt(ts.skipTrivia(sourceText, topBadPos), invalidElement.end, ts.Diagnostics.JSX_expressions_must_have_one_parent_element); - return finishNode(factory.createBinaryExpression(result, operatorToken as ts.Token, invalidElement), pos) as ts.Node as ts.JsxElement; + const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); + setTextRangePosWidth(operatorToken, invalidElement.pos, 0); + parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element); + return finishNode(factory.createBinaryExpression(result, operatorToken as Token, invalidElement), pos) as Node as JsxElement; } } return result; } - function parseJsxText(): ts.JsxText { + function parseJsxText(): JsxText { const pos = getNodePos(); - const node = factory.createJsxText(scanner.getTokenValue(), currentToken === ts.SyntaxKind.JsxTextAllWhiteSpaces); + const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces); currentToken = scanner.scanJsxToken(); return finishNode(node, pos); } - function parseJsxChild(openingTag: ts.JsxOpeningElement | ts.JsxOpeningFragment, token: ts.JsxTokenSyntaxKind): ts.JsxChild | undefined { + function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { switch (token) { - case ts.SyntaxKind.EndOfFileToken: + case SyntaxKind.EndOfFileToken: // If we hit EOF, issue the error at the tag that lacks the closing element // rather than at the end of the file (which is useless) - if (ts.isJsxOpeningFragment(openingTag)) { - parseErrorAtRange(openingTag, ts.Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); + if (isJsxOpeningFragment(openingTag)) { + parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); } else { // We want the error span to cover only 'Foo.Bar' in < Foo.Bar > // or to cover only 'Foo' in < Foo > const tag = openingTag.tagName; - const start = ts.skipTrivia(sourceText, tag.pos); - parseErrorAt(start, tag.end, ts.Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, ts.getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); + const start = skipTrivia(sourceText, tag.pos); + parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName)); } return undefined; - case ts.SyntaxKind.LessThanSlashToken: - case ts.SyntaxKind.ConflictMarkerTrivia: + case SyntaxKind.LessThanSlashToken: + case SyntaxKind.ConflictMarkerTrivia: return undefined; - case ts.SyntaxKind.JsxText: - case ts.SyntaxKind.JsxTextAllWhiteSpaces: + case SyntaxKind.JsxText: + case SyntaxKind.JsxTextAllWhiteSpaces: return parseJsxText(); - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: return parseJsxExpression(/*inExpressionContext*/ false); - case ts.SyntaxKind.LessThanToken: + case SyntaxKind.LessThanToken: return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false, /*topInvalidNodePosition*/ undefined, openingTag); default: - return ts.Debug.assertNever(token); + return Debug.assertNever(token); } } - function parseJsxChildren(openingTag: ts.JsxOpeningElement | ts.JsxOpeningFragment): ts.NodeArray { + function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { const list = []; const listPos = getNodePos(); const saveParsingContext = parsingContext; @@ -5618,8 +5684,8 @@ namespace Parser { const child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken()); if (!child) break; list.push(child); - if (ts.isJsxOpeningElement(openingTag) - && child?.kind === ts.SyntaxKind.JsxElement + if (isJsxOpeningElement(openingTag) + && child?.kind === SyntaxKind.JsxElement && !tagNamesAreEquivalent(child.openingElement.tagName, child.closingElement.tagName) && tagNamesAreEquivalent(openingTag.tagName, child.closingElement.tagName)) { // stop after parsing a mismatched child like
...(
) in order to reattach the
higher @@ -5631,28 +5697,28 @@ namespace Parser { return createNodeArray(list, listPos); } - function parseJsxAttributes(): ts.JsxAttributes { + function parseJsxAttributes(): JsxAttributes { const pos = getNodePos(); return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos); } - function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): ts.JsxOpeningElement | ts.JsxSelfClosingElement | ts.JsxOpeningFragment { + function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.LessThanToken); + parseExpected(SyntaxKind.LessThanToken); - if (token() === ts.SyntaxKind.GreaterThanToken) { + if (token() === SyntaxKind.GreaterThanToken) { // See below for explanation of scanJsxText scanJsxText(); return finishNode(factory.createJsxOpeningFragment(), pos); } const tagName = parseJsxElementName(); - const typeArguments = (contextFlags & ts.NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined; + const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined; const attributes = parseJsxAttributes(); - let node: ts.JsxOpeningLikeElement; + let node: JsxOpeningLikeElement; - if (token() === ts.SyntaxKind.GreaterThanToken) { + if (token() === SyntaxKind.GreaterThanToken) { // Closing tag, so scan the immediately-following text with the JSX scanning instead // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate // scanning errors @@ -5660,8 +5726,8 @@ namespace Parser { node = factory.createJsxOpeningElement(tagName, typeArguments, attributes); } else { - parseExpected(ts.SyntaxKind.SlashToken); - if (parseExpected(ts.SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { + parseExpected(SyntaxKind.SlashToken); + if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { // manually advance the scanner in order to look for jsx text inside jsx if (inExpressionContext) { nextToken(); @@ -5676,7 +5742,7 @@ namespace Parser { return finishNode(node, pos); } - function parseJsxElementName(): ts.JsxTagNameExpression { + function parseJsxElementName(): JsxTagNameExpression { const pos = getNodePos(); scanJsxIdentifier(); // JsxElement can have name in the form of @@ -5684,34 +5750,34 @@ namespace Parser { // primaryExpression in the form of an identifier and "this" keyword // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword // We only want to consider "this" as a primaryExpression - let expression: ts.JsxTagNameExpression = token() === ts.SyntaxKind.ThisKeyword ? - parseTokenNode() : parseIdentifierName(); - while (parseOptional(ts.SyntaxKind.DotToken)) { - expression = finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as ts.JsxTagNamePropertyAccess; + let expression: JsxTagNameExpression = token() === SyntaxKind.ThisKeyword ? + parseTokenNode() : parseIdentifierName(); + while (parseOptional(SyntaxKind.DotToken)) { + expression = finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess; } return expression; } - function parseJsxExpression(inExpressionContext: boolean): ts.JsxExpression | undefined { + function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined { const pos = getNodePos(); - if (!parseExpected(ts.SyntaxKind.OpenBraceToken)) { + if (!parseExpected(SyntaxKind.OpenBraceToken)) { return undefined; } - let dotDotDotToken: ts.DotDotDotToken | undefined; - let expression: ts.Expression | undefined; - if (token() !== ts.SyntaxKind.CloseBraceToken) { - dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + let dotDotDotToken: DotDotDotToken | undefined; + let expression: Expression | undefined; + if (token() !== SyntaxKind.CloseBraceToken) { + dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); // Only an AssignmentExpression is valid here per the JSX spec, // but we can unambiguously parse a comma sequence and provide // a better error message in grammar checking. expression = parseExpression(); } if (inExpressionContext) { - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } else { - if (parseExpected(ts.SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false)) { + if (parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false)) { scanJsxText(); } } @@ -5719,8 +5785,8 @@ namespace Parser { return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos); } - function parseJsxAttribute(): ts.JsxAttribute | ts.JsxSpreadAttribute { - if (token() === ts.SyntaxKind.OpenBraceToken) { + function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute { + if (token() === SyntaxKind.OpenBraceToken) { return parseJsxSpreadAttribute(); } @@ -5729,36 +5795,36 @@ namespace Parser { return finishNode(factory.createJsxAttribute(parseIdentifierName(), parseJsxAttributeValue()), pos); } - function parseJsxAttributeValue(): ts.JsxAttributeValue | undefined { - if (token() === ts.SyntaxKind.EqualsToken) { - if (scanJsxAttributeValue() === ts.SyntaxKind.StringLiteral) { - return parseLiteralNode() as ts.StringLiteral; + function parseJsxAttributeValue(): JsxAttributeValue | undefined { + if (token() === SyntaxKind.EqualsToken) { + if (scanJsxAttributeValue() === SyntaxKind.StringLiteral) { + return parseLiteralNode() as StringLiteral; } - if (token() === ts.SyntaxKind.OpenBraceToken) { + if (token() === SyntaxKind.OpenBraceToken) { return parseJsxExpression(/*inExpressionContext*/ true); } - if (token() === ts.SyntaxKind.LessThanToken) { + if (token() === SyntaxKind.LessThanToken) { return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true); } - parseErrorAtCurrentToken(ts.Diagnostics.or_JSX_element_expected); + parseErrorAtCurrentToken(Diagnostics.or_JSX_element_expected); } return undefined; } - function parseJsxSpreadAttribute(): ts.JsxSpreadAttribute { + function parseJsxSpreadAttribute(): JsxSpreadAttribute { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBraceToken); - parseExpected(ts.SyntaxKind.DotDotDotToken); + parseExpected(SyntaxKind.OpenBraceToken); + parseExpected(SyntaxKind.DotDotDotToken); const expression = parseExpression(); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); return finishNode(factory.createJsxSpreadAttribute(expression), pos); } - function parseJsxClosingElement(open: ts.JsxOpeningElement, inExpressionContext: boolean): ts.JsxClosingElement { + function parseJsxClosingElement(open: JsxOpeningElement, inExpressionContext: boolean): JsxClosingElement { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.LessThanSlashToken); + parseExpected(SyntaxKind.LessThanSlashToken); const tagName = parseJsxElementName(); - if (parseExpected(ts.SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { + if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { // manually advance the scanner in order to look for jsx text inside jsx if (inExpressionContext || !tagNamesAreEquivalent(open.tagName, tagName)) { nextToken(); @@ -5770,13 +5836,13 @@ namespace Parser { return finishNode(factory.createJsxClosingElement(tagName), pos); } - function parseJsxClosingFragment(inExpressionContext: boolean): ts.JsxClosingFragment { + function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.LessThanSlashToken); - if (ts.tokenIsIdentifierOrKeyword(token())) { - parseErrorAtRange(parseJsxElementName(), ts.Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment); + parseExpected(SyntaxKind.LessThanSlashToken); + if (tokenIsIdentifierOrKeyword(token())) { + parseErrorAtRange(parseJsxElementName(), Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment); } - if (parseExpected(ts.SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { + if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) { // manually advance the scanner in order to look for jsx text inside jsx if (inExpressionContext) { nextToken(); @@ -5788,41 +5854,41 @@ namespace Parser { return finishNode(factory.createJsxJsxClosingFragment(), pos); } - function parseTypeAssertion(): ts.TypeAssertion { + function parseTypeAssertion(): TypeAssertion { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.LessThanToken); + parseExpected(SyntaxKind.LessThanToken); const type = parseType(); - parseExpected(ts.SyntaxKind.GreaterThanToken); + parseExpected(SyntaxKind.GreaterThanToken); const expression = parseSimpleUnaryExpression(); return finishNode(factory.createTypeAssertion(type, expression), pos); } function nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate() { nextToken(); - return ts.tokenIsIdentifierOrKeyword(token()) - || token() === ts.SyntaxKind.OpenBracketToken + return tokenIsIdentifierOrKeyword(token()) + || token() === SyntaxKind.OpenBracketToken || isTemplateStartOfTaggedTemplate(); } function isStartOfOptionalPropertyOrElementAccessChain() { - return token() === ts.SyntaxKind.QuestionDotToken + return token() === SyntaxKind.QuestionDotToken && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate); } - function tryReparseOptionalChain(node: ts.Expression) { - if (node.flags & ts.NodeFlags.OptionalChain) { + function tryReparseOptionalChain(node: Expression) { + if (node.flags & NodeFlags.OptionalChain) { return true; } // check for an optional chain in a non-null expression - if (ts.isNonNullExpression(node)) { + if (isNonNullExpression(node)) { let expr = node.expression; - while (ts.isNonNullExpression(expr) && !(expr.flags & ts.NodeFlags.OptionalChain)) { + while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) { expr = expr.expression; } - if (expr.flags & ts.NodeFlags.OptionalChain) { + if (expr.flags & NodeFlags.OptionalChain) { // this is part of an optional chain. Walk down from `node` to `expression` and set the flag. - while (ts.isNonNullExpression(node)) { - (node as ts.Mutable).flags |= ts.NodeFlags.OptionalChain; + while (isNonNullExpression(node)) { + (node as Mutable).flags |= NodeFlags.OptionalChain; node = node.expression; } return true; @@ -5831,37 +5897,37 @@ namespace Parser { return false; } - function parsePropertyAccessExpressionRest(pos: number, expression: ts.LeftHandSideExpression, questionDotToken: ts.QuestionDotToken | undefined) { + function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { const name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true); const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression); const propertyAccess = isOptionalChain ? factory.createPropertyAccessChain(expression, questionDotToken, name) : factory.createPropertyAccessExpression(expression, name); - if (isOptionalChain && ts.isPrivateIdentifier(propertyAccess.name)) { - parseErrorAtRange(propertyAccess.name, ts.Diagnostics.An_optional_chain_cannot_contain_private_identifiers); + if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) { + parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers); } - if (ts.isExpressionWithTypeArguments(expression) && expression.typeArguments) { + if (isExpressionWithTypeArguments(expression) && expression.typeArguments) { const pos = expression.typeArguments.pos - 1; - const end = ts.skipTrivia(sourceText, expression.typeArguments.end) + 1; - parseErrorAt(pos, end, ts.Diagnostics.An_instantiation_expression_cannot_be_followed_by_a_property_access); + const end = skipTrivia(sourceText, expression.typeArguments.end) + 1; + parseErrorAt(pos, end, Diagnostics.An_instantiation_expression_cannot_be_followed_by_a_property_access); } return finishNode(propertyAccess, pos); } - function parseElementAccessExpressionRest(pos: number, expression: ts.LeftHandSideExpression, questionDotToken: ts.QuestionDotToken | undefined) { - let argumentExpression: ts.Expression; - if (token() === ts.SyntaxKind.CloseBracketToken) { - argumentExpression = createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, ts.Diagnostics.An_element_access_expression_should_take_an_argument); + function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { + let argumentExpression: Expression; + if (token() === SyntaxKind.CloseBracketToken) { + argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument); } else { const argument = allowInAnd(parseExpression); - if (ts.isStringOrNumericLiteralLike(argument)) { + if (isStringOrNumericLiteralLike(argument)) { argument.text = internIdentifier(argument.text); } argumentExpression = argument; } - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) ? factory.createElementAccessChain(expression, questionDotToken, argumentExpression) : @@ -5869,16 +5935,16 @@ namespace Parser { return finishNode(indexedAccess, pos); } - function parseMemberExpressionRest(pos: number, expression: ts.LeftHandSideExpression, allowOptionalChain: boolean): ts.MemberExpression { + function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { while (true) { - let questionDotToken: ts.QuestionDotToken | undefined; + let questionDotToken: QuestionDotToken | undefined; let isPropertyAccess = false; if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) { - questionDotToken = parseExpectedToken(ts.SyntaxKind.QuestionDotToken); - isPropertyAccess = ts.tokenIsIdentifierOrKeyword(token()); + questionDotToken = parseExpectedToken(SyntaxKind.QuestionDotToken); + isPropertyAccess = tokenIsIdentifierOrKeyword(token()); } else { - isPropertyAccess = parseOptional(ts.SyntaxKind.DotToken); + isPropertyAccess = parseOptional(SyntaxKind.DotToken); } if (isPropertyAccess) { @@ -5887,21 +5953,21 @@ namespace Parser { } // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName - if ((questionDotToken || !inDecoratorContext()) && parseOptional(ts.SyntaxKind.OpenBracketToken)) { + if ((questionDotToken || !inDecoratorContext()) && parseOptional(SyntaxKind.OpenBracketToken)) { expression = parseElementAccessExpressionRest(pos, expression, questionDotToken); continue; } if (isTemplateStartOfTaggedTemplate()) { // Absorb type arguments into TemplateExpression when preceding expression is ExpressionWithTypeArguments - expression = !questionDotToken && expression.kind === ts.SyntaxKind.ExpressionWithTypeArguments ? - parseTaggedTemplateRest(pos, (expression as ts.ExpressionWithTypeArguments).expression, questionDotToken, (expression as ts.ExpressionWithTypeArguments).typeArguments) : + expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments ? + parseTaggedTemplateRest(pos, (expression as ExpressionWithTypeArguments).expression, questionDotToken, (expression as ExpressionWithTypeArguments).typeArguments) : parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); continue; } if (!questionDotToken) { - if (token() === ts.SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { + if (token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { nextToken(); expression = finishNode(factory.createNonNullExpression(expression), pos); continue; @@ -5913,34 +5979,34 @@ namespace Parser { } } - return expression as ts.MemberExpression; + return expression as MemberExpression; } } function isTemplateStartOfTaggedTemplate() { - return token() === ts.SyntaxKind.NoSubstitutionTemplateLiteral || token() === ts.SyntaxKind.TemplateHead; + return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; } - function parseTaggedTemplateRest(pos: number, tag: ts.LeftHandSideExpression, questionDotToken: ts.QuestionDotToken | undefined, typeArguments: ts.NodeArray | undefined) { + function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined) { const tagExpression = factory.createTaggedTemplateExpression( tag, typeArguments, - token() === ts.SyntaxKind.NoSubstitutionTemplateLiteral ? - (reScanTemplateHeadOrNoSubstitutionTemplate(), parseLiteralNode() as ts.NoSubstitutionTemplateLiteral) : + token() === SyntaxKind.NoSubstitutionTemplateLiteral ? + (reScanTemplateHeadOrNoSubstitutionTemplate(), parseLiteralNode() as NoSubstitutionTemplateLiteral) : parseTemplateExpression(/*isTaggedTemplate*/ true) ); - if (questionDotToken || tag.flags & ts.NodeFlags.OptionalChain) { - (tagExpression as ts.Mutable).flags |= ts.NodeFlags.OptionalChain; + if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { + (tagExpression as Mutable).flags |= NodeFlags.OptionalChain; } tagExpression.questionDotToken = questionDotToken; return finishNode(tagExpression, pos); } - function parseCallExpressionRest(pos: number, expression: ts.LeftHandSideExpression): ts.LeftHandSideExpression { + function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); - let typeArguments: ts.NodeArray | undefined; - const questionDotToken = parseOptionalToken(ts.SyntaxKind.QuestionDotToken); + let typeArguments: NodeArray | undefined; + const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken); if (questionDotToken) { typeArguments = tryParse(parseTypeArgumentsInExpression); if (isTemplateStartOfTaggedTemplate()) { @@ -5948,11 +6014,11 @@ namespace Parser { continue; } } - if (typeArguments || token() === ts.SyntaxKind.OpenParenToken) { + if (typeArguments || token() === SyntaxKind.OpenParenToken) { // Absorb type arguments into CallExpression when preceding expression is ExpressionWithTypeArguments - if (!questionDotToken && expression.kind === ts.SyntaxKind.ExpressionWithTypeArguments) { - typeArguments = (expression as ts.ExpressionWithTypeArguments).typeArguments; - expression = (expression as ts.ExpressionWithTypeArguments).expression; + if (!questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments) { + typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; + expression = (expression as ExpressionWithTypeArguments).expression; } const argumentList = parseArgumentList(); const callExpr = questionDotToken || tryReparseOptionalChain(expression) ? @@ -5963,7 +6029,7 @@ namespace Parser { } if (questionDotToken) { // We parsed `?.` but then failed to parse anything, so report a missing identifier here. - const name = createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, ts.Diagnostics.Identifier_expected); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); expression = finishNode(factory.createPropertyAccessChain(expression, questionDotToken, name), pos); } break; @@ -5972,25 +6038,25 @@ namespace Parser { } function parseArgumentList() { - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.OpenParenToken); const result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); return result; } function parseTypeArgumentsInExpression() { - if ((contextFlags & ts.NodeFlags.JavaScriptFile) !== 0) { + if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) { // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators. return undefined; } - if (reScanLessThanToken() !== ts.SyntaxKind.LessThanToken) { + if (reScanLessThanToken() !== SyntaxKind.LessThanToken) { return undefined; } nextToken(); const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType); - if (reScanGreaterToken() !== ts.SyntaxKind.GreaterThanToken) { + if (reScanGreaterToken() !== SyntaxKind.GreaterThanToken) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } @@ -6006,17 +6072,17 @@ namespace Parser { function canFollowTypeArgumentsInExpression(): boolean { switch (token()) { // These tokens can follow a type argument list in a call expression. - case ts.SyntaxKind.OpenParenToken: // foo( - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` - case ts.SyntaxKind.TemplateHead: // foo `...${100}...` + case SyntaxKind.OpenParenToken: // foo( + case SyntaxKind.NoSubstitutionTemplateLiteral: // foo `...` + case SyntaxKind.TemplateHead: // foo `...${100}...` return true; // A type argument list followed by `<` never makes sense, and a type argument list followed // by `>` is ambiguous with a (re-scanned) `>>` operator, so we disqualify both. Also, in // this context, `+` and `-` are unary operators, not binary operators. - case ts.SyntaxKind.LessThanToken: - case ts.SyntaxKind.GreaterThanToken: - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: + case SyntaxKind.LessThanToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.PlusToken: + case SyntaxKind.MinusToken: return false; } // We favor the type argument list interpretation when it is immediately followed by @@ -6024,26 +6090,26 @@ namespace Parser { return scanner.hasPrecedingLineBreak() || isBinaryOperator() || !isStartOfExpression(); } - function parsePrimaryExpression(): ts.PrimaryExpression { + function parsePrimaryExpression(): PrimaryExpression { switch (token()) { - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: return parseLiteralNode(); - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.SuperKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - return parseTokenNode(); - case ts.SyntaxKind.OpenParenToken: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + return parseTokenNode(); + case SyntaxKind.OpenParenToken: return parseParenthesizedExpression(); - case ts.SyntaxKind.OpenBracketToken: + case SyntaxKind.OpenBracketToken: return parseArrayLiteralExpression(); - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: return parseObjectLiteralExpression(); - case ts.SyntaxKind.AsyncKeyword: + case SyntaxKind.AsyncKeyword: // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher. // If we encounter `async [no LineTerminator here] function` then this is an async // function; otherwise, its an identifier. @@ -6052,68 +6118,68 @@ namespace Parser { } return parseFunctionExpression(); - case ts.SyntaxKind.ClassKeyword: + case SyntaxKind.ClassKeyword: return parseClassExpression(); - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: return parseFunctionExpression(); - case ts.SyntaxKind.NewKeyword: + case SyntaxKind.NewKeyword: return parseNewExpressionOrNewDotTarget(); - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.SlashEqualsToken: - if (reScanSlashToken() === ts.SyntaxKind.RegularExpressionLiteral) { + case SyntaxKind.SlashToken: + case SyntaxKind.SlashEqualsToken: + if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) { return parseLiteralNode(); } break; - case ts.SyntaxKind.TemplateHead: + case SyntaxKind.TemplateHead: return parseTemplateExpression(/* isTaggedTemplate */ false); - case ts.SyntaxKind.PrivateIdentifier: + case SyntaxKind.PrivateIdentifier: return parsePrivateIdentifier(); } - return parseIdentifier(ts.Diagnostics.Expression_expected); + return parseIdentifier(Diagnostics.Expression_expected); } - function parseParenthesizedExpression(): ts.ParenthesizedExpression { + function parseParenthesizedExpression(): ParenthesizedExpression { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); return withJSDoc(finishNode(factory.createParenthesizedExpression(expression), pos), hasJSDoc); } - function parseSpreadElement(): ts.Expression { + function parseSpreadElement(): Expression { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.DotDotDotToken); + parseExpected(SyntaxKind.DotDotDotToken); const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return finishNode(factory.createSpreadElement(expression), pos); } - function parseArgumentOrArrayLiteralElement(): ts.Expression { - return token() === ts.SyntaxKind.DotDotDotToken ? parseSpreadElement() : - token() === ts.SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : + function parseArgumentOrArrayLiteralElement(): Expression { + return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() : + token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); } - function parseArgumentExpression(): ts.Expression { + function parseArgumentExpression(): Expression { return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement); } - function parseArrayLiteralExpression(): ts.ArrayLiteralExpression { + function parseArrayLiteralExpression(): ArrayLiteralExpression { const pos = getNodePos(); const openBracketPosition = scanner.getTokenPos(); - const openBracketParsed = parseExpected(ts.SyntaxKind.OpenBracketToken); + const openBracketParsed = parseExpected(SyntaxKind.OpenBracketToken); const multiLine = scanner.hasPrecedingLineBreak(); const elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.CloseBracketToken, openBracketParsed, openBracketPosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, openBracketParsed, openBracketPosition); return finishNode(factory.createArrayLiteralExpression(elements, multiLine), pos); } - function parseObjectLiteralElement(): ts.ObjectLiteralElementLike { + function parseObjectLiteralElement(): ObjectLiteralElementLike { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - if (parseOptionalToken(ts.SyntaxKind.DotDotDotToken)) { + if (parseOptionalToken(SyntaxKind.DotDotDotToken)) { const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc); } @@ -6121,22 +6187,22 @@ namespace Parser { const decorators = parseDecorators(); const modifiers = parseModifiers(); - if (parseContextualModifier(ts.SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.GetAccessor, SignatureFlags.None); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor, SignatureFlags.None); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.SetAccessor, SignatureFlags.None); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor, SignatureFlags.None); } - const asteriskToken = parseOptionalToken(ts.SyntaxKind.AsteriskToken); + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const tokenIsIdentifier = isIdentifier(); const name = parsePropertyName(); // Disallowing of optional property assignments and definite assignment assertion happens in the grammar checker. - const questionToken = parseOptionalToken(ts.SyntaxKind.QuestionToken); - const exclamationToken = parseOptionalToken(ts.SyntaxKind.ExclamationToken); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken); - if (asteriskToken || token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken) { + if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, exclamationToken); } @@ -6145,18 +6211,18 @@ namespace Parser { // CoverInitializedName[Yield] : // IdentifierReference[?Yield] Initializer[In, ?Yield] // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern - let node: ts.Mutable; - const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== ts.SyntaxKind.ColonToken); + let node: Mutable; + const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken); if (isShorthandPropertyAssignment) { - const equalsToken = parseOptionalToken(ts.SyntaxKind.EqualsToken); + const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken); const objectAssignmentInitializer = equalsToken ? allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)) : undefined; - node = factory.createShorthandPropertyAssignment(name as ts.Identifier, objectAssignmentInitializer); + node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer); // Save equals token for error reporting. // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful. node.equalsToken = equalsToken; } else { - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.ColonToken); const initializer = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)); node = factory.createPropertyAssignment(name, initializer); } @@ -6168,17 +6234,17 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseObjectLiteralExpression(): ts.ObjectLiteralExpression { + function parseObjectLiteralExpression(): ObjectLiteralExpression { const pos = getNodePos(); const openBracePosition = scanner.getTokenPos(); - const openBraceParsed = parseExpected(ts.SyntaxKind.OpenBraceToken); + const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken); const multiLine = scanner.hasPrecedingLineBreak(); const properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); return finishNode(factory.createObjectLiteralExpression(properties, multiLine), pos); } - function parseFunctionExpression(): ts.FunctionExpression { + function parseFunctionExpression(): FunctionExpression { // GeneratorExpression: // function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody } // @@ -6190,10 +6256,10 @@ namespace Parser { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(); - parseExpected(ts.SyntaxKind.FunctionKeyword); - const asteriskToken = parseOptionalToken(ts.SyntaxKind.AsteriskToken); + parseExpected(SyntaxKind.FunctionKeyword); + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = ts.some(modifiers, ts.isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) : isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) : isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) : @@ -6201,7 +6267,7 @@ namespace Parser { const typeParameters = parseTypeParameters(); const parameters = parseParameters(isGenerator | isAsync); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); const body = parseFunctionBlock(isGenerator | isAsync); setDecoratorContext(savedDecoratorContext); @@ -6210,57 +6276,57 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseOptionalBindingIdentifier(): ts.Identifier | undefined { + function parseOptionalBindingIdentifier(): Identifier | undefined { return isBindingIdentifier() ? parseBindingIdentifier() : undefined; } - function parseNewExpressionOrNewDotTarget(): ts.NewExpression | ts.MetaProperty { + function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.NewKeyword); - if (parseOptional(ts.SyntaxKind.DotToken)) { + parseExpected(SyntaxKind.NewKeyword); + if (parseOptional(SyntaxKind.DotToken)) { const name = parseIdentifierName(); - return finishNode(factory.createMetaProperty(ts.SyntaxKind.NewKeyword, name), pos); + return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos); } const expressionPos = getNodePos(); - let expression: ts.LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); - let typeArguments: ts.NodeArray | undefined; + let expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); + let typeArguments: NodeArray | undefined; // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments - if (expression.kind === ts.SyntaxKind.ExpressionWithTypeArguments) { - typeArguments = (expression as ts.ExpressionWithTypeArguments).typeArguments; - expression = (expression as ts.ExpressionWithTypeArguments).expression; + if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) { + typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; + expression = (expression as ExpressionWithTypeArguments).expression; } - if (token() === ts.SyntaxKind.QuestionDotToken) { - parseErrorAtCurrentToken(ts.Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, ts.getTextOfNodeFromSourceText(sourceText, expression)); + if (token() === SyntaxKind.QuestionDotToken) { + parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression)); } - const argumentList = token() === ts.SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; + const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; return finishNode(factory.createNewExpression(expression, typeArguments, argumentList), pos); } // STATEMENTS - function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: ts.DiagnosticMessage): ts.Block { + function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const openBracePosition = scanner.getTokenPos(); - const openBraceParsed = parseExpected(ts.SyntaxKind.OpenBraceToken, diagnosticMessage); + const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage); if (openBraceParsed || ignoreMissingOpenBrace) { const multiLine = scanner.hasPrecedingLineBreak(); const statements = parseList(ParsingContext.BlockStatements, parseStatement); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition); const result = withJSDoc(finishNode(factory.createBlock(statements, multiLine), pos), hasJSDoc); - if (token() === ts.SyntaxKind.EqualsToken) { - parseErrorAtCurrentToken(ts.Diagnostics.Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_the_whole_assignment_in_parentheses); + if (token() === SyntaxKind.EqualsToken) { + parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_the_whole_assignment_in_parentheses); nextToken(); } return result; } else { - const statements = createMissingList(); + const statements = createMissingList(); return withJSDoc(finishNode(factory.createBlock(statements, /*multiLine*/ undefined), pos), hasJSDoc); } } - function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: ts.DiagnosticMessage): ts.Block { + function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block { const savedYieldContext = inYieldContext(); setYieldContext(!!(flags & SignatureFlags.Yield)); @@ -6290,67 +6356,67 @@ namespace Parser { return block; } - function parseEmptyStatement(): ts.Statement { + function parseEmptyStatement(): Statement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.SemicolonToken); + parseExpected(SyntaxKind.SemicolonToken); return withJSDoc(finishNode(factory.createEmptyStatement(), pos), hasJSDoc); } - function parseIfStatement(): ts.IfStatement { + function parseIfStatement(): IfStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.IfKeyword); + parseExpected(SyntaxKind.IfKeyword); const openParenPosition = scanner.getTokenPos(); - const openParenParsed = parseExpected(ts.SyntaxKind.OpenParenToken); + const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); const thenStatement = parseStatement(); - const elseStatement = parseOptional(ts.SyntaxKind.ElseKeyword) ? parseStatement() : undefined; + const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined; return withJSDoc(finishNode(factory.createIfStatement(expression, thenStatement, elseStatement), pos), hasJSDoc); } - function parseDoStatement(): ts.DoStatement { + function parseDoStatement(): DoStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.DoKeyword); + parseExpected(SyntaxKind.DoKeyword); const statement = parseStatement(); - parseExpected(ts.SyntaxKind.WhileKeyword); + parseExpected(SyntaxKind.WhileKeyword); const openParenPosition = scanner.getTokenPos(); - const openParenParsed = parseExpected(ts.SyntaxKind.OpenParenToken); + const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby // do;while(0)x will have a semicolon inserted before x. - parseOptional(ts.SyntaxKind.SemicolonToken); + parseOptional(SyntaxKind.SemicolonToken); return withJSDoc(finishNode(factory.createDoStatement(statement, expression), pos), hasJSDoc); } - function parseWhileStatement(): ts.WhileStatement { + function parseWhileStatement(): WhileStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.WhileKeyword); + parseExpected(SyntaxKind.WhileKeyword); const openParenPosition = scanner.getTokenPos(); - const openParenParsed = parseExpected(ts.SyntaxKind.OpenParenToken); + const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); const statement = parseStatement(); return withJSDoc(finishNode(factory.createWhileStatement(expression, statement), pos), hasJSDoc); } - function parseForOrForInOrForOfStatement(): ts.Statement { + function parseForOrForInOrForOfStatement(): Statement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.ForKeyword); - const awaitToken = parseOptionalToken(ts.SyntaxKind.AwaitKeyword); - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.ForKeyword); + const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); + parseExpected(SyntaxKind.OpenParenToken); - let initializer!: ts.VariableDeclarationList | ts.Expression; - if (token() !== ts.SyntaxKind.SemicolonToken) { - if (token() === ts.SyntaxKind.VarKeyword || token() === ts.SyntaxKind.LetKeyword || token() === ts.SyntaxKind.ConstKeyword) { + let initializer!: VariableDeclarationList | Expression; + if (token() !== SyntaxKind.SemicolonToken) { + if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) { initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true); } else { @@ -6358,116 +6424,116 @@ namespace Parser { } } - let node: ts.IterationStatement; - if (awaitToken ? parseExpected(ts.SyntaxKind.OfKeyword) : parseOptional(ts.SyntaxKind.OfKeyword)) { + let node: IterationStatement; + if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { const expression = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); node = factory.createForOfStatement(awaitToken, initializer, expression, parseStatement()); } - else if (parseOptional(ts.SyntaxKind.InKeyword)) { + else if (parseOptional(SyntaxKind.InKeyword)) { const expression = allowInAnd(parseExpression); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); node = factory.createForInStatement(initializer, expression, parseStatement()); } else { - parseExpected(ts.SyntaxKind.SemicolonToken); - const condition = token() !== ts.SyntaxKind.SemicolonToken && token() !== ts.SyntaxKind.CloseParenToken + parseExpected(SyntaxKind.SemicolonToken); + const condition = token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken ? allowInAnd(parseExpression) : undefined; - parseExpected(ts.SyntaxKind.SemicolonToken); - const incrementor = token() !== ts.SyntaxKind.CloseParenToken + parseExpected(SyntaxKind.SemicolonToken); + const incrementor = token() !== SyntaxKind.CloseParenToken ? allowInAnd(parseExpression) : undefined; - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); node = factory.createForStatement(initializer, condition, incrementor, parseStatement()); } - return withJSDoc(finishNode(node, pos) as ts.ForStatement | ts.ForInOrOfStatement, hasJSDoc); + return withJSDoc(finishNode(node, pos) as ForStatement | ForInOrOfStatement, hasJSDoc); } - function parseBreakOrContinueStatement(kind: ts.SyntaxKind): ts.BreakOrContinueStatement { + function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(kind === ts.SyntaxKind.BreakStatement ? ts.SyntaxKind.BreakKeyword : ts.SyntaxKind.ContinueKeyword); + parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword); const label = canParseSemicolon() ? undefined : parseIdentifier(); parseSemicolon(); - const node = kind === ts.SyntaxKind.BreakStatement + const node = kind === SyntaxKind.BreakStatement ? factory.createBreakStatement(label) : factory.createContinueStatement(label); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseReturnStatement(): ts.ReturnStatement { + function parseReturnStatement(): ReturnStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.ReturnKeyword); + parseExpected(SyntaxKind.ReturnKeyword); const expression = canParseSemicolon() ? undefined : allowInAnd(parseExpression); parseSemicolon(); return withJSDoc(finishNode(factory.createReturnStatement(expression), pos), hasJSDoc); } - function parseWithStatement(): ts.WithStatement { + function parseWithStatement(): WithStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.WithKeyword); + parseExpected(SyntaxKind.WithKeyword); const openParenPosition = scanner.getTokenPos(); - const openParenParsed = parseExpected(ts.SyntaxKind.OpenParenToken); + const openParenParsed = parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpectedMatchingBrackets(ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); - const statement = doInsideOfContext(ts.NodeFlags.InWithStatement, parseStatement); + parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition); + const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement); return withJSDoc(finishNode(factory.createWithStatement(expression, statement), pos), hasJSDoc); } - function parseCaseClause(): ts.CaseClause { + function parseCaseClause(): CaseClause { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.CaseKeyword); + parseExpected(SyntaxKind.CaseKeyword); const expression = allowInAnd(parseExpression); - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.ColonToken); const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); return withJSDoc(finishNode(factory.createCaseClause(expression, statements), pos), hasJSDoc); } - function parseDefaultClause(): ts.DefaultClause { + function parseDefaultClause(): DefaultClause { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.DefaultKeyword); - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.DefaultKeyword); + parseExpected(SyntaxKind.ColonToken); const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement); return finishNode(factory.createDefaultClause(statements), pos); } - function parseCaseOrDefaultClause(): ts.CaseOrDefaultClause { - return token() === ts.SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause(); + function parseCaseOrDefaultClause(): CaseOrDefaultClause { + return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause(); } - function parseCaseBlock(): ts.CaseBlock { + function parseCaseBlock(): CaseBlock { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBraceToken); + parseExpected(SyntaxKind.OpenBraceToken); const clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); return finishNode(factory.createCaseBlock(clauses), pos); } - function parseSwitchStatement(): ts.SwitchStatement { + function parseSwitchStatement(): SwitchStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.SwitchKeyword); - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.SwitchKeyword); + parseExpected(SyntaxKind.OpenParenToken); const expression = allowInAnd(parseExpression); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); const caseBlock = parseCaseBlock(); return withJSDoc(finishNode(factory.createSwitchStatement(expression, caseBlock), pos), hasJSDoc); } - function parseThrowStatement(): ts.ThrowStatement { + function parseThrowStatement(): ThrowStatement { // ThrowStatement[Yield] : // throw [no LineTerminator here]Expression[In, ?Yield]; const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.ThrowKeyword); + parseExpected(SyntaxKind.ThrowKeyword); // Because of automatic semicolon insertion, we need to report error if this // throw could be terminated with a semicolon. Note: we can't call 'parseExpression' @@ -6486,33 +6552,33 @@ namespace Parser { } // TODO: Review for error recovery - function parseTryStatement(): ts.TryStatement { + function parseTryStatement(): TryStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.TryKeyword); + parseExpected(SyntaxKind.TryKeyword); const tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); - const catchClause = token() === ts.SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; + const catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined; // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. - let finallyBlock: ts.Block | undefined; - if (!catchClause || token() === ts.SyntaxKind.FinallyKeyword) { - parseExpected(ts.SyntaxKind.FinallyKeyword, ts.Diagnostics.catch_or_finally_expected); + let finallyBlock: Block | undefined; + if (!catchClause || token() === SyntaxKind.FinallyKeyword) { + parseExpected(SyntaxKind.FinallyKeyword, Diagnostics.catch_or_finally_expected); finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); } return withJSDoc(finishNode(factory.createTryStatement(tryBlock, catchClause, finallyBlock), pos), hasJSDoc); } - function parseCatchClause(): ts.CatchClause { + function parseCatchClause(): CatchClause { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.CatchKeyword); + parseExpected(SyntaxKind.CatchKeyword); let variableDeclaration; - if (parseOptional(ts.SyntaxKind.OpenParenToken)) { + if (parseOptional(SyntaxKind.OpenParenToken)) { variableDeclaration = parseVariableDeclaration(); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); } else { // Keep shape of node to avoid degrading performance. @@ -6523,24 +6589,24 @@ namespace Parser { return finishNode(factory.createCatchClause(variableDeclaration, block), pos); } - function parseDebuggerStatement(): ts.Statement { + function parseDebuggerStatement(): Statement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - parseExpected(ts.SyntaxKind.DebuggerKeyword); + parseExpected(SyntaxKind.DebuggerKeyword); parseSemicolon(); return withJSDoc(finishNode(factory.createDebuggerStatement(), pos), hasJSDoc); } - function parseExpressionOrLabeledStatement(): ts.ExpressionStatement | ts.LabeledStatement { + function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement { // Avoiding having to do the lookahead for a labeled statement by just trying to parse // out an expression, seeing if it is identifier and then seeing if it is followed by // a colon. const pos = getNodePos(); let hasJSDoc = hasPrecedingJSDocComment(); - let node: ts.ExpressionStatement | ts.LabeledStatement; - const hasParen = token() === ts.SyntaxKind.OpenParenToken; + let node: ExpressionStatement | LabeledStatement; + const hasParen = token() === SyntaxKind.OpenParenToken; const expression = allowInAnd(parseExpression); - if (ts.isIdentifier(expression) && parseOptional(ts.SyntaxKind.ColonToken)) { + if (ts.isIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) { node = factory.createLabeledStatement(expression, parseStatement()); } else { @@ -6558,33 +6624,33 @@ namespace Parser { function nextTokenIsIdentifierOrKeywordOnSameLine() { nextToken(); - return ts.tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak(); + return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak(); } function nextTokenIsClassKeywordOnSameLine() { nextToken(); - return token() === ts.SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak(); + return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak(); } function nextTokenIsFunctionKeywordOnSameLine() { nextToken(); - return token() === ts.SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak(); + return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak(); } function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() { nextToken(); - return (ts.tokenIsIdentifierOrKeyword(token()) || token() === ts.SyntaxKind.NumericLiteral || token() === ts.SyntaxKind.BigIntLiteral || token() === ts.SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak(); + return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak(); } function isDeclaration(): boolean { while (true) { switch (token()) { - case ts.SyntaxKind.VarKeyword: - case ts.SyntaxKind.LetKeyword: - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.ClassKeyword: - case ts.SyntaxKind.EnumKeyword: + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: return true; // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers; @@ -6608,20 +6674,20 @@ namespace Parser { // I {} // // could be legal, it would add complexity for very little gain. - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.TypeKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.TypeKeyword: return nextTokenIsIdentifierOnSameLine(); - case ts.SyntaxKind.ModuleKeyword: - case ts.SyntaxKind.NamespaceKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: return nextTokenIsIdentifierOrStringLiteralOnSameLine(); - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.AccessorKeyword: - case ts.SyntaxKind.AsyncKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.ReadonlyKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AccessorKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.ReadonlyKeyword: nextToken(); // ASI takes effect for this modifier. if (scanner.hasPrecedingLineBreak()) { @@ -6629,27 +6695,27 @@ namespace Parser { } continue; - case ts.SyntaxKind.GlobalKeyword: + case SyntaxKind.GlobalKeyword: nextToken(); - return token() === ts.SyntaxKind.OpenBraceToken || token() === ts.SyntaxKind.Identifier || token() === ts.SyntaxKind.ExportKeyword; + return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword; - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: nextToken(); - return token() === ts.SyntaxKind.StringLiteral || token() === ts.SyntaxKind.AsteriskToken || - token() === ts.SyntaxKind.OpenBraceToken || ts.tokenIsIdentifierOrKeyword(token()); - case ts.SyntaxKind.ExportKeyword: + return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken || + token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token()); + case SyntaxKind.ExportKeyword: let currentToken = nextToken(); - if (currentToken === ts.SyntaxKind.TypeKeyword) { + if (currentToken === SyntaxKind.TypeKeyword) { currentToken = lookAhead(nextToken); } - if (currentToken === ts.SyntaxKind.EqualsToken || currentToken === ts.SyntaxKind.AsteriskToken || - currentToken === ts.SyntaxKind.OpenBraceToken || currentToken === ts.SyntaxKind.DefaultKeyword || - currentToken === ts.SyntaxKind.AsKeyword) { + if (currentToken === SyntaxKind.EqualsToken || currentToken === SyntaxKind.AsteriskToken || + currentToken === SyntaxKind.OpenBraceToken || currentToken === SyntaxKind.DefaultKeyword || + currentToken === SyntaxKind.AsKeyword) { return true; } continue; - case ts.SyntaxKind.StaticKeyword: + case SyntaxKind.StaticKeyword: nextToken(); continue; default: @@ -6664,56 +6730,56 @@ namespace Parser { function isStartOfStatement(): boolean { switch (token()) { - case ts.SyntaxKind.AtToken: - case ts.SyntaxKind.SemicolonToken: - case ts.SyntaxKind.OpenBraceToken: - case ts.SyntaxKind.VarKeyword: - case ts.SyntaxKind.LetKeyword: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.ClassKeyword: - case ts.SyntaxKind.EnumKeyword: - case ts.SyntaxKind.IfKeyword: - case ts.SyntaxKind.DoKeyword: - case ts.SyntaxKind.WhileKeyword: - case ts.SyntaxKind.ForKeyword: - case ts.SyntaxKind.ContinueKeyword: - case ts.SyntaxKind.BreakKeyword: - case ts.SyntaxKind.ReturnKeyword: - case ts.SyntaxKind.WithKeyword: - case ts.SyntaxKind.SwitchKeyword: - case ts.SyntaxKind.ThrowKeyword: - case ts.SyntaxKind.TryKeyword: - case ts.SyntaxKind.DebuggerKeyword: + case SyntaxKind.AtToken: + case SyntaxKind.SemicolonToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.IfKeyword: + case SyntaxKind.DoKeyword: + case SyntaxKind.WhileKeyword: + case SyntaxKind.ForKeyword: + case SyntaxKind.ContinueKeyword: + case SyntaxKind.BreakKeyword: + case SyntaxKind.ReturnKeyword: + case SyntaxKind.WithKeyword: + case SyntaxKind.SwitchKeyword: + case SyntaxKind.ThrowKeyword: + case SyntaxKind.TryKeyword: + case SyntaxKind.DebuggerKeyword: // 'catch' and 'finally' do not actually indicate that the code is part of a statement, // however, we say they are here so that we may gracefully parse them and error later. // falls through - case ts.SyntaxKind.CatchKeyword: - case ts.SyntaxKind.FinallyKeyword: + case SyntaxKind.CatchKeyword: + case SyntaxKind.FinallyKeyword: return true; - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot); - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.ExportKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.ExportKeyword: return isStartOfDeclaration(); - case ts.SyntaxKind.AsyncKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.ModuleKeyword: - case ts.SyntaxKind.NamespaceKeyword: - case ts.SyntaxKind.TypeKeyword: - case ts.SyntaxKind.GlobalKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.GlobalKeyword: // When these don't start a declaration, they're an identifier in an expression statement return true; - case ts.SyntaxKind.AccessorKeyword: - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.ReadonlyKeyword: + case SyntaxKind.AccessorKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: // When these don't start a declaration, they may be the start of a class member if an identifier // immediately follows. Otherwise they're an identifier in an expression statement. return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine); @@ -6725,7 +6791,7 @@ namespace Parser { function nextTokenIsBindingIdentifierOrStartOfDestructuring() { nextToken(); - return isBindingIdentifier() || token() === ts.SyntaxKind.OpenBraceToken || token() === ts.SyntaxKind.OpenBracketToken; + return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken; } function isLetDeclaration() { @@ -6734,71 +6800,71 @@ namespace Parser { return lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuring); } - function parseStatement(): ts.Statement { + function parseStatement(): Statement { switch (token()) { - case ts.SyntaxKind.SemicolonToken: + case SyntaxKind.SemicolonToken: return parseEmptyStatement(); - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: return parseBlock(/*ignoreMissingOpenBrace*/ false); - case ts.SyntaxKind.VarKeyword: + case SyntaxKind.VarKeyword: return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); - case ts.SyntaxKind.LetKeyword: + case SyntaxKind.LetKeyword: if (isLetDeclaration()) { return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); } break; - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: return parseFunctionDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); - case ts.SyntaxKind.ClassKeyword: + case SyntaxKind.ClassKeyword: return parseClassDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined); - case ts.SyntaxKind.IfKeyword: + case SyntaxKind.IfKeyword: return parseIfStatement(); - case ts.SyntaxKind.DoKeyword: + case SyntaxKind.DoKeyword: return parseDoStatement(); - case ts.SyntaxKind.WhileKeyword: + case SyntaxKind.WhileKeyword: return parseWhileStatement(); - case ts.SyntaxKind.ForKeyword: + case SyntaxKind.ForKeyword: return parseForOrForInOrForOfStatement(); - case ts.SyntaxKind.ContinueKeyword: - return parseBreakOrContinueStatement(ts.SyntaxKind.ContinueStatement); - case ts.SyntaxKind.BreakKeyword: - return parseBreakOrContinueStatement(ts.SyntaxKind.BreakStatement); - case ts.SyntaxKind.ReturnKeyword: + case SyntaxKind.ContinueKeyword: + return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement); + case SyntaxKind.BreakKeyword: + return parseBreakOrContinueStatement(SyntaxKind.BreakStatement); + case SyntaxKind.ReturnKeyword: return parseReturnStatement(); - case ts.SyntaxKind.WithKeyword: + case SyntaxKind.WithKeyword: return parseWithStatement(); - case ts.SyntaxKind.SwitchKeyword: + case SyntaxKind.SwitchKeyword: return parseSwitchStatement(); - case ts.SyntaxKind.ThrowKeyword: + case SyntaxKind.ThrowKeyword: return parseThrowStatement(); - case ts.SyntaxKind.TryKeyword: + case SyntaxKind.TryKeyword: // Include 'catch' and 'finally' for error recovery. // falls through - case ts.SyntaxKind.CatchKeyword: - case ts.SyntaxKind.FinallyKeyword: + case SyntaxKind.CatchKeyword: + case SyntaxKind.FinallyKeyword: return parseTryStatement(); - case ts.SyntaxKind.DebuggerKeyword: + case SyntaxKind.DebuggerKeyword: return parseDebuggerStatement(); - case ts.SyntaxKind.AtToken: + case SyntaxKind.AtToken: return parseDeclaration(); - case ts.SyntaxKind.AsyncKeyword: - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.TypeKeyword: - case ts.SyntaxKind.ModuleKeyword: - case ts.SyntaxKind.NamespaceKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.EnumKeyword: - case ts.SyntaxKind.ExportKeyword: - case ts.SyntaxKind.ImportKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.AccessorKeyword: - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.ReadonlyKeyword: - case ts.SyntaxKind.GlobalKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.ImportKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AccessorKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.GlobalKeyword: if (isStartOfDeclaration()) { return parseDeclaration(); } @@ -6807,11 +6873,11 @@ namespace Parser { return parseExpressionOrLabeledStatement(); } - function isDeclareModifier(modifier: ts.Modifier) { - return modifier.kind === ts.SyntaxKind.DeclareKeyword; + function isDeclareModifier(modifier: Modifier) { + return modifier.kind === SyntaxKind.DeclareKeyword; } - function parseDeclaration(): ts.Statement { + function parseDeclaration(): Statement { // `parseListElement` attempted to get the reused node at this position, // but the ambient context flag was not yet set, so the node appeared // not reusable in that context. @@ -6819,7 +6885,7 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const decorators = parseDecorators(); const modifiers = parseModifiers(); - const isAmbient = ts.some(modifiers, isDeclareModifier); + const isAmbient = some(modifiers, isDeclareModifier); if (isAmbient) { const node = tryReuseAmbientDeclaration(pos); if (node) { @@ -6827,53 +6893,53 @@ namespace Parser { } for (const m of modifiers!) { - (m as ts.Mutable).flags |= ts.NodeFlags.Ambient; + (m as Mutable).flags |= NodeFlags.Ambient; } - return doInsideOfContext(ts.NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers)); + return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers)); } else { return parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers); } } - function tryReuseAmbientDeclaration(pos: number): ts.Statement | undefined { - return doInsideOfContext(ts.NodeFlags.Ambient, () => { + function tryReuseAmbientDeclaration(pos: number): Statement | undefined { + return doInsideOfContext(NodeFlags.Ambient, () => { const node = currentNode(parsingContext, pos); if (node) { - return consumeNode(node) as ts.Statement; + return consumeNode(node) as Statement; } }); } - function parseDeclarationWorker(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.Statement { + function parseDeclarationWorker(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): Statement { switch (token()) { - case ts.SyntaxKind.VarKeyword: - case ts.SyntaxKind.LetKeyword: - case ts.SyntaxKind.ConstKeyword: + case SyntaxKind.VarKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: return parseVariableStatement(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: return parseFunctionDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.ClassKeyword: + case SyntaxKind.ClassKeyword: return parseClassDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.InterfaceKeyword: + case SyntaxKind.InterfaceKeyword: return parseInterfaceDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.TypeKeyword: + case SyntaxKind.TypeKeyword: return parseTypeAliasDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.EnumKeyword: + case SyntaxKind.EnumKeyword: return parseEnumDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.GlobalKeyword: - case ts.SyntaxKind.ModuleKeyword: - case ts.SyntaxKind.NamespaceKeyword: + case SyntaxKind.GlobalKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: return parseModuleDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: return parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.ExportKeyword: + case SyntaxKind.ExportKeyword: nextToken(); switch (token()) { - case ts.SyntaxKind.DefaultKeyword: - case ts.SyntaxKind.EqualsToken: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.EqualsToken: return parseExportAssignment(pos, hasJSDoc, decorators, modifiers); - case ts.SyntaxKind.AsKeyword: + case SyntaxKind.AsKeyword: return parseNamespaceExportDeclaration(pos, hasJSDoc, decorators, modifiers); default: return parseExportDeclaration(pos, hasJSDoc, decorators, modifiers); @@ -6882,8 +6948,8 @@ namespace Parser { if (decorators || modifiers) { // We reached this point because we encountered decorators and/or modifiers and assumed a declaration // would follow. For recovery and error reporting purposes, return an incomplete declaration. - const missing = createMissingNode(ts.SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); - ts.setTextRangePos(missing, pos); + const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + setTextRangePos(missing, pos); missing.illegalDecorators = decorators; missing.modifiers = modifiers; return missing; @@ -6894,11 +6960,11 @@ namespace Parser { function nextTokenIsIdentifierOrStringLiteralOnSameLine() { nextToken(); - return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === ts.SyntaxKind.StringLiteral); + return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral); } - function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: ts.DiagnosticMessage): ts.Block | undefined { - if (token() !== ts.SyntaxKind.OpenBraceToken) { + function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { + if (token() !== SyntaxKind.OpenBraceToken) { if (flags & SignatureFlags.Type) { parseTypeMemberSemicolon(); return; @@ -6913,63 +6979,63 @@ namespace Parser { // DECLARATIONS - function parseArrayBindingElement(): ts.ArrayBindingElement { + function parseArrayBindingElement(): ArrayBindingElement { const pos = getNodePos(); - if (token() === ts.SyntaxKind.CommaToken) { + if (token() === SyntaxKind.CommaToken) { return finishNode(factory.createOmittedExpression(), pos); } - const dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const name = parseIdentifierOrPattern(); const initializer = parseInitializer(); return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos); } - function parseObjectBindingElement(): ts.BindingElement { + function parseObjectBindingElement(): BindingElement { const pos = getNodePos(); - const dotDotDotToken = parseOptionalToken(ts.SyntaxKind.DotDotDotToken); + const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const tokenIsIdentifier = isBindingIdentifier(); - let propertyName: ts.PropertyName | undefined = parsePropertyName(); - let name: ts.BindingName; - if (tokenIsIdentifier && token() !== ts.SyntaxKind.ColonToken) { - name = propertyName as ts.Identifier; + let propertyName: PropertyName | undefined = parsePropertyName(); + let name: BindingName; + if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) { + name = propertyName as Identifier; propertyName = undefined; } else { - parseExpected(ts.SyntaxKind.ColonToken); + parseExpected(SyntaxKind.ColonToken); name = parseIdentifierOrPattern(); } const initializer = parseInitializer(); return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos); } - function parseObjectBindingPattern(): ts.ObjectBindingPattern { + function parseObjectBindingPattern(): ObjectBindingPattern { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBraceToken); + parseExpected(SyntaxKind.OpenBraceToken); const elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); return finishNode(factory.createObjectBindingPattern(elements), pos); } - function parseArrayBindingPattern(): ts.ArrayBindingPattern { + function parseArrayBindingPattern(): ArrayBindingPattern { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.OpenBracketToken); + parseExpected(SyntaxKind.OpenBracketToken); const elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement); - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); return finishNode(factory.createArrayBindingPattern(elements), pos); } function isBindingIdentifierOrPrivateIdentifierOrPattern() { - return token() === ts.SyntaxKind.OpenBraceToken - || token() === ts.SyntaxKind.OpenBracketToken - || token() === ts.SyntaxKind.PrivateIdentifier + return token() === SyntaxKind.OpenBraceToken + || token() === SyntaxKind.OpenBracketToken + || token() === SyntaxKind.PrivateIdentifier || isBindingIdentifier(); } - function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: ts.DiagnosticMessage): ts.Identifier | ts.BindingPattern { - if (token() === ts.SyntaxKind.OpenBracketToken) { + function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern { + if (token() === SyntaxKind.OpenBracketToken) { return parseArrayBindingPattern(); } - if (token() === ts.SyntaxKind.OpenBraceToken) { + if (token() === SyntaxKind.OpenBraceToken) { return parseObjectBindingPattern(); } return parseBindingIdentifier(privateIdentifierDiagnosticMessage); @@ -6979,14 +7045,14 @@ namespace Parser { return parseVariableDeclaration(/*allowExclamation*/ true); } - function parseVariableDeclaration(allowExclamation?: boolean): ts.VariableDeclaration { + function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); - const name = parseIdentifierOrPattern(ts.Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations); - let exclamationToken: ts.ExclamationToken | undefined; - if (allowExclamation && name.kind === ts.SyntaxKind.Identifier && - token() === ts.SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { - exclamationToken = parseTokenNode>(); + const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations); + let exclamationToken: ExclamationToken | undefined; + if (allowExclamation && name.kind === SyntaxKind.Identifier && + token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) { + exclamationToken = parseTokenNode>(); } const type = parseTypeAnnotation(); const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer(); @@ -6994,21 +7060,21 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseVariableDeclarationList(inForStatementInitializer: boolean): ts.VariableDeclarationList { + function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList { const pos = getNodePos(); - let flags: ts.NodeFlags = 0; + let flags: NodeFlags = 0; switch (token()) { - case ts.SyntaxKind.VarKeyword: + case SyntaxKind.VarKeyword: break; - case ts.SyntaxKind.LetKeyword: - flags |= ts.NodeFlags.Let; + case SyntaxKind.LetKeyword: + flags |= NodeFlags.Let; break; - case ts.SyntaxKind.ConstKeyword: - flags |= ts.NodeFlags.Const; + case SyntaxKind.ConstKeyword: + flags |= NodeFlags.Const; break; default: - ts.Debug.fail(); + Debug.fail(); } nextToken(); @@ -7022,9 +7088,9 @@ namespace Parser { // So we need to look ahead to determine if 'of' should be treated as a keyword in // this context. // The checker will then give an error that there is an empty declaration list. - let declarations: readonly ts.VariableDeclaration[]; - if (token() === ts.SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) { - declarations = createMissingList(); + let declarations: readonly VariableDeclaration[]; + if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) { + declarations = createMissingList(); } else { const savedDisallowIn = inDisallowInContext(); @@ -7040,10 +7106,10 @@ namespace Parser { } function canFollowContextualOfKeyword(): boolean { - return nextTokenIsIdentifier() && nextToken() === ts.SyntaxKind.CloseParenToken; + return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken; } - function parseVariableStatement(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.VariableStatement { + function parseVariableStatement(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): VariableStatement { const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); const node = factory.createVariableStatement(modifiers, declarationList); @@ -7052,32 +7118,32 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.FunctionDeclaration { + function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): FunctionDeclaration { const savedAwaitContext = inAwaitContext(); - const modifierFlags = ts.modifiersToFlags(modifiers); - parseExpected(ts.SyntaxKind.FunctionKeyword); - const asteriskToken = parseOptionalToken(ts.SyntaxKind.AsteriskToken); + const modifierFlags = modifiersToFlags(modifiers); + parseExpected(SyntaxKind.FunctionKeyword); + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); // We don't parse the name here in await context, instead we will report a grammar error in the checker. - const name = modifierFlags & ts.ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier(); + const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier(); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = modifierFlags & ts.ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = modifierFlags & ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None; const typeParameters = parseTypeParameters(); - if (modifierFlags & ts.ModifierFlags.Export) setAwaitContext(/*value*/ true); + if (modifierFlags & ModifierFlags.Export) setAwaitContext(/*value*/ true); const parameters = parseParameters(isGenerator | isAsync); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); - const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, ts.Diagnostics.or_expected); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); + const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected); setAwaitContext(savedAwaitContext); const node = factory.createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseConstructorName() { - if (token() === ts.SyntaxKind.ConstructorKeyword) { - return parseExpected(ts.SyntaxKind.ConstructorKeyword); + if (token() === SyntaxKind.ConstructorKeyword) { + return parseExpected(SyntaxKind.ConstructorKeyword); } - if (token() === ts.SyntaxKind.StringLiteral && lookAhead(nextToken) === ts.SyntaxKind.OpenParenToken) { + if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) { return tryParse(() => { const literalNode = parseLiteralNode(); return literalNode.text === "constructor" ? literalNode : undefined; @@ -7085,19 +7151,19 @@ namespace Parser { } } - function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ConstructorDeclaration | undefined { + function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ConstructorDeclaration | undefined { return tryParse(() => { if (parseConstructorName()) { const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.None); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); - const body = parseFunctionBlockOrSemicolon(SignatureFlags.None, ts.Diagnostics.or_expected); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); + const body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected); const node = factory.createConstructorDeclaration(modifiers, parameters, body); // Attach invalid nodes if they exist so that we can report them in the grammar checker. - (node as ts.Mutable).illegalDecorators = decorators; - (node as ts.Mutable).typeParameters = typeParameters; - (node as ts.Mutable).type = type; + (node as Mutable).illegalDecorators = decorators; + (node as Mutable).typeParameters = typeParameters; + (node as Mutable).type = type; return withJSDoc(finishNode(node, pos), hasJSDoc); } }); @@ -7106,19 +7172,19 @@ namespace Parser { function parseMethodDeclaration( pos: number, hasJSDoc: boolean, - decorators: ts.NodeArray | undefined, - modifiers: ts.NodeArray | undefined, - asteriskToken: ts.AsteriskToken | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined, - exclamationToken: ts.ExclamationToken | undefined, - diagnosticMessage?: ts.DiagnosticMessage - ): ts.MethodDeclaration { + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined, + asteriskToken: AsteriskToken | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined, + exclamationToken: ExclamationToken | undefined, + diagnosticMessage?: DiagnosticMessage + ): MethodDeclaration { const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = ts.some(modifiers, ts.isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const typeParameters = parseTypeParameters(); const parameters = parseParameters(isGenerator | isAsync); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage); const node = factory.createMethodDeclaration( combineDecoratorsAndModifiers(decorators, modifiers), @@ -7132,21 +7198,21 @@ namespace Parser { ); // An exclamation token on a method is invalid syntax and will be handled by the grammar checker - (node as ts.Mutable).exclamationToken = exclamationToken; + (node as Mutable).exclamationToken = exclamationToken; return withJSDoc(finishNode(node, pos), hasJSDoc); } function parsePropertyDeclaration( pos: number, hasJSDoc: boolean, - decorators: ts.NodeArray | undefined, - modifiers: ts.NodeArray | undefined, - name: ts.PropertyName, - questionToken: ts.QuestionToken | undefined - ): ts.PropertyDeclaration { - const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(ts.SyntaxKind.ExclamationToken) : undefined; + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined, + name: PropertyName, + questionToken: QuestionToken | undefined + ): PropertyDeclaration { + const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined; const type = parseTypeAnnotation(); - const initializer = doOutsideOfContext(ts.NodeFlags.YieldContext | ts.NodeFlags.AwaitContext | ts.NodeFlags.DisallowInContext, parseInitializer); + const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer); parseSemicolonAfterPropertyName(name, type, initializer); const node = factory.createPropertyDeclaration( combineDecoratorsAndModifiers(decorators, modifiers), @@ -7160,44 +7226,44 @@ namespace Parser { function parsePropertyOrMethodDeclaration( pos: number, hasJSDoc: boolean, - decorators: ts.NodeArray | undefined, - modifiers: ts.NodeArray | undefined - ): ts.PropertyDeclaration | ts.MethodDeclaration { - const asteriskToken = parseOptionalToken(ts.SyntaxKind.AsteriskToken); + decorators: NodeArray | undefined, + modifiers: NodeArray | undefined + ): PropertyDeclaration | MethodDeclaration { + const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const name = parsePropertyName(); // Note: this is not legal as per the grammar. But we allow it in the parser and // report an error in the grammar checker. - const questionToken = parseOptionalToken(ts.SyntaxKind.QuestionToken); - if (asteriskToken || token() === ts.SyntaxKind.OpenParenToken || token() === ts.SyntaxKind.LessThanToken) { - return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, ts.Diagnostics.or_expected); + const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); + if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { + return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, Diagnostics.or_expected); } return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, questionToken); } - function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined, kind: ts.AccessorDeclaration["kind"], flags: SignatureFlags): ts.AccessorDeclaration { + function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"], flags: SignatureFlags): AccessorDeclaration { const name = parsePropertyName(); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.None); - const type = parseReturnType(ts.SyntaxKind.ColonToken, /*isType*/ false); + const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); const body = parseFunctionBlockOrSemicolon(flags); - const node = kind === ts.SyntaxKind.GetAccessor + const node = kind === SyntaxKind.GetAccessor ? factory.createGetAccessorDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, parameters, type, body) : factory.createSetAccessorDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, parameters, body); // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors - (node as ts.Mutable).typeParameters = typeParameters; - if (ts.isSetAccessorDeclaration(node)) (node as ts.Mutable).type = type; + (node as Mutable).typeParameters = typeParameters; + if (isSetAccessorDeclaration(node)) (node as Mutable).type = type; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isClassMemberStart(): boolean { - let idToken: ts.SyntaxKind | undefined; + let idToken: SyntaxKind | undefined; - if (token() === ts.SyntaxKind.AtToken) { + if (token() === SyntaxKind.AtToken) { return true; } // Eat up all modifiers, but hold on to the last one in case it is actually an identifier. - while (ts.isModifierKind(token())) { + while (isModifierKind(token())) { idToken = token(); // If the idToken is a class modifier (protected, private, public, and static), it is // certain that we are starting to parse class member. This allows better error recovery @@ -7205,14 +7271,14 @@ namespace Parser { // public foo() ... // true // public @dec blah ... // true; we will then report an error later // export public ... // true; we will then report an error later - if (ts.isClassMemberModifier(idToken)) { + if (isClassMemberModifier(idToken)) { return true; } nextToken(); } - if (token() === ts.SyntaxKind.AsteriskToken) { + if (token() === SyntaxKind.AsteriskToken) { return true; } @@ -7224,26 +7290,26 @@ namespace Parser { } // Index signatures and computed properties are class members; we can parse. - if (token() === ts.SyntaxKind.OpenBracketToken) { + if (token() === SyntaxKind.OpenBracketToken) { return true; } // If we were able to get any potential identifier... if (idToken !== undefined) { // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse. - if (!ts.isKeyword(idToken) || idToken === ts.SyntaxKind.SetKeyword || idToken === ts.SyntaxKind.GetKeyword) { + if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) { return true; } // If it *is* a keyword, but not an accessor, check a little farther along // to see if it should actually be parsed as a class member. switch (token()) { - case ts.SyntaxKind.OpenParenToken: // Method declaration - case ts.SyntaxKind.LessThanToken: // Generic Method declaration - case ts.SyntaxKind.ExclamationToken: // Non-null assertion on property name - case ts.SyntaxKind.ColonToken: // Type Annotation for declaration - case ts.SyntaxKind.EqualsToken: // Initializer for declaration - case ts.SyntaxKind.QuestionToken: // Not valid, but permitted so that it gets caught later on. + case SyntaxKind.OpenParenToken: // Method declaration + case SyntaxKind.LessThanToken: // Generic Method declaration + case SyntaxKind.ExclamationToken: // Non-null assertion on property name + case SyntaxKind.ColonToken: // Type Annotation for declaration + case SyntaxKind.EqualsToken: // Initializer for declaration + case SyntaxKind.QuestionToken: // Not valid, but permitted so that it gets caught later on. return true; default: // Covers @@ -7258,12 +7324,12 @@ namespace Parser { return false; } - function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.ModifiersArray | undefined): ts.ClassStaticBlockDeclaration { - parseExpectedToken(ts.SyntaxKind.StaticKeyword); + function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: ModifiersArray | undefined): ClassStaticBlockDeclaration { + parseExpectedToken(SyntaxKind.StaticKeyword); const body = parseClassStaticBlockBody(); const node = withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(body), pos), hasJSDoc); - (node as ts.Mutable).illegalDecorators = decorators; - (node as ts.Mutable).modifiers = modifiers; + (node as Mutable).illegalDecorators = decorators; + (node as Mutable).modifiers = modifiers; return node; } @@ -7283,11 +7349,11 @@ namespace Parser { } function parseDecoratorExpression() { - if (inAwaitContext() && token() === ts.SyntaxKind.AwaitKeyword) { + if (inAwaitContext() && token() === SyntaxKind.AwaitKeyword) { // `@await` is is disallowed in an [Await] context, but can cause parsing to go off the rails // This simply parses the missing identifier and moves on. const pos = getNodePos(); - const awaitExpression = parseIdentifier(ts.Diagnostics.Expression_expected); + const awaitExpression = parseIdentifier(Diagnostics.Expression_expected); nextToken(); const memberExpression = parseMemberExpressionRest(pos, awaitExpression, /*allowOptionalChain*/ true); return parseCallExpressionRest(pos, memberExpression); @@ -7295,39 +7361,39 @@ namespace Parser { return parseLeftHandSideExpressionOrHigher(); } - function tryParseDecorator(): ts.Decorator | undefined { + function tryParseDecorator(): Decorator | undefined { const pos = getNodePos(); - if (!parseOptional(ts.SyntaxKind.AtToken)) { + if (!parseOptional(SyntaxKind.AtToken)) { return undefined; } const expression = doInDecoratorContext(parseDecoratorExpression); return finishNode(factory.createDecorator(expression), pos); } - function parseDecorators(): ts.NodeArray | undefined { + function parseDecorators(): NodeArray | undefined { const pos = getNodePos(); let list, decorator; while (decorator = tryParseDecorator()) { - list = ts.append(list, decorator); + list = append(list, decorator); } return list && createNodeArray(list, pos); } - function tryParseModifier(permitInvalidConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, hasSeenStaticModifier?: boolean): ts.Modifier | undefined { + function tryParseModifier(permitInvalidConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, hasSeenStaticModifier?: boolean): Modifier | undefined { const pos = getNodePos(); const kind = token(); - if (token() === ts.SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) { + if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) { // We need to ensure that any subsequent modifiers appear on the same line // so that when 'const' is a standalone declaration, we don't issue an error. if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) { return undefined; } } - else if (stopOnStartOfClassStaticBlock && token() === ts.SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { + else if (stopOnStartOfClassStaticBlock && token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { return undefined; } - else if (hasSeenStaticModifier && token() === ts.SyntaxKind.StaticKeyword) { + else if (hasSeenStaticModifier && token() === SyntaxKind.StaticKeyword) { return undefined; } else { @@ -7336,14 +7402,14 @@ namespace Parser { } } - return finishNode(factory.createToken(kind as ts.Modifier["kind"]), pos); + return finishNode(factory.createToken(kind as Modifier["kind"]), pos); } - function combineDecoratorsAndModifiers(decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.NodeArray | undefined { + function combineDecoratorsAndModifiers(decorators: NodeArray | undefined, modifiers: NodeArray | undefined): NodeArray | undefined { if (!decorators) return modifiers; if (!modifiers) return decorators; - const decoratorsAndModifiers = factory.createNodeArray(ts.concatenate(decorators, modifiers)); - ts.setTextRangePosEnd(decoratorsAndModifiers, decorators.pos, modifiers.end); + const decoratorsAndModifiers = factory.createNodeArray(concatenate(decorators, modifiers)); + setTextRangePosEnd(decoratorsAndModifiers, decorators.pos, modifiers.end); return decoratorsAndModifiers; } @@ -7354,30 +7420,30 @@ namespace Parser { * * In such situations, 'permitInvalidConstAsModifier' should be set to true. */ - function parseModifiers(permitInvalidConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): ts.NodeArray | undefined { + function parseModifiers(permitInvalidConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined { const pos = getNodePos(); let list, modifier, hasSeenStatic = false; while (modifier = tryParseModifier(permitInvalidConstAsModifier, stopOnStartOfClassStaticBlock, hasSeenStatic)) { - if (modifier.kind === ts.SyntaxKind.StaticKeyword) hasSeenStatic = true; - list = ts.append(list, modifier); + if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStatic = true; + list = append(list, modifier); } return list && createNodeArray(list, pos); } - function parseModifiersForArrowFunction(): ts.NodeArray | undefined { - let modifiers: ts.NodeArray | undefined; - if (token() === ts.SyntaxKind.AsyncKeyword) { + function parseModifiersForArrowFunction(): NodeArray | undefined { + let modifiers: NodeArray | undefined; + if (token() === SyntaxKind.AsyncKeyword) { const pos = getNodePos(); nextToken(); - const modifier = finishNode(factory.createToken(ts.SyntaxKind.AsyncKeyword), pos); - modifiers = createNodeArray([modifier], pos); + const modifier = finishNode(factory.createToken(SyntaxKind.AsyncKeyword), pos); + modifiers = createNodeArray([modifier], pos); } return modifiers; } - function parseClassElement(): ts.ClassElement { + function parseClassElement(): ClassElement { const pos = getNodePos(); - if (token() === ts.SyntaxKind.SemicolonToken) { + if (token() === SyntaxKind.SemicolonToken) { nextToken(); return finishNode(factory.createSemicolonClassElement(), pos); } @@ -7385,19 +7451,19 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const decorators = parseDecorators(); const modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true, /*stopOnStartOfClassStaticBlock*/ true); - if (token() === ts.SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { + if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { return parseClassStaticBlockDeclaration(pos, hasJSDoc, decorators, modifiers); } - if (parseContextualModifier(ts.SyntaxKind.GetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.GetAccessor, SignatureFlags.None); + if (parseContextualModifier(SyntaxKind.GetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor, SignatureFlags.None); } - if (parseContextualModifier(ts.SyntaxKind.SetKeyword)) { - return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.SetAccessor, SignatureFlags.None); + if (parseContextualModifier(SyntaxKind.SetKeyword)) { + return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor, SignatureFlags.None); } - if (token() === ts.SyntaxKind.ConstructorKeyword || token() === ts.SyntaxKind.StringLiteral) { + if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) { const constructorDeclaration = tryParseConstructorDeclaration(pos, hasJSDoc, decorators, modifiers); if (constructorDeclaration) { return constructorDeclaration; @@ -7410,17 +7476,17 @@ namespace Parser { // It is very important that we check this *after* checking indexers because // the [ token can start an index signature or a computed property name - if (ts.tokenIsIdentifierOrKeyword(token()) || - token() === ts.SyntaxKind.StringLiteral || - token() === ts.SyntaxKind.NumericLiteral || - token() === ts.SyntaxKind.AsteriskToken || - token() === ts.SyntaxKind.OpenBracketToken) { - const isAmbient = ts.some(modifiers, isDeclareModifier); + if (tokenIsIdentifierOrKeyword(token()) || + token() === SyntaxKind.StringLiteral || + token() === SyntaxKind.NumericLiteral || + token() === SyntaxKind.AsteriskToken || + token() === SyntaxKind.OpenBracketToken) { + const isAmbient = some(modifiers, isDeclareModifier); if (isAmbient) { for (const m of modifiers!) { - (m as ts.Mutable).flags |= ts.NodeFlags.Ambient; + (m as Mutable).flags |= NodeFlags.Ambient; } - return doInsideOfContext(ts.NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers)); + return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers)); } else { return parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers); @@ -7429,50 +7495,50 @@ namespace Parser { if (decorators || modifiers) { // treat this as a property declaration with a missing name. - const name = createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, ts.Diagnostics.Declaration_expected); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, /*questionToken*/ undefined); } // 'isClassMemberStart' should have hinted not to attempt parsing. - return ts.Debug.fail("Should not have attempted to parse class member declaration."); + return Debug.fail("Should not have attempted to parse class member declaration."); } - function parseClassExpression(): ts.ClassExpression { - return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, ts.SyntaxKind.ClassExpression) as ts.ClassExpression; + function parseClassExpression(): ClassExpression { + return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression) as ClassExpression; } - function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ClassDeclaration { - return parseClassDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers, ts.SyntaxKind.ClassDeclaration) as ts.ClassDeclaration; + function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ClassDeclaration { + return parseClassDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers, SyntaxKind.ClassDeclaration) as ClassDeclaration; } - function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined, kind: ts.ClassLikeDeclaration["kind"]): ts.ClassLikeDeclaration { + function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration { const savedAwaitContext = inAwaitContext(); - parseExpected(ts.SyntaxKind.ClassKeyword); + parseExpected(SyntaxKind.ClassKeyword); // We don't parse the name here in await context, instead we will report a grammar error in the checker. const name = parseNameOfClassDeclarationOrExpression(); const typeParameters = parseTypeParameters(); - if (ts.some(modifiers, ts.isExportModifier)) setAwaitContext(/*value*/ true); + if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true); const heritageClauses = parseHeritageClauses(); let members; - if (parseExpected(ts.SyntaxKind.OpenBraceToken)) { + if (parseExpected(SyntaxKind.OpenBraceToken)) { // ClassTail[Yield,Await] : (Modified) See 14.5 // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } members = parseClassMembers(); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } setAwaitContext(savedAwaitContext); - const node = kind === ts.SyntaxKind.ClassDeclaration + const node = kind === SyntaxKind.ClassDeclaration ? factory.createClassDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, typeParameters, heritageClauses, members) : factory.createClassExpression(combineDecoratorsAndModifiers(decorators, modifiers), name, typeParameters, heritageClauses, members); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseNameOfClassDeclarationOrExpression(): ts.Identifier | undefined { + function parseNameOfClassDeclarationOrExpression(): Identifier | undefined { // implements is a future reserved word so // 'class implements' might mean either // - class expression with omitted name, 'implements' starts heritage clause @@ -7484,10 +7550,10 @@ namespace Parser { } function isImplementsClause() { - return token() === ts.SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword); + return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword); } - function parseHeritageClauses(): ts.NodeArray | undefined { + function parseHeritageClauses(): NodeArray | undefined { // ClassTail[Yield,Await] : (Modified) See 14.5 // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } @@ -7498,58 +7564,58 @@ namespace Parser { return undefined; } - function parseHeritageClause(): ts.HeritageClause { + function parseHeritageClause(): HeritageClause { const pos = getNodePos(); const tok = token(); - ts.Debug.assert(tok === ts.SyntaxKind.ExtendsKeyword || tok === ts.SyntaxKind.ImplementsKeyword); // isListElement() should ensure this. + Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this. nextToken(); const types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments); return finishNode(factory.createHeritageClause(tok, types), pos); } - function parseExpressionWithTypeArguments(): ts.ExpressionWithTypeArguments { + function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments { const pos = getNodePos(); const expression = parseLeftHandSideExpressionOrHigher(); - if (expression.kind === ts.SyntaxKind.ExpressionWithTypeArguments) { - return expression as ts.ExpressionWithTypeArguments; + if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) { + return expression as ExpressionWithTypeArguments; } const typeArguments = tryParseTypeArguments(); return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos); } - function tryParseTypeArguments(): ts.NodeArray | undefined { - return token() === ts.SyntaxKind.LessThanToken ? - parseBracketedList(ParsingContext.TypeArguments, parseType, ts.SyntaxKind.LessThanToken, ts.SyntaxKind.GreaterThanToken) : undefined; + function tryParseTypeArguments(): NodeArray | undefined { + return token() === SyntaxKind.LessThanToken ? + parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : undefined; } function isHeritageClause(): boolean { - return token() === ts.SyntaxKind.ExtendsKeyword || token() === ts.SyntaxKind.ImplementsKeyword; + return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; } - function parseClassMembers(): ts.NodeArray { + function parseClassMembers(): NodeArray { return parseList(ParsingContext.ClassMembers, parseClassElement); } - function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.InterfaceDeclaration { - parseExpected(ts.SyntaxKind.InterfaceKeyword); + function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): InterfaceDeclaration { + parseExpected(SyntaxKind.InterfaceKeyword); const name = parseIdentifier(); const typeParameters = parseTypeParameters(); const heritageClauses = parseHeritageClauses(); const members = parseObjectTypeMembers(); const node = factory.createInterfaceDeclaration(modifiers, name, typeParameters, heritageClauses, members); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.TypeAliasDeclaration { - parseExpected(ts.SyntaxKind.TypeKeyword); + function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): TypeAliasDeclaration { + parseExpected(SyntaxKind.TypeKeyword); const name = parseIdentifier(); const typeParameters = parseTypeParameters(); - parseExpected(ts.SyntaxKind.EqualsToken); - const type = token() === ts.SyntaxKind.IntrinsicKeyword && tryParse(parseKeywordAndNoDot) || parseType(); + parseExpected(SyntaxKind.EqualsToken); + const type = token() === SyntaxKind.IntrinsicKeyword && tryParse(parseKeywordAndNoDot) || parseType(); parseSemicolon(); const node = factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } @@ -7557,7 +7623,7 @@ namespace Parser { // In a non-ambient declaration, the grammar allows uninitialized members only in a // ConstantEnumMemberSection, which starts at the beginning of an enum declaration // or any time an integer literal initializer is encountered. - function parseEnumMember(): ts.EnumMember { + function parseEnumMember(): EnumMember { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const name = parsePropertyName(); @@ -7565,84 +7631,84 @@ namespace Parser { return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc); } - function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.EnumDeclaration { - parseExpected(ts.SyntaxKind.EnumKeyword); + function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): EnumDeclaration { + parseExpected(SyntaxKind.EnumKeyword); const name = parseIdentifier(); let members; - if (parseExpected(ts.SyntaxKind.OpenBraceToken)) { + if (parseExpected(SyntaxKind.OpenBraceToken)) { members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember)); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } const node = factory.createEnumDeclaration(modifiers, name, members); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleBlock(): ts.ModuleBlock { + function parseModuleBlock(): ModuleBlock { const pos = getNodePos(); let statements; - if (parseExpected(ts.SyntaxKind.OpenBraceToken)) { + if (parseExpected(SyntaxKind.OpenBraceToken)) { statements = parseList(ParsingContext.BlockStatements, parseStatement); - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } else { - statements = createMissingList(); + statements = createMissingList(); } return finishNode(factory.createModuleBlock(statements), pos); } - function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined, flags: ts.NodeFlags): ts.ModuleDeclaration { + function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, flags: NodeFlags): ModuleDeclaration { // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. - const namespaceFlag = flags & ts.NodeFlags.Namespace; + const namespaceFlag = flags & NodeFlags.Namespace; const name = parseIdentifier(); - const body = parseOptional(ts.SyntaxKind.DotToken) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*decorators*/ undefined, /*modifiers*/ undefined, ts.NodeFlags.NestedNamespace | namespaceFlag) as ts.NamespaceDeclaration + const body = parseOptional(SyntaxKind.DotToken) + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) as NamespaceDeclaration : parseModuleBlock(); const node = factory.createModuleDeclaration(modifiers, name, body, flags); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ModuleDeclaration { - let flags: ts.NodeFlags = 0; + function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { + let flags: NodeFlags = 0; let name; - if (token() === ts.SyntaxKind.GlobalKeyword) { + if (token() === SyntaxKind.GlobalKeyword) { // parse 'global' as name of global scope augmentation name = parseIdentifier(); - flags |= ts.NodeFlags.GlobalAugmentation; + flags |= NodeFlags.GlobalAugmentation; } else { - name = parseLiteralNode() as ts.StringLiteral; + name = parseLiteralNode() as StringLiteral; name.text = internIdentifier(name.text); } - let body: ts.ModuleBlock | undefined; - if (token() === ts.SyntaxKind.OpenBraceToken) { + let body: ModuleBlock | undefined; + if (token() === SyntaxKind.OpenBraceToken) { body = parseModuleBlock(); } else { parseSemicolon(); } const node = factory.createModuleDeclaration(modifiers, name, body, flags); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ModuleDeclaration { - let flags: ts.NodeFlags = 0; - if (token() === ts.SyntaxKind.GlobalKeyword) { + function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ModuleDeclaration { + let flags: NodeFlags = 0; + if (token() === SyntaxKind.GlobalKeyword) { // global augmentation return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers); } - else if (parseOptional(ts.SyntaxKind.NamespaceKeyword)) { - flags |= ts.NodeFlags.Namespace; + else if (parseOptional(SyntaxKind.NamespaceKeyword)) { + flags |= NodeFlags.Namespace; } else { - parseExpected(ts.SyntaxKind.ModuleKeyword); - if (token() === ts.SyntaxKind.StringLiteral) { + parseExpected(SyntaxKind.ModuleKeyword); + if (token() === SyntaxKind.StringLiteral) { return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers); } } @@ -7650,47 +7716,47 @@ namespace Parser { } function isExternalModuleReference() { - return token() === ts.SyntaxKind.RequireKeyword && + return token() === SyntaxKind.RequireKeyword && lookAhead(nextTokenIsOpenParen); } function nextTokenIsOpenParen() { - return nextToken() === ts.SyntaxKind.OpenParenToken; + return nextToken() === SyntaxKind.OpenParenToken; } function nextTokenIsOpenBrace() { - return nextToken() === ts.SyntaxKind.OpenBraceToken; + return nextToken() === SyntaxKind.OpenBraceToken; } function nextTokenIsSlash() { - return nextToken() === ts.SyntaxKind.SlashToken; + return nextToken() === SyntaxKind.SlashToken; } - function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.NamespaceExportDeclaration { - parseExpected(ts.SyntaxKind.AsKeyword); - parseExpected(ts.SyntaxKind.NamespaceKeyword); + function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): NamespaceExportDeclaration { + parseExpected(SyntaxKind.AsKeyword); + parseExpected(SyntaxKind.NamespaceKeyword); const name = parseIdentifier(); parseSemicolon(); const node = factory.createNamespaceExportDeclaration(name); // NamespaceExportDeclaration nodes cannot have decorators or modifiers, so we attach them here so we can report them in the grammar checker - (node as ts.Mutable).illegalDecorators = decorators; - (node as ts.Mutable).modifiers = modifiers; + (node as Mutable).illegalDecorators = decorators; + (node as Mutable).modifiers = modifiers; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ImportEqualsDeclaration | ts.ImportDeclaration { - parseExpected(ts.SyntaxKind.ImportKeyword); + function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ImportEqualsDeclaration | ImportDeclaration { + parseExpected(SyntaxKind.ImportKeyword); const afterImportPos = scanner.getStartPos(); // We don't parse the identifier here in await context, instead we will report a grammar error in the checker. - let identifier: ts.Identifier | undefined; + let identifier: Identifier | undefined; if (isIdentifier()) { identifier = parseIdentifier(); } let isTypeOnly = false; - if (token() !== ts.SyntaxKind.FromKeyword && + if (token() !== SyntaxKind.FromKeyword && identifier?.escapedText === "type" && (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration()) ) { @@ -7705,31 +7771,31 @@ namespace Parser { // ImportDeclaration: // import ImportClause from ModuleSpecifier ; // import ModuleSpecifier; - let importClause: ts.ImportClause | undefined; + let importClause: ImportClause | undefined; if (identifier || // import id - token() === ts.SyntaxKind.AsteriskToken || // import * - token() === ts.SyntaxKind.OpenBraceToken // import { + token() === SyntaxKind.AsteriskToken || // import * + token() === SyntaxKind.OpenBraceToken // import { ) { importClause = parseImportClause(identifier, afterImportPos, isTypeOnly); - parseExpected(ts.SyntaxKind.FromKeyword); + parseExpected(SyntaxKind.FromKeyword); } const moduleSpecifier = parseModuleSpecifier(); - let assertClause: ts.AssertClause | undefined; - if (token() === ts.SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) { + let assertClause: AssertClause | undefined; + if (token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) { assertClause = parseAssertClause(); } parseSemicolon(); const node = factory.createImportDeclaration(modifiers, importClause, moduleSpecifier, assertClause); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } function parseAssertEntry() { const pos = getNodePos(); - const name = ts.tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(ts.SyntaxKind.StringLiteral) as ts.StringLiteral; - parseExpected(ts.SyntaxKind.ColonToken); + const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral; + parseExpected(SyntaxKind.ColonToken); const value = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return finishNode(factory.createAssertEntry(name, value), pos); } @@ -7737,18 +7803,18 @@ namespace Parser { function parseAssertClause(skipAssertKeyword?: true) { const pos = getNodePos(); if (!skipAssertKeyword) { - parseExpected(ts.SyntaxKind.AssertKeyword); + parseExpected(SyntaxKind.AssertKeyword); } const openBracePosition = scanner.getTokenPos(); - if (parseExpected(ts.SyntaxKind.OpenBraceToken)) { + if (parseExpected(SyntaxKind.OpenBraceToken)) { const multiLine = scanner.hasPrecedingLineBreak(); const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true); - if (!parseExpected(ts.SyntaxKind.CloseBraceToken)) { - const lastError = ts.lastOrUndefined(parseDiagnostics); - if (lastError && lastError.code === ts.Diagnostics._0_expected.code) { - ts.addRelatedInfo( + if (!parseExpected(SyntaxKind.CloseBraceToken)) { + const lastError = lastOrUndefined(parseDiagnostics); + if (lastError && lastError.code === Diagnostics._0_expected.code) { + addRelatedInfo( lastError, - ts.createDetachedDiagnostic(fileName, openBracePosition, 1, ts.Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") + createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}") ); } } @@ -7761,26 +7827,26 @@ namespace Parser { } function tokenAfterImportDefinitelyProducesImportDeclaration() { - return token() === ts.SyntaxKind.AsteriskToken || token() === ts.SyntaxKind.OpenBraceToken; + return token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken; } function tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration() { // In `import id ___`, the current token decides whether to produce // an ImportDeclaration or ImportEqualsDeclaration. - return token() === ts.SyntaxKind.CommaToken || token() === ts.SyntaxKind.FromKeyword; + return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword; } - function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined, identifier: ts.Identifier, isTypeOnly: boolean): ts.ImportEqualsDeclaration { - parseExpected(ts.SyntaxKind.EqualsToken); + function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined, identifier: Identifier, isTypeOnly: boolean): ImportEqualsDeclaration { + parseExpected(SyntaxKind.EqualsToken); const moduleReference = parseModuleReference(); parseSemicolon(); const node = factory.createImportEqualsDeclaration(modifiers, isTypeOnly, identifier, moduleReference); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; const finished = withJSDoc(finishNode(node, pos), hasJSDoc); return finished; } - function parseImportClause(identifier: ts.Identifier | undefined, pos: number, isTypeOnly: boolean) { + function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -7790,10 +7856,10 @@ namespace Parser { // If there was no default import or if there is comma token after default import // parse namespace or named imports - let namedBindings: ts.NamespaceImport | ts.NamedImports | undefined; + let namedBindings: NamespaceImport | NamedImports | undefined; if (!identifier || - parseOptional(ts.SyntaxKind.CommaToken)) { - namedBindings = token() === ts.SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(ts.SyntaxKind.NamedImports); + parseOptional(SyntaxKind.CommaToken)) { + namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports); } return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos); @@ -7807,15 +7873,15 @@ namespace Parser { function parseExternalModuleReference() { const pos = getNodePos(); - parseExpected(ts.SyntaxKind.RequireKeyword); - parseExpected(ts.SyntaxKind.OpenParenToken); + parseExpected(SyntaxKind.RequireKeyword); + parseExpected(SyntaxKind.OpenParenToken); const expression = parseModuleSpecifier(); - parseExpected(ts.SyntaxKind.CloseParenToken); + parseExpected(SyntaxKind.CloseParenToken); return finishNode(factory.createExternalModuleReference(expression), pos); } - function parseModuleSpecifier(): ts.Expression { - if (token() === ts.SyntaxKind.StringLiteral) { + function parseModuleSpecifier(): Expression { + if (token() === SyntaxKind.StringLiteral) { const result = parseLiteralNode(); result.text = internIdentifier(result.text); return result; @@ -7828,19 +7894,19 @@ namespace Parser { } } - function parseNamespaceImport(): ts.NamespaceImport { + function parseNamespaceImport(): NamespaceImport { // NameSpaceImport: // * as ImportedBinding const pos = getNodePos(); - parseExpected(ts.SyntaxKind.AsteriskToken); - parseExpected(ts.SyntaxKind.AsKeyword); + parseExpected(SyntaxKind.AsteriskToken); + parseExpected(SyntaxKind.AsKeyword); const name = parseIdentifier(); return finishNode(factory.createNamespaceImport(name), pos); } - function parseNamedImportsOrExports(kind: ts.SyntaxKind.NamedImports): ts.NamedImports; - function parseNamedImportsOrExports(kind: ts.SyntaxKind.NamedExports): ts.NamedExports; - function parseNamedImportsOrExports(kind: ts.SyntaxKind): ts.NamedImportsOrExports { + function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports; + function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports; + function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports { const pos = getNodePos(); // NamedImports: @@ -7851,22 +7917,22 @@ namespace Parser { // ImportsList: // ImportSpecifier // ImportsList, ImportSpecifier - const node = kind === ts.SyntaxKind.NamedImports - ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken)) - : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken)); + const node = kind === SyntaxKind.NamedImports + ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)) + : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken)); return finishNode(node, pos); } function parseExportSpecifier() { const hasJSDoc = hasPrecedingJSDocComment(); - return withJSDoc(parseImportOrExportSpecifier(ts.SyntaxKind.ExportSpecifier) as ts.ExportSpecifier, hasJSDoc); + return withJSDoc(parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as ExportSpecifier, hasJSDoc); } function parseImportSpecifier() { - return parseImportOrExportSpecifier(ts.SyntaxKind.ImportSpecifier) as ts.ImportSpecifier; + return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as ImportSpecifier; } - function parseImportOrExportSpecifier(kind: ts.SyntaxKind): ts.ImportOrExportSpecifier { + function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier { const pos = getNodePos(); // ImportSpecifier: // BindingIdentifier @@ -7874,11 +7940,11 @@ namespace Parser { // ExportSpecifier: // IdentifierName // IdentifierName as IdentifierName - let checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); + let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); let checkIdentifierStart = scanner.getTokenPos(); let checkIdentifierEnd = scanner.getTextPos(); let isTypeOnly = false; - let propertyName: ts.Identifier | undefined; + let propertyName: Identifier | undefined; let canParseAsKeyword = true; let name = parseIdentifierName(); if (name.escapedText === "type") { @@ -7889,13 +7955,13 @@ namespace Parser { // import { type as } from "mod"; - isTypeOnly: true, name: as // import { type as as } from "mod"; - isTypeOnly: false, name: as, propertyName: type // import { type as as as } from "mod"; - isTypeOnly: true, name: as, propertyName: as - if (token() === ts.SyntaxKind.AsKeyword) { + if (token() === SyntaxKind.AsKeyword) { // { type as ...? } const firstAs = parseIdentifierName(); - if (token() === ts.SyntaxKind.AsKeyword) { + if (token() === SyntaxKind.AsKeyword) { // { type as as ...? } const secondAs = parseIdentifierName(); - if (ts.tokenIsIdentifierOrKeyword(token())) { + if (tokenIsIdentifierOrKeyword(token())) { // { type as as something } isTypeOnly = true; propertyName = firstAs; @@ -7909,7 +7975,7 @@ namespace Parser { canParseAsKeyword = false; } } - else if (ts.tokenIsIdentifierOrKeyword(token())) { + else if (tokenIsIdentifierOrKeyword(token())) { // { type as something } propertyName = name; canParseAsKeyword = false; @@ -7921,88 +7987,88 @@ namespace Parser { name = firstAs; } } - else if (ts.tokenIsIdentifierOrKeyword(token())) { + else if (tokenIsIdentifierOrKeyword(token())) { // { type something ...? } isTypeOnly = true; name = parseNameWithKeywordCheck(); } } - if (canParseAsKeyword && token() === ts.SyntaxKind.AsKeyword) { + if (canParseAsKeyword && token() === SyntaxKind.AsKeyword) { propertyName = name; - parseExpected(ts.SyntaxKind.AsKeyword); + parseExpected(SyntaxKind.AsKeyword); name = parseNameWithKeywordCheck(); } - if (kind === ts.SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) { - parseErrorAt(checkIdentifierStart, checkIdentifierEnd, ts.Diagnostics.Identifier_expected); + if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) { + parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected); } - const node = kind === ts.SyntaxKind.ImportSpecifier + const node = kind === SyntaxKind.ImportSpecifier ? factory.createImportSpecifier(isTypeOnly, propertyName, name) : factory.createExportSpecifier(isTypeOnly, propertyName, name); return finishNode(node, pos); function parseNameWithKeywordCheck() { - checkIdentifierIsKeyword = ts.isKeyword(token()) && !isIdentifier(); + checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier(); checkIdentifierStart = scanner.getTokenPos(); checkIdentifierEnd = scanner.getTextPos(); return parseIdentifierName(); } } - function parseNamespaceExport(pos: number): ts.NamespaceExport { + function parseNamespaceExport(pos: number): NamespaceExport { return finishNode(factory.createNamespaceExport(parseIdentifierName()), pos); } - function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ExportDeclaration { + function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportDeclaration { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); - let exportClause: ts.NamedExportBindings | undefined; - let moduleSpecifier: ts.Expression | undefined; - let assertClause: ts.AssertClause | undefined; - const isTypeOnly = parseOptional(ts.SyntaxKind.TypeKeyword); + let exportClause: NamedExportBindings | undefined; + let moduleSpecifier: Expression | undefined; + let assertClause: AssertClause | undefined; + const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword); const namespaceExportPos = getNodePos(); - if (parseOptional(ts.SyntaxKind.AsteriskToken)) { - if (parseOptional(ts.SyntaxKind.AsKeyword)) { + if (parseOptional(SyntaxKind.AsteriskToken)) { + if (parseOptional(SyntaxKind.AsKeyword)) { exportClause = parseNamespaceExport(namespaceExportPos); } - parseExpected(ts.SyntaxKind.FromKeyword); + parseExpected(SyntaxKind.FromKeyword); moduleSpecifier = parseModuleSpecifier(); } else { - exportClause = parseNamedImportsOrExports(ts.SyntaxKind.NamedExports); + exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports); // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios, // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`) // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect. - if (token() === ts.SyntaxKind.FromKeyword || (token() === ts.SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) { - parseExpected(ts.SyntaxKind.FromKeyword); + if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) { + parseExpected(SyntaxKind.FromKeyword); moduleSpecifier = parseModuleSpecifier(); } } - if (moduleSpecifier && token() === ts.SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) { + if (moduleSpecifier && token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) { assertClause = parseAssertClause(); } parseSemicolon(); setAwaitContext(savedAwaitContext); const node = factory.createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: ts.NodeArray | undefined, modifiers: ts.NodeArray | undefined): ts.ExportAssignment { + function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: NodeArray | undefined, modifiers: NodeArray | undefined): ExportAssignment { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); let isExportEquals: boolean | undefined; - if (parseOptional(ts.SyntaxKind.EqualsToken)) { + if (parseOptional(SyntaxKind.EqualsToken)) { isExportEquals = true; } else { - parseExpected(ts.SyntaxKind.DefaultKeyword); + parseExpected(SyntaxKind.DefaultKeyword); } const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); parseSemicolon(); setAwaitContext(savedAwaitContext); const node = factory.createExportAssignment(modifiers, isExportEquals, expression); - (node as ts.Mutable).illegalDecorators = decorators; + (node as Mutable).illegalDecorators = decorators; return withJSDoc(finishNode(node, pos), hasJSDoc); } @@ -8042,16 +8108,16 @@ namespace Parser { } export namespace JSDocParser { - export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: ts.JSDocTypeExpression, diagnostics: ts.Diagnostic[] } | undefined { - initializeState("file.js", content, ts.ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ts.ScriptKind.JS); + export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { + initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); scanner.setText(content, start, length); currentToken = scanner.scan(); const jsDocTypeExpression = parseJSDocTypeExpression(); - const sourceFile = createSourceFile("file.js", ts.ScriptTarget.Latest, ts.ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None, ts.noop); - const diagnostics = ts.attachFileToDiagnostics(parseDiagnostics, sourceFile); + const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(SyntaxKind.EndOfFileToken), NodeFlags.None, noop); + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = ts.attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); } clearState(); @@ -8060,12 +8126,12 @@ namespace Parser { } // Parses out a JSDoc type expression. - export function parseJSDocTypeExpression(mayOmitBraces?: boolean): ts.JSDocTypeExpression { + export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression { const pos = getNodePos(); - const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(ts.SyntaxKind.OpenBraceToken); - const type = doInsideOfContext(ts.NodeFlags.JSDoc, parseJSDocType); + const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken); + const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); if (!mayOmitBraces || hasBrace) { - parseExpectedJSDoc(ts.SyntaxKind.CloseBraceToken); + parseExpectedJSDoc(SyntaxKind.CloseBraceToken); } const result = factory.createJSDocTypeExpression(type); @@ -8073,18 +8139,18 @@ namespace Parser { return finishNode(result, pos); } - export function parseJSDocNameReference(): ts.JSDocNameReference { + export function parseJSDocNameReference(): JSDocNameReference { const pos = getNodePos(); - const hasBrace = parseOptional(ts.SyntaxKind.OpenBraceToken); + const hasBrace = parseOptional(SyntaxKind.OpenBraceToken); const p2 = getNodePos(); - let entityName: ts.EntityName | ts.JSDocMemberName = parseEntityName(/* allowReservedWords*/ false); - while (token() === ts.SyntaxKind.PrivateIdentifier) { + let entityName: EntityName | JSDocMemberName = parseEntityName(/* allowReservedWords*/ false); + while (token() === SyntaxKind.PrivateIdentifier) { reScanHashToken(); // rescan #id as # id nextTokenJSDoc(); // then skip the # entityName = finishNode(factory.createJSDocMemberName(entityName, parseIdentifier()), p2); } if (hasBrace) { - parseExpectedJSDoc(ts.SyntaxKind.CloseBraceToken); + parseExpectedJSDoc(SyntaxKind.CloseBraceToken); } const result = factory.createJSDocNameReference(entityName); @@ -8092,26 +8158,26 @@ namespace Parser { return finishNode(result, pos); } - export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: ts.JSDoc, diagnostics: ts.Diagnostic[] } | undefined { - initializeState("", content, ts.ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ts.ScriptKind.JS); - const jsDoc = doInsideOfContext(ts.NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); + export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined { + initializeState("", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS); + const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); - const sourceFile = { languageVariant: ts.LanguageVariant.Standard, text: content } as ts.SourceFile; - const diagnostics = ts.attachFileToDiagnostics(parseDiagnostics, sourceFile); + const sourceFile = { languageVariant: LanguageVariant.Standard, text: content } as SourceFile; + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); clearState(); return jsDoc ? { jsDoc, diagnostics } : undefined; } - export function parseJSDocComment(parent: ts.HasJSDoc, start: number, length: number): ts.JSDoc | undefined { + export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined { const saveToken = currentToken; const saveParseDiagnosticsLength = parseDiagnostics.length; const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; - const comment = doInsideOfContext(ts.NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); - ts.setParent(comment, parent); + const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length)); + setParent(comment, parent); - if (contextFlags & ts.NodeFlags.JavaScriptFile) { + if (contextFlags & NodeFlags.JavaScriptFile) { if (!jsDocDiagnostics) { jsDocDiagnostics = []; } @@ -8136,27 +8202,27 @@ namespace Parser { CallbackParameter = 1 << 2, } - function parseJSDocCommentWorker(start = 0, length: number | undefined): ts.JSDoc | undefined { + function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined { const content = sourceText; const end = length === undefined ? content.length : start + length; length = end - start; - ts.Debug.assert(start >= 0); - ts.Debug.assert(start <= end); - ts.Debug.assert(end <= content.length); + Debug.assert(start >= 0); + Debug.assert(start <= end); + Debug.assert(end <= content.length); // Check for /** (JSDoc opening part) if (!isJSDocLikeText(content, start)) { return undefined; } - let tags: ts.JSDocTag[]; + let tags: JSDocTag[]; let tagsPos: number; let tagsEnd: number; let linkEnd: number; let commentsPos: number | undefined; let comments: string[] = []; - const parts: ts.JSDocComment[] = []; + const parts: JSDocComment[] = []; // + 3 for leading /**, - 5 in total for /** */ return scanner.scanRange(start + 3, length - 5, () => { @@ -8176,14 +8242,14 @@ namespace Parser { } nextTokenJSDoc(); - while (parseOptionalJsdoc(ts.SyntaxKind.WhitespaceTrivia)); - if (parseOptionalJsdoc(ts.SyntaxKind.NewLineTrivia)) { + while (parseOptionalJsdoc(SyntaxKind.WhitespaceTrivia)); + if (parseOptionalJsdoc(SyntaxKind.NewLineTrivia)) { state = JSDocState.BeginningOfLine; indent = 0; } loop: while (true) { switch (token()) { - case ts.SyntaxKind.AtToken: + case SyntaxKind.AtToken: if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) { removeTrailingWhitespace(comments); if (!commentsPos) commentsPos = getNodePos(); @@ -8198,12 +8264,12 @@ namespace Parser { pushComment(scanner.getTokenText()); } break; - case ts.SyntaxKind.NewLineTrivia: + case SyntaxKind.NewLineTrivia: comments.push(scanner.getTokenText()); state = JSDocState.BeginningOfLine; indent = 0; break; - case ts.SyntaxKind.AsteriskToken: + case SyntaxKind.AsteriskToken: const asterisk = scanner.getTokenText(); if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) { // If we've already seen an asterisk, then we can no longer parse a tag on this line @@ -8216,7 +8282,7 @@ namespace Parser { indent += asterisk.length; } break; - case ts.SyntaxKind.WhitespaceTrivia: + case SyntaxKind.WhitespaceTrivia: // only collect whitespace if we're already saving comments or have just crossed the comment indent margin const whitespace = scanner.getTokenText(); if (state === JSDocState.SavingComments) { @@ -8227,9 +8293,9 @@ namespace Parser { } indent += whitespace.length; break; - case ts.SyntaxKind.EndOfFileToken: + case SyntaxKind.EndOfFileToken: break loop; - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: state = JSDocState.SavingComments; const commentEnd = scanner.getStartPos(); const linkStart = scanner.getTextPos() - 1; @@ -8259,7 +8325,7 @@ namespace Parser { if (parts.length && comments.length) { parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? start, commentsPos)); } - if (parts.length && tags) ts.Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set"); + if (parts.length && tags) Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set"); const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd); return finishNode(factory.createJSDocComment(parts.length ? createNodeArray(parts, start, commentsPos) : comments.length ? comments.join("") : undefined, tagsArray), start, end); }); @@ -8280,28 +8346,28 @@ namespace Parser { // We must use infinite lookahead, as there could be any number of newlines :( while (true) { nextTokenJSDoc(); - if (token() === ts.SyntaxKind.EndOfFileToken) { + if (token() === SyntaxKind.EndOfFileToken) { return true; } - if (!(token() === ts.SyntaxKind.WhitespaceTrivia || token() === ts.SyntaxKind.NewLineTrivia)) { + if (!(token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia)) { return false; } } } function skipWhitespace(): void { - if (token() === ts.SyntaxKind.WhitespaceTrivia || token() === ts.SyntaxKind.NewLineTrivia) { + if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range } } - while (token() === ts.SyntaxKind.WhitespaceTrivia || token() === ts.SyntaxKind.NewLineTrivia) { + while (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { nextTokenJSDoc(); } } function skipWhitespaceOrAsterisk(): string { - if (token() === ts.SyntaxKind.WhitespaceTrivia || token() === ts.SyntaxKind.NewLineTrivia) { + if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) { return ""; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range } @@ -8310,14 +8376,14 @@ namespace Parser { let precedingLineBreak = scanner.hasPrecedingLineBreak(); let seenLineBreak = false; let indentText = ""; - while ((precedingLineBreak && token() === ts.SyntaxKind.AsteriskToken) || token() === ts.SyntaxKind.WhitespaceTrivia || token() === ts.SyntaxKind.NewLineTrivia) { + while ((precedingLineBreak && token() === SyntaxKind.AsteriskToken) || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) { indentText += scanner.getTokenText(); - if (token() === ts.SyntaxKind.NewLineTrivia) { + if (token() === SyntaxKind.NewLineTrivia) { precedingLineBreak = true; seenLineBreak = true; indentText = ""; } - else if (token() === ts.SyntaxKind.AsteriskToken) { + else if (token() === SyntaxKind.AsteriskToken) { precedingLineBreak = false; } nextTokenJSDoc(); @@ -8326,14 +8392,14 @@ namespace Parser { } function parseTag(margin: number) { - ts.Debug.assert(token() === ts.SyntaxKind.AtToken); + Debug.assert(token() === SyntaxKind.AtToken); const start = scanner.getTokenPos(); nextTokenJSDoc(); const tagName = parseJSDocIdentifierName(/*message*/ undefined); const indentText = skipWhitespaceOrAsterisk(); - let tag: ts.JSDocTag | undefined; + let tag: JSDocTag | undefined; switch (tagName.escapedText) { case "author": tag = parseAuthorTag(start, tagName, margin, indentText); @@ -8412,10 +8478,10 @@ namespace Parser { return parseTagComments(margin, indentText.slice(margin)); } - function parseTagComments(indent: number, initialMargin?: string): string | ts.NodeArray | undefined { + function parseTagComments(indent: number, initialMargin?: string): string | NodeArray | undefined { const commentsPos = getNodePos(); let comments: string[] = []; - const parts: ts.JSDocComment[] = []; + const parts: JSDocComment[] = []; let linkEnd; let state = JSDocState.BeginningOfLine; let previousWhitespace = true; @@ -8434,16 +8500,16 @@ namespace Parser { } state = JSDocState.SawAsterisk; } - let tok = token() as ts.JSDocSyntaxKind; + let tok = token() as JSDocSyntaxKind; loop: while (true) { switch (tok) { - case ts.SyntaxKind.NewLineTrivia: + case SyntaxKind.NewLineTrivia: state = JSDocState.BeginningOfLine; // don't use pushComment here because we want to keep the margin unchanged comments.push(scanner.getTokenText()); indent = 0; break; - case ts.SyntaxKind.AtToken: + case SyntaxKind.AtToken: if (state === JSDocState.SavingBackticks || state === JSDocState.SavingComments && (!previousWhitespace || lookAhead(isNextJSDocTokenWhitespace))) { // @ doesn't start a new tag inside ``, and inside a comment, only after whitespace or not before whitespace @@ -8452,10 +8518,10 @@ namespace Parser { } scanner.setTextPos(scanner.getTextPos() - 1); // falls through - case ts.SyntaxKind.EndOfFileToken: + case SyntaxKind.EndOfFileToken: // Done break loop; - case ts.SyntaxKind.WhitespaceTrivia: + case SyntaxKind.WhitespaceTrivia: if (state === JSDocState.SavingComments || state === JSDocState.SavingBackticks) { pushComment(scanner.getTokenText()); } @@ -8468,7 +8534,7 @@ namespace Parser { indent += whitespace.length; } break; - case ts.SyntaxKind.OpenBraceToken: + case SyntaxKind.OpenBraceToken: state = JSDocState.SavingComments; const commentEnd = scanner.getStartPos(); const linkStart = scanner.getTextPos() - 1; @@ -8483,7 +8549,7 @@ namespace Parser { pushComment(scanner.getTokenText()); } break; - case ts.SyntaxKind.BacktickToken: + case SyntaxKind.BacktickToken: if (state === JSDocState.SavingBackticks) { state = JSDocState.SavingComments; } @@ -8492,7 +8558,7 @@ namespace Parser { } pushComment(scanner.getTokenText()); break; - case ts.SyntaxKind.AsteriskToken: + case SyntaxKind.AsteriskToken: if (state === JSDocState.BeginningOfLine) { // leading asterisks start recording on the *next* (non-whitespace) token state = JSDocState.SawAsterisk; @@ -8508,7 +8574,7 @@ namespace Parser { pushComment(scanner.getTokenText()); break; } - previousWhitespace = token() === ts.SyntaxKind.WhitespaceTrivia; + previousWhitespace = token() === SyntaxKind.WhitespaceTrivia; tok = nextTokenJSDoc(); } @@ -8527,7 +8593,7 @@ namespace Parser { function isNextJSDocTokenWhitespace() { const next = nextTokenJSDoc(); - return next === ts.SyntaxKind.WhitespaceTrivia || next === ts.SyntaxKind.NewLineTrivia; + return next === SyntaxKind.WhitespaceTrivia || next === SyntaxKind.NewLineTrivia; } function parseJSDocLink(start: number) { @@ -8539,18 +8605,18 @@ namespace Parser { skipWhitespace(); // parseEntityName logs an error for non-identifier, so create a MissingNode ourselves to avoid the error const p2 = getNodePos(); - let name: ts.EntityName | ts.JSDocMemberName | undefined = ts.tokenIsIdentifierOrKeyword(token()) + let name: EntityName | JSDocMemberName | undefined = tokenIsIdentifierOrKeyword(token()) ? parseEntityName(/*allowReservedWords*/ true) : undefined; if (name) { - while (token() === ts.SyntaxKind.PrivateIdentifier) { + while (token() === SyntaxKind.PrivateIdentifier) { reScanHashToken(); // rescan #id as # id nextTokenJSDoc(); // then skip the # name = finishNode(factory.createJSDocMemberName(name, parseIdentifier()), p2); } } const text = []; - while (token() !== ts.SyntaxKind.CloseBraceToken && token() !== ts.SyntaxKind.NewLineTrivia && token() !== ts.SyntaxKind.EndOfFileToken) { + while (token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia && token() !== SyntaxKind.EndOfFileToken) { text.push(scanner.getTokenText()); nextTokenJSDoc(); } @@ -8562,9 +8628,9 @@ namespace Parser { function parseJSDocLinkPrefix() { skipWhitespaceOrAsterisk(); - if (token() === ts.SyntaxKind.OpenBraceToken - && nextTokenJSDoc() === ts.SyntaxKind.AtToken - && ts.tokenIsIdentifierOrKeyword(nextTokenJSDoc())) { + if (token() === SyntaxKind.OpenBraceToken + && nextTokenJSDoc() === SyntaxKind.AtToken + && tokenIsIdentifierOrKeyword(nextTokenJSDoc())) { const kind = scanner.getTokenValue(); if (isJSDocLinkTag(kind)) return kind; } @@ -8574,11 +8640,11 @@ namespace Parser { return kind === "link" || kind === "linkcode" || kind === "linkplain"; } - function parseUnknownTag(start: number, tagName: ts.Identifier, indent: number, indentText: string) { + function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) { return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); } - function addTag(tag: ts.JSDocTag | undefined): void { + function addTag(tag: JSDocTag | undefined): void { if (!tag) { return; } @@ -8592,48 +8658,48 @@ namespace Parser { tagsEnd = tag.end; } - function tryParseTypeExpression(): ts.JSDocTypeExpression | undefined { + function tryParseTypeExpression(): JSDocTypeExpression | undefined { skipWhitespaceOrAsterisk(); - return token() === ts.SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; + return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; } - function parseBracketNameInPropertyAndParamTag(): { name: ts.EntityName, isBracketed: boolean } { + function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } { // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar' - const isBracketed = parseOptionalJsdoc(ts.SyntaxKind.OpenBracketToken); + const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken); if (isBracketed) { skipWhitespace(); } // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild - const isBackquoted = parseOptionalJsdoc(ts.SyntaxKind.BacktickToken); + const isBackquoted = parseOptionalJsdoc(SyntaxKind.BacktickToken); const name = parseJSDocEntityName(); if (isBackquoted) { - parseExpectedTokenJSDoc(ts.SyntaxKind.BacktickToken); + parseExpectedTokenJSDoc(SyntaxKind.BacktickToken); } if (isBracketed) { skipWhitespace(); // May have an optional default, e.g. '[foo = 42]' - if (parseOptionalToken(ts.SyntaxKind.EqualsToken)) { + if (parseOptionalToken(SyntaxKind.EqualsToken)) { parseExpression(); } - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.CloseBracketToken); } return { name, isBracketed }; } - function isObjectOrObjectArrayTypeReference(node: ts.TypeNode): boolean { + function isObjectOrObjectArrayTypeReference(node: TypeNode): boolean { switch (node.kind) { - case ts.SyntaxKind.ObjectKeyword: + case SyntaxKind.ObjectKeyword: return true; - case ts.SyntaxKind.ArrayType: - return isObjectOrObjectArrayTypeReference((node as ts.ArrayTypeNode).elementType); + case SyntaxKind.ArrayType: + return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType); default: - return ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments; + return isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments; } } - function parseParameterOrPropertyTag(start: number, tagName: ts.Identifier, target: PropertyLikeParse, indent: number): ts.JSDocParameterTag | ts.JSDocPropertyTag { + function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; skipWhitespaceOrAsterisk(); @@ -8658,35 +8724,35 @@ namespace Parser { return finishNode(result, start); } - function parseNestedTypeLiteral(typeExpression: ts.JSDocTypeExpression | undefined, name: ts.EntityName, target: PropertyLikeParse, indent: number) { + function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { const pos = getNodePos(); - let child: ts.JSDocPropertyLikeTag | ts.JSDocTypeTag | false; - let children: ts.JSDocPropertyLikeTag[] | undefined; + let child: JSDocPropertyLikeTag | JSDocTypeTag | false; + let children: JSDocPropertyLikeTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { - if (child.kind === ts.SyntaxKind.JSDocParameterTag || child.kind === ts.SyntaxKind.JSDocPropertyTag) { - children = ts.append(children, child); + if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { + children = append(children, child); } } if (children) { - const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === ts.SyntaxKind.ArrayType), pos); + const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos); return finishNode(factory.createJSDocTypeExpression(literal), pos); } } } - function parseReturnTag(start: number, tagName: ts.Identifier, indent: number, indentText: string): ts.JSDocReturnTag { - if (ts.some(tags, ts.isJSDocReturnTag)) { - parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); + function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag { + if (some(tags, isJSDocReturnTag)) { + parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText); } const typeExpression = tryParseTypeExpression(); return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); } - function parseTypeTag(start: number, tagName: ts.Identifier, indent?: number, indentText?: string): ts.JSDocTypeTag { - if (ts.some(tags, ts.isJSDocTypeTag)) { - parseErrorAt(tagName.pos, scanner.getTokenPos(), ts.Diagnostics._0_tag_already_specified, tagName.escapedText); + function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag { + if (some(tags, isJSDocTypeTag)) { + parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText); } const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); @@ -8694,15 +8760,15 @@ namespace Parser { return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start); } - function parseSeeTag(start: number, tagName: ts.Identifier, indent?: number, indentText?: string): ts.JSDocSeeTag { - const isMarkdownOrJSDocLink = token() === ts.SyntaxKind.OpenBracketToken - || lookAhead(() => nextTokenJSDoc() === ts.SyntaxKind.AtToken && ts.tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue())); + function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag { + const isMarkdownOrJSDocLink = token() === SyntaxKind.OpenBracketToken + || lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue())); const nameExpression = isMarkdownOrJSDocLink ? undefined : parseJSDocNameReference(); const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined; return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start); } - function parseAuthorTag(start: number, tagName: ts.Identifier, indent: number, indentText: string): ts.JSDocAuthorTag { + function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { const commentStart = getNodePos(); const textOnly = parseAuthorNameAndEmail(); let commentEnd = scanner.getStartPos(); @@ -8711,23 +8777,23 @@ namespace Parser { commentEnd = scanner.getStartPos(); } const allParts = typeof comments !== "string" - ? createNodeArray(ts.concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as ts.JSDocComment[], commentStart) // cast away readonly + ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], commentStart) // cast away readonly : textOnly.text + comments; return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start); } - function parseAuthorNameAndEmail(): ts.JSDocText { + function parseAuthorNameAndEmail(): JSDocText { const comments: string[] = []; let inEmail = false; let token = scanner.getToken(); - while (token !== ts.SyntaxKind.EndOfFileToken && token !== ts.SyntaxKind.NewLineTrivia) { - if (token === ts.SyntaxKind.LessThanToken) { + while (token !== SyntaxKind.EndOfFileToken && token !== SyntaxKind.NewLineTrivia) { + if (token === SyntaxKind.LessThanToken) { inEmail = true; } - else if (token === ts.SyntaxKind.AtToken && !inEmail) { + else if (token === SyntaxKind.AtToken && !inEmail) { break; } - else if (token === ts.SyntaxKind.GreaterThanToken && inEmail) { + else if (token === SyntaxKind.GreaterThanToken && inEmail) { comments.push(scanner.getTokenText()); scanner.setTextPos(scanner.getTokenPos() + 1); break; @@ -8739,57 +8805,57 @@ namespace Parser { return factory.createJSDocText(comments.join("")); } - function parseImplementsTag(start: number, tagName: ts.Identifier, margin: number, indentText: string): ts.JSDocImplementsTag { + function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag { const className = parseExpressionWithTypeArgumentsForAugments(); return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseAugmentsTag(start: number, tagName: ts.Identifier, margin: number, indentText: string): ts.JSDocAugmentsTag { + function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag { const className = parseExpressionWithTypeArgumentsForAugments(); return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseExpressionWithTypeArgumentsForAugments(): ts.ExpressionWithTypeArguments & { expression: ts.Identifier | ts.PropertyAccessEntityNameExpression } { - const usedBrace = parseOptional(ts.SyntaxKind.OpenBraceToken); + function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } { + const usedBrace = parseOptional(SyntaxKind.OpenBraceToken); const pos = getNodePos(); const expression = parsePropertyAccessEntityNameExpression(); const typeArguments = tryParseTypeArguments(); - const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ts.ExpressionWithTypeArguments & { expression: ts.Identifier | ts.PropertyAccessEntityNameExpression }; + const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression }; const res = finishNode(node, pos); if (usedBrace) { - parseExpected(ts.SyntaxKind.CloseBraceToken); + parseExpected(SyntaxKind.CloseBraceToken); } return res; } function parsePropertyAccessEntityNameExpression() { const pos = getNodePos(); - let node: ts.Identifier | ts.PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); - while (parseOptional(ts.SyntaxKind.DotToken)) { + let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); + while (parseOptional(SyntaxKind.DotToken)) { const name = parseJSDocIdentifierName(); - node = finishNode(factory.createPropertyAccessExpression(node, name), pos) as ts.PropertyAccessEntityNameExpression; + node = finishNode(factory.createPropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression; } return node; } - function parseSimpleTag(start: number, createTag: (tagName: ts.Identifier | undefined, comment?: string | ts.NodeArray) => ts.JSDocTag, tagName: ts.Identifier, margin: number, indentText: string): ts.JSDocTag { + function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag { return finishNode(createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseThisTag(start: number, tagName: ts.Identifier, margin: number, indentText: string): ts.JSDocThisTag { + function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseEnumTag(start: number, tagName: ts.Identifier, margin: number, indentText: string): ts.JSDocEnumTag { + function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseTypedefTag(start: number, tagName: ts.Identifier, indent: number, indentText: string): ts.JSDocTypedefTag { - let typeExpression: ts.JSDocTypeExpression | ts.JSDocTypeLiteral | undefined = tryParseTypeExpression(); + function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag { + let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); skipWhitespaceOrAsterisk(); const fullName = parseJSDocTypeNameWithNamespace(); @@ -8798,17 +8864,17 @@ namespace Parser { let end: number | undefined; if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { - let child: ts.JSDocTypeTag | ts.JSDocPropertyTag | false; - let childTypeTag: ts.JSDocTypeTag | undefined; - let jsDocPropertyTags: ts.JSDocPropertyTag[] | undefined; + let child: JSDocTypeTag | JSDocPropertyTag | false; + let childTypeTag: JSDocTypeTag | undefined; + let jsDocPropertyTags: JSDocPropertyTag[] | undefined; let hasChildren = false; while (child = tryParse(() => parseChildPropertyTag(indent))) { hasChildren = true; - if (child.kind === ts.SyntaxKind.JSDocTypeTag) { + if (child.kind === SyntaxKind.JSDocTypeTag) { if (childTypeTag) { - const lastError = parseErrorAtCurrentToken(ts.Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags); + const lastError = parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags); if (lastError) { - ts.addRelatedInfo(lastError, ts.createDetachedDiagnostic(fileName, 0, 0, ts.Diagnostics.The_tag_was_first_specified_here)); + addRelatedInfo(lastError, createDetachedDiagnostic(fileName, 0, 0, Diagnostics.The_tag_was_first_specified_here)); } break; } @@ -8817,11 +8883,11 @@ namespace Parser { } } else { - jsDocPropertyTags = ts.append(jsDocPropertyTags, child); + jsDocPropertyTags = append(jsDocPropertyTags, child); } } if (hasChildren) { - const isArrayType = typeExpression && typeExpression.type.kind === ts.SyntaxKind.ArrayType; + const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType; const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType); typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? childTypeTag.typeExpression : @@ -8845,18 +8911,18 @@ namespace Parser { function parseJSDocTypeNameWithNamespace(nested?: boolean) { const pos = scanner.getTokenPos(); - if (!ts.tokenIsIdentifierOrKeyword(token())) { + if (!tokenIsIdentifierOrKeyword(token())) { return undefined; } const typeNameOrNamespaceName = parseJSDocIdentifierName(); - if (parseOptional(ts.SyntaxKind.DotToken)) { + if (parseOptional(SyntaxKind.DotToken)) { const body = parseJSDocTypeNameWithNamespace(/*nested*/ true); const jsDocNamespaceNode = factory.createModuleDeclaration( /*modifiers*/ undefined, typeNameOrNamespaceName, body, - nested ? ts.NodeFlags.NestedNamespace : undefined - ) as ts.JSDocNamespaceDeclaration; + nested ? NodeFlags.NestedNamespace : undefined + ) as JSDocNamespaceDeclaration; return finishNode(jsDocNamespaceNode, pos); } @@ -8869,24 +8935,24 @@ namespace Parser { function parseCallbackTagParameters(indent: number) { const pos = getNodePos(); - let child: ts.JSDocParameterTag | false; + let child: JSDocParameterTag | false; let parameters; - while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as ts.JSDocParameterTag)) { - parameters = ts.append(parameters, child); + while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) { + parameters = append(parameters, child); } return createNodeArray(parameters || [], pos); } - function parseCallbackTag(start: number, tagName: ts.Identifier, indent: number, indentText: string): ts.JSDocCallbackTag { + function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); let comment = parseTagComments(indent); const parameters = parseCallbackTagParameters(indent); const returnTag = tryParse(() => { - if (parseOptionalJsdoc(ts.SyntaxKind.AtToken)) { + if (parseOptionalJsdoc(SyntaxKind.AtToken)) { const tag = parseTag(indent); - if (tag && tag.kind === ts.SyntaxKind.JSDocReturnTag) { - return tag as ts.JSDocReturnTag; + if (tag && tag.kind === SyntaxKind.JSDocReturnTag) { + return tag as JSDocReturnTag; } } }); @@ -8898,7 +8964,7 @@ namespace Parser { return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); } - function escapedTextsEqual(a: ts.EntityName, b: ts.EntityName): boolean { + function escapedTextsEqual(a: EntityName, b: EntityName): boolean { while (!ts.isIdentifier(a) || !ts.isIdentifier(b)) { if (!ts.isIdentifier(a) && !ts.isIdentifier(b) && a.right.escapedText === b.right.escapedText) { a = a.left; @@ -8912,18 +8978,18 @@ namespace Parser { } function parseChildPropertyTag(indent: number) { - return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as ts.JSDocTypeTag | ts.JSDocPropertyTag | false; + return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | false; } - function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: ts.EntityName): ts.JSDocTypeTag | ts.JSDocPropertyTag | ts.JSDocParameterTag | false { + function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { let canParseTag = true; let seenAsterisk = false; while (true) { switch (nextTokenJSDoc()) { - case ts.SyntaxKind.AtToken: + case SyntaxKind.AtToken: if (canParseTag) { const child = tryParseChildTag(target, indent); - if (child && (child.kind === ts.SyntaxKind.JSDocParameterTag || child.kind === ts.SyntaxKind.JSDocPropertyTag) && + if (child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && target !== PropertyLikeParse.CallbackParameter && name && (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) { return false; @@ -8932,27 +8998,27 @@ namespace Parser { } seenAsterisk = false; break; - case ts.SyntaxKind.NewLineTrivia: + case SyntaxKind.NewLineTrivia: canParseTag = true; seenAsterisk = false; break; - case ts.SyntaxKind.AsteriskToken: + case SyntaxKind.AsteriskToken: if (seenAsterisk) { canParseTag = false; } seenAsterisk = true; break; - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: canParseTag = false; break; - case ts.SyntaxKind.EndOfFileToken: + case SyntaxKind.EndOfFileToken: return false; } } } - function tryParseChildTag(target: PropertyLikeParse, indent: number): ts.JSDocTypeTag | ts.JSDocPropertyTag | ts.JSDocParameterTag | false { - ts.Debug.assert(token() === ts.SyntaxKind.AtToken); + function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false { + Debug.assert(token() === SyntaxKind.AtToken); const start = scanner.getStartPos(); nextTokenJSDoc(); @@ -8982,21 +9048,21 @@ namespace Parser { function parseTemplateTagTypeParameter() { const typeParameterPos = getNodePos(); - const isBracketed = parseOptionalJsdoc(ts.SyntaxKind.OpenBracketToken); + const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken); if (isBracketed) { skipWhitespace(); } - const name = parseJSDocIdentifierName(ts.Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); + const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); - let defaultType: ts.TypeNode | undefined; + let defaultType: TypeNode | undefined; if (isBracketed) { skipWhitespace(); - parseExpected(ts.SyntaxKind.EqualsToken); - defaultType = doInsideOfContext(ts.NodeFlags.JSDoc, parseJSDocType); - parseExpected(ts.SyntaxKind.CloseBracketToken); + parseExpected(SyntaxKind.EqualsToken); + defaultType = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); + parseExpected(SyntaxKind.CloseBracketToken); } - if (ts.nodeIsMissing(name)) { + if (nodeIsMissing(name)) { return undefined; } return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, /*constraint*/ undefined, defaultType), typeParameterPos); @@ -9012,11 +9078,11 @@ namespace Parser { typeParameters.push(node); } skipWhitespaceOrAsterisk(); - } while (parseOptionalJsdoc(ts.SyntaxKind.CommaToken)); + } while (parseOptionalJsdoc(SyntaxKind.CommaToken)); return createNodeArray(typeParameters, pos); } - function parseTemplateTag(start: number, tagName: ts.Identifier, indent: number, indentText: string): ts.JSDocTemplateTag { + function parseTemplateTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTemplateTag { // The template tag looks like one of the following: // @template T,U,V // @template {Constraint} T @@ -9028,12 +9094,12 @@ namespace Parser { // TODO: Determine whether we should enforce this in the checker. // TODO: Consider moving the `constraint` to the first type parameter as we could then remove `getEffectiveConstraintOfTypeParameter`. // TODO: Consider only parsing a single type parameter if there is a constraint. - const constraint = token() === ts.SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; + const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; const typeParameters = parseTemplateTagTypeParameters(); return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); } - function parseOptionalJsdoc(t: ts.JSDocSyntaxKind): boolean { + function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean { if (token() === t) { nextTokenJSDoc(); return true; @@ -9041,27 +9107,27 @@ namespace Parser { return false; } - function parseJSDocEntityName(): ts.EntityName { - let entity: ts.EntityName = parseJSDocIdentifierName(); - if (parseOptional(ts.SyntaxKind.OpenBracketToken)) { - parseExpected(ts.SyntaxKind.CloseBracketToken); + function parseJSDocEntityName(): EntityName { + let entity: EntityName = parseJSDocIdentifierName(); + if (parseOptional(SyntaxKind.OpenBracketToken)) { + parseExpected(SyntaxKind.CloseBracketToken); // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking. // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}> // but it's not worth it to enforce that restriction. } - while (parseOptional(ts.SyntaxKind.DotToken)) { + while (parseOptional(SyntaxKind.DotToken)) { const name = parseJSDocIdentifierName(); - if (parseOptional(ts.SyntaxKind.OpenBracketToken)) { - parseExpected(ts.SyntaxKind.CloseBracketToken); + if (parseOptional(SyntaxKind.OpenBracketToken)) { + parseExpected(SyntaxKind.CloseBracketToken); } entity = createQualifiedName(entity, name); } return entity; } - function parseJSDocIdentifierName(message?: ts.DiagnosticMessage): ts.Identifier { - if (!ts.tokenIsIdentifierOrKeyword(token())) { - return createMissingNode(ts.SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || ts.Diagnostics.Identifier_expected); + function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier { + if (!tokenIsIdentifierOrKeyword(token())) { + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); } identifierCount++; @@ -9078,11 +9144,11 @@ namespace Parser { } namespace IncrementalParser { - export function updateSourceFile(sourceFile: ts.SourceFile, newText: string, textChangeRange: ts.TextChangeRange, aggressiveChecks: boolean): ts.SourceFile { - aggressiveChecks = aggressiveChecks || ts.Debug.shouldAssert(ts.AssertionLevel.Aggressive); + export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { + aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive); checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); - if (ts.textChangeRangeIsUnchanged(textChangeRange)) { + if (textChangeRangeIsUnchanged(textChangeRange)) { // if the text didn't change, then we can just return our current source file as-is. return sourceFile; } @@ -9099,8 +9165,8 @@ namespace IncrementalParser { // This is because we do incremental parsing in-place. i.e. we take nodes from the old // tree and give them new positions and parents. From that point on, trusting the old // tree at all is not possible as far too much of it may violate invariants. - const incrementalSourceFile = sourceFile as ts.Node as IncrementalNode; - ts.Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); + const incrementalSourceFile = sourceFile as Node as IncrementalNode; + Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed); incrementalSourceFile.hasBeenIncrementallyParsed = true; Parser.fixupParentReferences(incrementalSourceFile); const oldText = sourceFile.text; @@ -9113,14 +9179,14 @@ namespace IncrementalParser { // Ensure that extending the affected range only moved the start of the change range // earlier in the file. - ts.Debug.assert(changeRange.span.start <= textChangeRange.span.start); - ts.Debug.assert(ts.textSpanEnd(changeRange.span) === ts.textSpanEnd(textChangeRange.span)); - ts.Debug.assert(ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)) === ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange))); + Debug.assert(changeRange.span.start <= textChangeRange.span.start); + Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span)); + Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange))); // The is the amount the nodes after the edit range need to be adjusted. It can be // positive (if the edit added characters), negative (if the edit deleted characters) // or zero (if this was a pure overwrite with nothing added/removed). - const delta = ts.textChangeRangeNewSpan(changeRange).length - changeRange.span.length; + const delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length; // If we added or removed characters during the edit, then we need to go and adjust all // the nodes after the edit. Those nodes may move forward (if we inserted chars) or they @@ -9142,7 +9208,7 @@ namespace IncrementalParser { // Also, mark any syntax elements that intersect the changed span. We know, up front, // that we cannot reuse these elements. updateTokenPositionsAndMarkElements(incrementalSourceFile, - changeRange.span.start, ts.textSpanEnd(changeRange.span), ts.textSpanEnd(ts.textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); + changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks); // Now that we've set up our internal incremental state just proceed and parse the // source file in the normal fashion. When possible the parser will retrieve and @@ -9159,7 +9225,7 @@ namespace IncrementalParser { sourceFile.commentDirectives, result.commentDirectives, changeRange.span.start, - ts.textSpanEnd(changeRange.span), + textSpanEnd(changeRange.span), delta, oldText, newText, @@ -9170,35 +9236,35 @@ namespace IncrementalParser { } function getNewCommentDirectives( - oldDirectives: ts.CommentDirective[] | undefined, - newDirectives: ts.CommentDirective[] | undefined, + oldDirectives: CommentDirective[] | undefined, + newDirectives: CommentDirective[] | undefined, changeStart: number, changeRangeOldEnd: number, delta: number, oldText: string, newText: string, aggressiveChecks: boolean - ): ts.CommentDirective[] | undefined { + ): CommentDirective[] | undefined { if (!oldDirectives) return newDirectives; - let commentDirectives: ts.CommentDirective[] | undefined; + let commentDirectives: CommentDirective[] | undefined; let addedNewlyScannedDirectives = false; for (const directive of oldDirectives) { const { range, type } = directive; // Range before the change if (range.end < changeStart) { - commentDirectives = ts.append(commentDirectives, directive); + commentDirectives = append(commentDirectives, directive); } else if (range.pos > changeRangeOldEnd) { addNewlyScannedDirectives(); // Node is entirely past the change range. We need to move both its pos and // end, forward or backward appropriately. - const updatedDirective: ts.CommentDirective = { + const updatedDirective: CommentDirective = { range: { pos: range.pos + delta, end: range.end + delta }, type }; - commentDirectives = ts.append(commentDirectives, updatedDirective); + commentDirectives = append(commentDirectives, updatedDirective); if (aggressiveChecks) { - ts.Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end)); + Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end)); } } // Ignore ranges that fall in change range @@ -9239,16 +9305,16 @@ namespace IncrementalParser { node._children = undefined; } - ts.setTextRangePosEnd(node, node.pos + delta, node.end + delta); + setTextRangePosEnd(node, node.pos + delta, node.end + delta); if (aggressiveChecks && shouldCheckNode(node)) { - ts.Debug.assert(text === newText.substring(node.pos, node.end)); + Debug.assert(text === newText.substring(node.pos, node.end)); } forEachChild(node, visitNode, visitArray); - if (ts.hasJSDocNodes(node)) { + if (hasJSDocNodes(node)) { for (const jsDocComment of node.jsDoc!) { - visitNode(jsDocComment as ts.Node as IncrementalNode); + visitNode(jsDocComment as Node as IncrementalNode); } } checkNodePositions(node, aggressiveChecks); @@ -9256,7 +9322,7 @@ namespace IncrementalParser { function visitArray(array: IncrementalNodeArray) { array._children = undefined; - ts.setTextRangePosEnd(array, array.pos + delta, array.end + delta); + setTextRangePosEnd(array, array.pos + delta, array.end + delta); for (const node of array) { visitNode(node); @@ -9264,11 +9330,11 @@ namespace IncrementalParser { } } - function shouldCheckNode(node: ts.Node) { + function shouldCheckNode(node: Node) { switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.Identifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.Identifier: return true; } @@ -9276,9 +9342,9 @@ namespace IncrementalParser { } function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { - ts.Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); - ts.Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); - ts.Debug.assert(element.pos <= element.end); + Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); + Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); + Debug.assert(element.pos <= element.end); // We have an element that intersects the change range in some way. It may have its // start, or its end (or both) in the changed range. We want to adjust any part @@ -9340,29 +9406,29 @@ namespace IncrementalParser { // possible. Or Move backward to the new-end if it's in the 'Y' range. Math.min(element.end, changeRangeNewEnd); - ts.Debug.assert(pos <= end); + Debug.assert(pos <= end); if (element.parent) { - ts.Debug.assertGreaterThanOrEqual(pos, element.parent.pos); - ts.Debug.assertLessThanOrEqual(end, element.parent.end); + Debug.assertGreaterThanOrEqual(pos, element.parent.pos); + Debug.assertLessThanOrEqual(end, element.parent.end); } - ts.setTextRangePosEnd(element, pos, end); + setTextRangePosEnd(element, pos, end); } - function checkNodePositions(node: ts.Node, aggressiveChecks: boolean) { + function checkNodePositions(node: Node, aggressiveChecks: boolean) { if (aggressiveChecks) { let pos = node.pos; - const visitNode = (child: ts.Node) => { - ts.Debug.assert(child.pos >= pos); + const visitNode = (child: Node) => { + Debug.assert(child.pos >= pos); pos = child.end; }; - if (ts.hasJSDocNodes(node)) { + if (hasJSDocNodes(node)) { for (const jsDocComment of node.jsDoc!) { visitNode(jsDocComment); } } forEachChild(node, visitNode); - ts.Debug.assert(pos <= node.end); + Debug.assert(pos <= node.end); } } @@ -9380,7 +9446,7 @@ namespace IncrementalParser { return; function visitNode(child: IncrementalNode) { - ts.Debug.assert(child.pos <= child.end); + Debug.assert(child.pos <= child.end); if (child.pos > changeRangeOldEnd) { // Node is entirely past the change range. We need to move both its pos and // end, forward or backward appropriately. @@ -9399,9 +9465,9 @@ namespace IncrementalParser { // Adjust the pos or end (or both) of the intersecting element accordingly. adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); forEachChild(child, visitNode, visitArray); - if (ts.hasJSDocNodes(child)) { + if (hasJSDocNodes(child)) { for (const jsDocComment of child.jsDoc!) { - visitNode(jsDocComment as ts.Node as IncrementalNode); + visitNode(jsDocComment as Node as IncrementalNode); } } checkNodePositions(child, aggressiveChecks); @@ -9409,11 +9475,11 @@ namespace IncrementalParser { } // Otherwise, the node is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); + Debug.assert(fullEnd < changeStart); } function visitArray(array: IncrementalNodeArray) { - ts.Debug.assert(array.pos <= array.end); + Debug.assert(array.pos <= array.end); if (array.pos > changeRangeOldEnd) { // Array is entirely after the change range. We need to move it, and move any of // its children. @@ -9438,11 +9504,11 @@ namespace IncrementalParser { } // Otherwise, the array is entirely before the change range. No need to do anything with it. - ts.Debug.assert(fullEnd < changeStart); + Debug.assert(fullEnd < changeStart); } } - function extendToAffectedRange(sourceFile: ts.SourceFile, changeRange: ts.TextChangeRange): ts.TextChangeRange { + function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange { // Consider the following code: // void foo() { /; } // @@ -9462,21 +9528,21 @@ namespace IncrementalParser { // start of the tree. for (let i = 0; start > 0 && i <= maxLookahead; i++) { const nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start); - ts.Debug.assert(nearestNode.pos <= start); + Debug.assert(nearestNode.pos <= start); const position = nearestNode.pos; start = Math.max(0, position - 1); } - const finalSpan = ts.createTextSpanFromBounds(start, ts.textSpanEnd(changeRange.span)); + const finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span)); const finalLength = changeRange.newLength + (changeRange.span.start - start); - return ts.createTextChangeRange(finalSpan, finalLength); + return createTextChangeRange(finalSpan, finalLength); } - function findNearestNodeStartingBeforeOrAtPosition(sourceFile: ts.SourceFile, position: number): ts.Node { - let bestResult: ts.Node = sourceFile; - let lastNodeEntirelyBeforePosition: ts.Node | undefined; + function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { + let bestResult: Node = sourceFile; + let lastNodeEntirelyBeforePosition: Node | undefined; forEachChild(sourceFile, visit); @@ -9489,9 +9555,9 @@ namespace IncrementalParser { return bestResult; - function getLastDescendant(node: ts.Node): ts.Node { + function getLastDescendant(node: Node): Node { while (true) { - const lastChild = ts.getLastChild(node); + const lastChild = getLastChild(node); if (lastChild) { node = lastChild; } @@ -9501,8 +9567,8 @@ namespace IncrementalParser { } } - function visit(child: ts.Node) { - if (ts.nodeIsMissing(child)) { + function visit(child: Node) { + if (nodeIsMissing(child)) { // Missing nodes are effectively invisible to us. We never even consider them // When trying to find the nearest node before us. return; @@ -9532,7 +9598,7 @@ namespace IncrementalParser { return true; } else { - ts.Debug.assert(child.end <= position); + Debug.assert(child.end <= position); // The child ends entirely before this position. Say you have the following // (where $ is the position) // @@ -9550,7 +9616,7 @@ namespace IncrementalParser { } } else { - ts.Debug.assert(child.pos > position); + Debug.assert(child.pos > position); // We're now at a node that is entirely past the position we're searching for. // This node (and all following nodes) could never contribute to the result, // so just skip them by returning 'true' here. @@ -9559,35 +9625,35 @@ namespace IncrementalParser { } } - function checkChangeRange(sourceFile: ts.SourceFile, newText: string, textChangeRange: ts.TextChangeRange, aggressiveChecks: boolean) { + function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { const oldText = sourceFile.text; if (textChangeRange) { - ts.Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); + Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); - if (aggressiveChecks || ts.Debug.shouldAssert(ts.AssertionLevel.VeryAggressive)) { + if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) { const oldTextPrefix = oldText.substr(0, textChangeRange.span.start); const newTextPrefix = newText.substr(0, textChangeRange.span.start); - ts.Debug.assert(oldTextPrefix === newTextPrefix); + Debug.assert(oldTextPrefix === newTextPrefix); - const oldTextSuffix = oldText.substring(ts.textSpanEnd(textChangeRange.span), oldText.length); - const newTextSuffix = newText.substring(ts.textSpanEnd(ts.textChangeRangeNewSpan(textChangeRange)), newText.length); - ts.Debug.assert(oldTextSuffix === newTextSuffix); + const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length); + const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length); + Debug.assert(oldTextSuffix === newTextSuffix); } } } - interface IncrementalElement extends ts.ReadonlyTextRange { - readonly parent: ts.Node; + interface IncrementalElement extends ReadonlyTextRange { + readonly parent: Node; intersectsChange: boolean; length?: number; - _children: ts.Node[] | undefined; + _children: Node[] | undefined; } - export interface IncrementalNode extends ts.Node, IncrementalElement { + export interface IncrementalNode extends Node, IncrementalElement { hasBeenIncrementallyParsed: boolean; } - interface IncrementalNodeArray extends ts.NodeArray, IncrementalElement { + interface IncrementalNodeArray extends NodeArray, IncrementalElement { length: number; } @@ -9598,11 +9664,11 @@ namespace IncrementalParser { currentNode(position: number): IncrementalNode; } - export function createSyntaxCursor(sourceFile: ts.SourceFile): SyntaxCursor { - let currentArray: ts.NodeArray = sourceFile.statements; + export function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor { + let currentArray: NodeArray = sourceFile.statements; let currentArrayIndex = 0; - ts.Debug.assert(currentArrayIndex < currentArray.length); + Debug.assert(currentArrayIndex < currentArray.length); let current = currentArray[currentArrayIndex]; let lastQueriedPosition = InvalidPosition.Value; @@ -9636,7 +9702,7 @@ namespace IncrementalParser { lastQueriedPosition = position; // Either we don'd have a node, or we have a node at the position being asked for. - ts.Debug.assert(!current || current.pos === position); + Debug.assert(!current || current.pos === position); return current as IncrementalNode; } }; @@ -9654,7 +9720,7 @@ namespace IncrementalParser { forEachChild(sourceFile, visitNode, visitArray); return; - function visitNode(node: ts.Node) { + function visitNode(node: Node) { if (position >= node.pos && position < node.end) { // Position was within this node. Keep searching deeper to find the node. forEachChild(node, visitNode, visitArray); @@ -9667,7 +9733,7 @@ namespace IncrementalParser { return false; } - function visitArray(array: ts.NodeArray) { + function visitArray(array: NodeArray) { if (position >= array.pos && position < array.end) { // position was in this array. Search through this array to see if we find a // viable element. @@ -9706,46 +9772,46 @@ namespace IncrementalParser { /** @internal */ export function isDeclarationFileName(fileName: string): boolean { - return ts.fileExtensionIsOneOf(fileName, ts.supportedDeclarationExtensions); + return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions); } /*@internal*/ export interface PragmaContext { - languageVersion: ts.ScriptTarget; - pragmas?: ts.PragmaMap; - checkJsDirective?: ts.CheckJsDirective; - referencedFiles: ts.FileReference[]; - typeReferenceDirectives: ts.FileReference[]; - libReferenceDirectives: ts.FileReference[]; - amdDependencies: ts.AmdDependency[]; + languageVersion: ScriptTarget; + pragmas?: PragmaMap; + checkJsDirective?: CheckJsDirective; + referencedFiles: FileReference[]; + typeReferenceDirectives: FileReference[]; + libReferenceDirectives: FileReference[]; + amdDependencies: AmdDependency[]; hasNoDefaultLib?: boolean; moduleName?: string; } -function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined { +function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ModuleKind.ESNext | ModuleKind.CommonJS | undefined { if (!mode) { return undefined; } if (mode === "import") { - return ts.ModuleKind.ESNext; + return ModuleKind.ESNext; } if (mode === "require") { - return ts.ModuleKind.CommonJS; + return ModuleKind.CommonJS; } - reportDiagnostic(pos, end - pos, ts.Diagnostics.resolution_mode_should_be_either_require_or_import); + reportDiagnostic(pos, end - pos, Diagnostics.resolution_mode_should_be_either_require_or_import); return undefined; } /*@internal*/ export function processCommentPragmas(context: PragmaContext, sourceText: string): void { - const pragmas: ts.PragmaPseudoMapEntry[] = []; + const pragmas: PragmaPseudoMapEntry[] = []; - for (const range of ts.getLeadingCommentRanges(sourceText, 0) || ts.emptyArray) { + for (const range of getLeadingCommentRanges(sourceText, 0) || emptyArray) { const comment = sourceText.substring(range.pos, range.end); extractPragmas(pragmas, range, comment); } - context.pragmas = new ts.Map() as ts.PragmaMap; + context.pragmas = new Map() as PragmaMap; for (const pragma of pragmas) { if (context.pragmas.has(pragma.name)) { const currentValue = context.pragmas.get(pragma.name); @@ -9762,7 +9828,7 @@ export function processCommentPragmas(context: PragmaContext, sourceText: string } /*@internal*/ -type PragmaDiagnosticReporter = (pos: number, length: number, message: ts.DiagnosticMessage) => void; +type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void; /*@internal*/ export function processPragmasIntoFields(context: PragmaContext, reportDiagnostic: PragmaDiagnosticReporter): void { @@ -9780,7 +9846,7 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti const referencedFiles = context.referencedFiles; const typeReferenceDirectives = context.typeReferenceDirectives; const libReferenceDirectives = context.libReferenceDirectives; - ts.forEach(ts.toArray(entryOrList) as ts.PragmaPseudoMap["reference"][], arg => { + forEach(toArray(entryOrList) as PragmaPseudoMap["reference"][], arg => { const { types, lib, path, ["resolution-mode"]: res } = arg.arguments; if (arg.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; @@ -9796,14 +9862,14 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value }); } else { - reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, ts.Diagnostics.Invalid_reference_directive_syntax); + reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax); } }); break; } case "amd-dependency": { - context.amdDependencies = ts.map( - ts.toArray(entryOrList) as ts.PragmaPseudoMap["amd-dependency"][], + context.amdDependencies = map( + toArray(entryOrList) as PragmaPseudoMap["amd-dependency"][], x => ({ name: x.arguments.name, path: x.arguments.path })); break; } @@ -9812,20 +9878,20 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti for (const entry of entryOrList) { if (context.moduleName) { // TODO: It's probably fine to issue this diagnostic on all instances of the pragma - reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, ts.Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); + reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments); } - context.moduleName = (entry as ts.PragmaPseudoMap["amd-module"]).arguments.name; + context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name; } } else { - context.moduleName = (entryOrList as ts.PragmaPseudoMap["amd-module"]).arguments.name; + context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name; } break; } case "ts-nocheck": case "ts-check": { // _last_ of either nocheck or check in a file is the "winner" - ts.forEach(ts.toArray(entryOrList), entry => { + forEach(toArray(entryOrList), entry => { if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) { context.checkJsDirective = { enabled: key === "ts-check", @@ -9841,12 +9907,12 @@ export function processPragmasIntoFields(context: PragmaContext, reportDiagnosti case "jsximportsource": case "jsxruntime": return; // Accessed directly - default: ts.Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? + default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? } }); } -const namedArgRegExCache = new ts.Map(); +const namedArgRegExCache = new Map(); function getNamedArgRegEx(name: string): RegExp { if (namedArgRegExCache.has(name)) { return namedArgRegExCache.get(name)!; @@ -9858,12 +9924,12 @@ function getNamedArgRegEx(name: string): RegExp { const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im; const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im; -function extractPragmas(pragmas: ts.PragmaPseudoMapEntry[], range: ts.CommentRange, text: string) { - const tripleSlash = range.kind === ts.SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text); +function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) { + const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text); if (tripleSlash) { - const name = tripleSlash[1].toLowerCase() as keyof ts.PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks - const pragma = ts.commentPragmas[name] as ts.PragmaDefinition; - if (!pragma || !(pragma.kind! & ts.PragmaKindFlags.TripleSlashXML)) { + const name = tripleSlash[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks + const pragma = commentPragmas[name] as PragmaDefinition; + if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) { return; } if (pragma.args) { @@ -9889,46 +9955,46 @@ function extractPragmas(pragmas: ts.PragmaPseudoMapEntry[], range: ts.CommentRan } } } - pragmas.push({ name, args: { arguments: argument, range } } as ts.PragmaPseudoMapEntry); + pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry); } else { - pragmas.push({ name, args: { arguments: {}, range } } as ts.PragmaPseudoMapEntry); + pragmas.push({ name, args: { arguments: {}, range } } as PragmaPseudoMapEntry); } return; } - const singleLine = range.kind === ts.SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text); + const singleLine = range.kind === SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text); if (singleLine) { - return addPragmaForMatch(pragmas, range, ts.PragmaKindFlags.SingleLine, singleLine); + return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine); } - if (range.kind === ts.SyntaxKind.MultiLineCommentTrivia) { + if (range.kind === SyntaxKind.MultiLineCommentTrivia) { const multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating) let multiLineMatch: RegExpExecArray | null; while (multiLineMatch = multiLinePragmaRegEx.exec(text)) { - addPragmaForMatch(pragmas, range, ts.PragmaKindFlags.MultiLine, multiLineMatch); + addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch); } } } -function addPragmaForMatch(pragmas: ts.PragmaPseudoMapEntry[], range: ts.CommentRange, kind: ts.PragmaKindFlags, match: RegExpExecArray) { +function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) { if (!match) return; - const name = match[1].toLowerCase() as keyof ts.PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks - const pragma = ts.commentPragmas[name] as ts.PragmaDefinition; + const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks + const pragma = commentPragmas[name] as PragmaDefinition; if (!pragma || !(pragma.kind! & kind)) { return; } const args = match[2]; // Split on spaces and match up positionally with definition const argument = getNamedPragmaArguments(pragma, args); if (argument === "fail") return; // Missing required argument, fail to parse it - pragmas.push({ name, args: { arguments: argument, range } } as ts.PragmaPseudoMapEntry); + pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry); return; } -function getNamedPragmaArguments(pragma: ts.PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" { +function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" { if (!text) return {}; if (!pragma.args) return {}; - const args = ts.trimString(text).split(/\s+/); + const args = trimString(text).split(/\s+/); const argMap: {[index: string]: string} = {}; for (let i = 0; i < pragma.args.length; i++) { const argument = pragma.args[i]; @@ -9936,7 +10002,7 @@ function getNamedPragmaArguments(pragma: ts.PragmaDefinition, text: string | und return "fail"; } if (argument.captureSpan) { - return ts.Debug.fail("Capture spans not yet implemented for non-xml pragmas"); + return Debug.fail("Capture spans not yet implemented for non-xml pragmas"); } argMap[argument.name] = args[i]; } @@ -9944,22 +10010,22 @@ function getNamedPragmaArguments(pragma: ts.PragmaDefinition, text: string | und } /** @internal */ -export function tagNamesAreEquivalent(lhs: ts.JsxTagNameExpression, rhs: ts.JsxTagNameExpression): boolean { +export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean { if (lhs.kind !== rhs.kind) { return false; } - if (lhs.kind === ts.SyntaxKind.Identifier) { - return lhs.escapedText === (rhs as ts.Identifier).escapedText; + if (lhs.kind === SyntaxKind.Identifier) { + return lhs.escapedText === (rhs as Identifier).escapedText; } - if (lhs.kind === ts.SyntaxKind.ThisKeyword) { + if (lhs.kind === SyntaxKind.ThisKeyword) { return true; } // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element - return (lhs as ts.PropertyAccessExpression).name.escapedText === (rhs as ts.PropertyAccessExpression).name.escapedText && - tagNamesAreEquivalent((lhs as ts.PropertyAccessExpression).expression as ts.JsxTagNameExpression, (rhs as ts.PropertyAccessExpression).expression as ts.JsxTagNameExpression); + return (lhs as PropertyAccessExpression).name.escapedText === (rhs as PropertyAccessExpression).name.escapedText && + tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression); } diff --git a/src/compiler/path.ts b/src/compiler/path.ts index 8433e734053c2..6bdb17f88ad3f 100644 --- a/src/compiler/path.ts +++ b/src/compiler/path.ts @@ -1,4 +1,8 @@ -import * as ts from "./_namespaces/ts"; +import { + CharacterCodes, compareStringsCaseInsensitive, compareStringsCaseSensitive, compareValues, Comparison, Debug, + endsWith, equateStringsCaseInsensitive, equateStringsCaseSensitive, GetCanonicalFileName, getStringComparer, + identity, lastOrUndefined, Path, some, startsWith, stringContains, +} from "./_namespaces/ts"; /** @internal */ /** @@ -19,7 +23,7 @@ const backslashRegExp = /\\/g; * Determines whether a charCode corresponds to `/` or `\`. */ export function isAnyDirectorySeparator(charCode: number): boolean { - return charCode === ts.CharacterCodes.slash || charCode === ts.CharacterCodes.backslash; + return charCode === CharacterCodes.slash || charCode === CharacterCodes.backslash; } /** @internal */ @@ -87,12 +91,12 @@ export function pathIsBareSpecifier(path: string): boolean { /** @internal */ export function hasExtension(fileName: string): boolean { - return ts.stringContains(getBaseFileName(fileName), "."); + return stringContains(getBaseFileName(fileName), "."); } /** @internal */ export function fileExtensionIs(path: string, extension: string): boolean { - return path.length > extension.length && ts.endsWith(path, extension); + return path.length > extension.length && endsWith(path, extension); } /** @internal */ @@ -117,16 +121,16 @@ export function hasTrailingDirectorySeparator(path: string) { //// Path Parsing function isVolumeCharacter(charCode: number) { - return (charCode >= ts.CharacterCodes.a && charCode <= ts.CharacterCodes.z) || - (charCode >= ts.CharacterCodes.A && charCode <= ts.CharacterCodes.Z); + return (charCode >= CharacterCodes.a && charCode <= CharacterCodes.z) || + (charCode >= CharacterCodes.A && charCode <= CharacterCodes.Z); } function getFileUrlVolumeSeparatorEnd(url: string, start: number) { const ch0 = url.charCodeAt(start); - if (ch0 === ts.CharacterCodes.colon) return start + 1; - if (ch0 === ts.CharacterCodes.percent && url.charCodeAt(start + 1) === ts.CharacterCodes._3) { + if (ch0 === CharacterCodes.colon) return start + 1; + if (ch0 === CharacterCodes.percent && url.charCodeAt(start + 1) === CharacterCodes._3) { const ch2 = url.charCodeAt(start + 2); - if (ch2 === ts.CharacterCodes.a || ch2 === ts.CharacterCodes.A) return start + 3; + if (ch2 === CharacterCodes.a || ch2 === CharacterCodes.A) return start + 3; } return -1; } @@ -140,19 +144,19 @@ function getEncodedRootLength(path: string): number { const ch0 = path.charCodeAt(0); // POSIX or UNC - if (ch0 === ts.CharacterCodes.slash || ch0 === ts.CharacterCodes.backslash) { + if (ch0 === CharacterCodes.slash || ch0 === CharacterCodes.backslash) { if (path.charCodeAt(1) !== ch0) return 1; // POSIX: "/" (or non-normalized "\") - const p1 = path.indexOf(ch0 === ts.CharacterCodes.slash ? directorySeparator : altDirectorySeparator, 2); + const p1 = path.indexOf(ch0 === CharacterCodes.slash ? directorySeparator : altDirectorySeparator, 2); if (p1 < 0) return path.length; // UNC: "//server" or "\\server" return p1 + 1; // UNC: "//server/" or "\\server\" } // DOS - if (isVolumeCharacter(ch0) && path.charCodeAt(1) === ts.CharacterCodes.colon) { + if (isVolumeCharacter(ch0) && path.charCodeAt(1) === CharacterCodes.colon) { const ch2 = path.charCodeAt(2); - if (ch2 === ts.CharacterCodes.slash || ch2 === ts.CharacterCodes.backslash) return 3; // DOS: "c:/" or "c:\" + if (ch2 === CharacterCodes.slash || ch2 === CharacterCodes.backslash) return 3; // DOS: "c:/" or "c:\" if (path.length === 2) return 2; // DOS: "c:" (but not "c:d") } @@ -171,7 +175,7 @@ function getEncodedRootLength(path: string): number { isVolumeCharacter(path.charCodeAt(authorityEnd + 1))) { const volumeSeparatorEnd = getFileUrlVolumeSeparatorEnd(path, authorityEnd + 2); if (volumeSeparatorEnd !== -1) { - if (path.charCodeAt(volumeSeparatorEnd) === ts.CharacterCodes.slash) { + if (path.charCodeAt(volumeSeparatorEnd) === CharacterCodes.slash) { // URL: "file:///c:/", "file://localhost/c:/", "file:///c%3a/", "file://localhost/c%3a/" return ~(volumeSeparatorEnd + 1); } @@ -244,7 +248,7 @@ export function getRootLength(path: string) { * getDirectoryPath("http://typescriptlang.org") === "http://typescriptlang.org" * ``` */ -export function getDirectoryPath(path: ts.Path): ts.Path; +export function getDirectoryPath(path: Path): Path; /** @internal */ /** * Returns the path except for its basename. Semantics align with NodeJS's `path.dirname` @@ -352,8 +356,8 @@ export function getBaseFileName(path: string, extensions?: string | readonly str } function tryGetExtensionFromPath(path: string, extension: string, stringEqualityComparer: (a: string, b: string) => boolean) { - if (!ts.startsWith(extension, ".")) extension = "." + extension; - if (path.length >= extension.length && path.charCodeAt(path.length - extension.length) === ts.CharacterCodes.dot) { + if (!startsWith(extension, ".")) extension = "." + extension; + if (path.length >= extension.length && path.charCodeAt(path.length - extension.length) === CharacterCodes.dot) { const pathExtension = path.slice(path.length - extension.length); if (stringEqualityComparer(pathExtension, extension)) { return pathExtension; @@ -400,7 +404,7 @@ export function getAnyExtensionFromPath(path: string, extensions?: string | read // Retrieves any string from the final "." onwards from a base file name. // Unlike extensionFromPath, which throws an exception on unrecognized extensions. if (extensions) { - return getAnyExtensionFromPathWorker(removeTrailingDirectorySeparator(path), extensions, ignoreCase ? ts.equateStringsCaseInsensitive : ts.equateStringsCaseSensitive); + return getAnyExtensionFromPathWorker(removeTrailingDirectorySeparator(path), extensions, ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive); } const baseFileName = getBaseFileName(path); const extensionIndex = baseFileName.lastIndexOf("."); @@ -413,7 +417,7 @@ export function getAnyExtensionFromPath(path: string, extensions?: string | read function pathComponents(path: string, rootLength: number) { const root = path.substring(0, rootLength); const rest = path.substring(rootLength).split(directorySeparator); - if (rest.length && !ts.lastOrUndefined(rest)) rest.pop(); + if (rest.length && !lastOrUndefined(rest)) rest.pop(); return [root, ...rest]; } @@ -489,7 +493,7 @@ export function normalizeSlashes(path: string): string { * `"."` or `".."` entries in the path. */ export function reducePathComponents(components: readonly string[]) { - if (!ts.some(components)) return []; + if (!some(components)) return []; const reduced = [components[0]]; for (let i = 1; i < components.length; i++) { const component = components[i]; @@ -555,7 +559,7 @@ export function combinePaths(path: string, ...paths: (string | undefined)[]): st * ``` */ export function resolvePath(path: string, ...paths: (string | undefined)[]): string { - return normalizePath(ts.some(paths) ? combinePaths(path, ...paths) : normalizeSlashes(path)); + return normalizePath(some(paths) ? combinePaths(path, ...paths) : normalizeSlashes(path)); } /** @internal */ @@ -609,11 +613,11 @@ export function getNormalizedAbsolutePathWithoutRoot(fileName: string, currentDi } /** @internal */ -export function toPath(fileName: string, basePath: string | undefined, getCanonicalFileName: (path: string) => string): ts.Path { +export function toPath(fileName: string, basePath: string | undefined, getCanonicalFileName: (path: string) => string): Path { const nonCanonicalizedPath = isRootedDiskPath(fileName) ? normalizePath(fileName) : getNormalizedAbsolutePath(fileName, basePath); - return getCanonicalFileName(nonCanonicalizedPath) as ts.Path; + return getCanonicalFileName(nonCanonicalizedPath) as Path; } //// Path Mutation @@ -627,7 +631,7 @@ export function toPath(fileName: string, basePath: string | undefined, getCanoni * removeTrailingDirectorySeparator("/path/to/file.ext/") === "/path/to/file.ext" * ``` */ -export function removeTrailingDirectorySeparator(path: ts.Path): ts.Path; +export function removeTrailingDirectorySeparator(path: Path): Path; /** @internal */ export function removeTrailingDirectorySeparator(path: string): string; /** @internal */ @@ -648,7 +652,7 @@ export function removeTrailingDirectorySeparator(path: string) { * ensureTrailingDirectorySeparator("/path/to/file.ext/") === "/path/to/file.ext/" * ``` */ -export function ensureTrailingDirectorySeparator(path: ts.Path): ts.Path; +export function ensureTrailingDirectorySeparator(path: Path): Path; /** @internal */ export function ensureTrailingDirectorySeparator(path: string): string; /** @internal */ @@ -699,7 +703,7 @@ export function changeAnyExtension(path: string, ext: string, extensions: string /** @internal */ export function changeAnyExtension(path: string, ext: string, extensions?: string | readonly string[], ignoreCase?: boolean) { const pathext = extensions !== undefined && ignoreCase !== undefined ? getAnyExtensionFromPath(path, extensions, ignoreCase) : getAnyExtensionFromPath(path); - return pathext ? path.slice(0, path.length - pathext.length) + (ts.startsWith(ext, ".") ? ext : "." + ext) : path; + return pathext ? path.slice(0, path.length - pathext.length) + (startsWith(ext, ".") ? ext : "." + ext) : path; } //// Path Comparisons @@ -707,17 +711,17 @@ export function changeAnyExtension(path: string, ext: string, extensions?: strin // check path for these segments: '', '.'. '..' const relativePathSegmentRegExp = /(?:\/\/)|(?:^|\/)\.\.?(?:$|\/)/; -function comparePathsWorker(a: string, b: string, componentComparer: (a: string, b: string) => ts.Comparison) { - if (a === b) return ts.Comparison.EqualTo; - if (a === undefined) return ts.Comparison.LessThan; - if (b === undefined) return ts.Comparison.GreaterThan; +function comparePathsWorker(a: string, b: string, componentComparer: (a: string, b: string) => Comparison) { + if (a === b) return Comparison.EqualTo; + if (a === undefined) return Comparison.LessThan; + if (b === undefined) return Comparison.GreaterThan; // NOTE: Performance optimization - shortcut if the root segments differ as there would be no // need to perform path reduction. const aRoot = a.substring(0, getRootLength(a)); const bRoot = b.substring(0, getRootLength(b)); - const result = ts.compareStringsCaseInsensitive(aRoot, bRoot); - if (result !== ts.Comparison.EqualTo) { + const result = compareStringsCaseInsensitive(aRoot, bRoot); + if (result !== Comparison.EqualTo) { return result; } @@ -736,11 +740,11 @@ function comparePathsWorker(a: string, b: string, componentComparer: (a: string, const sharedLength = Math.min(aComponents.length, bComponents.length); for (let i = 1; i < sharedLength; i++) { const result = componentComparer(aComponents[i], bComponents[i]); - if (result !== ts.Comparison.EqualTo) { + if (result !== Comparison.EqualTo) { return result; } } - return ts.compareValues(aComponents.length, bComponents.length); + return compareValues(aComponents.length, bComponents.length); } /** @internal */ @@ -748,7 +752,7 @@ function comparePathsWorker(a: string, b: string, componentComparer: (a: string, * Performs a case-sensitive comparison of two paths. Path roots are always compared case-insensitively. */ export function comparePathsCaseSensitive(a: string, b: string) { - return comparePathsWorker(a, b, ts.compareStringsCaseSensitive); + return comparePathsWorker(a, b, compareStringsCaseSensitive); } /** @internal */ @@ -756,16 +760,16 @@ export function comparePathsCaseSensitive(a: string, b: string) { * Performs a case-insensitive comparison of two paths. */ export function comparePathsCaseInsensitive(a: string, b: string) { - return comparePathsWorker(a, b, ts.compareStringsCaseInsensitive); + return comparePathsWorker(a, b, compareStringsCaseInsensitive); } /** @internal */ /** * Compare two paths using the provided case sensitivity. */ -export function comparePaths(a: string, b: string, ignoreCase?: boolean): ts.Comparison; +export function comparePaths(a: string, b: string, ignoreCase?: boolean): Comparison; /** @internal */ -export function comparePaths(a: string, b: string, currentDirectory: string, ignoreCase?: boolean): ts.Comparison; +export function comparePaths(a: string, b: string, currentDirectory: string, ignoreCase?: boolean): Comparison; /** @internal */ export function comparePaths(a: string, b: string, currentDirectory?: string | boolean, ignoreCase?: boolean) { if (typeof currentDirectory === "string") { @@ -775,7 +779,7 @@ export function comparePaths(a: string, b: string, currentDirectory?: string | b else if (typeof currentDirectory === "boolean") { ignoreCase = currentDirectory; } - return comparePathsWorker(a, b, ts.getStringComparer(ignoreCase)); + return comparePathsWorker(a, b, getStringComparer(ignoreCase)); } /** @internal */ @@ -802,9 +806,9 @@ export function containsPath(parent: string, child: string, currentDirectory?: s return false; } - const componentEqualityComparer = ignoreCase ? ts.equateStringsCaseInsensitive : ts.equateStringsCaseSensitive; + const componentEqualityComparer = ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive; for (let i = 0; i < parentComponents.length; i++) { - const equalityComparer = i === 0 ? ts.equateStringsCaseInsensitive : componentEqualityComparer; + const equalityComparer = i === 0 ? equateStringsCaseInsensitive : componentEqualityComparer; if (!equalityComparer(parentComponents[i], childComponents[i])) { return false; } @@ -820,16 +824,16 @@ export function containsPath(parent: string, child: string, currentDirectory?: s * * Use `containsPath` if file names are not already reduced and absolute. */ -export function startsWithDirectory(fileName: string, directoryName: string, getCanonicalFileName: ts.GetCanonicalFileName): boolean { +export function startsWithDirectory(fileName: string, directoryName: string, getCanonicalFileName: GetCanonicalFileName): boolean { const canonicalFileName = getCanonicalFileName(fileName); const canonicalDirectoryName = getCanonicalFileName(directoryName); - return ts.startsWith(canonicalFileName, canonicalDirectoryName + "/") || ts.startsWith(canonicalFileName, canonicalDirectoryName + "\\"); + return startsWith(canonicalFileName, canonicalDirectoryName + "/") || startsWith(canonicalFileName, canonicalDirectoryName + "\\"); } //// Relative Paths /** @internal */ -export function getPathComponentsRelativeTo(from: string, to: string, stringEqualityComparer: (a: string, b: string) => boolean, getCanonicalFileName: ts.GetCanonicalFileName) { +export function getPathComponentsRelativeTo(from: string, to: string, stringEqualityComparer: (a: string, b: string) => boolean, getCanonicalFileName: GetCanonicalFileName) { const fromComponents = reducePathComponents(getPathComponents(from)); const toComponents = reducePathComponents(getPathComponents(to)); @@ -837,7 +841,7 @@ export function getPathComponentsRelativeTo(from: string, to: string, stringEqua for (start = 0; start < fromComponents.length && start < toComponents.length; start++) { const fromComponent = getCanonicalFileName(fromComponents[start]); const toComponent = getCanonicalFileName(toComponents[start]); - const comparer = start === 0 ? ts.equateStringsCaseInsensitive : stringEqualityComparer; + const comparer = start === 0 ? equateStringsCaseInsensitive : stringEqualityComparer; if (!comparer(fromComponent, toComponent)) break; } @@ -862,13 +866,13 @@ export function getRelativePathFromDirectory(from: string, to: string, ignoreCas /** * Gets a relative path that can be used to traverse between `from` and `to`. */ -export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileName: ts.GetCanonicalFileName): string; // eslint-disable-line @typescript-eslint/unified-signatures +export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileName: GetCanonicalFileName): string; // eslint-disable-line @typescript-eslint/unified-signatures /** @internal */ -export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileNameOrIgnoreCase: ts.GetCanonicalFileName | boolean) { - ts.Debug.assert((getRootLength(fromDirectory) > 0) === (getRootLength(to) > 0), "Paths must either both be absolute or both be relative"); - const getCanonicalFileName = typeof getCanonicalFileNameOrIgnoreCase === "function" ? getCanonicalFileNameOrIgnoreCase : ts.identity; +export function getRelativePathFromDirectory(fromDirectory: string, to: string, getCanonicalFileNameOrIgnoreCase: GetCanonicalFileName | boolean) { + Debug.assert((getRootLength(fromDirectory) > 0) === (getRootLength(to) > 0), "Paths must either both be absolute or both be relative"); + const getCanonicalFileName = typeof getCanonicalFileNameOrIgnoreCase === "function" ? getCanonicalFileNameOrIgnoreCase : identity; const ignoreCase = typeof getCanonicalFileNameOrIgnoreCase === "boolean" ? getCanonicalFileNameOrIgnoreCase : false; - const pathComponents = getPathComponentsRelativeTo(fromDirectory, to, ignoreCase ? ts.equateStringsCaseInsensitive : ts.equateStringsCaseSensitive, getCanonicalFileName); + const pathComponents = getPathComponentsRelativeTo(fromDirectory, to, ignoreCase ? equateStringsCaseInsensitive : equateStringsCaseSensitive, getCanonicalFileName); return getPathFromPathComponents(pathComponents); } @@ -880,16 +884,16 @@ export function convertToRelativePath(absoluteOrRelativePath: string, basePath: } /** @internal */ -export function getRelativePathFromFile(from: string, to: string, getCanonicalFileName: ts.GetCanonicalFileName) { +export function getRelativePathFromFile(from: string, to: string, getCanonicalFileName: GetCanonicalFileName) { return ensurePathIsNonModuleName(getRelativePathFromDirectory(getDirectoryPath(from), to, getCanonicalFileName)); } /** @internal */ -export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: ts.GetCanonicalFileName, isAbsolutePathAnUrl: boolean) { +export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, relativeOrAbsolutePath: string, currentDirectory: string, getCanonicalFileName: GetCanonicalFileName, isAbsolutePathAnUrl: boolean) { const pathComponents = getPathComponentsRelativeTo( resolvePath(currentDirectory, directoryPathOrUrl), resolvePath(currentDirectory, relativeOrAbsolutePath), - ts.equateStringsCaseSensitive, + equateStringsCaseSensitive, getCanonicalFileName ); @@ -908,11 +912,11 @@ export function getRelativePathToDirectoryOrUrl(directoryPathOrUrl: string, rela /** * Calls `callback` on `directory` and every ancestor directory it has, returning the first defined result. */ -export function forEachAncestorDirectory(directory: ts.Path, callback: (directory: ts.Path) => T | undefined): T | undefined; +export function forEachAncestorDirectory(directory: Path, callback: (directory: Path) => T | undefined): T | undefined; /** @internal */ export function forEachAncestorDirectory(directory: string, callback: (directory: string) => T | undefined): T | undefined; /** @internal */ -export function forEachAncestorDirectory(directory: ts.Path, callback: (directory: ts.Path) => T | undefined): T | undefined { +export function forEachAncestorDirectory(directory: Path, callback: (directory: Path) => T | undefined): T | undefined { while (true) { const result = callback(directory); if (result !== undefined) { @@ -929,6 +933,6 @@ export function forEachAncestorDirectory(directory: ts.Path, callback: (direc } /** @internal */ -export function isNodeModulesDirectory(dirPath: ts.Path) { - return ts.endsWith(dirPath, "/node_modules"); +export function isNodeModulesDirectory(dirPath: Path) { + return endsWith(dirPath, "/node_modules"); } diff --git a/src/compiler/perfLogger.ts b/src/compiler/perfLogger.ts index 6c0227e454192..eb225b9ce4904 100644 --- a/src/compiler/perfLogger.ts +++ b/src/compiler/perfLogger.ts @@ -1,27 +1,27 @@ -import * as ts from "./_namespaces/ts"; +import { noop } from "./_namespaces/ts"; type PerfLogger = typeof import("@microsoft/typescript-etw"); const nullLogger: PerfLogger = { - logEvent: ts.noop, - logErrEvent: ts.noop, - logPerfEvent: ts.noop, - logInfoEvent: ts.noop, - logStartCommand: ts.noop, - logStopCommand: ts.noop, - logStartUpdateProgram: ts.noop, - logStopUpdateProgram: ts.noop, - logStartUpdateGraph: ts.noop, - logStopUpdateGraph: ts.noop, - logStartResolveModule: ts.noop, - logStopResolveModule: ts.noop, - logStartParseSourceFile: ts.noop, - logStopParseSourceFile: ts.noop, - logStartReadFile: ts.noop, - logStopReadFile: ts.noop, - logStartBindFile: ts.noop, - logStopBindFile: ts.noop, - logStartScheduledOperation: ts.noop, - logStopScheduledOperation: ts.noop, + logEvent: noop, + logErrEvent: noop, + logPerfEvent: noop, + logInfoEvent: noop, + logStartCommand: noop, + logStopCommand: noop, + logStartUpdateProgram: noop, + logStopUpdateProgram: noop, + logStartUpdateGraph: noop, + logStopUpdateGraph: noop, + logStartResolveModule: noop, + logStopResolveModule: noop, + logStartParseSourceFile: noop, + logStopParseSourceFile: noop, + logStartReadFile: noop, + logStopReadFile: noop, + logStartBindFile: noop, + logStopBindFile: noop, + logStartScheduledOperation: noop, + logStopScheduledOperation: noop, }; // Load optional module to enable Event Tracing for Windows diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 4e2e52e6e34cd..859dab41340b7 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -1,11 +1,13 @@ -import * as ts from "./_namespaces/ts"; +import { + Debug, Map, noop, Performance, PerformanceHooks, sys, System, timestamp, tryGetNativePerformanceHooks, +} from "./_namespaces/ts"; /** Performance measurements for the compiler. */ -let perfHooks: ts.PerformanceHooks | undefined; +let perfHooks: PerformanceHooks | undefined; // when set, indicates the implementation of `Performance` to use for user timing. // when unset, indicates user timing is unavailable or disabled. -let performanceImpl: ts.Performance | undefined; +let performanceImpl: Performance | undefined; /** @internal */ export interface Timer { @@ -38,19 +40,19 @@ export function createTimer(measureName: string, startMarkName: string, endMarkN measure(measureName, startMarkName, endMarkName); } else if (enterCount < 0) { - ts.Debug.fail("enter/exit count does not match."); + Debug.fail("enter/exit count does not match."); } } } /** @internal */ -export const nullTimer: Timer = { enter: ts.noop, exit: ts.noop }; +export const nullTimer: Timer = { enter: noop, exit: noop }; let enabled = false; -let timeorigin = ts.timestamp(); -const marks = new ts.Map(); -const counts = new ts.Map(); -const durations = new ts.Map(); +let timeorigin = timestamp(); +const marks = new Map(); +const counts = new Map(); +const durations = new Map(); /** @internal */ /** @@ -62,7 +64,7 @@ export function mark(markName: string) { if (enabled) { const count = counts.get(markName) ?? 0; counts.set(markName, count + 1); - marks.set(markName, ts.timestamp()); + marks.set(markName, timestamp()); performanceImpl?.mark(markName); } } @@ -79,7 +81,7 @@ export function mark(markName: string) { */ export function measure(measureName: string, startMarkName?: string, endMarkName?: string) { if (enabled) { - const end = (endMarkName !== undefined ? marks.get(endMarkName) : undefined) ?? ts.timestamp(); + const end = (endMarkName !== undefined ? marks.get(endMarkName) : undefined) ?? timestamp(); const start = (startMarkName !== undefined ? marks.get(startMarkName) : undefined) ?? timeorigin; const previousDuration = durations.get(measureName) || 0; durations.set(measureName, previousDuration + (end - start)); @@ -152,10 +154,10 @@ export function isEnabled() { /** @internal */ /** Enables (and resets) performance measurements for the compiler. */ -export function enable(system: ts.System = ts.sys) { +export function enable(system: System = sys) { if (!enabled) { enabled = true; - perfHooks ||= ts.tryGetNativePerformanceHooks(); + perfHooks ||= tryGetNativePerformanceHooks(); if (perfHooks) { timeorigin = perfHooks.performance.timeOrigin; // NodeJS's Web Performance API is currently slower than expected, but we'd still like diff --git a/src/compiler/performanceCore.ts b/src/compiler/performanceCore.ts index 4394c425204ed..15d3c41994d90 100644 --- a/src/compiler/performanceCore.ts +++ b/src/compiler/performanceCore.ts @@ -1,4 +1,4 @@ -import * as ts from "./_namespaces/ts"; +import { Version, VersionRange } from "./_namespaces/ts"; // The following definitions provide the minimum compatible support for the Web Performance User Timings API // between browsers and NodeJS: @@ -90,8 +90,8 @@ function tryGetNodePerformanceHooks(): PerformanceHooks | undefined { // match the Web Performance API specification. Node's implementation did not allow // optional `start` and `end` arguments for `performance.measure`. // See https://github.com/nodejs/node/pull/32651 for more information. - const version = new ts.Version(process.versions.node); - const range = new ts.VersionRange("<12.16.3 || 13 <13.13"); + const version = new Version(process.versions.node); + const range = new VersionRange("<12.16.3 || 13 <13.13"); if (range.test(version)) { performance = { get timeOrigin() { return nodePerformance.timeOrigin; }, diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2377ba9bffce9..c307a3c748f97 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,24 +1,85 @@ import * as ts from "./_namespaces/ts"; +import { + __String, addEmitFlags, addRange, append, arrayFrom, arrayIsEqualTo, AsExpression, AssertClause, BuilderProgram, + CancellationToken, canHaveModifiers, chainDiagnosticMessages, changeExtension, changesAffectingProgramStructure, + changesAffectModuleResolution, clone, combinePaths, CommentDirective, CommentDirectivesMap, compareDataObjects, + comparePaths, compareValues, Comparison, CompilerHost, CompilerOptions, computeLineAndCharacterOfPosition, + concatenate, contains, containsIgnoredPath, containsPath, convertToRelativePath, createCommentDirectivesMap, + createCompilerDiagnostic, createCompilerDiagnosticFromMessageChain, createDiagnosticCollection, + createDiagnosticForNodeInSourceFile, createDiagnosticForRange, createFileDiagnostic, + createFileDiagnosticFromMessageChain, createGetCanonicalFileName, createInputFilesWithFilePaths, + createModeAwareCache, createModuleResolutionCache, createMultiMap, CreateProgramOptions, createSourceFile, + CreateSourceFileOptions, createSymlinkCache, createTypeChecker, createTypeReferenceDirectiveResolutionCache, + CustomTransformers, Debug, DeclarationWithTypeParameterChildren, Diagnostic, DiagnosticCategory, + diagnosticCategoryName, DiagnosticMessage, DiagnosticMessageChain, DiagnosticReporter, Diagnostics, + DiagnosticWithLocation, directorySeparator, DirectoryStructureHost, emitFiles, EmitFlags, EmitHost, EmitOnly, + EmitResult, emptyArray, ensureTrailingDirectorySeparator, equateStringsCaseInsensitive, equateStringsCaseSensitive, + ESMap, explainIfFileIsRedirectAndImpliedFormat, ExportAssignment, ExportDeclaration, Extension, extensionFromPath, + externalHelpersModuleNameText, factory, fileExtensionIs, fileExtensionIsOneOf, FileIncludeKind, FileIncludeReason, + fileIncludeReasonToDiagnostics, FilePreprocessingDiagnostics, FilePreprocessingDiagnosticsKind, FileReference, + filter, find, firstDefined, firstDefinedIterator, flatMap, flatten, forEach, forEachAncestorDirectory, forEachChild, + forEachChildRecursively, forEachEmittedFile, forEachEntry, forEachKey, FunctionLikeDeclaration, + getAllowJSCompilerOption, getAutomaticTypeDirectiveNames, getBaseFileName, GetCanonicalFileName, + getCommonSourceDirectoryOfConfig, getDefaultLibFileName, getDirectoryPath, getEmitDeclarations, getEmitModuleKind, + getEmitModuleResolutionKind, getEmitScriptTarget, getErrorSpanForNode, getExternalModuleName, + getJSXImplicitImportBase, getJSXRuntimeImport, getLineAndCharacterOfPosition, getLineStarts, getMatchedFileSpec, + getMatchedIncludeSpec, getNewLineCharacter, getNormalizedAbsolutePath, getNormalizedAbsolutePathWithoutRoot, + getNormalizedPathComponents, getOutputDeclarationFileName, getOutputPathsForBundle, getPackageScopeForPath, + getPathFromPathComponents, getPositionOfLineAndCharacter, getPropertyArrayElementValue, getPropertyAssignment, + getResolvedModule, getRootLength, getSetExternalModuleIndicator, getSpellingSuggestion, getStrictOptionValue, + getSupportedExtensions, getSupportedExtensionsWithJsonIfResolveJsonModule, getTemporaryModuleResolutionState, + getTextOfIdentifierOrLiteral, getTransformers, getTsBuildInfoEmitOutputFilePath, getTsConfigObjectLiteralExpression, + getTsConfigPropArray, getTsConfigPropArrayElementValue, HasChangedAutomaticTypeDirectiveNames, + hasChangesInResolutions, hasExtension, HasInvalidatedResolutions, hasJSDocNodes, hasJSFileExtension, + hasJsonModuleEmitEnabled, hasProperty, hasSyntacticModifier, hasZeroOrOneAsteriskCharacter, HeritageClause, + Identifier, identity, ImportClause, ImportDeclaration, ImportOrExportSpecifier, InputFiles, inverseJsxOptionMap, + isAmbientModule, isAnyImportOrReExport, isArray, isArrayLiteralExpression, isBuildInfoFile, isCheckJsEnabledForFile, + isDeclarationFileName, isDecorator, isExportDeclaration, isExternalModule, isExternalModuleNameRelative, + isIdentifierText, isImportCall, isImportDeclaration, isImportEqualsDeclaration, isImportSpecifier, isImportTypeNode, + isIncrementalCompilation, isInJSFile, isLiteralImportTypeNode, isModifier, isModuleDeclaration, + isObjectLiteralExpression, isPlainJsFile, isRequireCall, isRootedDiskPath, isSourceFileJS, isString, + isStringLiteral, isStringLiteralLike, isTraceEnabled, JsonSourceFile, JsxEmit, length, libMap, libs, Map, + mapDefined, mapDefinedIterator, maybeBind, memoize, MethodDeclaration, ModifierFlags, ModifierLike, ModuleBlock, + ModuleDeclaration, ModuleKind, ModuleResolutionCache, ModuleResolutionHost, moduleResolutionIsEqualTo, + ModuleResolutionKind, Mutable, Node, NodeArray, NodeFlags, nodeModulesPathPart, NodeWithTypeArguments, noop, + normalizePath, notImplementedResolver, noTransformers, ObjectLiteralExpression, OperationCanceledException, + optionsHaveChanges, outFile, PackageId, packageIdToPackageName, packageIdToString, PackageJsonInfoCache, padLeft, + ParameterDeclaration, ParseConfigFileHost, ParsedCommandLine, parseIsolatedEntityName, + parseJsonSourceFileConfigFileContent, Path, pathIsAbsolute, pathIsRelative, Program, ProgramHost, ProjectReference, + ProjectReferenceFile, projectReferenceIsEqualTo, PropertyDeclaration, ReferencedFile, removeFileExtension, + removePrefix, removeSuffix, resolutionExtensionIsTSOrJson, resolveConfigFileProjectName, ResolvedConfigFileName, + ResolvedModuleFull, ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, + ResolvedTypeReferenceDirective, resolveModuleName, resolveModuleNameFromCache, resolveTypeReferenceDirective, + returnFalse, returnUndefined, SatisfiesExpression, ScriptKind, ScriptTarget, Set, setParent, setParentRecursive, + setResolvedModule, setResolvedTypeReferenceDirective, skipTrivia, skipTypeChecking, some, + sortAndDeduplicateDiagnostics, SortedReadonlyArray, SourceFile, sourceFileAffectingCompilerOptions, + sourceFileMayBeEmitted, SourceOfProjectReferenceRedirect, stableSort, startsWith, Statement, stringContains, + StringLiteral, StringLiteralLike, StructureIsReused, supportedJSExtensionsFlat, SymlinkCache, SyntaxKind, sys, + targetOptionDeclaration, toFileNameLowerCase, tokenToString, trace, tracing, trimStringEnd, TsConfigSourceFile, + TypeChecker, typeDirectiveIsEqualTo, TypeReferenceDirectiveResolutionCache, UnparsedSource, VariableDeclaration, + VariableStatement, walkUpParenthesizedExpressions, WriteFileCallback, WriteFileCallbackData, + writeFileEnsuringDirectories, zipToModeAwareCache, +} from "./_namespaces/ts"; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean, configName = "tsconfig.json"): string | undefined { - return ts.forEachAncestorDirectory(searchPath, ancestor => { - const fileName = ts.combinePaths(ancestor, configName); + return forEachAncestorDirectory(searchPath, ancestor => { + const fileName = combinePaths(ancestor, configName); return fileExists(fileName) ? fileName : undefined; }); } export function resolveTripleslashReference(moduleName: string, containingFile: string): string { - const basePath = ts.getDirectoryPath(containingFile); - const referencedFileName = ts.isRootedDiskPath(moduleName) ? moduleName : ts.combinePaths(basePath, moduleName); - return ts.normalizePath(referencedFileName); + const basePath = getDirectoryPath(containingFile); + const referencedFileName = isRootedDiskPath(moduleName) ? moduleName : combinePaths(basePath, moduleName); + return normalizePath(referencedFileName); } /* @internal */ -export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly string[], currentDirectory: string, getCanonicalFileName: ts.GetCanonicalFileName): string { +export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly string[], currentDirectory: string, getCanonicalFileName: GetCanonicalFileName): string { let commonPathComponents: string[] | undefined; - const failed = ts.forEach(fileNames, sourceFile => { + const failed = forEach(fileNames, sourceFile => { // Each file contributes into common source file path - const sourcePathComponents = ts.getNormalizedPathComponents(sourceFile, currentDirectory); + const sourcePathComponents = getNormalizedPathComponents(sourceFile, currentDirectory); sourcePathComponents.pop(); // The base file name is not part of the common directory path if (!commonPathComponents) { @@ -56,19 +117,19 @@ export function computeCommonSourceDirectoryOfFilenames(fileNames: readonly stri return currentDirectory; } - return ts.getPathFromPathComponents(commonPathComponents); + return getPathFromPathComponents(commonPathComponents); } -export function createCompilerHost(options: ts.CompilerOptions, setParentNodes?: boolean): ts.CompilerHost { +export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { return createCompilerHostWorker(options, setParentNodes); } /*@internal*/ export function createGetSourceFile( - readFile: ts.ProgramHost["readFile"], - getCompilerOptions: () => ts.CompilerOptions, + readFile: ProgramHost["readFile"], + getCompilerOptions: () => CompilerOptions, setParentNodes: boolean | undefined -): ts.CompilerHost["getSourceFile"] { +): CompilerHost["getSourceFile"] { return (fileName, languageVersionOrOptions, onError) => { let text: string | undefined; try { @@ -83,7 +144,7 @@ export function createGetSourceFile( } text = ""; } - return text !== undefined ? ts.createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) : undefined; + return text !== undefined ? createSourceFile(fileName, text, languageVersionOrOptions, setParentNodes) : undefined; }; } @@ -92,7 +153,7 @@ export function createWriteFileMeasuringIO( actualWriteFile: (path: string, data: string, writeByteOrderMark: boolean) => void, createDirectory: (path: string) => void, directoryExists: (path: string) => boolean -): ts.CompilerHost["writeFile"] { +): CompilerHost["writeFile"] { return (fileName, data, writeByteOrderMark, onError) => { try { ts.performance.mark("beforeIOWrite"); @@ -100,7 +161,7 @@ export function createWriteFileMeasuringIO( // NOTE: If patchWriteFileEnsuringDirectory has been called, // the system.writeFile will do its own directory creation and // the ensureDirectoriesExist call will always be redundant. - ts.writeFileEnsuringDirectories( + writeFileEnsuringDirectories( fileName, data, writeByteOrderMark, @@ -121,9 +182,9 @@ export function createWriteFileMeasuringIO( } /*@internal*/ -export function createCompilerHostWorker(options: ts.CompilerOptions, setParentNodes?: boolean, system = ts.sys): ts.CompilerHost { - const existingDirectories = new ts.Map(); - const getCanonicalFileName = ts.createGetCanonicalFileName(system.useCaseSensitiveFileNames); +export function createCompilerHostWorker(options: CompilerOptions, setParentNodes?: boolean, system = sys): CompilerHost { + const existingDirectories = new Map(); + const getCanonicalFileName = createGetCanonicalFileName(system.useCaseSensitiveFileNames); function directoryExists(directoryPath: string): boolean { if (existingDirectories.has(directoryPath)) { return true; @@ -136,21 +197,21 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN } function getDefaultLibLocation(): string { - return ts.getDirectoryPath(ts.normalizePath(system.getExecutingFilePath())); + return getDirectoryPath(normalizePath(system.getExecutingFilePath())); } - const newLine = ts.getNewLineCharacter(options, () => system.newLine); + const newLine = getNewLineCharacter(options, () => system.newLine); const realpath = system.realpath && ((path: string) => system.realpath!(path)); - const compilerHost: ts.CompilerHost = { + const compilerHost: CompilerHost = { getSourceFile: createGetSourceFile(fileName => compilerHost.readFile(fileName), () => options, setParentNodes), getDefaultLibLocation, - getDefaultLibFileName: options => ts.combinePaths(getDefaultLibLocation(), ts.getDefaultLibFileName(options)), + getDefaultLibFileName: options => combinePaths(getDefaultLibLocation(), getDefaultLibFileName(options)), writeFile: createWriteFileMeasuringIO( (path, data, writeByteOrderMark) => system.writeFile(path, data, writeByteOrderMark), path => (compilerHost.createDirectory || system.createDirectory)(path), path => directoryExists(path), ), - getCurrentDirectory: ts.memoize(() => system.getCurrentDirectory()), + getCurrentDirectory: memoize(() => system.getCurrentDirectory()), useCaseSensitiveFileNames: () => system.useCaseSensitiveFileNames, getCanonicalFileName, getNewLine: () => newLine, @@ -163,7 +224,7 @@ export function createCompilerHostWorker(options: ts.CompilerOptions, setParentN realpath, readDirectory: (path, extensions, include, exclude, depth) => system.readDirectory(path, extensions, include, exclude, depth), createDirectory: d => system.createDirectory(d), - createHash: ts.maybeBind(system, system.createHash) + createHash: maybeBind(system, system.createHash) }; return compilerHost; } @@ -174,24 +235,24 @@ interface CompilerHostLikeForCache { readFile(fileName: string, encoding?: string): string | undefined; directoryExists?(directory: string): boolean; createDirectory?(directory: string): void; - writeFile?: ts.WriteFileCallback; + writeFile?: WriteFileCallback; } /*@internal*/ export function changeCompilerHostLikeToUseCache( host: CompilerHostLikeForCache, - toPath: (fileName: string) => ts.Path, - getSourceFile?: ts.CompilerHost["getSourceFile"] + toPath: (fileName: string) => Path, + getSourceFile?: CompilerHost["getSourceFile"] ) { const originalReadFile = host.readFile; const originalFileExists = host.fileExists; const originalDirectoryExists = host.directoryExists; const originalCreateDirectory = host.createDirectory; const originalWriteFile = host.writeFile; - const readFileCache = new ts.Map(); - const fileExistsCache = new ts.Map(); - const directoryExistsCache = new ts.Map(); - const sourceFileCache = new ts.Map>(); + const readFileCache = new Map(); + const fileExistsCache = new Map(); + const directoryExistsCache = new Map(); + const sourceFileCache = new Map>(); const readFileWithCache = (fileName: string): string | undefined => { const key = toPath(fileName); @@ -199,7 +260,7 @@ export function changeCompilerHostLikeToUseCache( if (value !== undefined) return value !== false ? value : undefined; return setReadFileCache(key, fileName); }; - const setReadFileCache = (key: ts.Path, fileName: string) => { + const setReadFileCache = (key: Path, fileName: string) => { const newValue = originalReadFile.call(host, fileName); readFileCache.set(key, newValue !== undefined ? newValue : false); return newValue; @@ -209,23 +270,23 @@ export function changeCompilerHostLikeToUseCache( const value = readFileCache.get(key); if (value !== undefined) return value !== false ? value : undefined; // could be .d.ts from output // Cache json or buildInfo - if (!ts.fileExtensionIs(fileName, ts.Extension.Json) && !ts.isBuildInfoFile(fileName)) { + if (!fileExtensionIs(fileName, Extension.Json) && !isBuildInfoFile(fileName)) { return originalReadFile.call(host, fileName); } return setReadFileCache(key, fileName); }; - const getSourceFileWithCache: ts.CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => { + const getSourceFileWithCache: CompilerHost["getSourceFile"] | undefined = getSourceFile ? (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => { const key = toPath(fileName); - const impliedNodeFormat: ts.SourceFile["impliedNodeFormat"] = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions.impliedNodeFormat : undefined; + const impliedNodeFormat: SourceFile["impliedNodeFormat"] = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions.impliedNodeFormat : undefined; const forImpliedNodeFormat = sourceFileCache.get(impliedNodeFormat); const value = forImpliedNodeFormat?.get(key); if (value) return value; const sourceFile = getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile); - if (sourceFile && (ts.isDeclarationFileName(fileName) || ts.fileExtensionIs(fileName, ts.Extension.Json))) { - sourceFileCache.set(impliedNodeFormat, (forImpliedNodeFormat || new ts.Map()).set(key, sourceFile)); + if (sourceFile && (isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json))) { + sourceFileCache.set(impliedNodeFormat, (forImpliedNodeFormat || new Map()).set(key, sourceFile)); } return sourceFile; } : undefined; @@ -292,21 +353,21 @@ export function changeCompilerHostLikeToUseCache( }; } -export function getPreEmitDiagnostics(program: ts.Program, sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; -/*@internal*/ export function getPreEmitDiagnostics(program: ts.BuilderProgram, sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[]; // eslint-disable-line @typescript-eslint/unified-signatures -export function getPreEmitDiagnostics(program: ts.Program | ts.BuilderProgram, sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { - let diagnostics: ts.Diagnostic[] | undefined; - diagnostics = ts.addRange(diagnostics, program.getConfigFileParsingDiagnostics()); - diagnostics = ts.addRange(diagnostics, program.getOptionsDiagnostics(cancellationToken)); - diagnostics = ts.addRange(diagnostics, program.getSyntacticDiagnostics(sourceFile, cancellationToken)); - diagnostics = ts.addRange(diagnostics, program.getGlobalDiagnostics(cancellationToken)); - diagnostics = ts.addRange(diagnostics, program.getSemanticDiagnostics(sourceFile, cancellationToken)); +export function getPreEmitDiagnostics(program: Program, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; +/*@internal*/ export function getPreEmitDiagnostics(program: BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[]; // eslint-disable-line @typescript-eslint/unified-signatures +export function getPreEmitDiagnostics(program: Program | BuilderProgram, sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { + let diagnostics: Diagnostic[] | undefined; + diagnostics = addRange(diagnostics, program.getConfigFileParsingDiagnostics()); + diagnostics = addRange(diagnostics, program.getOptionsDiagnostics(cancellationToken)); + diagnostics = addRange(diagnostics, program.getSyntacticDiagnostics(sourceFile, cancellationToken)); + diagnostics = addRange(diagnostics, program.getGlobalDiagnostics(cancellationToken)); + diagnostics = addRange(diagnostics, program.getSemanticDiagnostics(sourceFile, cancellationToken)); - if (ts.getEmitDeclarations(program.getCompilerOptions())) { - diagnostics = ts.addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, cancellationToken)); + if (getEmitDeclarations(program.getCompilerOptions())) { + diagnostics = addRange(diagnostics, program.getDeclarationDiagnostics(sourceFile, cancellationToken)); } - return ts.sortAndDeduplicateDiagnostics(diagnostics || ts.emptyArray); + return sortAndDeduplicateDiagnostics(diagnostics || emptyArray); } export interface FormatDiagnosticsHost { @@ -315,7 +376,7 @@ export interface FormatDiagnosticsHost { getNewLine(): string; } -export function formatDiagnostics(diagnostics: readonly ts.Diagnostic[], host: FormatDiagnosticsHost): string { +export function formatDiagnostics(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string { let output = ""; for (const diagnostic of diagnostics) { @@ -324,13 +385,13 @@ export function formatDiagnostics(diagnostics: readonly ts.Diagnostic[], host: F return output; } -export function formatDiagnostic(diagnostic: ts.Diagnostic, host: FormatDiagnosticsHost): string { - const errorMessage = `${ts.diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`; +export function formatDiagnostic(diagnostic: Diagnostic, host: FormatDiagnosticsHost): string { + const errorMessage = `${diagnosticCategoryName(diagnostic)} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine())}${host.getNewLine()}`; if (diagnostic.file) { - const { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); // TODO: GH#18217 + const { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start!); // TODO: GH#18217 const fileName = diagnostic.file.fileName; - const relativeFileName = ts.convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)); + const relativeFileName = convertToRelativePath(fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)); return `${relativeFileName}(${line + 1},${character + 1}): ` + errorMessage; } @@ -351,12 +412,12 @@ const resetEscapeSequence = "\u001b[0m"; const ellipsis = "..."; const halfIndent = " "; const indent = " "; -function getCategoryFormat(category: ts.DiagnosticCategory): ForegroundColorEscapeSequences { +function getCategoryFormat(category: DiagnosticCategory): ForegroundColorEscapeSequences { switch (category) { - case ts.DiagnosticCategory.Error: return ForegroundColorEscapeSequences.Red; - case ts.DiagnosticCategory.Warning: return ForegroundColorEscapeSequences.Yellow; - case ts.DiagnosticCategory.Suggestion: return ts.Debug.fail("Should never get an Info diagnostic on the command line."); - case ts.DiagnosticCategory.Message: return ForegroundColorEscapeSequences.Blue; + case DiagnosticCategory.Error: return ForegroundColorEscapeSequences.Red; + case DiagnosticCategory.Warning: return ForegroundColorEscapeSequences.Yellow; + case DiagnosticCategory.Suggestion: return Debug.fail("Should never get an Info diagnostic on the command line."); + case DiagnosticCategory.Message: return ForegroundColorEscapeSequences.Blue; } } @@ -365,10 +426,10 @@ export function formatColorAndReset(text: string, formatStyle: string) { return formatStyle + text + resetEscapeSequence; } -function formatCodeSpan(file: ts.SourceFile, start: number, length: number, indent: string, squiggleColor: ForegroundColorEscapeSequences, host: FormatDiagnosticsHost) { - const { line: firstLine, character: firstLineChar } = ts.getLineAndCharacterOfPosition(file, start); - const { line: lastLine, character: lastLineChar } = ts.getLineAndCharacterOfPosition(file, start + length); - const lastLineInFile = ts.getLineAndCharacterOfPosition(file, file.text.length).line; +function formatCodeSpan(file: SourceFile, start: number, length: number, indent: string, squiggleColor: ForegroundColorEscapeSequences, host: FormatDiagnosticsHost) { + const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); + const { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); + const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; const hasMoreThanFiveLines = (lastLine - firstLine) >= 4; let gutterWidth = (lastLine + 1 + "").length; @@ -382,22 +443,22 @@ function formatCodeSpan(file: ts.SourceFile, start: number, length: number, inde // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - context += indent + formatColorAndReset(ts.padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); + context += indent + formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); i = lastLine - 1; } - const lineStart = ts.getPositionOfLineAndCharacter(file, i, 0); - const lineEnd = i < lastLineInFile ? ts.getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; + const lineStart = getPositionOfLineAndCharacter(file, i, 0); + const lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; let lineContent = file.text.slice(lineStart, lineEnd); - lineContent = ts.trimStringEnd(lineContent); // trim from end + lineContent = trimStringEnd(lineContent); // trim from end lineContent = lineContent.replace(/\t/g, " "); // convert tabs to single spaces // Output the gutter and the actual contents of the line. - context += indent + formatColorAndReset(ts.padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + context += indent + formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; context += lineContent + host.getNewLine(); // Output the gutter and the error span for the line using tildes. - context += indent + formatColorAndReset(ts.padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; + context += indent + formatColorAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; context += squiggleColor; if (i === firstLine) { // If we're on the last line, then limit it to the last character of the last line. @@ -420,9 +481,9 @@ function formatCodeSpan(file: ts.SourceFile, start: number, length: number, inde } /* @internal */ -export function formatLocation(file: ts.SourceFile, start: number, host: FormatDiagnosticsHost, color = formatColorAndReset) { - const { line: firstLine, character: firstLineChar } = ts.getLineAndCharacterOfPosition(file, start); // TODO: GH#18217 - const relativeFileName = host ? ts.convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; +export function formatLocation(file: SourceFile, start: number, host: FormatDiagnosticsHost, color = formatColorAndReset) { + const { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); // TODO: GH#18217 + const relativeFileName = host ? convertToRelativePath(file.fileName, host.getCurrentDirectory(), fileName => host.getCanonicalFileName(fileName)) : file.fileName; let output = ""; output += color(relativeFileName, ForegroundColorEscapeSequences.Cyan); @@ -433,7 +494,7 @@ export function formatLocation(file: ts.SourceFile, start: number, host: FormatD return output; } -export function formatDiagnosticsWithColorAndContext(diagnostics: readonly ts.Diagnostic[], host: FormatDiagnosticsHost): string { +export function formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost): string { let output = ""; for (const diagnostic of diagnostics) { if (diagnostic.file) { @@ -442,7 +503,7 @@ export function formatDiagnosticsWithColorAndContext(diagnostics: readonly ts.Di output += " - "; } - output += formatColorAndReset(ts.diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category)); + output += formatColorAndReset(diagnosticCategoryName(diagnostic), getCategoryFormat(diagnostic.category)); output += formatColorAndReset(` TS${diagnostic.code}: `, ForegroundColorEscapeSequences.Grey); output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()); @@ -467,8 +528,8 @@ export function formatDiagnosticsWithColorAndContext(diagnostics: readonly ts.Di return output; } -export function flattenDiagnosticMessageText(diag: string | ts.DiagnosticMessageChain | undefined, newLine: string, indent = 0): string { - if (ts.isString(diag)) { +export function flattenDiagnosticMessageText(diag: string | DiagnosticMessageChain | undefined, newLine: string, indent = 0): string { + if (isString(diag)) { return diag; } else if (diag === undefined) { @@ -493,17 +554,17 @@ export function flattenDiagnosticMessageText(diag: string | ts.DiagnosticMessage } /* @internal */ -export function loadWithTypeDirectiveCache(names: string[] | readonly ts.FileReference[], containingFile: string, redirectedReference: ts.ResolvedProjectReference | undefined, containingFileMode: ts.SourceFile["impliedNodeFormat"], loader: (name: string, containingFile: string, redirectedReference: ts.ResolvedProjectReference | undefined, resolutionMode: ts.SourceFile["impliedNodeFormat"]) => T): T[] { +export function loadWithTypeDirectiveCache(names: string[] | readonly FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, containingFileMode: SourceFile["impliedNodeFormat"], loader: (name: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined, resolutionMode: SourceFile["impliedNodeFormat"]) => T): T[] { if (names.length === 0) { return []; } const resolutions: T[] = []; - const cache = new ts.Map(); + const cache = new Map(); for (const name of names) { let result: T; const mode = getModeForFileReference(name, containingFileMode); // We lower-case all type references because npm automatically lowercases all packages. See GH#9824. - const strName = ts.isString(name) ? name : name.fileName.toLowerCase(); + const strName = isString(name) ? name : name.fileName.toLowerCase(); const cacheKey = mode !== undefined ? `${mode}|${strName}` : strName; if (cache.has(cacheKey)) { result = cache.get(cacheKey)!; @@ -524,17 +585,17 @@ export function loadWithTypeDirectiveCache(names: string[] | readonly ts.File * @internal */ export interface SourceFileImportsList { - /* @internal */ imports: ts.SourceFile["imports"]; - /* @internal */ moduleAugmentations: ts.SourceFile["moduleAugmentations"]; - impliedNodeFormat?: ts.SourceFile["impliedNodeFormat"]; + /* @internal */ imports: SourceFile["imports"]; + /* @internal */ moduleAugmentations: SourceFile["moduleAugmentations"]; + impliedNodeFormat?: SourceFile["impliedNodeFormat"]; } /** * Calculates the resulting resolution mode for some reference in some file - this is generally the explicitly * provided resolution mode in the reference, unless one is not present, in which case it is the mode of the containing file. */ -export function getModeForFileReference(ref: ts.FileReference | string, containingFileMode: ts.SourceFile["impliedNodeFormat"]) { - return (ts.isString(ref) ? containingFileMode : ref.resolutionMode) || containingFileMode; +export function getModeForFileReference(ref: FileReference | string, containingFileMode: SourceFile["impliedNodeFormat"]) { + return (isString(ref) ? containingFileMode : ref.resolutionMode) || containingFileMode; } /** @@ -544,11 +605,11 @@ export function getModeForFileReference(ref: ts.FileReference | string, containi * @param file File to fetch the resolution mode within * @param index Index into the file's complete resolution list to get the resolution of - this is a concatenation of the file's imports and module augmentations */ -export function getModeForResolutionAtIndex(file: ts.SourceFile, index: number): ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined; +export function getModeForResolutionAtIndex(file: SourceFile, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined; /** @internal */ // eslint-disable-next-line @typescript-eslint/unified-signatures -export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined; -export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined { +export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined; +export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: number): ModuleKind.CommonJS | ModuleKind.ESNext | undefined { if (file.impliedNodeFormat === undefined) return undefined; // we ensure all elements of file.imports and file.moduleAugmentations have the relevant parent pointers set during program setup, // so it's safe to use them even pre-bind @@ -556,8 +617,8 @@ export function getModeForResolutionAtIndex(file: SourceFileImportsList, index: } /* @internal */ -export function isExclusivelyTypeOnlyImportOrExport(decl: ts.ImportDeclaration | ts.ExportDeclaration) { - if (ts.isExportDeclaration(decl)) { +export function isExclusivelyTypeOnlyImportOrExport(decl: ImportDeclaration | ExportDeclaration) { + if (isExportDeclaration(decl)) { return decl.isTypeOnly; } if (decl.importClause?.isTypeOnly) { @@ -575,9 +636,9 @@ export function isExclusivelyTypeOnlyImportOrExport(decl: ts.ImportDeclaration | * @param usage The module reference string * @returns The final resolution mode of the import */ -export function getModeForUsageLocation(file: {impliedNodeFormat?: ts.SourceFile["impliedNodeFormat"]}, usage: ts.StringLiteralLike) { +export function getModeForUsageLocation(file: {impliedNodeFormat?: SourceFile["impliedNodeFormat"]}, usage: StringLiteralLike) { if (file.impliedNodeFormat === undefined) return undefined; - if ((ts.isImportDeclaration(usage.parent) || ts.isExportDeclaration(usage.parent))) { + if ((isImportDeclaration(usage.parent) || isExportDeclaration(usage.parent))) { const isTypeOnly = isExclusivelyTypeOnlyImportOrExport(usage.parent); if (isTypeOnly) { const override = getResolutionModeOverrideForClause(usage.parent.assertClause); @@ -586,50 +647,50 @@ export function getModeForUsageLocation(file: {impliedNodeFormat?: ts.SourceFile } } } - if (usage.parent.parent && ts.isImportTypeNode(usage.parent.parent)) { + if (usage.parent.parent && isImportTypeNode(usage.parent.parent)) { const override = getResolutionModeOverrideForClause(usage.parent.parent.assertions?.assertClause); if (override) { return override; } } - if (file.impliedNodeFormat !== ts.ModuleKind.ESNext) { + if (file.impliedNodeFormat !== ModuleKind.ESNext) { // in cjs files, import call expressions are esm format, otherwise everything is cjs - return ts.isImportCall(ts.walkUpParenthesizedExpressions(usage.parent)) ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS; + return isImportCall(walkUpParenthesizedExpressions(usage.parent)) ? ModuleKind.ESNext : ModuleKind.CommonJS; } // in esm files, import=require statements are cjs format, otherwise everything is esm // imports are only parent'd up to their containing declaration/expression, so access farther parents with care - const exprParentParent = ts.walkUpParenthesizedExpressions(usage.parent)?.parent; - return exprParentParent && ts.isImportEqualsDeclaration(exprParentParent) ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext; + const exprParentParent = walkUpParenthesizedExpressions(usage.parent)?.parent; + return exprParentParent && isImportEqualsDeclaration(exprParentParent) ? ModuleKind.CommonJS : ModuleKind.ESNext; } /* @internal */ -export function getResolutionModeOverrideForClause(clause: ts.AssertClause | undefined, grammarErrorOnNode?: (node: ts.Node, diagnostic: ts.DiagnosticMessage) => void) { +export function getResolutionModeOverrideForClause(clause: AssertClause | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void) { if (!clause) return undefined; - if (ts.length(clause.elements) !== 1) { - grammarErrorOnNode?.(clause, ts.Diagnostics.Type_import_assertions_should_have_exactly_one_key_resolution_mode_with_value_import_or_require); + if (length(clause.elements) !== 1) { + grammarErrorOnNode?.(clause, Diagnostics.Type_import_assertions_should_have_exactly_one_key_resolution_mode_with_value_import_or_require); return undefined; } const elem = clause.elements[0]; - if (!ts.isStringLiteralLike(elem.name)) return undefined; + if (!isStringLiteralLike(elem.name)) return undefined; if (elem.name.text !== "resolution-mode") { - grammarErrorOnNode?.(elem.name, ts.Diagnostics.resolution_mode_is_the_only_valid_key_for_type_import_assertions); + grammarErrorOnNode?.(elem.name, Diagnostics.resolution_mode_is_the_only_valid_key_for_type_import_assertions); return undefined; } - if (!ts.isStringLiteralLike(elem.value)) return undefined; + if (!isStringLiteralLike(elem.value)) return undefined; if (elem.value.text !== "import" && elem.value.text !== "require") { - grammarErrorOnNode?.(elem.value, ts.Diagnostics.resolution_mode_should_be_either_require_or_import); + grammarErrorOnNode?.(elem.value, Diagnostics.resolution_mode_should_be_either_require_or_import); return undefined; } - return elem.value.text === "import" ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS; + return elem.value.text === "import" ? ModuleKind.ESNext : ModuleKind.CommonJS; } /* @internal */ -export function loadWithModeAwareCache(names: string[], containingFile: ts.SourceFile, containingFileName: string, redirectedReference: ts.ResolvedProjectReference | undefined, loader: (name: string, resolverMode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined, containingFileName: string, redirectedReference: ts.ResolvedProjectReference | undefined) => T): T[] { +export function loadWithModeAwareCache(names: string[], containingFile: SourceFile, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined, loader: (name: string, resolverMode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined) => T): T[] { if (names.length === 0) { return []; } const resolutions: T[] = []; - const cache = new ts.Map(); + const cache = new Map(); let i = 0; for (const name of names) { let result: T; @@ -649,26 +710,26 @@ export function loadWithModeAwareCache(names: string[], containingFile: ts.So /* @internal */ export function forEachResolvedProjectReference( - resolvedProjectReferences: readonly (ts.ResolvedProjectReference | undefined)[] | undefined, - cb: (resolvedProjectReference: ts.ResolvedProjectReference, parent: ts.ResolvedProjectReference | undefined) => T | undefined + resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined, + cb: (resolvedProjectReference: ResolvedProjectReference, parent: ResolvedProjectReference | undefined) => T | undefined ): T | undefined { return forEachProjectReference(/*projectReferences*/ undefined, resolvedProjectReferences, (resolvedRef, parent) => resolvedRef && cb(resolvedRef, parent)); } function forEachProjectReference( - projectReferences: readonly ts.ProjectReference[] | undefined, - resolvedProjectReferences: readonly (ts.ResolvedProjectReference | undefined)[] | undefined, - cbResolvedRef: (resolvedRef: ts.ResolvedProjectReference | undefined, parent: ts.ResolvedProjectReference | undefined, index: number) => T | undefined, - cbRef?: (projectReferences: readonly ts.ProjectReference[] | undefined, parent: ts.ResolvedProjectReference | undefined) => T | undefined + projectReferences: readonly ProjectReference[] | undefined, + resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined, + cbResolvedRef: (resolvedRef: ResolvedProjectReference | undefined, parent: ResolvedProjectReference | undefined, index: number) => T | undefined, + cbRef?: (projectReferences: readonly ProjectReference[] | undefined, parent: ResolvedProjectReference | undefined) => T | undefined ): T | undefined { - let seenResolvedRefs: ts.Set | undefined; + let seenResolvedRefs: Set | undefined; return worker(projectReferences, resolvedProjectReferences, /*parent*/ undefined); function worker( - projectReferences: readonly ts.ProjectReference[] | undefined, - resolvedProjectReferences: readonly (ts.ResolvedProjectReference | undefined)[] | undefined, - parent: ts.ResolvedProjectReference | undefined, + projectReferences: readonly ProjectReference[] | undefined, + resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined, + parent: ResolvedProjectReference | undefined, ): T | undefined { // Visit project references first @@ -677,7 +738,7 @@ function forEachProjectReference( if (result) return result; } - return ts.forEach(resolvedProjectReferences, (resolvedRef, index) => { + return forEach(resolvedProjectReferences, (resolvedRef, index) => { if (resolvedRef && seenResolvedRefs?.has(resolvedRef.sourceFile.path)) { // ignore recursives return undefined; @@ -686,7 +747,7 @@ function forEachProjectReference( const result = cbResolvedRef(resolvedRef, parent, index); if (result || !resolvedRef) return result; - (seenResolvedRefs ||= new ts.Set()).add(resolvedRef.sourceFile.path); + (seenResolvedRefs ||= new Set()).add(resolvedRef.sourceFile.path); return worker(resolvedRef.commandLine.projectReferences, resolvedRef.references, resolvedRef); }); } @@ -695,18 +756,18 @@ function forEachProjectReference( /* @internal */ export const inferredTypesContainingFile = "__inferred type names__.ts"; -interface DiagnosticCache { - perFile?: ts.ESMap; +interface DiagnosticCache { + perFile?: ESMap; allDiagnostics?: readonly T[]; } /*@internal*/ -export function isReferencedFile(reason: ts.FileIncludeReason | undefined): reason is ts.ReferencedFile { +export function isReferencedFile(reason: FileIncludeReason | undefined): reason is ReferencedFile { switch (reason?.kind) { - case ts.FileIncludeKind.Import: - case ts.FileIncludeKind.ReferenceFile: - case ts.FileIncludeKind.TypeReferenceDirective: - case ts.FileIncludeKind.LibReferenceDirective: + case FileIncludeKind.Import: + case FileIncludeKind.ReferenceFile: + case FileIncludeKind.TypeReferenceDirective: + case FileIncludeKind.LibReferenceDirective: return true; default: return false; @@ -715,16 +776,16 @@ export function isReferencedFile(reason: ts.FileIncludeReason | undefined): reas /*@internal*/ export interface ReferenceFileLocation { - file: ts.SourceFile; + file: SourceFile; pos: number; end: number; - packageId: ts.PackageId | undefined; + packageId: PackageId | undefined; } /*@internal*/ export interface SyntheticReferenceFileLocation { - file: ts.SourceFile; - packageId: ts.PackageId | undefined; + file: SourceFile; + packageId: PackageId | undefined; text: string; } @@ -734,30 +795,30 @@ export function isReferenceFileLocation(location: ReferenceFileLocation | Synthe } /*@internal*/ -export function getReferencedFileLocation(getSourceFileByPath: (path: ts.Path) => ts.SourceFile | undefined, ref: ts.ReferencedFile): ReferenceFileLocation | SyntheticReferenceFileLocation { - const file = ts.Debug.checkDefined(getSourceFileByPath(ref.file)); +export function getReferencedFileLocation(getSourceFileByPath: (path: Path) => SourceFile | undefined, ref: ReferencedFile): ReferenceFileLocation | SyntheticReferenceFileLocation { + const file = Debug.checkDefined(getSourceFileByPath(ref.file)); const { kind, index } = ref; - let pos: number | undefined, end: number | undefined, packageId: ts.PackageId | undefined, resolutionMode: ts.FileReference["resolutionMode"] | undefined; + let pos: number | undefined, end: number | undefined, packageId: PackageId | undefined, resolutionMode: FileReference["resolutionMode"] | undefined; switch (kind) { - case ts.FileIncludeKind.Import: + case FileIncludeKind.Import: const importLiteral = getModuleNameStringLiteralAt(file, index); packageId = file.resolvedModules?.get(importLiteral.text, getModeForResolutionAtIndex(file, index))?.packageId; if (importLiteral.pos === -1) return { file, packageId, text: importLiteral.text }; - pos = ts.skipTrivia(file.text, importLiteral.pos); + pos = skipTrivia(file.text, importLiteral.pos); end = importLiteral.end; break; - case ts.FileIncludeKind.ReferenceFile: + case FileIncludeKind.ReferenceFile: ({ pos, end } = file.referencedFiles[index]); break; - case ts.FileIncludeKind.TypeReferenceDirective: + case FileIncludeKind.TypeReferenceDirective: ({ pos, end, resolutionMode } = file.typeReferenceDirectives[index]); - packageId = file.resolvedTypeReferenceDirectiveNames?.get(ts.toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.packageId; + packageId = file.resolvedTypeReferenceDirectiveNames?.get(toFileNameLowerCase(file.typeReferenceDirectives[index].fileName), resolutionMode || file.impliedNodeFormat)?.packageId; break; - case ts.FileIncludeKind.LibReferenceDirective: + case FileIncludeKind.LibReferenceDirective: ({ pos, end } = file.libReferenceDirectives[index]); break; default: - return ts.Debug.assertNever(kind); + return Debug.assertNever(kind); } return { file, pos, end, packageId }; } @@ -767,26 +828,26 @@ export function getReferencedFileLocation(getSourceFileByPath: (path: ts.Path) = */ /* @internal */ export function isProgramUptoDate( - program: ts.Program | undefined, + program: Program | undefined, rootFileNames: string[], - newOptions: ts.CompilerOptions, - getSourceVersion: (path: ts.Path, fileName: string) => string | undefined, + newOptions: CompilerOptions, + getSourceVersion: (path: Path, fileName: string) => string | undefined, fileExists: (fileName: string) => boolean, - hasInvalidatedResolutions: ts.HasInvalidatedResolutions, - hasChangedAutomaticTypeDirectiveNames: ts.HasChangedAutomaticTypeDirectiveNames | undefined, - getParsedCommandLine: (fileName: string) => ts.ParsedCommandLine | undefined, - projectReferences: readonly ts.ProjectReference[] | undefined + hasInvalidatedResolutions: HasInvalidatedResolutions, + hasChangedAutomaticTypeDirectiveNames: HasChangedAutomaticTypeDirectiveNames | undefined, + getParsedCommandLine: (fileName: string) => ParsedCommandLine | undefined, + projectReferences: readonly ProjectReference[] | undefined ): boolean { // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date if (!program || hasChangedAutomaticTypeDirectiveNames?.()) return false; // If root file names don't match - if (!ts.arrayIsEqualTo(program.getRootFileNames(), rootFileNames)) return false; + if (!arrayIsEqualTo(program.getRootFileNames(), rootFileNames)) return false; - let seenResolvedRefs: ts.ResolvedProjectReference[] | undefined; + let seenResolvedRefs: ResolvedProjectReference[] | undefined; // If project references don't match - if (!ts.arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) return false; + if (!arrayIsEqualTo(program.getProjectReferences(), projectReferences, projectReferenceUptoDate)) return false; // If any file is not up-to-date, then the whole program is not up-to-date if (program.getSourceFiles().some(sourceFileNotUptoDate)) return false; @@ -796,7 +857,7 @@ export function isProgramUptoDate( const currentOptions = program.getCompilerOptions(); // If the compilation settings do no match, then the program is not up-to-date - if (!ts.compareDataObjects(currentOptions, newOptions)) return false; + if (!compareDataObjects(currentOptions, newOptions)) return false; // If everything matches but the text of config file is changed, // error locations can change for program options, so update the program @@ -804,24 +865,24 @@ export function isProgramUptoDate( return true; - function sourceFileNotUptoDate(sourceFile: ts.SourceFile) { + function sourceFileNotUptoDate(sourceFile: SourceFile) { return !sourceFileVersionUptoDate(sourceFile) || hasInvalidatedResolutions(sourceFile.path); } - function sourceFileVersionUptoDate(sourceFile: ts.SourceFile) { + function sourceFileVersionUptoDate(sourceFile: SourceFile) { return sourceFile.version === getSourceVersion(sourceFile.resolvedPath, sourceFile.fileName); } - function projectReferenceUptoDate(oldRef: ts.ProjectReference, newRef: ts.ProjectReference, index: number) { - return ts.projectReferenceIsEqualTo(oldRef, newRef) && + function projectReferenceUptoDate(oldRef: ProjectReference, newRef: ProjectReference, index: number) { + return projectReferenceIsEqualTo(oldRef, newRef) && resolvedProjectReferenceUptoDate(program!.getResolvedProjectReferences()![index], oldRef); } - function resolvedProjectReferenceUptoDate(oldResolvedRef: ts.ResolvedProjectReference | undefined, oldRef: ts.ProjectReference): boolean { + function resolvedProjectReferenceUptoDate(oldResolvedRef: ResolvedProjectReference | undefined, oldRef: ProjectReference): boolean { if (oldResolvedRef) { // Assume true - if (ts.contains(seenResolvedRefs, oldResolvedRef)) return true; + if (contains(seenResolvedRefs, oldResolvedRef)) return true; const refPath = resolveProjectReferencePath(oldRef); const newParsedCommandLine = getParsedCommandLine(refPath); @@ -833,13 +894,13 @@ export function isProgramUptoDate( if (oldResolvedRef.commandLine.options.configFile !== newParsedCommandLine.options.configFile) return false; // check file names - if (!ts.arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newParsedCommandLine.fileNames)) return false; + if (!arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newParsedCommandLine.fileNames)) return false; // Add to seen before checking the referenced paths of this config file (seenResolvedRefs || (seenResolvedRefs = [])).push(oldResolvedRef); // If child project references are upto date, this project reference is uptodate - return !ts.forEach(oldResolvedRef.references, (childResolvedRef, index) => + return !forEach(oldResolvedRef.references, (childResolvedRef, index) => !resolvedProjectReferenceUptoDate(childResolvedRef, oldResolvedRef.commandLine.projectReferences![index])); } @@ -850,7 +911,7 @@ export function isProgramUptoDate( } } -export function getConfigFileParsingDiagnostics(configFileParseResult: ts.ParsedCommandLine): readonly ts.Diagnostic[] { +export function getConfigFileParsingDiagnostics(configFileParseResult: ParsedCommandLine): readonly Diagnostic[] { return configFileParseResult.options.configFile ? [...configFileParseResult.options.configFile.parseDiagnostics, ...configFileParseResult.errors] : configFileParseResult.errors; @@ -866,7 +927,7 @@ export function getConfigFileParsingDiagnostics(configFileParseResult: ts.Parsed * @param options The compiler options to perform the analysis under - relevant options are `moduleResolution` and `traceResolution` * @returns `undefined` if the path has no relevant implied format, `ModuleKind.ESNext` for esm format, and `ModuleKind.CommonJS` for cjs format */ -export function getImpliedNodeFormatForFile(fileName: ts.Path, packageJsonInfoCache: ts.PackageJsonInfoCache | undefined, host: ts.ModuleResolutionHost, options: ts.CompilerOptions): ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined { +export function getImpliedNodeFormatForFile(fileName: Path, packageJsonInfoCache: PackageJsonInfoCache | undefined, host: ModuleResolutionHost, options: CompilerOptions): ModuleKind.ESNext | ModuleKind.CommonJS | undefined { const result = getImpliedNodeFormatForFileWorker(fileName, packageJsonInfoCache, host, options); return typeof result === "object" ? result.impliedNodeFormat : result; } @@ -874,139 +935,139 @@ export function getImpliedNodeFormatForFile(fileName: ts.Path, packageJsonInfoCa /*@internal*/ export function getImpliedNodeFormatForFileWorker( fileName: string, - packageJsonInfoCache: ts.PackageJsonInfoCache | undefined, - host: ts.ModuleResolutionHost, - options: ts.CompilerOptions, + packageJsonInfoCache: PackageJsonInfoCache | undefined, + host: ModuleResolutionHost, + options: CompilerOptions, ) { - switch (ts.getEmitModuleResolutionKind(options)) { - case ts.ModuleResolutionKind.Node16: - case ts.ModuleResolutionKind.NodeNext: - return ts.fileExtensionIsOneOf(fileName, [ts.Extension.Dmts, ts.Extension.Mts, ts.Extension.Mjs]) ? ts.ModuleKind.ESNext : - ts.fileExtensionIsOneOf(fileName, [ts.Extension.Dcts, ts.Extension.Cts, ts.Extension.Cjs]) ? ts.ModuleKind.CommonJS : - ts.fileExtensionIsOneOf(fileName, [ts.Extension.Dts, ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Js, ts.Extension.Jsx]) ? lookupFromPackageJson() : + switch (getEmitModuleResolutionKind(options)) { + case ModuleResolutionKind.Node16: + case ModuleResolutionKind.NodeNext: + return fileExtensionIsOneOf(fileName, [Extension.Dmts, Extension.Mts, Extension.Mjs]) ? ModuleKind.ESNext : + fileExtensionIsOneOf(fileName, [Extension.Dcts, Extension.Cts, Extension.Cjs]) ? ModuleKind.CommonJS : + fileExtensionIsOneOf(fileName, [Extension.Dts, Extension.Ts, Extension.Tsx, Extension.Js, Extension.Jsx]) ? lookupFromPackageJson() : undefined; // other extensions, like `json` or `tsbuildinfo`, are set as `undefined` here but they should never be fed through the transformer pipeline default: return undefined; } - function lookupFromPackageJson(): Partial { - const state = ts.getTemporaryModuleResolutionState(packageJsonInfoCache, host, options); + function lookupFromPackageJson(): Partial { + const state = getTemporaryModuleResolutionState(packageJsonInfoCache, host, options); const packageJsonLocations: string[] = []; state.failedLookupLocations = packageJsonLocations; state.affectingLocations = packageJsonLocations; - const packageJsonScope = ts.getPackageScopeForPath(fileName, state); - const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS; + const packageJsonScope = getPackageScopeForPath(fileName, state); + const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS; return { impliedNodeFormat, packageJsonLocations, packageJsonScope }; } } /** @internal */ -export const plainJSErrors: ts.Set = new ts.Set([ +export const plainJSErrors: Set = new Set([ // binder errors - ts.Diagnostics.Cannot_redeclare_block_scoped_variable_0.code, - ts.Diagnostics.A_module_cannot_have_multiple_default_exports.code, - ts.Diagnostics.Another_export_default_is_here.code, - ts.Diagnostics.The_first_export_default_is_here.code, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module.code, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode.code, - ts.Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here.code, - ts.Diagnostics.constructor_is_a_reserved_word.code, - ts.Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode.code, - ts.Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode.code, - ts.Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode.code, - ts.Diagnostics.Invalid_use_of_0_in_strict_mode.code, - ts.Diagnostics.A_label_is_not_allowed_here.code, - ts.Diagnostics.Octal_literals_are_not_allowed_in_strict_mode.code, - ts.Diagnostics.with_statements_are_not_allowed_in_strict_mode.code, + Diagnostics.Cannot_redeclare_block_scoped_variable_0.code, + Diagnostics.A_module_cannot_have_multiple_default_exports.code, + Diagnostics.Another_export_default_is_here.code, + Diagnostics.The_first_export_default_is_here.code, + Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module.code, + Diagnostics.Identifier_expected_0_is_a_reserved_word_in_strict_mode_Modules_are_automatically_in_strict_mode.code, + Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here.code, + Diagnostics.constructor_is_a_reserved_word.code, + Diagnostics.delete_cannot_be_called_on_an_identifier_in_strict_mode.code, + Diagnostics.Code_contained_in_a_class_is_evaluated_in_JavaScript_s_strict_mode_which_does_not_allow_this_use_of_0_For_more_information_see_https_Colon_Slash_Slashdeveloper_mozilla_org_Slashen_US_Slashdocs_SlashWeb_SlashJavaScript_SlashReference_SlashStrict_mode.code, + Diagnostics.Invalid_use_of_0_Modules_are_automatically_in_strict_mode.code, + Diagnostics.Invalid_use_of_0_in_strict_mode.code, + Diagnostics.A_label_is_not_allowed_here.code, + Diagnostics.Octal_literals_are_not_allowed_in_strict_mode.code, + Diagnostics.with_statements_are_not_allowed_in_strict_mode.code, // grammar errors - ts.Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement.code, - ts.Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement.code, - ts.Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name.code, - ts.Diagnostics.A_class_member_cannot_have_the_0_keyword.code, - ts.Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name.code, - ts.Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement.code, - ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code, - ts.Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code, - ts.Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement.code, - ts.Diagnostics.A_default_export_must_be_at_the_top_level_of_a_file_or_module_declaration.code, - ts.Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context.code, - ts.Diagnostics.A_destructuring_declaration_must_have_an_initializer.code, - ts.Diagnostics.A_get_accessor_cannot_have_parameters.code, - ts.Diagnostics.A_rest_element_cannot_contain_a_binding_pattern.code, - ts.Diagnostics.A_rest_element_cannot_have_a_property_name.code, - ts.Diagnostics.A_rest_element_cannot_have_an_initializer.code, - ts.Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern.code, - ts.Diagnostics.A_rest_parameter_cannot_have_an_initializer.code, - ts.Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list.code, - ts.Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma.code, - ts.Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block.code, - ts.Diagnostics.A_set_accessor_cannot_have_rest_parameter.code, - ts.Diagnostics.A_set_accessor_must_have_exactly_one_parameter.code, - ts.Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module.code, - ts.Diagnostics.An_export_declaration_cannot_have_modifiers.code, - ts.Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module.code, - ts.Diagnostics.An_import_declaration_cannot_have_modifiers.code, - ts.Diagnostics.An_object_member_cannot_be_declared_optional.code, - ts.Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element.code, - ts.Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable.code, - ts.Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause.code, - ts.Diagnostics.Catch_clause_variable_cannot_have_an_initializer.code, - ts.Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator.code, - ts.Diagnostics.Classes_can_only_extend_a_single_class.code, - ts.Diagnostics.Classes_may_not_have_a_field_named_constructor.code, - ts.Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code, - ts.Diagnostics.Duplicate_label_0.code, - ts.Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments.code, - ts.Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block.code, - ts.Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression.code, - ts.Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name.code, - ts.Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array.code, - ts.Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names.code, - ts.Diagnostics.Jump_target_cannot_cross_function_boundary.code, - ts.Diagnostics.Line_terminator_not_permitted_before_arrow.code, - ts.Diagnostics.Modifiers_cannot_appear_here.code, - ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement.code, - ts.Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement.code, - ts.Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies.code, - ts.Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code, - ts.Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier.code, - ts.Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain.code, - ts.Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async.code, - ts.Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer.code, - ts.Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer.code, - ts.Diagnostics.Trailing_comma_not_allowed.code, - ts.Diagnostics.Variable_declaration_list_cannot_be_empty.code, - ts.Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses.code, - ts.Diagnostics._0_expected.code, - ts.Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2.code, - ts.Diagnostics._0_list_cannot_be_empty.code, - ts.Diagnostics._0_modifier_already_seen.code, - ts.Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration.code, - ts.Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element.code, - ts.Diagnostics._0_modifier_cannot_appear_on_a_parameter.code, - ts.Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind.code, - ts.Diagnostics._0_modifier_cannot_be_used_here.code, - ts.Diagnostics._0_modifier_must_precede_1_modifier.code, - ts.Diagnostics.const_declarations_can_only_be_declared_inside_a_block.code, - ts.Diagnostics.const_declarations_must_be_initialized.code, - ts.Diagnostics.extends_clause_already_seen.code, - ts.Diagnostics.let_declarations_can_only_be_declared_inside_a_block.code, - ts.Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations.code, - ts.Diagnostics.Class_constructor_may_not_be_a_generator.code, - ts.Diagnostics.Class_constructor_may_not_be_an_accessor.code, - ts.Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code, + Diagnostics.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement.code, + Diagnostics.A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement.code, + Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name.code, + Diagnostics.A_class_member_cannot_have_the_0_keyword.code, + Diagnostics.A_comma_expression_is_not_allowed_in_a_computed_property_name.code, + Diagnostics.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement.code, + Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code, + Diagnostics.A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement.code, + Diagnostics.A_default_clause_cannot_appear_more_than_once_in_a_switch_statement.code, + Diagnostics.A_default_export_must_be_at_the_top_level_of_a_file_or_module_declaration.code, + Diagnostics.A_definite_assignment_assertion_is_not_permitted_in_this_context.code, + Diagnostics.A_destructuring_declaration_must_have_an_initializer.code, + Diagnostics.A_get_accessor_cannot_have_parameters.code, + Diagnostics.A_rest_element_cannot_contain_a_binding_pattern.code, + Diagnostics.A_rest_element_cannot_have_a_property_name.code, + Diagnostics.A_rest_element_cannot_have_an_initializer.code, + Diagnostics.A_rest_element_must_be_last_in_a_destructuring_pattern.code, + Diagnostics.A_rest_parameter_cannot_have_an_initializer.code, + Diagnostics.A_rest_parameter_must_be_last_in_a_parameter_list.code, + Diagnostics.A_rest_parameter_or_binding_pattern_may_not_have_a_trailing_comma.code, + Diagnostics.A_return_statement_cannot_be_used_inside_a_class_static_block.code, + Diagnostics.A_set_accessor_cannot_have_rest_parameter.code, + Diagnostics.A_set_accessor_must_have_exactly_one_parameter.code, + Diagnostics.An_export_declaration_can_only_be_used_at_the_top_level_of_a_module.code, + Diagnostics.An_export_declaration_cannot_have_modifiers.code, + Diagnostics.An_import_declaration_can_only_be_used_at_the_top_level_of_a_module.code, + Diagnostics.An_import_declaration_cannot_have_modifiers.code, + Diagnostics.An_object_member_cannot_be_declared_optional.code, + Diagnostics.Argument_of_dynamic_import_cannot_be_spread_element.code, + Diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable.code, + Diagnostics.Cannot_redeclare_identifier_0_in_catch_clause.code, + Diagnostics.Catch_clause_variable_cannot_have_an_initializer.code, + Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator.code, + Diagnostics.Classes_can_only_extend_a_single_class.code, + Diagnostics.Classes_may_not_have_a_field_named_constructor.code, + Diagnostics.Did_you_mean_to_use_a_Colon_An_can_only_follow_a_property_name_when_the_containing_object_literal_is_part_of_a_destructuring_pattern.code, + Diagnostics.Duplicate_label_0.code, + Diagnostics.Dynamic_imports_can_only_accept_a_module_specifier_and_an_optional_assertion_as_arguments.code, + Diagnostics.For_await_loops_cannot_be_used_inside_a_class_static_block.code, + Diagnostics.JSX_attributes_must_only_be_assigned_a_non_empty_expression.code, + Diagnostics.JSX_elements_cannot_have_multiple_attributes_with_the_same_name.code, + Diagnostics.JSX_expressions_may_not_use_the_comma_operator_Did_you_mean_to_write_an_array.code, + Diagnostics.JSX_property_access_expressions_cannot_include_JSX_namespace_names.code, + Diagnostics.Jump_target_cannot_cross_function_boundary.code, + Diagnostics.Line_terminator_not_permitted_before_arrow.code, + Diagnostics.Modifiers_cannot_appear_here.code, + Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_in_statement.code, + Diagnostics.Only_a_single_variable_declaration_is_allowed_in_a_for_of_statement.code, + Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies.code, + Diagnostics.Private_identifiers_are_only_allowed_in_class_bodies_and_may_only_be_used_as_part_of_a_class_member_declaration_property_access_or_on_the_left_hand_side_of_an_in_expression.code, + Diagnostics.Property_0_is_not_accessible_outside_class_1_because_it_has_a_private_identifier.code, + Diagnostics.Tagged_template_expressions_are_not_permitted_in_an_optional_chain.code, + Diagnostics.The_left_hand_side_of_a_for_of_statement_may_not_be_async.code, + Diagnostics.The_variable_declaration_of_a_for_in_statement_cannot_have_an_initializer.code, + Diagnostics.The_variable_declaration_of_a_for_of_statement_cannot_have_an_initializer.code, + Diagnostics.Trailing_comma_not_allowed.code, + Diagnostics.Variable_declaration_list_cannot_be_empty.code, + Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses.code, + Diagnostics._0_expected.code, + Diagnostics._0_is_not_a_valid_meta_property_for_keyword_1_Did_you_mean_2.code, + Diagnostics._0_list_cannot_be_empty.code, + Diagnostics._0_modifier_already_seen.code, + Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration.code, + Diagnostics._0_modifier_cannot_appear_on_a_module_or_namespace_element.code, + Diagnostics._0_modifier_cannot_appear_on_a_parameter.code, + Diagnostics._0_modifier_cannot_appear_on_class_elements_of_this_kind.code, + Diagnostics._0_modifier_cannot_be_used_here.code, + Diagnostics._0_modifier_must_precede_1_modifier.code, + Diagnostics.const_declarations_can_only_be_declared_inside_a_block.code, + Diagnostics.const_declarations_must_be_initialized.code, + Diagnostics.extends_clause_already_seen.code, + Diagnostics.let_declarations_can_only_be_declared_inside_a_block.code, + Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations.code, + Diagnostics.Class_constructor_may_not_be_a_generator.code, + Diagnostics.Class_constructor_may_not_be_an_accessor.code, + Diagnostics.await_expressions_are_only_allowed_within_async_functions_and_at_the_top_levels_of_modules.code, ]); /** * Determine if source file needs to be re-created even if its text hasn't changed */ -function shouldProgramCreateNewSourceFiles(program: ts.Program | undefined, newOptions: ts.CompilerOptions): boolean { +function shouldProgramCreateNewSourceFiles(program: Program | undefined, newOptions: CompilerOptions): boolean { if (!program) return false; // If any compiler options change, we can't reuse old source file even if version match // The change in options like these could result in change in syntax tree or `sourceFile.bindDiagnostics`. - return ts.optionsHaveChanges(program.getCompilerOptions(), newOptions, ts.sourceFileAffectingCompilerOptions); + return optionsHaveChanges(program.getCompilerOptions(), newOptions, sourceFileAffectingCompilerOptions); } -function createCreateProgramOptions(rootNames: readonly string[], options: ts.CompilerOptions, host?: ts.CompilerHost, oldProgram?: ts.Program, configFileParsingDiagnostics?: readonly ts.Diagnostic[]): ts.CreateProgramOptions { +function createCreateProgramOptions(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): CreateProgramOptions { return { rootNames, options, @@ -1026,7 +1087,7 @@ function createCreateProgramOptions(rootNames: readonly string[], options: ts.Co * @param createProgramOptions - The options for creating a program. * @returns A 'Program' object. */ -export function createProgram(createProgramOptions: ts.CreateProgramOptions): ts.Program; +export function createProgram(createProgramOptions: CreateProgramOptions): Program; /** * Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions' * that represent a compilation unit. @@ -1041,26 +1102,26 @@ export function createProgram(createProgramOptions: ts.CreateProgramOptions): ts * @param configFileParsingDiagnostics - error during config file parsing * @returns A 'Program' object. */ -export function createProgram(rootNames: readonly string[], options: ts.CompilerOptions, host?: ts.CompilerHost, oldProgram?: ts.Program, configFileParsingDiagnostics?: readonly ts.Diagnostic[]): ts.Program; -export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateProgramOptions, _options?: ts.CompilerOptions, _host?: ts.CompilerHost, _oldProgram?: ts.Program, _configFileParsingDiagnostics?: readonly ts.Diagnostic[]): ts.Program { - const createProgramOptions = ts.isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 +export function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program; +export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program { + const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217 const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions; let { oldProgram } = createProgramOptions; - let processingDefaultLibFiles: ts.SourceFile[] | undefined; - let processingOtherFiles: ts.SourceFile[] | undefined; - let files: ts.SourceFile[]; - let symlinks: ts.SymlinkCache | undefined; + let processingDefaultLibFiles: SourceFile[] | undefined; + let processingOtherFiles: SourceFile[] | undefined; + let files: SourceFile[]; + let symlinks: SymlinkCache | undefined; let commonSourceDirectory: string; - let typeChecker: ts.TypeChecker; - let classifiableNames: ts.Set; - const ambientModuleNameToUnmodifiedFileName = new ts.Map(); - let fileReasons = ts.createMultiMap(); - const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache = {}; - const cachedDeclarationDiagnosticsForFile: DiagnosticCache = {}; + let typeChecker: TypeChecker; + let classifiableNames: Set<__String>; + const ambientModuleNameToUnmodifiedFileName = new Map(); + let fileReasons = createMultiMap(); + const cachedBindAndCheckDiagnosticsForFile: DiagnosticCache = {}; + const cachedDeclarationDiagnosticsForFile: DiagnosticCache = {}; - let resolvedTypeReferenceDirectives = ts.createModeAwareCache(); - let fileProcessingDiagnostics: ts.FilePreprocessingDiagnostics[] | undefined; + let resolvedTypeReferenceDirectives = createModeAwareCache(); + let fileProcessingDiagnostics: FilePreprocessingDiagnostics[] | undefined; // The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules. // This works as imported modules are discovered recursively in a depth first manner, specifically: @@ -1074,58 +1135,58 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // If a module has some of its imports skipped due to being at the depth limit under node_modules, then track // this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed. - const modulesWithElidedImports = new ts.Map(); + const modulesWithElidedImports = new Map(); // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. - const sourceFilesFoundSearchingNodeModules = new ts.Map(); + const sourceFilesFoundSearchingNodeModules = new Map(); - ts.tracing?.push(ts.tracing.Phase.Program, "createProgram", { configFilePath: options.configFilePath, rootDir: options.rootDir }, /*separateBeginAndEnd*/ true); + tracing?.push(tracing.Phase.Program, "createProgram", { configFilePath: options.configFilePath, rootDir: options.rootDir }, /*separateBeginAndEnd*/ true); ts.performance.mark("beforeProgram"); const host = createProgramOptions.host || createCompilerHost(options); const configParsingHost = parseConfigHostFromCompilerHostLike(host); let skipDefaultLib = options.noLib; - const getDefaultLibraryFileName = ts.memoize(() => host.getDefaultLibFileName(options)); - const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : ts.getDirectoryPath(getDefaultLibraryFileName()); - const programDiagnostics = ts.createDiagnosticCollection(); + const getDefaultLibraryFileName = memoize(() => host.getDefaultLibFileName(options)); + const defaultLibraryPath = host.getDefaultLibLocation ? host.getDefaultLibLocation() : getDirectoryPath(getDefaultLibraryFileName()); + const programDiagnostics = createDiagnosticCollection(); const currentDirectory = host.getCurrentDirectory(); - const supportedExtensions = ts.getSupportedExtensions(options); - const supportedExtensionsWithJsonIfResolveJsonModule = ts.getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); + const supportedExtensions = getSupportedExtensions(options); + const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions); // Map storing if there is emit blocking diagnostics for given input - const hasEmitBlockingDiagnostics = new ts.Map(); - let _compilerOptionsObjectLiteralSyntax: ts.ObjectLiteralExpression | false | undefined; + const hasEmitBlockingDiagnostics = new Map(); + let _compilerOptionsObjectLiteralSyntax: ObjectLiteralExpression | false | undefined; - let moduleResolutionCache: ts.ModuleResolutionCache | undefined; - let typeReferenceDirectiveResolutionCache: ts.TypeReferenceDirectiveResolutionCache | undefined; - let actualResolveModuleNamesWorker: (moduleNames: string[], containingFile: ts.SourceFile, containingFileName: string, reusedNames?: string[], redirectedReference?: ts.ResolvedProjectReference) => ts.ResolvedModuleFull[]; - const hasInvalidatedResolutions = host.hasInvalidatedResolutions || ts.returnFalse; + let moduleResolutionCache: ModuleResolutionCache | undefined; + let typeReferenceDirectiveResolutionCache: TypeReferenceDirectiveResolutionCache | undefined; + let actualResolveModuleNamesWorker: (moduleNames: string[], containingFile: SourceFile, containingFileName: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) => ResolvedModuleFull[]; + const hasInvalidatedResolutions = host.hasInvalidatedResolutions || returnFalse; if (host.resolveModuleNames) { - actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, reusedNames, redirectedReference) => host.resolveModuleNames!(ts.Debug.checkEachDefined(moduleNames), containingFileName, reusedNames, redirectedReference, options, containingFile).map(resolved => { + actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, reusedNames, redirectedReference) => host.resolveModuleNames!(Debug.checkEachDefined(moduleNames), containingFileName, reusedNames, redirectedReference, options, containingFile).map(resolved => { // An older host may have omitted extension, in which case we should infer it from the file extension of resolvedFileName. - if (!resolved || (resolved as ts.ResolvedModuleFull).extension !== undefined) { - return resolved as ts.ResolvedModuleFull; + if (!resolved || (resolved as ResolvedModuleFull).extension !== undefined) { + return resolved as ResolvedModuleFull; } - const withExtension = ts.clone(resolved) as ts.ResolvedModuleFull; - withExtension.extension = ts.extensionFromPath(resolved.resolvedFileName); + const withExtension = clone(resolved) as ResolvedModuleFull; + withExtension.extension = extensionFromPath(resolved.resolvedFileName); return withExtension; }); moduleResolutionCache = host.getModuleResolutionCache?.(); } else { - moduleResolutionCache = ts.createModuleResolutionCache(currentDirectory, getCanonicalFileName, options); - const loader = (moduleName: string, resolverMode: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined, containingFileName: string, redirectedReference: ts.ResolvedProjectReference | undefined) => ts.resolveModuleName(moduleName, containingFileName, options, host, moduleResolutionCache, redirectedReference, resolverMode).resolvedModule!; // TODO: GH#18217 - actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, _reusedNames, redirectedReference) => loadWithModeAwareCache(ts.Debug.checkEachDefined(moduleNames), containingFile, containingFileName, redirectedReference, loader); + moduleResolutionCache = createModuleResolutionCache(currentDirectory, getCanonicalFileName, options); + const loader = (moduleName: string, resolverMode: ModuleKind.CommonJS | ModuleKind.ESNext | undefined, containingFileName: string, redirectedReference: ResolvedProjectReference | undefined) => resolveModuleName(moduleName, containingFileName, options, host, moduleResolutionCache, redirectedReference, resolverMode).resolvedModule!; // TODO: GH#18217 + actualResolveModuleNamesWorker = (moduleNames, containingFile, containingFileName, _reusedNames, redirectedReference) => loadWithModeAwareCache(Debug.checkEachDefined(moduleNames), containingFile, containingFileName, redirectedReference, loader); } - let actualResolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[] | readonly ts.FileReference[], containingFile: string, redirectedReference?: ts.ResolvedProjectReference, containingFileMode?: ts.SourceFile["impliedNodeFormat"] | undefined) => (ts.ResolvedTypeReferenceDirective | undefined)[]; + let actualResolveTypeReferenceDirectiveNamesWorker: (typeDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference?: ResolvedProjectReference, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined) => (ResolvedTypeReferenceDirective | undefined)[]; if (host.resolveTypeReferenceDirectives) { - actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, containingFileMode) => host.resolveTypeReferenceDirectives!(ts.Debug.checkEachDefined(typeDirectiveNames), containingFile, redirectedReference, options, containingFileMode); + actualResolveTypeReferenceDirectiveNamesWorker = (typeDirectiveNames, containingFile, redirectedReference, containingFileMode) => host.resolveTypeReferenceDirectives!(Debug.checkEachDefined(typeDirectiveNames), containingFile, redirectedReference, options, containingFileMode); } else { - typeReferenceDirectiveResolutionCache = ts.createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()); - const loader = (typesRef: string, containingFile: string, redirectedReference: ts.ResolvedProjectReference | undefined, resolutionMode: ts.SourceFile["impliedNodeFormat"] | undefined) => ts.resolveTypeReferenceDirective( + typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache(currentDirectory, getCanonicalFileName, /*options*/ undefined, moduleResolutionCache?.getPackageJsonInfoCache()); + const loader = (typesRef: string, containingFile: string, redirectedReference: ResolvedProjectReference | undefined, resolutionMode: SourceFile["impliedNodeFormat"] | undefined) => resolveTypeReferenceDirective( typesRef, containingFile, options, @@ -1134,17 +1195,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP typeReferenceDirectiveResolutionCache, resolutionMode, ).resolvedTypeReferenceDirective!; // TODO: GH#18217 - actualResolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference, containingFileMode) => loadWithTypeDirectiveCache(ts.Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, containingFileMode, loader); + actualResolveTypeReferenceDirectiveNamesWorker = (typeReferenceDirectiveNames, containingFile, redirectedReference, containingFileMode) => loadWithTypeDirectiveCache(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, containingFileMode, loader); } // Map from a stringified PackageId to the source file with that id. // Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile). // `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around. - const packageIdToSourceFile = new ts.Map(); + const packageIdToSourceFile = new Map(); // Maps from a SourceFile's `.path` to the name of the package it was imported with. - let sourceFileToPackageName = new ts.Map(); + let sourceFileToPackageName = new Map(); // Key is a file name. Value is the (non-empty, or undefined) list of files that redirect to it. - let redirectTargetsMap = ts.createMultiMap(); + let redirectTargetsMap = createMultiMap(); let usesUriStyleNodeCoreModules = false; /** @@ -1153,17 +1214,17 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP * - false if sourceFile missing for source of project reference redirect * - undefined otherwise */ - const filesByName = new ts.Map(); - let missingFilePaths: readonly ts.Path[] | undefined; + const filesByName = new Map(); + let missingFilePaths: readonly Path[] | undefined; // stores 'filename -> file association' ignoring case // used to track cases when two file names differ only in casing - const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? new ts.Map() : undefined; + const filesByNameIgnoreCase = host.useCaseSensitiveFileNames() ? new Map() : undefined; // A parallel array to projectReferences storing the results of reading in the referenced tsconfig files - let resolvedProjectReferences: readonly (ts.ResolvedProjectReference | undefined)[] | undefined; - let projectReferenceRedirects: ts.ESMap | undefined; - let mapFromFileToProjectReferenceRedirects: ts.ESMap | undefined; - let mapFromToProjectReferenceRedirectSource: ts.ESMap | undefined; + let resolvedProjectReferences: readonly (ResolvedProjectReference | undefined)[] | undefined; + let projectReferenceRedirects: ESMap | undefined; + let mapFromFileToProjectReferenceRedirects: ESMap | undefined; + let mapFromToProjectReferenceRedirectSource: ESMap | undefined; const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect?.() && !options.disableSourceOfProjectReferenceRedirect; @@ -1178,16 +1239,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP }); const readFile = host.readFile.bind(host) as typeof host.readFile; - ts.tracing?.push(ts.tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram }); + tracing?.push(tracing.Phase.Program, "shouldProgramCreateNewSourceFiles", { hasOldProgram: !!oldProgram }); const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options); - ts.tracing?.pop(); + tracing?.pop(); // We set `structuralIsReused` to `undefined` because `tryReuseStructureFromOldProgram` calls `tryReuseStructureFromOldProgram` which checks // `structuralIsReused`, which would be a TDZ violation if it was not set in advance to `undefined`. - let structureIsReused: ts.StructureIsReused; - ts.tracing?.push(ts.tracing.Phase.Program, "tryReuseStructureFromOldProgram", {}); + let structureIsReused: StructureIsReused; + tracing?.push(tracing.Phase.Program, "tryReuseStructureFromOldProgram", {}); structureIsReused = tryReuseStructureFromOldProgram(); // eslint-disable-line prefer-const - ts.tracing?.pop(); - if (structureIsReused !== ts.StructureIsReused.Completely) { + tracing?.pop(); + if (structureIsReused !== StructureIsReused.Completely) { processingDefaultLibFiles = []; processingOtherFiles = []; @@ -1198,23 +1259,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (rootNames.length) { resolvedProjectReferences?.forEach((parsedRef, index) => { if (!parsedRef) return; - const out = ts.outFile(parsedRef.commandLine.options); + const out = outFile(parsedRef.commandLine.options); if (useSourceOfProjectReferenceRedirect) { - if (out || ts.getEmitModuleKind(parsedRef.commandLine.options) === ts.ModuleKind.None) { + if (out || getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) { for (const fileName of parsedRef.commandLine.fileNames) { - processProjectReferenceFile(fileName, { kind: ts.FileIncludeKind.SourceFromProjectReference, index }); + processProjectReferenceFile(fileName, { kind: FileIncludeKind.SourceFromProjectReference, index }); } } } else { if (out) { - processProjectReferenceFile(ts.changeExtension(out, ".d.ts"), { kind: ts.FileIncludeKind.OutputFromProjectReference, index }); + processProjectReferenceFile(changeExtension(out, ".d.ts"), { kind: FileIncludeKind.OutputFromProjectReference, index }); } - else if (ts.getEmitModuleKind(parsedRef.commandLine.options) === ts.ModuleKind.None) { - const getCommonSourceDirectory = ts.memoize(() => ts.getCommonSourceDirectoryOfConfig(parsedRef.commandLine, !host.useCaseSensitiveFileNames())); + else if (getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) { + const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(parsedRef.commandLine, !host.useCaseSensitiveFileNames())); for (const fileName of parsedRef.commandLine.fileNames) { - if (!ts.isDeclarationFileName(fileName) && !ts.fileExtensionIs(fileName, ts.Extension.Json)) { - processProjectReferenceFile(ts.getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory), { kind: ts.FileIncludeKind.OutputFromProjectReference, index }); + if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, Extension.Json)) { + processProjectReferenceFile(getOutputDeclarationFileName(fileName, parsedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory), { kind: FileIncludeKind.OutputFromProjectReference, index }); } } } @@ -1223,24 +1284,24 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - ts.tracing?.push(ts.tracing.Phase.Program, "processRootFiles", { count: rootNames.length }); - ts.forEach(rootNames, (name, index) => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, { kind: ts.FileIncludeKind.RootFile, index })); - ts.tracing?.pop(); + tracing?.push(tracing.Phase.Program, "processRootFiles", { count: rootNames.length }); + forEach(rootNames, (name, index) => processRootFile(name, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.RootFile, index })); + tracing?.pop(); // load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders - const typeReferences: string[] = rootNames.length ? ts.getAutomaticTypeDirectiveNames(options, host) : ts.emptyArray; + const typeReferences: string[] = rootNames.length ? getAutomaticTypeDirectiveNames(options, host) : emptyArray; if (typeReferences.length) { - ts.tracing?.push(ts.tracing.Phase.Program, "processTypeReferences", { count: typeReferences.length }); + tracing?.push(tracing.Phase.Program, "processTypeReferences", { count: typeReferences.length }); // This containingFilename needs to match with the one used in managed-side - const containingDirectory = options.configFilePath ? ts.getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(); - const containingFilename = ts.combinePaths(containingDirectory, inferredTypesContainingFile); + const containingDirectory = options.configFilePath ? getDirectoryPath(options.configFilePath) : host.getCurrentDirectory(); + const containingFilename = combinePaths(containingDirectory, inferredTypesContainingFile); const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename); for (let i = 0; i < typeReferences.length; i++) { // under node16/nodenext module resolution, load `types`/ata include names as cjs resolution results by passing an `undefined` mode - processTypeReferenceDirective(typeReferences[i], /*mode*/ undefined, resolutions[i], { kind: ts.FileIncludeKind.AutomaticTypeDirectiveFile, typeReference: typeReferences[i], packageId: resolutions[i]?.packageId }); + processTypeReferenceDirective(typeReferences[i], /*mode*/ undefined, resolutions[i], { kind: FileIncludeKind.AutomaticTypeDirectiveFile, typeReference: typeReferences[i], packageId: resolutions[i]?.packageId }); } - ts.tracing?.pop(); + tracing?.pop(); } // Do not process the default library if: @@ -1252,22 +1313,22 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // otherwise, using options specified in '--lib' instead of '--target' default library file const defaultLibraryFileName = getDefaultLibraryFileName(); if (!options.lib && defaultLibraryFileName) { - processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: ts.FileIncludeKind.LibFile }); + processRootFile(defaultLibraryFileName, /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile }); } else { - ts.forEach(options.lib, (libFileName, index) => { - processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: ts.FileIncludeKind.LibFile, index }); + forEach(options.lib, (libFileName, index) => { + processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ false, { kind: FileIncludeKind.LibFile, index }); }); } } - missingFilePaths = ts.arrayFrom(ts.mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as ts.Path : undefined)); - files = ts.stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); + missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); + files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); processingDefaultLibFiles = undefined; processingOtherFiles = undefined; } - ts.Debug.assert(!!missingFilePaths); + Debug.assert(!!missingFilePaths); // Release any files we have acquired in the old program but are // not part of the new program. @@ -1310,7 +1371,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // unconditionally set oldProgram to undefined to prevent it from being captured in closure oldProgram = undefined; - const program: ts.Program = { + const program: Program = { getRootFileNames: () => rootNames, getSourceFile, getSourceFileByPath, @@ -1375,35 +1436,35 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // Add file processingDiagnostics fileProcessingDiagnostics?.forEach(diagnostic => { switch (diagnostic.kind) { - case ts.FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic: - return programDiagnostics.add(createDiagnosticExplainingFile(diagnostic.file && getSourceFileByPath(diagnostic.file), diagnostic.fileProcessingReason, diagnostic.diagnostic, diagnostic.args || ts.emptyArray)); - case ts.FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic: + case FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic: + return programDiagnostics.add(createDiagnosticExplainingFile(diagnostic.file && getSourceFileByPath(diagnostic.file), diagnostic.fileProcessingReason, diagnostic.diagnostic, diagnostic.args || emptyArray)); + case FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic: const { file, pos, end } = getReferencedFileLocation(getSourceFileByPath, diagnostic.reason) as ReferenceFileLocation; - return programDiagnostics.add(ts.createFileDiagnostic(file, ts.Debug.checkDefined(pos), ts.Debug.checkDefined(end) - pos, diagnostic.diagnostic, ...diagnostic.args || ts.emptyArray)); + return programDiagnostics.add(createFileDiagnostic(file, Debug.checkDefined(pos), Debug.checkDefined(end) - pos, diagnostic.diagnostic, ...diagnostic.args || emptyArray)); default: - ts.Debug.assertNever(diagnostic); + Debug.assertNever(diagnostic); } }); verifyCompilerOptions(); ts.performance.mark("afterProgram"); ts.performance.measure("Program", "beforeProgram", "afterProgram"); - ts.tracing?.pop(); + tracing?.pop(); return program; - function addResolutionDiagnostics(list: ts.Diagnostic[] | undefined) { + function addResolutionDiagnostics(list: Diagnostic[] | undefined) { if (!list) return; for (const elem of list) { programDiagnostics.add(elem); } } - function pullDiagnosticsFromCache(names: string[] | readonly ts.FileReference[], containingFile: ts.SourceFile) { + function pullDiagnosticsFromCache(names: string[] | readonly FileReference[], containingFile: SourceFile) { if (!moduleResolutionCache) return; - const containingFileName = ts.getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); - const containingFileMode = !ts.isString(containingFile) ? containingFile.impliedNodeFormat : undefined; - const containingDir = ts.getDirectoryPath(containingFileName); + const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); + const containingFileMode = !isString(containingFile) ? containingFile.impliedNodeFormat : undefined; + const containingDir = getDirectoryPath(containingFileName); const redirectedReference = getRedirectReferenceForResolution(containingFile); let i = 0; for (const n of names) { @@ -1416,43 +1477,43 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // This may totally change if/when the issue of output paths not mapping to input files is fixed in a broader context // When it is, how we extract diagnostics from the module name resolver will have the be refined - the current cache // APIs wrapping the underlying resolver make it almost impossible to smuggle the diagnostics out in a generalized way - if (ts.isExternalModuleNameRelative(name)) continue; + if (isExternalModuleNameRelative(name)) continue; const diags = moduleResolutionCache.getOrCreateCacheForModuleName(name, mode, redirectedReference).get(containingDir)?.resolutionDiagnostics; addResolutionDiagnostics(diags); } } - function resolveModuleNamesWorker(moduleNames: string[], containingFile: ts.SourceFile, reusedNames: string[] | undefined): readonly ts.ResolvedModuleFull[] { - if (!moduleNames.length) return ts.emptyArray; - const containingFileName = ts.getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); + function resolveModuleNamesWorker(moduleNames: string[], containingFile: SourceFile, reusedNames: string[] | undefined): readonly ResolvedModuleFull[] { + if (!moduleNames.length) return emptyArray; + const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory); const redirectedReference = getRedirectReferenceForResolution(containingFile); - ts.tracing?.push(ts.tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); + tracing?.push(tracing.Phase.Program, "resolveModuleNamesWorker", { containingFileName }); ts.performance.mark("beforeResolveModule"); const result = actualResolveModuleNamesWorker(moduleNames, containingFile, containingFileName, reusedNames, redirectedReference); ts.performance.mark("afterResolveModule"); ts.performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule"); - ts.tracing?.pop(); + tracing?.pop(); pullDiagnosticsFromCache(moduleNames, containingFile); return result; } - function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: string[] | readonly ts.FileReference[], containingFile: string | ts.SourceFile): readonly (ts.ResolvedTypeReferenceDirective | undefined)[] { + function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string | SourceFile): readonly (ResolvedTypeReferenceDirective | undefined)[] { if (!typeDirectiveNames.length) return []; - const containingFileName = !ts.isString(containingFile) ? ts.getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; - const redirectedReference = !ts.isString(containingFile) ? getRedirectReferenceForResolution(containingFile) : undefined; - const containingFileMode = !ts.isString(containingFile) ? containingFile.impliedNodeFormat : undefined; - ts.tracing?.push(ts.tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName }); + const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile; + const redirectedReference = !isString(containingFile) ? getRedirectReferenceForResolution(containingFile) : undefined; + const containingFileMode = !isString(containingFile) ? containingFile.impliedNodeFormat : undefined; + tracing?.push(tracing.Phase.Program, "resolveTypeReferenceDirectiveNamesWorker", { containingFileName }); ts.performance.mark("beforeResolveTypeReference"); const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference, containingFileMode); ts.performance.mark("afterResolveTypeReference"); ts.performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference"); - ts.tracing?.pop(); + tracing?.pop(); return result; } - function getRedirectReferenceForResolution(file: ts.SourceFile) { + function getRedirectReferenceForResolution(file: SourceFile) { const redirect = getResolvedProjectReferenceToRedirect(file.originalFileName); - if (redirect || !ts.isDeclarationFileName(file.originalFileName)) return redirect; + if (redirect || !isDeclarationFileName(file.originalFileName)) return redirect; // The originalFileName could not be actual source file name if file found was d.ts from referecned project // So in this case try to look up if this is output from referenced project, if it is use the redirected project in that case @@ -1463,52 +1524,52 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // but the resolved real path may be the .d.ts from project reference // Note:: Currently we try the real path only if the // file is from node_modules to avoid having to run real path on all file paths - if (!host.realpath || !options.preserveSymlinks || !ts.stringContains(file.originalFileName, ts.nodeModulesPathPart)) return undefined; + if (!host.realpath || !options.preserveSymlinks || !stringContains(file.originalFileName, nodeModulesPathPart)) return undefined; const realDeclarationPath = toPath(host.realpath(file.originalFileName)); return realDeclarationPath === file.path ? undefined : getRedirectReferenceForResolutionFromSourceOfProject(realDeclarationPath); } - function getRedirectReferenceForResolutionFromSourceOfProject(filePath: ts.Path) { + function getRedirectReferenceForResolutionFromSourceOfProject(filePath: Path) { const source = getSourceOfProjectReferenceRedirect(filePath); - if (ts.isString(source)) return getResolvedProjectReferenceToRedirect(source); + if (isString(source)) return getResolvedProjectReferenceToRedirect(source); if (!source) return undefined; // Output of .d.ts file so return resolved ref that matches the out file name return forEachResolvedProjectReference(resolvedRef => { - const out = ts.outFile(resolvedRef.commandLine.options); + const out = outFile(resolvedRef.commandLine.options); if (!out) return undefined; return toPath(out) === filePath ? resolvedRef : undefined; }); } - function compareDefaultLibFiles(a: ts.SourceFile, b: ts.SourceFile) { - return ts.compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b)); + function compareDefaultLibFiles(a: SourceFile, b: SourceFile) { + return compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b)); } - function getDefaultLibFilePriority(a: ts.SourceFile) { - if (ts.containsPath(defaultLibraryPath, a.fileName, /*ignoreCase*/ false)) { - const basename = ts.getBaseFileName(a.fileName); + function getDefaultLibFilePriority(a: SourceFile) { + if (containsPath(defaultLibraryPath, a.fileName, /*ignoreCase*/ false)) { + const basename = getBaseFileName(a.fileName); if (basename === "lib.d.ts" || basename === "lib.es6.d.ts") return 0; - const name = ts.removeSuffix(ts.removePrefix(basename, "lib."), ".d.ts"); - const index = ts.libs.indexOf(name); + const name = removeSuffix(removePrefix(basename, "lib."), ".d.ts"); + const index = libs.indexOf(name); if (index !== -1) return index + 1; } - return ts.libs.length + 2; + return libs.length + 2; } - function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, mode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations | undefined { - return moduleResolutionCache && ts.resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache, mode); + function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, mode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations | undefined { + return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache, mode); } - function toPath(fileName: string): ts.Path { + function toPath(fileName: string): Path { return ts.toPath(fileName, currentDirectory, getCanonicalFileName); } function getCommonSourceDirectory() { if (commonSourceDirectory === undefined) { - const emittedFiles = ts.filter(files, file => ts.sourceFileMayBeEmitted(file, program)); + const emittedFiles = filter(files, file => sourceFileMayBeEmitted(file, program)); commonSourceDirectory = ts.getCommonSourceDirectory( options, - () => ts.mapDefined(emittedFiles, file => file.isDeclarationFile ? undefined : file.fileName), + () => mapDefined(emittedFiles, file => file.isDeclarationFile ? undefined : file.fileName), currentDirectory, getCanonicalFileName, commonSourceDirectory => checkSourceFilesBelongToPath(emittedFiles, commonSourceDirectory) @@ -1521,7 +1582,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (!classifiableNames) { // Initialize a checker so that all our files are bound. getTypeChecker(); - classifiableNames = new ts.Set(); + classifiableNames = new Set(); for (const sourceFile of files) { sourceFile.classifiableNames?.forEach(value => classifiableNames.add(value)); @@ -1531,8 +1592,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return classifiableNames; } - function resolveModuleNamesReusingOldState(moduleNames: string[], file: ts.SourceFile): readonly (ts.ResolvedModuleFull | undefined)[] { - if (structureIsReused === ts.StructureIsReused.Not && !file.ambientModuleNames.length) { + function resolveModuleNamesReusingOldState(moduleNames: string[], file: SourceFile): readonly (ResolvedModuleFull | undefined)[] { + if (structureIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) { // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules, // the best we can do is fallback to the default logic. return resolveModuleNamesWorker(moduleNames, file, /*reusedNames*/ undefined); @@ -1548,7 +1609,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // which per above occurred during the current program creation. // Since we assume the filesystem does not change during program creation, // it is safe to reuse resolutions from the earlier call. - const result: (ts.ResolvedModuleFull | undefined)[] = []; + const result: (ResolvedModuleFull | undefined)[] = []; let i = 0; for (const moduleName of moduleNames) { const resolvedModule = file.resolvedModules.get(moduleName, getModeForResolutionAtIndex(file, i)); @@ -1573,26 +1634,26 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP * Needs to be reset to undefined before returning, * * ResolvedModuleFull instance: can be reused. */ - let result: (ts.ResolvedModuleFull | undefined)[] | undefined; + let result: (ResolvedModuleFull | undefined)[] | undefined; let reusedNames: string[] | undefined; /** A transient placeholder used to mark predicted resolution in the result list. */ - const predictedToResolveToAmbientModuleMarker: ts.ResolvedModuleFull = {} as any; + const predictedToResolveToAmbientModuleMarker: ResolvedModuleFull = {} as any; for (let i = 0; i < moduleNames.length; i++) { const moduleName = moduleNames[i]; // If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions if (file === oldSourceFile && !hasInvalidatedResolutions(oldSourceFile.path)) { - const oldResolvedModule = ts.getResolvedModule(oldSourceFile, moduleName, getModeForResolutionAtIndex(oldSourceFile, i)); + const oldResolvedModule = getResolvedModule(oldSourceFile, moduleName, getModeForResolutionAtIndex(oldSourceFile, i)); if (oldResolvedModule) { - if (ts.isTraceEnabled(options, host)) { - ts.trace(host, + if (isTraceEnabled(options, host)) { + trace(host, oldResolvedModule.packageId ? - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2, moduleName, - ts.getNormalizedAbsolutePath(file.originalFileName, currentDirectory), + getNormalizedAbsolutePath(file.originalFileName, currentDirectory), oldResolvedModule.resolvedFileName, - oldResolvedModule.packageId && ts.packageIdToString(oldResolvedModule.packageId) + oldResolvedModule.packageId && packageIdToString(oldResolvedModule.packageId) ); } (result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule; @@ -1605,10 +1666,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // - resolved to an ambient module in the old program whose declaration is in an unmodified file // (so the same module declaration will land in the new program) let resolvesToAmbientModuleInNonModifiedFile = false; - if (ts.contains(file.ambientModuleNames, moduleName)) { + if (contains(file.ambientModuleNames, moduleName)) { resolvesToAmbientModuleInNonModifiedFile = true; - if (ts.isTraceEnabled(options, host)) { - ts.trace(host, ts.Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, ts.getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, getNormalizedAbsolutePath(file.originalFileName, currentDirectory)); } } else { @@ -1626,12 +1687,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const resolutions = unknownModuleNames && unknownModuleNames.length ? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames) - : ts.emptyArray; + : emptyArray; // Combine results of resolutions and predicted results if (!result) { // There were no unresolved/ambient resolutions. - ts.Debug.assert(resolutions.length === moduleNames.length); + Debug.assert(resolutions.length === moduleNames.length); return resolutions; } @@ -1649,15 +1710,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP j++; } } - ts.Debug.assert(j === resolutions.length); + Debug.assert(j === resolutions.length); return result; // If we change our policy of rechecking failed lookups on each program create, // we should adjust the value returned here. function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, index: number): boolean { - if (index >= ts.length(oldSourceFile?.imports) + ts.length(oldSourceFile?.moduleAugmentations)) return false; // mode index out of bounds, don't reuse resolution - const resolutionToFile = ts.getResolvedModule(oldSourceFile, moduleName, oldSourceFile && getModeForResolutionAtIndex(oldSourceFile, index)); + if (index >= length(oldSourceFile?.imports) + length(oldSourceFile?.moduleAugmentations)) return false; // mode index out of bounds, don't reuse resolution + const resolutionToFile = getResolvedModule(oldSourceFile, moduleName, oldSourceFile && getModeForResolutionAtIndex(oldSourceFile, index)); const resolvedFile = resolutionToFile && oldProgram!.getSourceFile(resolutionToFile.resolvedFileName); if (resolutionToFile && resolvedFile) { // In the old program, we resolved to an ambient module that was in the same @@ -1674,8 +1735,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return false; } - if (ts.isTraceEnabled(options, host)) { - ts.trace(host, ts.Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, unmodifiedFile); + if (isTraceEnabled(options, host)) { + trace(host, Diagnostics.Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified, moduleName, unmodifiedFile); } return true; } @@ -1692,7 +1753,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // Resolved project reference has gone missing or changed return !newResolvedRef || newResolvedRef.sourceFile !== oldResolvedRef.sourceFile || - !ts.arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newResolvedRef.commandLine.fileNames); + !arrayIsEqualTo(oldResolvedRef.commandLine.fileNames, newResolvedRef.commandLine.fileNames); } else { // A previously-unresolved reference may be resolved now @@ -1702,52 +1763,52 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP (oldProjectReferences, parent) => { // If array of references is changed, we cant resue old program const newReferences = parent ? getResolvedProjectReferenceByPath(parent.sourceFile.path)!.commandLine.projectReferences : projectReferences; - return !ts.arrayIsEqualTo(oldProjectReferences, newReferences, ts.projectReferenceIsEqualTo); + return !arrayIsEqualTo(oldProjectReferences, newReferences, projectReferenceIsEqualTo); } ); } - function tryReuseStructureFromOldProgram(): ts.StructureIsReused { + function tryReuseStructureFromOldProgram(): StructureIsReused { if (!oldProgram) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } // check properties that can affect structure of the program or module resolution strategy // if any of these properties has changed - structure cannot be reused const oldOptions = oldProgram.getCompilerOptions(); - if (ts.changesAffectModuleResolution(oldOptions, options)) { - return ts.StructureIsReused.Not; + if (changesAffectModuleResolution(oldOptions, options)) { + return StructureIsReused.Not; } // there is an old program, check if we can reuse its structure const oldRootNames = oldProgram.getRootFileNames(); - if (!ts.arrayIsEqualTo(oldRootNames, rootNames)) { - return ts.StructureIsReused.Not; + if (!arrayIsEqualTo(oldRootNames, rootNames)) { + return StructureIsReused.Not; } // Check if any referenced project tsconfig files are different if (!canReuseProjectReferences()) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } if (projectReferences) { resolvedProjectReferences = projectReferences.map(parseProjectReferenceConfigFile); } // check if program source files has changed in the way that can affect structure of the program - const newSourceFiles: ts.SourceFile[] = []; - const modifiedSourceFiles: { oldFile: ts.SourceFile, newFile: ts.SourceFile }[] = []; - structureIsReused = ts.StructureIsReused.Completely; + const newSourceFiles: SourceFile[] = []; + const modifiedSourceFiles: { oldFile: SourceFile, newFile: SourceFile }[] = []; + structureIsReused = StructureIsReused.Completely; // If the missing file paths are now present, it can change the progam structure, // and hence cant reuse the structure. // This is same as how we dont reuse the structure if one of the file from old program is now missing if (oldProgram.getMissingFilePaths().some(missingFilePath => host.fileExists(missingFilePath))) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } const oldSourceFiles = oldProgram.getSourceFiles(); const enum SeenPackageName { Exists, Modified } - const seenPackageNames = new ts.Map(); + const seenPackageNames = new Map(); for (const oldSourceFile of oldSourceFiles) { const sourceFileOptions = getCreateSourceFileOptions(oldSourceFile.fileName, moduleResolutionCache, host, options); @@ -1756,12 +1817,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP : host.getSourceFile(oldSourceFile.fileName, sourceFileOptions, /*onError*/ undefined, shouldCreateNewSourceFile || sourceFileOptions.impliedNodeFormat !== oldSourceFile.impliedNodeFormat); // TODO: GH#18217 if (!newSourceFile) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } newSourceFile.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; newSourceFile.packageJsonScope = sourceFileOptions.packageJsonScope; - ts.Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`"); + Debug.assert(!newSourceFile.redirectInfo, "Host should not return a redirect source file from `getSourceFile`"); let fileChanged: boolean; if (oldSourceFile.redirectInfo) { @@ -1769,7 +1830,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // This lets us know if the unredirected file has changed. If it has we should break the redirect. if (newSourceFile !== oldSourceFile.redirectInfo.unredirected) { // Underlying file has changed. Might not redirect anymore. Must rebuild program. - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } fileChanged = false; newSourceFile = oldSourceFile; // Use the redirect. @@ -1777,7 +1838,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP else if (oldProgram.redirectTargetsMap.has(oldSourceFile.path)) { // If a redirected-to source file changes, the redirect may be broken. if (newSourceFile !== oldSourceFile) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } fileChanged = false; } @@ -1798,48 +1859,48 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const prevKind = seenPackageNames.get(packageName); const newKind = fileChanged ? SeenPackageName.Modified : SeenPackageName.Exists; if ((prevKind !== undefined && newKind === SeenPackageName.Modified) || prevKind === SeenPackageName.Modified) { - return ts.StructureIsReused.Not; + return StructureIsReused.Not; } seenPackageNames.set(packageName, newKind); } if (fileChanged) { if (oldSourceFile.impliedNodeFormat !== newSourceFile.impliedNodeFormat) { - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } // The `newSourceFile` object was created for the new program. - else if (!ts.arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { + else if (!arrayIsEqualTo(oldSourceFile.libReferenceDirectives, newSourceFile.libReferenceDirectives, fileReferenceIsEqualTo)) { // 'lib' references has changed. Matches behavior in changesAffectModuleResolution - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } else if (oldSourceFile.hasNoDefaultLib !== newSourceFile.hasNoDefaultLib) { // value of no-default-lib has changed // this will affect if default library is injected into the list of files - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } // check tripleslash references - else if (!ts.arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { + else if (!arrayIsEqualTo(oldSourceFile.referencedFiles, newSourceFile.referencedFiles, fileReferenceIsEqualTo)) { // tripleslash references has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } else { // check imports and module augmentations collectExternalModuleReferences(newSourceFile); - if (!ts.arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { + if (!arrayIsEqualTo(oldSourceFile.imports, newSourceFile.imports, moduleNameIsEqualTo)) { // imports has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } - else if (!ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { + else if (!arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations, moduleNameIsEqualTo)) { // moduleAugmentations has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } - else if ((oldSourceFile.flags & ts.NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & ts.NodeFlags.PermanentlySetIncrementalFlags)) { + else if ((oldSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags) !== (newSourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags)) { // dynamicImport has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } - else if (!ts.arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { + else if (!arrayIsEqualTo(oldSourceFile.typeReferenceDirectives, newSourceFile.typeReferenceDirectives, fileReferenceIsEqualTo)) { // 'types' references has changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; } } @@ -1848,7 +1909,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } else if (hasInvalidatedResolutions(oldSourceFile.path)) { // 'module/types' references could have changed - structureIsReused = ts.StructureIsReused.SafeModules; + structureIsReused = StructureIsReused.SafeModules; // add file to the modified list so that we will resolve it later modifiedSourceFiles.push({ oldFile: oldSourceFile, newFile: newSourceFile }); @@ -1858,13 +1919,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP newSourceFiles.push(newSourceFile); } - if (structureIsReused !== ts.StructureIsReused.Completely) { + if (structureIsReused !== StructureIsReused.Completely) { return structureIsReused; } const modifiedFiles = modifiedSourceFiles.map(f => f.oldFile); for (const oldFile of oldSourceFiles) { - if (!ts.contains(modifiedFiles, oldFile)) { + if (!contains(modifiedFiles, oldFile)) { for (const moduleName of oldFile.ambientModuleNames) { ambientModuleNameToUnmodifiedFileName.set(moduleName, oldFile.fileName); } @@ -1875,10 +1936,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const moduleNames = getModuleNames(newSourceFile); const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFile); // ensure that module resolution results are still correct - const resolutionsChanged = ts.hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, oldSourceFile, ts.moduleResolutionIsEqualTo); + const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, oldSourceFile, moduleResolutionIsEqualTo); if (resolutionsChanged) { - structureIsReused = ts.StructureIsReused.SafeModules; - newSourceFile.resolvedModules = ts.zipToModeAwareCache(newSourceFile, moduleNames, resolutions); + structureIsReused = StructureIsReused.SafeModules; + newSourceFile.resolvedModules = zipToModeAwareCache(newSourceFile, moduleNames, resolutions); } else { newSourceFile.resolvedModules = oldSourceFile.resolvedModules; @@ -1886,28 +1947,28 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const typesReferenceDirectives = newSourceFile.typeReferenceDirectives; const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFile); // ensure that types resolutions are still correct - const typeReferenceResolutionsChanged = ts.hasChangesInResolutions(typesReferenceDirectives, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, oldSourceFile, ts.typeDirectiveIsEqualTo); + const typeReferenceResolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, oldSourceFile, typeDirectiveIsEqualTo); if (typeReferenceResolutionsChanged) { - structureIsReused = ts.StructureIsReused.SafeModules; - newSourceFile.resolvedTypeReferenceDirectiveNames = ts.zipToModeAwareCache(newSourceFile, typesReferenceDirectives, typeReferenceResolutions); + structureIsReused = StructureIsReused.SafeModules; + newSourceFile.resolvedTypeReferenceDirectiveNames = zipToModeAwareCache(newSourceFile, typesReferenceDirectives, typeReferenceResolutions); } else { newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames; } } - if (structureIsReused !== ts.StructureIsReused.Completely) { + if (structureIsReused !== StructureIsReused.Completely) { return structureIsReused; } - if (ts.changesAffectingProgramStructure(oldOptions, options) || host.hasChangedAutomaticTypeDirectiveNames?.()) { - return ts.StructureIsReused.SafeModules; + if (changesAffectingProgramStructure(oldOptions, options) || host.hasChangedAutomaticTypeDirectiveNames?.()) { + return StructureIsReused.SafeModules; } missingFilePaths = oldProgram.getMissingFilePaths(); // update fileName -> file mapping - ts.Debug.assert(newSourceFiles.length === oldProgram.getSourceFiles().length); + Debug.assert(newSourceFiles.length === oldProgram.getSourceFiles().length); for (const newSourceFile of newSourceFiles) { filesByName.set(newSourceFile.path, newSourceFile); } @@ -1936,10 +1997,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP redirectTargetsMap = oldProgram.redirectTargetsMap; usesUriStyleNodeCoreModules = oldProgram.usesUriStyleNodeCoreModules; - return ts.StructureIsReused.Completely; + return StructureIsReused.Completely; } - function getEmitHost(writeFileCallback?: ts.WriteFileCallback): ts.EmitHost { + function getEmitHost(writeFileCallback?: WriteFileCallback): EmitHost { return { getPrependNodes, getCanonicalFileName, @@ -1963,7 +2024,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // Use local caches const path = toPath(f); if (getSourceFileByPath(path)) return true; - if (ts.contains(missingFilePaths, path)) return false; + if (contains(missingFilePaths, path)) return false; // Before falling back to the host return host.fileExists(f); }, @@ -1972,7 +2033,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref), redirectTargetsMap, getFileIncludeReasons: program.getFileIncludeReasons, - createHash: ts.maybeBind(host, host.createHash), + createHash: maybeBind(host, host.createHash), }; } @@ -1981,28 +2042,28 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP text: string, writeByteOrderMark: boolean, onError?: (message: string) => void, - sourceFiles?: readonly ts.SourceFile[], - data?: ts.WriteFileCallbackData + sourceFiles?: readonly SourceFile[], + data?: WriteFileCallbackData ) { host.writeFile(fileName, text, writeByteOrderMark, onError, sourceFiles, data); } - function emitBuildInfo(writeFileCallback?: ts.WriteFileCallback): ts.EmitResult { - ts.Debug.assert(!ts.outFile(options)); - ts.tracing?.push(ts.tracing.Phase.Emit, "emitBuildInfo", {}, /*separateBeginAndEnd*/ true); + function emitBuildInfo(writeFileCallback?: WriteFileCallback): EmitResult { + Debug.assert(!outFile(options)); + tracing?.push(tracing.Phase.Emit, "emitBuildInfo", {}, /*separateBeginAndEnd*/ true); ts.performance.mark("beforeEmit"); - const emitResult = ts.emitFiles( - ts.notImplementedResolver, + const emitResult = emitFiles( + notImplementedResolver, getEmitHost(writeFileCallback), /*targetSourceFile*/ undefined, - /*transformers*/ ts.noTransformers, + /*transformers*/ noTransformers, /*emitOnlyDtsFiles*/ false, /*onlyBuildInfo*/ true ); ts.performance.mark("afterEmit"); ts.performance.measure("Emit", "beforeEmit", "afterEmit"); - ts.tracing?.pop(); + tracing?.pop(); return emitResult; } @@ -2027,11 +2088,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP ); } - function isSourceFileFromExternalLibrary(file: ts.SourceFile): boolean { + function isSourceFileFromExternalLibrary(file: SourceFile): boolean { return !!sourceFilesFoundSearchingNodeModules.get(file.path); } - function isSourceFileDefaultLibrary(file: ts.SourceFile): boolean { + function isSourceFileDefaultLibrary(file: SourceFile): boolean { if (!file.isDeclarationFile) { return false; } @@ -2046,23 +2107,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // If '--lib' is not specified, include default library file according to '--target' // otherwise, using options specified in '--lib' instead of '--target' default library file - const equalityComparer = host.useCaseSensitiveFileNames() ? ts.equateStringsCaseSensitive : ts.equateStringsCaseInsensitive; + const equalityComparer = host.useCaseSensitiveFileNames() ? equateStringsCaseSensitive : equateStringsCaseInsensitive; if (!options.lib) { return equalityComparer(file.fileName, getDefaultLibraryFileName()); } else { - return ts.some(options.lib, libFileName => equalityComparer(file.fileName, pathForLibFile(libFileName))); + return some(options.lib, libFileName => equalityComparer(file.fileName, pathForLibFile(libFileName))); } } function getTypeChecker() { - return typeChecker || (typeChecker = ts.createTypeChecker(program)); + return typeChecker || (typeChecker = createTypeChecker(program)); } - function emit(sourceFile?: ts.SourceFile, writeFileCallback?: ts.WriteFileCallback, cancellationToken?: ts.CancellationToken, emitOnly?: boolean | ts.EmitOnly, transformers?: ts.CustomTransformers, forceDtsEmit?: boolean): ts.EmitResult { - ts.tracing?.push(ts.tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true); + function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnly?: boolean | EmitOnly, transformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { + tracing?.push(tracing.Phase.Emit, "emit", { path: sourceFile?.path }, /*separateBeginAndEnd*/ true); const result = runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnly, transformers, forceDtsEmit)); - ts.tracing?.pop(); + tracing?.pop(); return result; } @@ -2070,7 +2131,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return hasEmitBlockingDiagnostics.has(toPath(emitFileName)); } - function emitWorker(program: ts.Program, sourceFile: ts.SourceFile | undefined, writeFileCallback: ts.WriteFileCallback | undefined, cancellationToken: ts.CancellationToken | undefined, emitOnly?: boolean | ts.EmitOnly, customTransformers?: ts.CustomTransformers, forceDtsEmit?: boolean): ts.EmitResult { + function emitWorker(program: Program, sourceFile: SourceFile | undefined, writeFileCallback: WriteFileCallback | undefined, cancellationToken: CancellationToken | undefined, emitOnly?: boolean | EmitOnly, customTransformers?: CustomTransformers, forceDtsEmit?: boolean): EmitResult { if (!forceDtsEmit) { const result = handleNoEmitOptions(program, sourceFile, writeFileCallback, cancellationToken); if (result) return result; @@ -2084,15 +2145,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // This is because in the -out scenario all files need to be emitted, and therefore all // files need to be type checked. And the way to specify that all files need to be type // checked is to not pass the file to getEmitResolver. - const emitResolver = getTypeChecker().getEmitResolver(ts.outFile(options) ? undefined : sourceFile, cancellationToken); + const emitResolver = getTypeChecker().getEmitResolver(outFile(options) ? undefined : sourceFile, cancellationToken); ts.performance.mark("beforeEmit"); - const emitResult = ts.emitFiles( + const emitResult = emitFiles( emitResolver, getEmitHost(writeFileCallback), sourceFile, - ts.getTransformers(options, customTransformers, emitOnly), + getTransformers(options, customTransformers, emitOnly), emitOnly, /*onlyBuildInfo*/ false, forceDtsEmit @@ -2103,22 +2164,22 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return emitResult; } - function getSourceFile(fileName: string): ts.SourceFile | undefined { + function getSourceFile(fileName: string): SourceFile | undefined { return getSourceFileByPath(toPath(fileName)); } - function getSourceFileByPath(path: ts.Path): ts.SourceFile | undefined { + function getSourceFileByPath(path: Path): SourceFile | undefined { return filesByName.get(path) || undefined; } - function getDiagnosticsHelper( - sourceFile: ts.SourceFile | undefined, - getDiagnostics: (sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken | undefined) => readonly T[], - cancellationToken: ts.CancellationToken | undefined): readonly T[] { + function getDiagnosticsHelper( + sourceFile: SourceFile | undefined, + getDiagnostics: (sourceFile: SourceFile, cancellationToken: CancellationToken | undefined) => readonly T[], + cancellationToken: CancellationToken | undefined): readonly T[] { if (sourceFile) { return getDiagnostics(sourceFile, cancellationToken); } - return ts.sortAndDeduplicateDiagnostics(ts.flatMap(program.getSourceFiles(), sourceFile => { + return sortAndDeduplicateDiagnostics(flatMap(program.getSourceFiles(), sourceFile => { if (cancellationToken) { cancellationToken.throwIfCancellationRequested(); } @@ -2126,27 +2187,27 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP })); } - function getSyntacticDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.DiagnosticWithLocation[] { + function getSyntacticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[] { return getDiagnosticsHelper(sourceFile, getSyntacticDiagnosticsForFile, cancellationToken); } - function getSemanticDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { + function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } - function getCachedSemanticDiagnostics(sourceFile?: ts.SourceFile): readonly ts.Diagnostic[] | undefined { + function getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined { return sourceFile ? cachedBindAndCheckDiagnosticsForFile.perFile?.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; } - function getBindAndCheckDiagnostics(sourceFile: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.Diagnostic[] { + function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } - function getProgramDiagnostics(sourceFile: ts.SourceFile): readonly ts.Diagnostic[] { - if (ts.skipTypeChecking(sourceFile, options, program)) { - return ts.emptyArray; + function getProgramDiagnostics(sourceFile: SourceFile): readonly Diagnostic[] { + if (skipTypeChecking(sourceFile, options, program)) { + return emptyArray; } const programDiagnosticsInFile = programDiagnostics.getDiagnostics(sourceFile.fileName); @@ -2157,10 +2218,10 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, programDiagnosticsInFile).diagnostics; } - function getDeclarationDiagnostics(sourceFile?: ts.SourceFile, cancellationToken?: ts.CancellationToken): readonly ts.DiagnosticWithLocation[] { + function getDeclarationDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly DiagnosticWithLocation[] { const options = program.getCompilerOptions(); // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit) - if (!sourceFile || ts.outFile(options)) { + if (!sourceFile || outFile(options)) { return getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } else { @@ -2168,14 +2229,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function getSyntacticDiagnosticsForFile(sourceFile: ts.SourceFile): readonly ts.DiagnosticWithLocation[] { + function getSyntacticDiagnosticsForFile(sourceFile: SourceFile): readonly DiagnosticWithLocation[] { // For JavaScript files, we report semantic errors for using TypeScript-only // constructs from within a JavaScript file as syntactic errors. - if (ts.isSourceFileJS(sourceFile)) { + if (isSourceFileJS(sourceFile)) { if (!sourceFile.additionalSyntacticDiagnostics) { sourceFile.additionalSyntacticDiagnostics = getJSSyntacticDiagnosticsForFile(sourceFile); } - return ts.concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics); + return concatenate(sourceFile.additionalSyntacticDiagnostics, sourceFile.parseDiagnostics); } return sourceFile.parseDiagnostics; } @@ -2185,7 +2246,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return func(); } catch (e) { - if (e instanceof ts.OperationCanceledException) { + if (e instanceof OperationCanceledException) { // We were canceled while performing the operation. Because our type checker // might be a bad state, we need to throw it away. typeChecker = undefined!; @@ -2195,51 +2256,51 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function getSemanticDiagnosticsForFile(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken | undefined): readonly ts.Diagnostic[] { - return ts.concatenate( + function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { + return concatenate( filterSemanticDiagnostics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken), options), getProgramDiagnostics(sourceFile) ); } - function getBindAndCheckDiagnosticsForFile(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken | undefined): readonly ts.Diagnostic[] { + function getBindAndCheckDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedBindAndCheckDiagnosticsForFile, getBindAndCheckDiagnosticsForFileNoCache); } - function getBindAndCheckDiagnosticsForFileNoCache(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken | undefined): readonly ts.Diagnostic[] { + function getBindAndCheckDiagnosticsForFileNoCache(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] { return runWithCancellationToken(() => { - if (ts.skipTypeChecking(sourceFile, options, program)) { - return ts.emptyArray; + if (skipTypeChecking(sourceFile, options, program)) { + return emptyArray; } const typeChecker = getTypeChecker(); - ts.Debug.assert(!!sourceFile.bindDiagnostics); + Debug.assert(!!sourceFile.bindDiagnostics); - const isJs = sourceFile.scriptKind === ts.ScriptKind.JS || sourceFile.scriptKind === ts.ScriptKind.JSX; - const isCheckJs = isJs && ts.isCheckJsEnabledForFile(sourceFile, options); - const isPlainJs = ts.isPlainJsFile(sourceFile, options.checkJs); + const isJs = sourceFile.scriptKind === ScriptKind.JS || sourceFile.scriptKind === ScriptKind.JSX; + const isCheckJs = isJs && isCheckJsEnabledForFile(sourceFile, options); + const isPlainJs = isPlainJsFile(sourceFile, options.checkJs); const isTsNoCheck = !!sourceFile.checkJsDirective && sourceFile.checkJsDirective.enabled === false; // By default, only type-check .ts, .tsx, Deferred, plain JS, checked JS and External // - plain JS: .js files with no // ts-check and checkJs: undefined // - check JS: .js files with either // ts-check or checkJs: true // - external: files that are added by plugins - const includeBindAndCheckDiagnostics = !isTsNoCheck && (sourceFile.scriptKind === ts.ScriptKind.TS || sourceFile.scriptKind === ts.ScriptKind.TSX - || sourceFile.scriptKind === ts.ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ts.ScriptKind.Deferred); - let bindDiagnostics: readonly ts.Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : ts.emptyArray; - let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : ts.emptyArray; + const includeBindAndCheckDiagnostics = !isTsNoCheck && (sourceFile.scriptKind === ScriptKind.TS || sourceFile.scriptKind === ScriptKind.TSX + || sourceFile.scriptKind === ScriptKind.External || isPlainJs || isCheckJs || sourceFile.scriptKind === ScriptKind.Deferred); + let bindDiagnostics: readonly Diagnostic[] = includeBindAndCheckDiagnostics ? sourceFile.bindDiagnostics : emptyArray; + let checkDiagnostics = includeBindAndCheckDiagnostics ? typeChecker.getDiagnostics(sourceFile, cancellationToken) : emptyArray; if (isPlainJs) { - bindDiagnostics = ts.filter(bindDiagnostics, d => plainJSErrors.has(d.code)); - checkDiagnostics = ts.filter(checkDiagnostics, d => plainJSErrors.has(d.code)); + bindDiagnostics = filter(bindDiagnostics, d => plainJSErrors.has(d.code)); + checkDiagnostics = filter(checkDiagnostics, d => plainJSErrors.has(d.code)); } // skip ts-expect-error errors in plain JS files, and skip JSDoc errors except in checked JS return getMergedBindAndCheckDiagnostics(sourceFile, includeBindAndCheckDiagnostics && !isPlainJs, bindDiagnostics, checkDiagnostics, isCheckJs ? sourceFile.jsDocDiagnostics : undefined); }); } - function getMergedBindAndCheckDiagnostics(sourceFile: ts.SourceFile, includeBindAndCheckDiagnostics: boolean, ...allDiagnostics: (readonly ts.Diagnostic[] | undefined)[]) { - const flatDiagnostics = ts.flatten(allDiagnostics); + function getMergedBindAndCheckDiagnostics(sourceFile: SourceFile, includeBindAndCheckDiagnostics: boolean, ...allDiagnostics: (readonly Diagnostic[] | undefined)[]) { + const flatDiagnostics = flatten(allDiagnostics); if (!includeBindAndCheckDiagnostics || !sourceFile.commentDirectives?.length) { return flatDiagnostics; } @@ -2247,7 +2308,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const { diagnostics, directives } = getDiagnosticsWithPrecedingDirectives(sourceFile, sourceFile.commentDirectives, flatDiagnostics); for (const errorExpectation of directives.getUnusedExpectations()) { - diagnostics.push(ts.createDiagnosticForRange(sourceFile, errorExpectation.range, ts.Diagnostics.Unused_ts_expect_error_directive)); + diagnostics.push(createDiagnosticForRange(sourceFile, errorExpectation.range, Diagnostics.Unused_ts_expect_error_directive)); } return diagnostics; @@ -2257,16 +2318,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP * Creates a map of comment directives along with the diagnostics immediately preceded by one of them. * Comments that match to any of those diagnostics are marked as used. */ - function getDiagnosticsWithPrecedingDirectives(sourceFile: ts.SourceFile, commentDirectives: ts.CommentDirective[], flatDiagnostics: ts.Diagnostic[]) { + function getDiagnosticsWithPrecedingDirectives(sourceFile: SourceFile, commentDirectives: CommentDirective[], flatDiagnostics: Diagnostic[]) { // Diagnostics are only reported if there is no comment directive preceding them // This will modify the directives map by marking "used" ones with a corresponding diagnostic - const directives = ts.createCommentDirectivesMap(sourceFile, commentDirectives); + const directives = createCommentDirectivesMap(sourceFile, commentDirectives); const diagnostics = flatDiagnostics.filter(diagnostic => markPrecedingCommentDirectiveLine(diagnostic, directives) === -1); return { diagnostics, directives }; } - function getSuggestionDiagnostics(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken): readonly ts.DiagnosticWithLocation[] { + function getSuggestionDiagnostics(sourceFile: SourceFile, cancellationToken: CancellationToken): readonly DiagnosticWithLocation[] { return runWithCancellationToken(() => { return getTypeChecker().getSuggestionDiagnostics(sourceFile, cancellationToken); }); @@ -2275,15 +2336,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP /** * @returns The line index marked as preceding the diagnostic, or -1 if none was. */ - function markPrecedingCommentDirectiveLine(diagnostic: ts.Diagnostic, directives: ts.CommentDirectivesMap) { + function markPrecedingCommentDirectiveLine(diagnostic: Diagnostic, directives: CommentDirectivesMap) { const { file, start } = diagnostic; if (!file) { return -1; } // Start out with the line just before the text - const lineStarts = ts.getLineStarts(file); - let line = ts.computeLineAndCharacterOfPosition(lineStarts, start!).line - 1; // TODO: GH#18217 + const lineStarts = getLineStarts(file); + let line = computeLineAndCharacterOfPosition(lineStarts, start!).line - 1; // TODO: GH#18217 while (line >= 0) { // As soon as that line is known to have a comment directive, use that if (directives.markUsed(line)) { @@ -2302,233 +2363,233 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return -1; } - function getJSSyntacticDiagnosticsForFile(sourceFile: ts.SourceFile): ts.DiagnosticWithLocation[] { + function getJSSyntacticDiagnosticsForFile(sourceFile: SourceFile): DiagnosticWithLocation[] { return runWithCancellationToken(() => { - const diagnostics: ts.DiagnosticWithLocation[] = []; + const diagnostics: DiagnosticWithLocation[] = []; walk(sourceFile, sourceFile); - ts.forEachChildRecursively(sourceFile, walk, walkArray); + forEachChildRecursively(sourceFile, walk, walkArray); return diagnostics; - function walk(node: ts.Node, parent: ts.Node) { + function walk(node: Node, parent: Node) { // Return directly from the case if the given node doesnt want to visit each child // Otherwise break to visit each child switch (parent.kind) { - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - if ((parent as ts.ParameterDeclaration | ts.PropertyDeclaration | ts.MethodDeclaration).questionToken === node) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); + case SyntaxKind.Parameter: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + if ((parent as ParameterDeclaration | PropertyDeclaration | MethodDeclaration).questionToken === node) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?")); return "skip"; } // falls through - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: + case SyntaxKind.VariableDeclaration: // type annotation - if ((parent as ts.FunctionLikeDeclaration | ts.VariableDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration).type === node) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files)); + if ((parent as FunctionLikeDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration).type === node) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_annotations_can_only_be_used_in_TypeScript_files)); return "skip"; } } switch (node.kind) { - case ts.SyntaxKind.ImportClause: - if ((node as ts.ImportClause).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(parent, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "import type")); + case SyntaxKind.ImportClause: + if ((node as ImportClause).isTypeOnly) { + diagnostics.push(createDiagnosticForNode(parent, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "import type")); return "skip"; } break; - case ts.SyntaxKind.ExportDeclaration: - if ((node as ts.ExportDeclaration).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "export type")); + case SyntaxKind.ExportDeclaration: + if ((node as ExportDeclaration).isTypeOnly) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, "export type")); return "skip"; } break; - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - if ((node as ts.ImportOrExportSpecifier).isTypeOnly) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, ts.isImportSpecifier(node) ? "import...type" : "export...type")); + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + if ((node as ImportOrExportSpecifier).isTypeOnly) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, isImportSpecifier(node) ? "import...type" : "export...type")); return "skip"; } break; - case ts.SyntaxKind.ImportEqualsDeclaration: - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.import_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.ImportEqualsDeclaration: + diagnostics.push(createDiagnosticForNode(node, Diagnostics.import_can_only_be_used_in_TypeScript_files)); return "skip"; - case ts.SyntaxKind.ExportAssignment: - if ((node as ts.ExportAssignment).isExportEquals) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.export_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.ExportAssignment: + if ((node as ExportAssignment).isExportEquals) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics.export_can_only_be_used_in_TypeScript_files)); return "skip"; } break; - case ts.SyntaxKind.HeritageClause: - const heritageClause = node as ts.HeritageClause; - if (heritageClause.token === ts.SyntaxKind.ImplementsKeyword) { - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.implements_clauses_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.HeritageClause: + const heritageClause = node as HeritageClause; + if (heritageClause.token === SyntaxKind.ImplementsKeyword) { + diagnostics.push(createDiagnosticForNode(node, Diagnostics.implements_clauses_can_only_be_used_in_TypeScript_files)); return "skip"; } break; - case ts.SyntaxKind.InterfaceDeclaration: - const interfaceKeyword = ts.tokenToString(ts.SyntaxKind.InterfaceKeyword); - ts.Debug.assertIsDefined(interfaceKeyword); - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, interfaceKeyword)); + case SyntaxKind.InterfaceDeclaration: + const interfaceKeyword = tokenToString(SyntaxKind.InterfaceKeyword); + Debug.assertIsDefined(interfaceKeyword); + diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, interfaceKeyword)); return "skip"; - case ts.SyntaxKind.ModuleDeclaration: - const moduleKeyword = node.flags & ts.NodeFlags.Namespace ? ts.tokenToString(ts.SyntaxKind.NamespaceKeyword) : ts.tokenToString(ts.SyntaxKind.ModuleKeyword); - ts.Debug.assertIsDefined(moduleKeyword); - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, moduleKeyword)); + case SyntaxKind.ModuleDeclaration: + const moduleKeyword = node.flags & NodeFlags.Namespace ? tokenToString(SyntaxKind.NamespaceKeyword) : tokenToString(SyntaxKind.ModuleKeyword); + Debug.assertIsDefined(moduleKeyword); + diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, moduleKeyword)); return "skip"; - case ts.SyntaxKind.TypeAliasDeclaration: - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Type_aliases_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.TypeAliasDeclaration: + diagnostics.push(createDiagnosticForNode(node, Diagnostics.Type_aliases_can_only_be_used_in_TypeScript_files)); return "skip"; - case ts.SyntaxKind.EnumDeclaration: - const enumKeyword = ts.Debug.checkDefined(ts.tokenToString(ts.SyntaxKind.EnumKeyword)); - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, enumKeyword)); + case SyntaxKind.EnumDeclaration: + const enumKeyword = Debug.checkDefined(tokenToString(SyntaxKind.EnumKeyword)); + diagnostics.push(createDiagnosticForNode(node, Diagnostics._0_declarations_can_only_be_used_in_TypeScript_files, enumKeyword)); return "skip"; - case ts.SyntaxKind.NonNullExpression: - diagnostics.push(createDiagnosticForNode(node, ts.Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.NonNullExpression: + diagnostics.push(createDiagnosticForNode(node, Diagnostics.Non_null_assertions_can_only_be_used_in_TypeScript_files)); return "skip"; - case ts.SyntaxKind.AsExpression: - diagnostics.push(createDiagnosticForNode((node as ts.AsExpression).type, ts.Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.AsExpression: + diagnostics.push(createDiagnosticForNode((node as AsExpression).type, Diagnostics.Type_assertion_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; - case ts.SyntaxKind.SatisfiesExpression: - diagnostics.push(createDiagnosticForNode((node as ts.SatisfiesExpression).type, ts.Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); + case SyntaxKind.SatisfiesExpression: + diagnostics.push(createDiagnosticForNode((node as SatisfiesExpression).type, Diagnostics.Type_satisfaction_expressions_can_only_be_used_in_TypeScript_files)); return "skip"; - case ts.SyntaxKind.TypeAssertionExpression: - ts.Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. + case SyntaxKind.TypeAssertionExpression: + Debug.fail(); // Won't parse these in a JS file anyway, as they are interpreted as JSX. } } - function walkArray(nodes: ts.NodeArray, parent: ts.Node) { - if (ts.canHaveModifiers(parent) && parent.modifiers === nodes && ts.some(nodes, ts.isDecorator) && !options.experimentalDecorators) { - diagnostics.push(createDiagnosticForNode(parent, ts.Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning)); + function walkArray(nodes: NodeArray, parent: Node) { + if (canHaveModifiers(parent) && parent.modifiers === nodes && some(nodes, isDecorator) && !options.experimentalDecorators) { + diagnostics.push(createDiagnosticForNode(parent, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_in_your_tsconfig_or_jsconfig_to_remove_this_warning)); } switch (parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ArrowFunction: // Check type parameters - if (nodes === (parent as ts.DeclarationWithTypeParameterChildren).typeParameters) { - diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.Type_parameter_declarations_can_only_be_used_in_TypeScript_files)); + if (nodes === (parent as DeclarationWithTypeParameterChildren).typeParameters) { + diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Type_parameter_declarations_can_only_be_used_in_TypeScript_files)); return "skip"; } // falls through - case ts.SyntaxKind.VariableStatement: + case SyntaxKind.VariableStatement: // Check modifiers - if (nodes === (parent as ts.VariableStatement).modifiers) { - checkModifiers((parent as ts.VariableStatement).modifiers!, parent.kind === ts.SyntaxKind.VariableStatement); + if (nodes === (parent as VariableStatement).modifiers) { + checkModifiers((parent as VariableStatement).modifiers!, parent.kind === SyntaxKind.VariableStatement); return "skip"; } break; - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertyDeclaration: // Check modifiers of property declaration - if (nodes === (parent as ts.PropertyDeclaration).modifiers) { - for (const modifier of nodes as ts.NodeArray) { - if (ts.isModifier(modifier) - && modifier.kind !== ts.SyntaxKind.StaticKeyword - && modifier.kind !== ts.SyntaxKind.AccessorKeyword) { - diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, ts.tokenToString(modifier.kind))); + if (nodes === (parent as PropertyDeclaration).modifiers) { + for (const modifier of nodes as NodeArray) { + if (isModifier(modifier) + && modifier.kind !== SyntaxKind.StaticKeyword + && modifier.kind !== SyntaxKind.AccessorKeyword) { + diagnostics.push(createDiagnosticForNode(modifier, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, tokenToString(modifier.kind))); } } return "skip"; } break; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: // Check modifiers of parameter declaration - if (nodes === (parent as ts.ParameterDeclaration).modifiers && ts.some(nodes, ts.isModifier)) { - diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.Parameter_modifiers_can_only_be_used_in_TypeScript_files)); + if (nodes === (parent as ParameterDeclaration).modifiers && some(nodes, isModifier)) { + diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Parameter_modifiers_can_only_be_used_in_TypeScript_files)); return "skip"; } break; - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.ExpressionWithTypeArguments: - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.TaggedTemplateExpression: // Check type arguments - if (nodes === (parent as ts.NodeWithTypeArguments).typeArguments) { - diagnostics.push(createDiagnosticForNodeArray(nodes, ts.Diagnostics.Type_arguments_can_only_be_used_in_TypeScript_files)); + if (nodes === (parent as NodeWithTypeArguments).typeArguments) { + diagnostics.push(createDiagnosticForNodeArray(nodes, Diagnostics.Type_arguments_can_only_be_used_in_TypeScript_files)); return "skip"; } break; } } - function checkModifiers(modifiers: ts.NodeArray, isConstValid: boolean) { + function checkModifiers(modifiers: NodeArray, isConstValid: boolean) { for (const modifier of modifiers) { switch (modifier.kind) { - case ts.SyntaxKind.ConstKeyword: + case SyntaxKind.ConstKeyword: if (isConstValid) { continue; } // to report error, // falls through - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.ReadonlyKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.OverrideKeyword: - case ts.SyntaxKind.InKeyword: - case ts.SyntaxKind.OutKeyword: - diagnostics.push(createDiagnosticForNode(modifier, ts.Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, ts.tokenToString(modifier.kind))); + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.OverrideKeyword: + case SyntaxKind.InKeyword: + case SyntaxKind.OutKeyword: + diagnostics.push(createDiagnosticForNode(modifier, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, tokenToString(modifier.kind))); break; // These are all legal modifiers. - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.ExportKeyword: - case ts.SyntaxKind.DefaultKeyword: - case ts.SyntaxKind.AccessorKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.AccessorKeyword: } } } - function createDiagnosticForNodeArray(nodes: ts.NodeArray, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): ts.DiagnosticWithLocation { + function createDiagnosticForNodeArray(nodes: NodeArray, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation { const start = nodes.pos; - return ts.createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2); + return createFileDiagnostic(sourceFile, start, nodes.end - start, message, arg0, arg1, arg2); } // Since these are syntactic diagnostics, parent might not have been set // this means the sourceFile cannot be infered from the node - function createDiagnosticForNode(node: ts.Node, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): ts.DiagnosticWithLocation { - return ts.createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); + function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation { + return createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2); } }); } - function getDeclarationDiagnosticsWorker(sourceFile: ts.SourceFile | undefined, cancellationToken: ts.CancellationToken | undefined): readonly ts.DiagnosticWithLocation[] { + function getDeclarationDiagnosticsWorker(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] { return getAndCacheDiagnostics(sourceFile, cancellationToken, cachedDeclarationDiagnosticsForFile, getDeclarationDiagnosticsForFileNoCache); } - function getDeclarationDiagnosticsForFileNoCache(sourceFile: ts.SourceFile | undefined, cancellationToken: ts.CancellationToken | undefined): readonly ts.DiagnosticWithLocation[] { + function getDeclarationDiagnosticsForFileNoCache(sourceFile: SourceFile | undefined, cancellationToken: CancellationToken | undefined): readonly DiagnosticWithLocation[] { return runWithCancellationToken(() => { const resolver = getTypeChecker().getEmitResolver(sourceFile, cancellationToken); // Don't actually write any files since we're just getting diagnostics. - return ts.getDeclarationDiagnostics(getEmitHost(ts.noop), resolver, sourceFile) || ts.emptyArray; + return ts.getDeclarationDiagnostics(getEmitHost(noop), resolver, sourceFile) || emptyArray; }); } - function getAndCacheDiagnostics( + function getAndCacheDiagnostics( sourceFile: T, - cancellationToken: ts.CancellationToken | undefined, + cancellationToken: CancellationToken | undefined, cache: DiagnosticCache, - getDiagnostics: (sourceFile: T, cancellationToken: ts.CancellationToken | undefined) => readonly U[], + getDiagnostics: (sourceFile: T, cancellationToken: CancellationToken | undefined) => readonly U[], ): readonly U[] { const cachedResult = sourceFile @@ -2540,7 +2601,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } const result = getDiagnostics(sourceFile, cancellationToken); if (sourceFile) { - (cache.perFile || (cache.perFile = new ts.Map())).set(sourceFile.path, result); + (cache.perFile || (cache.perFile = new Map())).set(sourceFile.path, result); } else { cache.allDiagnostics = result; @@ -2548,72 +2609,72 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return result; } - function getDeclarationDiagnosticsForFile(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken): readonly ts.DiagnosticWithLocation[] { + function getDeclarationDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken): readonly DiagnosticWithLocation[] { return sourceFile.isDeclarationFile ? [] : getDeclarationDiagnosticsWorker(sourceFile, cancellationToken); } - function getOptionsDiagnostics(): ts.SortedReadonlyArray { - return ts.sortAndDeduplicateDiagnostics(ts.concatenate( + function getOptionsDiagnostics(): SortedReadonlyArray { + return sortAndDeduplicateDiagnostics(concatenate( programDiagnostics.getGlobalDiagnostics(), getOptionsDiagnosticsOfConfigFile() )); } function getOptionsDiagnosticsOfConfigFile() { - if (!options.configFile) return ts.emptyArray; + if (!options.configFile) return emptyArray; let diagnostics = programDiagnostics.getDiagnostics(options.configFile.fileName); forEachResolvedProjectReference(resolvedRef => { - diagnostics = ts.concatenate(diagnostics, programDiagnostics.getDiagnostics(resolvedRef.sourceFile.fileName)); + diagnostics = concatenate(diagnostics, programDiagnostics.getDiagnostics(resolvedRef.sourceFile.fileName)); }); return diagnostics; } - function getGlobalDiagnostics(): ts.SortedReadonlyArray { - return rootNames.length ? ts.sortAndDeduplicateDiagnostics(getTypeChecker().getGlobalDiagnostics().slice()) : ts.emptyArray as any as ts.SortedReadonlyArray; + function getGlobalDiagnostics(): SortedReadonlyArray { + return rootNames.length ? sortAndDeduplicateDiagnostics(getTypeChecker().getGlobalDiagnostics().slice()) : emptyArray as any as SortedReadonlyArray; } - function getConfigFileParsingDiagnostics(): readonly ts.Diagnostic[] { - return configFileParsingDiagnostics || ts.emptyArray; + function getConfigFileParsingDiagnostics(): readonly Diagnostic[] { + return configFileParsingDiagnostics || emptyArray; } - function processRootFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: ts.FileIncludeReason) { - processSourceFile(ts.normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined, reason); + function processRootFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason) { + processSourceFile(normalizePath(fileName), isDefaultLib, ignoreNoDefaultLib, /*packageId*/ undefined, reason); } - function fileReferenceIsEqualTo(a: ts.FileReference, b: ts.FileReference): boolean { + function fileReferenceIsEqualTo(a: FileReference, b: FileReference): boolean { return a.fileName === b.fileName; } - function moduleNameIsEqualTo(a: ts.StringLiteralLike | ts.Identifier, b: ts.StringLiteralLike | ts.Identifier): boolean { - return a.kind === ts.SyntaxKind.Identifier - ? b.kind === ts.SyntaxKind.Identifier && a.escapedText === b.escapedText - : b.kind === ts.SyntaxKind.StringLiteral && a.text === b.text; + function moduleNameIsEqualTo(a: StringLiteralLike | Identifier, b: StringLiteralLike | Identifier): boolean { + return a.kind === SyntaxKind.Identifier + ? b.kind === SyntaxKind.Identifier && a.escapedText === b.escapedText + : b.kind === SyntaxKind.StringLiteral && a.text === b.text; } - function createSyntheticImport(text: string, file: ts.SourceFile) { - const externalHelpersModuleReference = ts.factory.createStringLiteral(text); - const importDecl = ts.factory.createImportDeclaration(/*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference, /*assertClause*/ undefined); - ts.addEmitFlags(importDecl, ts.EmitFlags.NeverApplyImportHelper); - ts.setParent(externalHelpersModuleReference, importDecl); - ts.setParent(importDecl, file); + function createSyntheticImport(text: string, file: SourceFile) { + const externalHelpersModuleReference = factory.createStringLiteral(text); + const importDecl = factory.createImportDeclaration(/*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference, /*assertClause*/ undefined); + addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper); + setParent(externalHelpersModuleReference, importDecl); + setParent(importDecl, file); // explicitly unset the synthesized flag on these declarations so the checker API will answer questions about them // (which is required to build the dependency graph for incremental emit) - (externalHelpersModuleReference as ts.Mutable).flags &= ~ts.NodeFlags.Synthesized; - (importDecl as ts.Mutable).flags &= ~ts.NodeFlags.Synthesized; + (externalHelpersModuleReference as Mutable).flags &= ~NodeFlags.Synthesized; + (importDecl as Mutable).flags &= ~NodeFlags.Synthesized; return externalHelpersModuleReference; } - function collectExternalModuleReferences(file: ts.SourceFile): void { + function collectExternalModuleReferences(file: SourceFile): void { if (file.imports) { return; } - const isJavaScriptFile = ts.isSourceFileJS(file); - const isExternalModuleFile = ts.isExternalModule(file); + const isJavaScriptFile = isSourceFileJS(file); + const isExternalModuleFile = isExternalModule(file); // file.imports may not be undefined if there exists dynamic import - let imports: ts.StringLiteralLike[] | undefined; - let moduleAugmentations: (ts.StringLiteral | ts.Identifier)[] | undefined; + let imports: StringLiteralLike[] | undefined; + let moduleAugmentations: (StringLiteral | Identifier)[] | undefined; let ambientModules: string[] | undefined; // If we are importing helpers, we need to add a synthetic reference to resolve the @@ -2622,9 +2683,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP && !file.isDeclarationFile) { if (options.importHelpers) { // synthesize 'import "tslib"' declaration - imports = [createSyntheticImport(ts.externalHelpersModuleNameText, file)]; + imports = [createSyntheticImport(externalHelpersModuleNameText, file)]; } - const jsxImport = ts.getJSXRuntimeImport(ts.getJSXImplicitImportBase(options, file), options); + const jsxImport = getJSXRuntimeImport(getJSXImplicitImportBase(options, file), options); if (jsxImport) { // synthesize `import "base/jsx-runtime"` declaration (imports ||= []).push(createSyntheticImport(jsxImport, file)); @@ -2634,40 +2695,40 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP for (const node of file.statements) { collectModuleReferences(node, /*inAmbientModule*/ false); } - if ((file.flags & ts.NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) { + if ((file.flags & NodeFlags.PossiblyContainsDynamicImport) || isJavaScriptFile) { collectDynamicImportOrRequireCalls(file); } - file.imports = imports || ts.emptyArray; - file.moduleAugmentations = moduleAugmentations || ts.emptyArray; - file.ambientModuleNames = ambientModules || ts.emptyArray; + file.imports = imports || emptyArray; + file.moduleAugmentations = moduleAugmentations || emptyArray; + file.ambientModuleNames = ambientModules || emptyArray; return; - function collectModuleReferences(node: ts.Statement, inAmbientModule: boolean): void { - if (ts.isAnyImportOrReExport(node)) { - const moduleNameExpr = ts.getExternalModuleName(node); + function collectModuleReferences(node: Statement, inAmbientModule: boolean): void { + if (isAnyImportOrReExport(node)) { + const moduleNameExpr = getExternalModuleName(node); // TypeScript 1.0 spec (April 2014): 12.1.6 // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules // only through top - level external module names. Relative external module names are not permitted. - if (moduleNameExpr && ts.isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !ts.isExternalModuleNameRelative(moduleNameExpr.text))) { - ts.setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here - imports = ts.append(imports, moduleNameExpr); + if (moduleNameExpr && isStringLiteral(moduleNameExpr) && moduleNameExpr.text && (!inAmbientModule || !isExternalModuleNameRelative(moduleNameExpr.text))) { + setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here + imports = append(imports, moduleNameExpr); if (!usesUriStyleNodeCoreModules && currentNodeModulesDepth === 0 && !file.isDeclarationFile) { - usesUriStyleNodeCoreModules = ts.startsWith(moduleNameExpr.text, "node:"); + usesUriStyleNodeCoreModules = startsWith(moduleNameExpr.text, "node:"); } } } - else if (ts.isModuleDeclaration(node)) { - if (ts.isAmbientModule(node) && (inAmbientModule || ts.hasSyntacticModifier(node, ts.ModifierFlags.Ambient) || file.isDeclarationFile)) { - (node.name as ts.Mutable).parent = node; - const nameText = ts.getTextOfIdentifierOrLiteral(node.name); + else if (isModuleDeclaration(node)) { + if (isAmbientModule(node) && (inAmbientModule || hasSyntacticModifier(node, ModifierFlags.Ambient) || file.isDeclarationFile)) { + (node.name as Mutable).parent = node; + const nameText = getTextOfIdentifierOrLiteral(node.name); // Ambient module declarations can be interpreted as augmentations for some existing external modules. // This will happen in two cases: // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name // immediately nested in top level ambient module declaration . - if (isExternalModuleFile || (inAmbientModule && !ts.isExternalModuleNameRelative(nameText))) { + if (isExternalModuleFile || (inAmbientModule && !isExternalModuleNameRelative(nameText))) { (moduleAugmentations || (moduleAugmentations = [])).push(node.name); } else if (!inAmbientModule) { @@ -2681,7 +2742,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // Relative external module names are not permitted // NOTE: body of ambient module is always a module block, if it exists - const body = (node as ts.ModuleDeclaration).body as ts.ModuleBlock; + const body = (node as ModuleDeclaration).body as ModuleBlock; if (body) { for (const statement of body.statements) { collectModuleReferences(statement, /*inAmbientModule*/ true); @@ -2692,36 +2753,36 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function collectDynamicImportOrRequireCalls(file: ts.SourceFile) { + function collectDynamicImportOrRequireCalls(file: SourceFile) { const r = /import|require/g; while (r.exec(file.text) !== null) { // eslint-disable-line no-null/no-null const node = getNodeAtPosition(file, r.lastIndex); - if (isJavaScriptFile && ts.isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { - ts.setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here - imports = ts.append(imports, node.arguments[0]); + if (isJavaScriptFile && isRequireCall(node, /*checkArgumentIsStringLiteralLike*/ true)) { + setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here + imports = append(imports, node.arguments[0]); } // we have to check the argument list has length of at least 1. We will still have to process these even though we have parsing error. - else if (ts.isImportCall(node) && node.arguments.length >= 1 && ts.isStringLiteralLike(node.arguments[0])) { - ts.setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here - imports = ts.append(imports, node.arguments[0]); + else if (isImportCall(node) && node.arguments.length >= 1 && isStringLiteralLike(node.arguments[0])) { + setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here + imports = append(imports, node.arguments[0]); } - else if (ts.isLiteralImportTypeNode(node)) { - ts.setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here - imports = ts.append(imports, node.argument.literal); + else if (isLiteralImportTypeNode(node)) { + setParentRecursive(node, /*incremental*/ false); // we need parent data on imports before the program is fully bound, so we ensure it's set here + imports = append(imports, node.argument.literal); } } } /** Returns a token if position is in [start-of-leading-trivia, end), includes JSDoc only in JS files */ - function getNodeAtPosition(sourceFile: ts.SourceFile, position: number): ts.Node { - let current: ts.Node = sourceFile; - const getContainingChild = (child: ts.Node) => { - if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === ts.SyntaxKind.EndOfFileToken)))) { + function getNodeAtPosition(sourceFile: SourceFile, position: number): Node { + let current: Node = sourceFile; + const getContainingChild = (child: Node) => { + if (child.pos <= position && (position < child.end || (position === child.end && (child.kind === SyntaxKind.EndOfFileToken)))) { return child; } }; while (true) { - const child = isJavaScriptFile && ts.hasJSDocNodes(current) && ts.forEach(current.jsDoc, getContainingChild) || ts.forEachChild(current, getContainingChild); + const child = isJavaScriptFile && hasJSDocNodes(current) && forEach(current.jsDoc, getContainingChild) || forEachChild(current, getContainingChild); if (!child) { return current; } @@ -2730,34 +2791,34 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function getLibFileFromReference(ref: ts.FileReference) { - const libName = ts.toFileNameLowerCase(ref.fileName); - const libFileName = ts.libMap.get(libName); + function getLibFileFromReference(ref: FileReference) { + const libName = toFileNameLowerCase(ref.fileName); + const libFileName = libMap.get(libName); if (libFileName) { return getSourceFile(pathForLibFile(libFileName)); } } /** This should have similar behavior to 'processSourceFile' without diagnostics or mutation. */ - function getSourceFileFromReference(referencingFile: ts.SourceFile | ts.UnparsedSource, ref: ts.FileReference): ts.SourceFile | undefined { + function getSourceFileFromReference(referencingFile: SourceFile | UnparsedSource, ref: FileReference): SourceFile | undefined { return getSourceFileFromReferenceWorker(resolveTripleslashReference(ref.fileName, referencingFile.fileName), getSourceFile); } function getSourceFileFromReferenceWorker( fileName: string, - getSourceFile: (fileName: string) => ts.SourceFile | undefined, - fail?: (diagnostic: ts.DiagnosticMessage, ...argument: string[]) => void, - reason?: ts.FileIncludeReason): ts.SourceFile | undefined { + getSourceFile: (fileName: string) => SourceFile | undefined, + fail?: (diagnostic: DiagnosticMessage, ...argument: string[]) => void, + reason?: FileIncludeReason): SourceFile | undefined { - if (ts.hasExtension(fileName)) { + if (hasExtension(fileName)) { const canonicalFileName = host.getCanonicalFileName(fileName); - if (!options.allowNonTsExtensions && !ts.forEach(ts.flatten(supportedExtensionsWithJsonIfResolveJsonModule), extension => ts.fileExtensionIs(canonicalFileName, extension))) { + if (!options.allowNonTsExtensions && !forEach(flatten(supportedExtensionsWithJsonIfResolveJsonModule), extension => fileExtensionIs(canonicalFileName, extension))) { if (fail) { - if (ts.hasJSFileExtension(canonicalFileName)) { - fail(ts.Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName); + if (hasJSFileExtension(canonicalFileName)) { + fail(Diagnostics.File_0_is_a_JavaScript_file_Did_you_mean_to_enable_the_allowJs_option, fileName); } else { - fail(ts.Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + ts.flatten(supportedExtensions).join("', '") + "'"); + fail(Diagnostics.File_0_has_an_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'"); } } return undefined; @@ -2768,14 +2829,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (!sourceFile) { const redirect = getProjectReferenceRedirect(fileName); if (redirect) { - fail(ts.Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, fileName); + fail(Diagnostics.Output_file_0_has_not_been_built_from_source_file_1, redirect, fileName); } else { - fail(ts.Diagnostics.File_0_not_found, fileName); + fail(Diagnostics.File_0_not_found, fileName); } } else if (isReferencedFile(reason) && canonicalFileName === host.getCanonicalFileName(getSourceFileByPath(reason.file)!.fileName)) { - fail(ts.Diagnostics.A_file_cannot_have_a_reference_to_itself); + fail(Diagnostics.A_file_cannot_have_a_reference_to_itself); } } return sourceFile; @@ -2785,19 +2846,19 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (sourceFileNoExtension) return sourceFileNoExtension; if (fail && options.allowNonTsExtensions) { - fail(ts.Diagnostics.File_0_not_found, fileName); + fail(Diagnostics.File_0_not_found, fileName); return undefined; } // Only try adding extensions from the first supported group (which should be .ts/.tsx/.d.ts) - const sourceFileWithAddedExtension = ts.forEach(supportedExtensions[0], extension => getSourceFile(fileName + extension)); - if (fail && !sourceFileWithAddedExtension) fail(ts.Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + ts.flatten(supportedExtensions).join("', '") + "'"); + const sourceFileWithAddedExtension = forEach(supportedExtensions[0], extension => getSourceFile(fileName + extension)); + if (fail && !sourceFileWithAddedExtension) fail(Diagnostics.Could_not_resolve_the_path_0_with_the_extensions_Colon_1, fileName, "'" + flatten(supportedExtensions).join("', '") + "'"); return sourceFileWithAddedExtension; } } /** This has side effects through `findSourceFile`. */ - function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: ts.PackageId | undefined, reason: ts.FileIncludeReason): void { + function processSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, packageId: PackageId | undefined, reason: FileIncludeReason): void { getSourceFileFromReferenceWorker( fileName, fileName => findSourceFile(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId), // TODO: GH#18217 @@ -2806,22 +2867,22 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP ); } - function processProjectReferenceFile(fileName: string, reason: ts.ProjectReferenceFile) { + function processProjectReferenceFile(fileName: string, reason: ProjectReferenceFile) { return processSourceFile(fileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, reason); } - function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFile: ts.SourceFile, reason: ts.FileIncludeReason): void { - const hasExistingReasonToReportErrorOn = !isReferencedFile(reason) && ts.some(fileReasons.get(existingFile.path), isReferencedFile); + function reportFileNamesDifferOnlyInCasingError(fileName: string, existingFile: SourceFile, reason: FileIncludeReason): void { + const hasExistingReasonToReportErrorOn = !isReferencedFile(reason) && some(fileReasons.get(existingFile.path), isReferencedFile); if (hasExistingReasonToReportErrorOn) { - addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, ts.Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, [existingFile.fileName, fileName]); + addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, Diagnostics.Already_included_file_name_0_differs_from_file_name_1_only_in_casing, [existingFile.fileName, fileName]); } else { - addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, ts.Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, [fileName, existingFile.fileName]); + addFilePreprocessingFileExplainingDiagnostic(existingFile, reason, Diagnostics.File_name_0_differs_from_already_included_file_name_1_only_in_casing, [fileName, existingFile.fileName]); } } - function createRedirectSourceFile(redirectTarget: ts.SourceFile, unredirected: ts.SourceFile, fileName: string, path: ts.Path, resolvedPath: ts.Path, originalFileName: string, sourceFileOptions: ts.CreateSourceFileOptions): ts.SourceFile { - const redirect: ts.SourceFile = Object.create(redirectTarget); + function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string, sourceFileOptions: CreateSourceFileOptions): SourceFile { + const redirect: SourceFile = Object.create(redirectTarget); redirect.fileName = fileName; redirect.path = path; redirect.resolvedPath = resolvedPath; @@ -2832,42 +2893,42 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); Object.defineProperties(redirect, { id: { - get(this: ts.SourceFile) { return this.redirectInfo!.redirectTarget.id; }, - set(this: ts.SourceFile, value: ts.SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; }, + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; }, + set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; }, }, symbol: { - get(this: ts.SourceFile) { return this.redirectInfo!.redirectTarget.symbol; }, - set(this: ts.SourceFile, value: ts.SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; }, + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; }, + set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; }, }, }); return redirect; } // Get source file from normalized fileName - function findSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: ts.FileIncludeReason, packageId: ts.PackageId | undefined): ts.SourceFile | undefined { - ts.tracing?.push(ts.tracing.Phase.Program, "findSourceFile", { + function findSourceFile(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined { + tracing?.push(tracing.Phase.Program, "findSourceFile", { fileName, isDefaultLib: isDefaultLib || undefined, - fileIncludeKind: (ts.FileIncludeKind as any)[reason.kind], + fileIncludeKind: (FileIncludeKind as any)[reason.kind], }); const result = findSourceFileWorker(fileName, isDefaultLib, ignoreNoDefaultLib, reason, packageId); - ts.tracing?.pop(); + tracing?.pop(); return result; } - function getCreateSourceFileOptions(fileName: string, moduleResolutionCache: ts.ModuleResolutionCache | undefined, host: ts.CompilerHost, options: ts.CompilerOptions): ts.CreateSourceFileOptions { + function getCreateSourceFileOptions(fileName: string, moduleResolutionCache: ModuleResolutionCache | undefined, host: CompilerHost, options: CompilerOptions): CreateSourceFileOptions { // It's a _little odd_ that we can't set `impliedNodeFormat` until the program step - but it's the first and only time we have a resolution cache // and a freshly made source file node on hand at the same time, and we need both to set the field. Persisting the resolution cache all the way // to the check and emit steps would be bad - so we much prefer detecting and storing the format information on the source file node upfront. - const result = getImpliedNodeFormatForFileWorker(ts.getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options); - const languageVersion = ts.getEmitScriptTarget(options); - const setExternalModuleIndicator = ts.getSetExternalModuleIndicator(options); + const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options); + const languageVersion = getEmitScriptTarget(options); + const setExternalModuleIndicator = getSetExternalModuleIndicator(options); return typeof result === "object" ? { ...result, languageVersion, setExternalModuleIndicator } : { languageVersion, impliedNodeFormat: result, setExternalModuleIndicator }; } - function findSourceFileWorker(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: ts.FileIncludeReason, packageId: ts.PackageId | undefined): ts.SourceFile | undefined { + function findSourceFileWorker(fileName: string, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, reason: FileIncludeReason, packageId: PackageId | undefined): SourceFile | undefined { const path = toPath(fileName); if (useSourceOfProjectReferenceRedirect) { let source = getSourceOfProjectReferenceRedirect(path); @@ -2878,13 +2939,13 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (!source && host.realpath && options.preserveSymlinks && - ts.isDeclarationFileName(fileName) && - ts.stringContains(fileName, ts.nodeModulesPathPart)) { + isDeclarationFileName(fileName) && + stringContains(fileName, nodeModulesPathPart)) { const realPath = toPath(host.realpath(fileName)); if (realPath !== path) source = getSourceOfProjectReferenceRedirect(realPath); } if (source) { - const file = ts.isString(source) ? + const file = isString(source) ? findSourceFile(source, isDefaultLib, ignoreNoDefaultLib, reason, packageId) : undefined; if (file) addFileToFilesByName(file, path, /*redirectedPath*/ undefined); @@ -2904,8 +2965,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP fileName = getProjectReferenceRedirect(fileName) || fileName; } // Check if it differs only in drive letters its ok to ignore that error: - const checkedAbsolutePath = ts.getNormalizedAbsolutePathWithoutRoot(checkedName, currentDirectory); - const inputAbsolutePath = ts.getNormalizedAbsolutePathWithoutRoot(fileName, currentDirectory); + const checkedAbsolutePath = getNormalizedAbsolutePathWithoutRoot(checkedName, currentDirectory); + const inputAbsolutePath = getNormalizedAbsolutePathWithoutRoot(fileName, currentDirectory); if (checkedAbsolutePath !== inputAbsolutePath) { reportFileNamesDifferOnlyInCasingError(fileName, file, reason); } @@ -2937,11 +2998,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return file || undefined; } - let redirectedPath: ts.Path | undefined; + let redirectedPath: Path | undefined; if (isReferencedFile(reason) && !useSourceOfProjectReferenceRedirect) { const redirectProject = getProjectReferenceRedirectProject(fileName); if (redirectProject) { - if (ts.outFile(redirectProject.commandLine.options)) { + if (outFile(redirectProject.commandLine.options)) { // Shouldnt create many to 1 mapping file in --out scenario return undefined; } @@ -2961,12 +3022,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const file = host.getSourceFile( fileName, sourceFileOptions, - hostErrorMessage => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, ts.Diagnostics.Cannot_read_file_0_Colon_1, [fileName, hostErrorMessage]), + hostErrorMessage => addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_read_file_0_Colon_1, [fileName, hostErrorMessage]), shouldCreateNewSourceFile || (oldProgram?.getSourceFileByPath(toPath(fileName))?.impliedNodeFormat !== sourceFileOptions.impliedNodeFormat) ); if (packageId) { - const packageIdKey = ts.packageIdToString(packageId); + const packageIdKey = packageIdToString(packageId); const fileFromPackageId = packageIdToSourceFile.get(packageIdKey); if (fileFromPackageId) { // Some other SourceFile already exists with this package name and version. @@ -2975,14 +3036,14 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP redirectTargetsMap.add(fileFromPackageId.path, fileName); addFileToFilesByName(dupFile, path, redirectedPath); addFileIncludeReason(dupFile, reason); - sourceFileToPackageName.set(path, ts.packageIdToPackageName(packageId)); + sourceFileToPackageName.set(path, packageIdToPackageName(packageId)); processingOtherFiles!.push(dupFile); return dupFile; } else if (file) { // This is the first source file to have this packageId. packageIdToSourceFile.set(packageIdKey, file); - sourceFileToPackageName.set(path, ts.packageIdToPackageName(packageId)); + sourceFileToPackageName.set(path, packageIdToPackageName(packageId)); } } addFileToFilesByName(file, path, redirectedPath); @@ -2998,7 +3059,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP addFileIncludeReason(file, reason); if (host.useCaseSensitiveFileNames()) { - const pathLowerCase = ts.toFileNameLowerCase(path); + const pathLowerCase = toFileNameLowerCase(path); // for case-sensitive file systems check if we've already seen some file with similar filename ignoring case const existingFile = filesByNameIgnoreCase!.get(pathLowerCase); if (existingFile) { @@ -3033,11 +3094,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return file; } - function addFileIncludeReason(file: ts.SourceFile | undefined, reason: ts.FileIncludeReason) { + function addFileIncludeReason(file: SourceFile | undefined, reason: FileIncludeReason) { if (file) fileReasons.add(file.path, reason); } - function addFileToFilesByName(file: ts.SourceFile | undefined, path: ts.Path, redirectedPath: ts.Path | undefined) { + function addFileToFilesByName(file: SourceFile | undefined, path: Path, redirectedPath: Path | undefined) { if (redirectedPath) { filesByName.set(redirectedPath, file); filesByName.set(path, file || false); @@ -3054,7 +3115,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP function getProjectReferenceRedirectProject(fileName: string) { // Ignore dts or any json files - if (!resolvedProjectReferences || !resolvedProjectReferences.length || ts.isDeclarationFileName(fileName) || ts.fileExtensionIs(fileName, ts.Extension.Json)) { + if (!resolvedProjectReferences || !resolvedProjectReferences.length || isDeclarationFileName(fileName) || fileExtensionIs(fileName, Extension.Json)) { return undefined; } @@ -3064,11 +3125,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } - function getProjectReferenceOutputName(referencedProject: ts.ResolvedProjectReference, fileName: string) { - const out = ts.outFile(referencedProject.commandLine.options); + function getProjectReferenceOutputName(referencedProject: ResolvedProjectReference, fileName: string) { + const out = outFile(referencedProject.commandLine.options); return out ? - ts.changeExtension(out, ts.Extension.Dts) : - ts.getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames()); + changeExtension(out, Extension.Dts) : + getOutputDeclarationFileName(fileName, referencedProject.commandLine, !host.useCaseSensitiveFileNames()); } /** @@ -3076,7 +3137,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP */ function getResolvedProjectReferenceToRedirect(fileName: string) { if (mapFromFileToProjectReferenceRedirects === undefined) { - mapFromFileToProjectReferenceRedirects = new ts.Map(); + mapFromFileToProjectReferenceRedirects = new Map(); forEachResolvedProjectReference(referencedProject => { // not input file from the referenced project, ignore if (toPath(options.configFilePath!) !== referencedProject.sourceFile.path) { @@ -3091,27 +3152,27 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } function forEachResolvedProjectReference( - cb: (resolvedProjectReference: ts.ResolvedProjectReference) => T | undefined + cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined ): T | undefined { return ts.forEachResolvedProjectReference(resolvedProjectReferences, cb); } - function getSourceOfProjectReferenceRedirect(path: ts.Path) { - if (!ts.isDeclarationFileName(path)) return undefined; + function getSourceOfProjectReferenceRedirect(path: Path) { + if (!isDeclarationFileName(path)) return undefined; if (mapFromToProjectReferenceRedirectSource === undefined) { - mapFromToProjectReferenceRedirectSource = new ts.Map(); + mapFromToProjectReferenceRedirectSource = new Map(); forEachResolvedProjectReference(resolvedRef => { - const out = ts.outFile(resolvedRef.commandLine.options); + const out = outFile(resolvedRef.commandLine.options); if (out) { // Dont know which source file it means so return true? - const outputDts = ts.changeExtension(out, ts.Extension.Dts); + const outputDts = changeExtension(out, Extension.Dts); mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), true); } else { - const getCommonSourceDirectory = ts.memoize(() => ts.getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames())); - ts.forEach(resolvedRef.commandLine.fileNames, fileName => { - if (!ts.isDeclarationFileName(fileName) && !ts.fileExtensionIs(fileName, ts.Extension.Json)) { - const outputDts = ts.getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory); + const getCommonSourceDirectory = memoize(() => getCommonSourceDirectoryOfConfig(resolvedRef.commandLine, !host.useCaseSensitiveFileNames())); + forEach(resolvedRef.commandLine.fileNames, fileName => { + if (!isDeclarationFileName(fileName) && !fileExtensionIs(fileName, Extension.Json)) { + const outputDts = getOutputDeclarationFileName(fileName, resolvedRef.commandLine, !host.useCaseSensitiveFileNames(), getCommonSourceDirectory); mapFromToProjectReferenceRedirectSource!.set(toPath(outputDts), fileName); } }); @@ -3125,7 +3186,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return useSourceOfProjectReferenceRedirect && !!getResolvedProjectReferenceToRedirect(fileName); } - function getResolvedProjectReferenceByPath(projectReferencePath: ts.Path): ts.ResolvedProjectReference | undefined { + function getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined { if (!projectReferenceRedirects) { return undefined; } @@ -3133,19 +3194,19 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return projectReferenceRedirects.get(projectReferencePath) || undefined; } - function processReferencedFiles(file: ts.SourceFile, isDefaultLib: boolean) { - ts.forEach(file.referencedFiles, (ref, index) => { + function processReferencedFiles(file: SourceFile, isDefaultLib: boolean) { + forEach(file.referencedFiles, (ref, index) => { processSourceFile( resolveTripleslashReference(ref.fileName, file.fileName), isDefaultLib, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined, - { kind: ts.FileIncludeKind.ReferenceFile, file: file.path, index, } + { kind: FileIncludeKind.ReferenceFile, file: file.path, index, } ); }); } - function processTypeReferenceDirectives(file: ts.SourceFile) { + function processTypeReferenceDirectives(file: SourceFile) { const typeDirectives = file.typeReferenceDirectives; if (!typeDirectives) { return; @@ -3156,32 +3217,32 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const ref = file.typeReferenceDirectives[index]; const resolvedTypeReferenceDirective = resolutions[index]; // store resolved type directive on the file - const fileName = ts.toFileNameLowerCase(ref.fileName); - ts.setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); + const fileName = toFileNameLowerCase(ref.fileName); + setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective); const mode = ref.resolutionMode || file.impliedNodeFormat; - if (mode && ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.Node16 && ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeNext) { - programDiagnostics.add(ts.createDiagnosticForRange(file, ref, ts.Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext)); + if (mode && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) { + programDiagnostics.add(createDiagnosticForRange(file, ref, Diagnostics.resolution_mode_assertions_are_only_supported_when_moduleResolution_is_node16_or_nodenext)); } - processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: ts.FileIncludeKind.TypeReferenceDirective, file: file.path, index, }); + processTypeReferenceDirective(fileName, mode, resolvedTypeReferenceDirective, { kind: FileIncludeKind.TypeReferenceDirective, file: file.path, index, }); } } function processTypeReferenceDirective( typeReferenceDirective: string, - mode: ts.SourceFile["impliedNodeFormat"] | undefined, - resolvedTypeReferenceDirective: ts.ResolvedTypeReferenceDirective | undefined, - reason: ts.FileIncludeReason + mode: SourceFile["impliedNodeFormat"] | undefined, + resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined, + reason: FileIncludeReason ): void { - ts.tracing?.push(ts.tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined }); + tracing?.push(tracing.Phase.Program, "processTypeReferenceDirective", { directive: typeReferenceDirective, hasResolved: !!resolvedTypeReferenceDirective, refKind: reason.kind, refPath: isReferencedFile(reason) ? reason.file : undefined }); processTypeReferenceDirectiveWorker(typeReferenceDirective, mode, resolvedTypeReferenceDirective, reason); - ts.tracing?.pop(); + tracing?.pop(); } function processTypeReferenceDirectiveWorker( typeReferenceDirective: string, - mode: ts.SourceFile["impliedNodeFormat"] | undefined, - resolvedTypeReferenceDirective: ts.ResolvedTypeReferenceDirective | undefined, - reason: ts.FileIncludeReason + mode: SourceFile["impliedNodeFormat"] | undefined, + resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined, + reason: FileIncludeReason ): void { // If we already found this library as a primary reference - nothing to do @@ -3209,7 +3270,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP addFilePreprocessingFileExplainingDiagnostic( existingFile, reason, - ts.Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, + Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict, [typeReferenceDirective, resolvedTypeReferenceDirective.resolvedFileName, previousResolution.resolvedFileName] ); } @@ -3226,7 +3287,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (resolvedTypeReferenceDirective.isExternalLibraryImport) currentNodeModulesDepth--; } else { - addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, ts.Diagnostics.Cannot_find_type_definition_file_for_0, [typeReferenceDirective]); + addFilePreprocessingFileExplainingDiagnostic(/*file*/ undefined, reason, Diagnostics.Cannot_find_type_definition_file_for_0, [typeReferenceDirective]); } if (saveResolution) { @@ -3245,29 +3306,29 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP path += (i === 2 ? "/" : "-") + components[i]; i++; } - const resolveFrom = ts.combinePaths(currentDirectory, `__lib_node_modules_lookup_${libFileName}__.ts`); - const localOverrideModuleResult = ts.resolveModuleName("@typescript/lib-" + path, resolveFrom, { moduleResolution: ts.ModuleResolutionKind.NodeJs }, host, moduleResolutionCache); + const resolveFrom = combinePaths(currentDirectory, `__lib_node_modules_lookup_${libFileName}__.ts`); + const localOverrideModuleResult = resolveModuleName("@typescript/lib-" + path, resolveFrom, { moduleResolution: ModuleResolutionKind.NodeJs }, host, moduleResolutionCache); if (localOverrideModuleResult?.resolvedModule) { return localOverrideModuleResult.resolvedModule.resolvedFileName; } - return ts.combinePaths(defaultLibraryPath, libFileName); + return combinePaths(defaultLibraryPath, libFileName); } - function processLibReferenceDirectives(file: ts.SourceFile) { - ts.forEach(file.libReferenceDirectives, (libReference, index) => { - const libName = ts.toFileNameLowerCase(libReference.fileName); - const libFileName = ts.libMap.get(libName); + function processLibReferenceDirectives(file: SourceFile) { + forEach(file.libReferenceDirectives, (libReference, index) => { + const libName = toFileNameLowerCase(libReference.fileName); + const libFileName = libMap.get(libName); if (libFileName) { // we ignore any 'no-default-lib' reference set on this file. - processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { kind: ts.FileIncludeKind.LibReferenceDirective, file: file.path, index, }); + processRootFile(pathForLibFile(libFileName), /*isDefaultLib*/ true, /*ignoreNoDefaultLib*/ true, { kind: FileIncludeKind.LibReferenceDirective, file: file.path, index, }); } else { - const unqualifiedLibName = ts.removeSuffix(ts.removePrefix(libName, "lib."), ".d.ts"); - const suggestion = ts.getSpellingSuggestion(unqualifiedLibName, ts.libs, ts.identity); - const diagnostic = suggestion ? ts.Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 : ts.Diagnostics.Cannot_find_lib_definition_for_0; + const unqualifiedLibName = removeSuffix(removePrefix(libName, "lib."), ".d.ts"); + const suggestion = getSpellingSuggestion(unqualifiedLibName, libs, identity); + const diagnostic = suggestion ? Diagnostics.Cannot_find_lib_definition_for_0_Did_you_mean_1 : Diagnostics.Cannot_find_lib_definition_for_0; (fileProcessingDiagnostics ||= []).push({ - kind: ts.FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic, - reason: { kind: ts.FileIncludeKind.LibReferenceDirective, file: file.path, index, }, + kind: FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic, + reason: { kind: FileIncludeKind.LibReferenceDirective, file: file.path, index, }, diagnostic, args: [libName, suggestion] }); @@ -3279,24 +3340,24 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return host.getCanonicalFileName(fileName); } - function processImportedModules(file: ts.SourceFile) { + function processImportedModules(file: SourceFile) { collectExternalModuleReferences(file); if (file.imports.length || file.moduleAugmentations.length) { // Because global augmentation doesn't have string literal name, we can check for global augmentation as such. const moduleNames = getModuleNames(file); const resolutions = resolveModuleNamesReusingOldState(moduleNames, file); - ts.Debug.assert(resolutions.length === moduleNames.length); + Debug.assert(resolutions.length === moduleNames.length); const optionsForFile = (useSourceOfProjectReferenceRedirect ? getRedirectReferenceForResolution(file)?.commandLine.options : undefined) || options; for (let index = 0; index < moduleNames.length; index++) { const resolution = resolutions[index]; - ts.setResolvedModule(file, moduleNames[index], resolution, getModeForResolutionAtIndex(file, index)); + setResolvedModule(file, moduleNames[index], resolution, getModeForResolutionAtIndex(file, index)); if (!resolution) { continue; } const isFromNodeModulesSearch = resolution.isExternalLibraryImport; - const isJsFile = !ts.resolutionExtensionIsTSOrJson(resolution.extension); + const isJsFile = !resolutionExtensionIsTSOrJson(resolution.extension); const isJsFileFromNodeModules = isFromNodeModulesSearch && isJsFile; const resolvedFileName = resolution.resolvedFileName; @@ -3317,8 +3378,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP && !optionsForFile.noResolve && index < file.imports.length && !elideImport - && !(isJsFile && !ts.getAllowJSCompilerOption(optionsForFile)) - && (ts.isInJSFile(file.imports[index]) || !(file.imports[index].flags & ts.NodeFlags.JSDoc)); + && !(isJsFile && !getAllowJSCompilerOption(optionsForFile)) + && (isInJSFile(file.imports[index]) || !(file.imports[index].flags & NodeFlags.JSDoc)); if (elideImport) { modulesWithElidedImports.set(file.path, true); @@ -3328,7 +3389,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP resolvedFileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, - { kind: ts.FileIncludeKind.Import, file: file.path, index, }, + { kind: FileIncludeKind.Import, file: file.path, index, }, resolution.packageId, ); } @@ -3344,16 +3405,16 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function checkSourceFilesBelongToPath(sourceFiles: readonly ts.SourceFile[], rootDirectory: string): boolean { + function checkSourceFilesBelongToPath(sourceFiles: readonly SourceFile[], rootDirectory: string): boolean { let allFilesBelongToPath = true; - const absoluteRootDirectoryPath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(rootDirectory, currentDirectory)); + const absoluteRootDirectoryPath = host.getCanonicalFileName(getNormalizedAbsolutePath(rootDirectory, currentDirectory)); for (const sourceFile of sourceFiles) { if (!sourceFile.isDeclarationFile) { - const absoluteSourceFilePath = host.getCanonicalFileName(ts.getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); + const absoluteSourceFilePath = host.getCanonicalFileName(getNormalizedAbsolutePath(sourceFile.fileName, currentDirectory)); if (absoluteSourceFilePath.indexOf(absoluteRootDirectoryPath) !== 0) { addProgramDiagnosticExplainingFile( sourceFile, - ts.Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, + Diagnostics.File_0_is_not_under_rootDir_1_rootDir_is_expected_to_contain_all_source_files, [sourceFile.fileName, rootDirectory] ); allFilesBelongToPath = false; @@ -3364,9 +3425,9 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return allFilesBelongToPath; } - function parseProjectReferenceConfigFile(ref: ts.ProjectReference): ts.ResolvedProjectReference | undefined { + function parseProjectReferenceConfigFile(ref: ProjectReference): ResolvedProjectReference | undefined { if (!projectReferenceRedirects) { - projectReferenceRedirects = new ts.Map(); + projectReferenceRedirects = new Map(); } // The actual filename (i.e. add "/tsconfig.json" if necessary) @@ -3377,8 +3438,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return fromCache || undefined; } - let commandLine: ts.ParsedCommandLine | undefined; - let sourceFile: ts.JsonSourceFile | undefined; + let commandLine: ParsedCommandLine | undefined; + let sourceFile: JsonSourceFile | undefined; if (host.getParsedCommandLine) { commandLine = host.getParsedCommandLine(refPath); if (!commandLine) { @@ -3386,27 +3447,27 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP projectReferenceRedirects.set(sourceFilePath, false); return undefined; } - sourceFile = ts.Debug.checkDefined(commandLine.options.configFile); - ts.Debug.assert(!sourceFile.path || sourceFile.path === sourceFilePath); + sourceFile = Debug.checkDefined(commandLine.options.configFile); + Debug.assert(!sourceFile.path || sourceFile.path === sourceFilePath); addFileToFilesByName(sourceFile, sourceFilePath, /*redirectedPath*/ undefined); } else { // An absolute path pointing to the containing directory of the config file - const basePath = ts.getNormalizedAbsolutePath(ts.getDirectoryPath(refPath), host.getCurrentDirectory()); - sourceFile = host.getSourceFile(refPath, ts.ScriptTarget.JSON) as ts.JsonSourceFile | undefined; + const basePath = getNormalizedAbsolutePath(getDirectoryPath(refPath), host.getCurrentDirectory()); + sourceFile = host.getSourceFile(refPath, ScriptTarget.JSON) as JsonSourceFile | undefined; addFileToFilesByName(sourceFile, sourceFilePath, /*redirectedPath*/ undefined); if (sourceFile === undefined) { projectReferenceRedirects.set(sourceFilePath, false); return undefined; } - commandLine = ts.parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); + commandLine = parseJsonSourceFileConfigFileContent(sourceFile, configParsingHost, basePath, /*existingOptions*/ undefined, refPath); } sourceFile.fileName = refPath; sourceFile.path = sourceFilePath; sourceFile.resolvedPath = sourceFilePath; sourceFile.originalFileName = refPath; - const resolvedRef: ts.ResolvedProjectReference = { commandLine, sourceFile }; + const resolvedRef: ResolvedProjectReference = { commandLine, sourceFile }; projectReferenceRedirects.set(sourceFilePath, resolvedRef); if (commandLine.projectReferences) { resolvedRef.references = commandLine.projectReferences.map(parseProjectReferenceConfigFile); @@ -3415,62 +3476,62 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } function verifyCompilerOptions() { - if (options.strictPropertyInitialization && !ts.getStrictOptionValue(options, "strictNullChecks")) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks"); + if (options.strictPropertyInitialization && !getStrictOptionValue(options, "strictNullChecks")) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks"); } - if (options.exactOptionalPropertyTypes && !ts.getStrictOptionValue(options, "strictNullChecks")) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "exactOptionalPropertyTypes", "strictNullChecks"); + if (options.exactOptionalPropertyTypes && !getStrictOptionValue(options, "strictNullChecks")) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "exactOptionalPropertyTypes", "strictNullChecks"); } if (options.isolatedModules) { if (options.out) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "isolatedModules"); } if (options.outFile) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "outFile", "isolatedModules"); } } if (options.inlineSourceMap) { if (options.sourceMap) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "sourceMap", "inlineSourceMap"); } if (options.mapRoot) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "mapRoot", "inlineSourceMap"); } } if (options.composite) { if (options.declaration === false) { - createDiagnosticForOptionName(ts.Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration"); + createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_declaration_emit, "declaration"); } if (options.incremental === false) { - createDiagnosticForOptionName(ts.Diagnostics.Composite_projects_may_not_disable_incremental_compilation, "declaration"); + createDiagnosticForOptionName(Diagnostics.Composite_projects_may_not_disable_incremental_compilation, "declaration"); } } - const outputFile = ts.outFile(options); + const outputFile = outFile(options); if (options.tsBuildInfoFile) { - if (!ts.isIncrementalCompilation(options)) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite"); + if (!isIncrementalCompilation(options)) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "tsBuildInfoFile", "incremental", "composite"); } } else if (options.incremental && !outputFile && !options.configFilePath) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified)); + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified)); } verifyProjectReferences(); // List of collected files is complete; validate exhautiveness if this is a project with a file list if (options.composite) { - const rootPaths = new ts.Set(rootNames.map(toPath)); + const rootPaths = new Set(rootNames.map(toPath)); for (const file of files) { // Ignore file that is not emitted - if (ts.sourceFileMayBeEmitted(file, program) && !rootPaths.has(file.path)) { + if (sourceFileMayBeEmitted(file, program) && !rootPaths.has(file.path)) { addProgramDiagnosticExplainingFile( file, - ts.Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern, + Diagnostics.File_0_is_not_listed_within_the_file_list_of_project_1_Projects_must_list_all_files_or_use_an_include_pattern, [file.fileName, options.configFilePath || ""] ); } @@ -3479,124 +3540,124 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP if (options.paths) { for (const key in options.paths) { - if (!ts.hasProperty(options.paths, key)) { + if (!hasProperty(options.paths, key)) { continue; } - if (!ts.hasZeroOrOneAsteriskCharacter(key)) { - createDiagnosticForOptionPaths(/*onKey*/ true, key, ts.Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); + if (!hasZeroOrOneAsteriskCharacter(key)) { + createDiagnosticForOptionPaths(/*onKey*/ true, key, Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key); } - if (ts.isArray(options.paths[key])) { + if (isArray(options.paths[key])) { const len = options.paths[key].length; if (len === 0) { - createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key); } for (let i = 0; i < len; i++) { const subst = options.paths[key][i]; const typeOfSubst = typeof subst; if (typeOfSubst === "string") { - if (!ts.hasZeroOrOneAsteriskCharacter(subst)) { - createDiagnosticForOptionPathKeyValue(key, i, ts.Diagnostics.Substitution_0_in_pattern_1_can_have_at_most_one_Asterisk_character, subst, key); + if (!hasZeroOrOneAsteriskCharacter(subst)) { + createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_in_pattern_1_can_have_at_most_one_Asterisk_character, subst, key); } - if (!options.baseUrl && !ts.pathIsRelative(subst) && !ts.pathIsAbsolute(subst)) { - createDiagnosticForOptionPathKeyValue(key, i, ts.Diagnostics.Non_relative_paths_are_not_allowed_when_baseUrl_is_not_set_Did_you_forget_a_leading_Slash); + if (!options.baseUrl && !pathIsRelative(subst) && !pathIsAbsolute(subst)) { + createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Non_relative_paths_are_not_allowed_when_baseUrl_is_not_set_Did_you_forget_a_leading_Slash); } } else { - createDiagnosticForOptionPathKeyValue(key, i, ts.Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst); + createDiagnosticForOptionPathKeyValue(key, i, Diagnostics.Substitution_0_for_pattern_1_has_incorrect_type_expected_string_got_2, subst, key, typeOfSubst); } } } else { - createDiagnosticForOptionPaths(/*onKey*/ false, key, ts.Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); + createDiagnosticForOptionPaths(/*onKey*/ false, key, Diagnostics.Substitutions_for_pattern_0_should_be_an_array, key); } } } if (!options.sourceMap && !options.inlineSourceMap) { if (options.inlineSources) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources"); + createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "inlineSources"); } if (options.sourceRoot) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot"); + createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided, "sourceRoot"); } } if (options.out && options.outFile) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "out", "outFile"); } if (options.mapRoot && !(options.sourceMap || options.declarationMap)) { // Error to specify --mapRoot without --sourcemap - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "mapRoot", "sourceMap", "declarationMap"); } if (options.declarationDir) { - if (!ts.getEmitDeclarations(options)) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationDir", "declaration", "composite"); + if (!getEmitDeclarations(options)) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationDir", "declaration", "composite"); } if (outputFile) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "declarationDir", options.out ? "out" : "outFile"); } } - if (options.declarationMap && !ts.getEmitDeclarations(options)) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationMap", "declaration", "composite"); + if (options.declarationMap && !getEmitDeclarations(options)) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "declarationMap", "declaration", "composite"); } if (options.lib && options.noLib) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"); } - if (options.noImplicitUseStrict && ts.getStrictOptionValue(options, "alwaysStrict")) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); + if (options.noImplicitUseStrict && getStrictOptionValue(options, "alwaysStrict")) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); } - const languageVersion = ts.getEmitScriptTarget(options); + const languageVersion = getEmitScriptTarget(options); - const firstNonAmbientExternalModuleSourceFile = ts.find(files, f => ts.isExternalModule(f) && !f.isDeclarationFile); + const firstNonAmbientExternalModuleSourceFile = find(files, f => isExternalModule(f) && !f.isDeclarationFile); if (options.isolatedModules) { - if (options.module === ts.ModuleKind.None && languageVersion < ts.ScriptTarget.ES2015) { - createDiagnosticForOptionName(ts.Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); + if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES2015) { + createDiagnosticForOptionName(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher, "isolatedModules", "target"); } if (options.preserveConstEnums === false) { - createDiagnosticForOptionName(ts.Diagnostics.Option_preserveConstEnums_cannot_be_disabled_when_isolatedModules_is_enabled, "preserveConstEnums", "isolatedModules"); + createDiagnosticForOptionName(Diagnostics.Option_preserveConstEnums_cannot_be_disabled_when_isolatedModules_is_enabled, "preserveConstEnums", "isolatedModules"); } for (const file of files) { - if (!ts.isExternalModule(file) && !ts.isSourceFileJS(file) && !file.isDeclarationFile && file.scriptKind !== ts.ScriptKind.JSON) { - const span = ts.getErrorSpanForNode(file, file); - programDiagnostics.add(ts.createFileDiagnostic(file, span.start, span.length, - ts.Diagnostics._0_cannot_be_compiled_under_isolatedModules_because_it_is_considered_a_global_script_file_Add_an_import_export_or_an_empty_export_statement_to_make_it_a_module, ts.getBaseFileName(file.fileName))); + if (!isExternalModule(file) && !isSourceFileJS(file) && !file.isDeclarationFile && file.scriptKind !== ScriptKind.JSON) { + const span = getErrorSpanForNode(file, file); + programDiagnostics.add(createFileDiagnostic(file, span.start, span.length, + Diagnostics._0_cannot_be_compiled_under_isolatedModules_because_it_is_considered_a_global_script_file_Add_an_import_export_or_an_empty_export_statement_to_make_it_a_module, getBaseFileName(file.fileName))); } } } - else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ts.ScriptTarget.ES2015 && options.module === ts.ModuleKind.None) { + else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES2015 && options.module === ModuleKind.None) { // We cannot use createDiagnosticFromNode because nodes do not have parents yet - const span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); + const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); + programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none)); } // Cannot specify module gen that isn't amd or system with --out if (outputFile && !options.emitDeclarationOnly) { - if (options.module && !(options.module === ts.ModuleKind.AMD || options.module === ts.ModuleKind.System)) { - createDiagnosticForOptionName(ts.Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); + if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) { + createDiagnosticForOptionName(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile", "module"); } else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) { - const span = ts.getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); - programDiagnostics.add(ts.createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, ts.Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); + const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, typeof firstNonAmbientExternalModuleSourceFile.externalModuleIndicator === "boolean" ? firstNonAmbientExternalModuleSourceFile : firstNonAmbientExternalModuleSourceFile.externalModuleIndicator!); + programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile")); } } if (options.resolveJsonModule) { - if (ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs && - ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.Node16 && - ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeNext) { - createDiagnosticForOptionName(ts.Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule"); + if (getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeJs && + getEmitModuleResolutionKind(options) !== ModuleResolutionKind.Node16 && + getEmitModuleResolutionKind(options) !== ModuleResolutionKind.NodeNext) { + createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_without_node_module_resolution_strategy, "resolveJsonModule"); } // Any emit other than common js, amd, es2015 or esnext is error - else if (!ts.hasJsonModuleEmitEnabled(options)) { - createDiagnosticForOptionName(ts.Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_esNext, "resolveJsonModule", "module"); + else if (!hasJsonModuleEmitEnabled(options)) { + createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_esNext, "resolveJsonModule", "module"); } } @@ -3611,82 +3672,82 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP const dir = getCommonSourceDirectory(); // If we failed to find a good common directory, but outDir is specified and at least one of our files is on a windows drive/URL/other resource, add a failure - if (options.outDir && dir === "" && files.some(file => ts.getRootLength(file.fileName) > 1)) { - createDiagnosticForOptionName(ts.Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); + if (options.outDir && dir === "" && files.some(file => getRootLength(file.fileName) > 1)) { + createDiagnosticForOptionName(Diagnostics.Cannot_find_the_common_subdirectory_path_for_the_input_files, "outDir"); } } - if (options.useDefineForClassFields && languageVersion === ts.ScriptTarget.ES3) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, "useDefineForClassFields"); + if (options.useDefineForClassFields && languageVersion === ScriptTarget.ES3) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_target_is_ES3, "useDefineForClassFields"); } - if (options.checkJs && !ts.getAllowJSCompilerOption(options)) { - programDiagnostics.add(ts.createCompilerDiagnostic(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs")); + if (options.checkJs && !getAllowJSCompilerOption(options)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "checkJs", "allowJs")); } if (options.emitDeclarationOnly) { - if (!ts.getEmitDeclarations(options)) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); + if (!getEmitDeclarations(options)) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1_or_option_2, "emitDeclarationOnly", "declaration", "composite"); } if (options.noEmit) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "emitDeclarationOnly", "noEmit"); } } if (options.emitDecoratorMetadata && !options.experimentalDecorators) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"); } if (options.jsxFactory) { if (options.reactNamespace) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "reactNamespace", "jsxFactory"); } - if (options.jsx === ts.JsxEmit.ReactJSX || options.jsx === ts.JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", ts.inverseJsxOptionMap.get("" + options.jsx)); + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFactory", inverseJsxOptionMap.get("" + options.jsx)); } - if (!ts.parseIsolatedEntityName(options.jsxFactory, languageVersion)) { - createOptionValueDiagnostic("jsxFactory", ts.Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory); + if (!parseIsolatedEntityName(options.jsxFactory, languageVersion)) { + createOptionValueDiagnostic("jsxFactory", Diagnostics.Invalid_value_for_jsxFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFactory); } } - else if (options.reactNamespace && !ts.isIdentifierText(options.reactNamespace, languageVersion)) { - createOptionValueDiagnostic("reactNamespace", ts.Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace); + else if (options.reactNamespace && !isIdentifierText(options.reactNamespace, languageVersion)) { + createOptionValueDiagnostic("reactNamespace", Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace); } if (options.jsxFragmentFactory) { if (!options.jsxFactory) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory"); + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory"); } - if (options.jsx === ts.JsxEmit.ReactJSX || options.jsx === ts.JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", ts.inverseJsxOptionMap.get("" + options.jsx)); + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxFragmentFactory", inverseJsxOptionMap.get("" + options.jsx)); } - if (!ts.parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) { - createOptionValueDiagnostic("jsxFragmentFactory", ts.Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory); + if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) { + createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory); } } if (options.reactNamespace) { - if (options.jsx === ts.JsxEmit.ReactJSX || options.jsx === ts.JsxEmit.ReactJSXDev) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", ts.inverseJsxOptionMap.get("" + options.jsx)); + if (options.jsx === JsxEmit.ReactJSX || options.jsx === JsxEmit.ReactJSXDev) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "reactNamespace", inverseJsxOptionMap.get("" + options.jsx)); } } if (options.jsxImportSource) { - if (options.jsx === ts.JsxEmit.React) { - createDiagnosticForOptionName(ts.Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", ts.inverseJsxOptionMap.get("" + options.jsx)); + if (options.jsx === JsxEmit.React) { + createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_when_option_jsx_is_1, "jsxImportSource", inverseJsxOptionMap.get("" + options.jsx)); } } - if (options.preserveValueImports && ts.getEmitModuleKind(options) < ts.ModuleKind.ES2015) { - createOptionValueDiagnostic("importsNotUsedAsValues", ts.Diagnostics.Option_preserveValueImports_can_only_be_used_when_module_is_set_to_es2015_or_later); + if (options.preserveValueImports && getEmitModuleKind(options) < ModuleKind.ES2015) { + createOptionValueDiagnostic("importsNotUsedAsValues", Diagnostics.Option_preserveValueImports_can_only_be_used_when_module_is_set_to_es2015_or_later); } // If the emit is enabled make sure that every output file is unique and not overwriting any of the input files if (!options.noEmit && !options.suppressOutputPathCheck) { const emitHost = getEmitHost(); - const emitFilesSeen = new ts.Set(); - ts.forEachEmittedFile(emitHost, (emitFileNames) => { + const emitFilesSeen = new Set(); + forEachEmittedFile(emitHost, (emitFileNames) => { if (!options.emitDeclarationOnly) { verifyEmitFilePath(emitFileNames.jsFilePath, emitFilesSeen); } @@ -3695,25 +3756,25 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } // Verify that all the emit files are unique and don't overwrite input files - function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: ts.Set) { + function verifyEmitFilePath(emitFileName: string | undefined, emitFilesSeen: Set) { if (emitFileName) { const emitFilePath = toPath(emitFileName); // Report error if the output overwrites input file if (filesByName.has(emitFilePath)) { - let chain: ts.DiagnosticMessageChain | undefined; + let chain: DiagnosticMessageChain | undefined; if (!options.configFilePath) { // The program is from either an inferred project or an external project - chain = ts.chainDiagnosticMessages(/*details*/ undefined, ts.Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); + chain = chainDiagnosticMessages(/*details*/ undefined, Diagnostics.Adding_a_tsconfig_json_file_will_help_organize_projects_that_contain_both_TypeScript_and_JavaScript_files_Learn_more_at_https_Colon_Slash_Slashaka_ms_Slashtsconfig); } - chain = ts.chainDiagnosticMessages(chain, ts.Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); - blockEmittingOfFile(emitFileName, ts.createCompilerDiagnosticFromMessageChain(chain)); + chain = chainDiagnosticMessages(chain, Diagnostics.Cannot_write_file_0_because_it_would_overwrite_input_file, emitFileName); + blockEmittingOfFile(emitFileName, createCompilerDiagnosticFromMessageChain(chain)); } - const emitFileKey = !host.useCaseSensitiveFileNames() ? ts.toFileNameLowerCase(emitFilePath) : emitFilePath; + const emitFileKey = !host.useCaseSensitiveFileNames() ? toFileNameLowerCase(emitFilePath) : emitFilePath; // Report error if multiple files write into same file if (emitFilesSeen.has(emitFileKey)) { // Already seen the same emit file - report error - blockEmittingOfFile(emitFileName, ts.createCompilerDiagnostic(ts.Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); + blockEmittingOfFile(emitFileName, createCompilerDiagnostic(Diagnostics.Cannot_write_file_0_because_it_would_be_overwritten_by_multiple_input_files, emitFileName)); } else { emitFilesSeen.add(emitFileKey); @@ -3722,39 +3783,39 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } - function createDiagnosticExplainingFile(file: ts.SourceFile | undefined, fileProcessingReason: ts.FileIncludeReason | undefined, diagnostic: ts.DiagnosticMessage, args: (string | number | undefined)[] | undefined): ts.Diagnostic { - let fileIncludeReasons: ts.DiagnosticMessageChain[] | undefined; - let relatedInfo: ts.Diagnostic[] | undefined; + function createDiagnosticExplainingFile(file: SourceFile | undefined, fileProcessingReason: FileIncludeReason | undefined, diagnostic: DiagnosticMessage, args: (string | number | undefined)[] | undefined): Diagnostic { + let fileIncludeReasons: DiagnosticMessageChain[] | undefined; + let relatedInfo: Diagnostic[] | undefined; let locationReason = isReferencedFile(fileProcessingReason) ? fileProcessingReason : undefined; if (file) fileReasons.get(file.path)?.forEach(processReason); if (fileProcessingReason) processReason(fileProcessingReason); // If we have location and there is only one reason file is in which is the location, dont add details for file include if (locationReason && fileIncludeReasons?.length === 1) fileIncludeReasons = undefined; const location = locationReason && getReferencedFileLocation(getSourceFileByPath, locationReason); - const fileIncludeReasonDetails = fileIncludeReasons && ts.chainDiagnosticMessages(fileIncludeReasons, ts.Diagnostics.The_file_is_in_the_program_because_Colon); - const redirectInfo = file && ts.explainIfFileIsRedirectAndImpliedFormat(file); - const chain = ts.chainDiagnosticMessages(redirectInfo ? fileIncludeReasonDetails ? [fileIncludeReasonDetails, ...redirectInfo] : redirectInfo : fileIncludeReasonDetails, diagnostic, ...args || ts.emptyArray); + const fileIncludeReasonDetails = fileIncludeReasons && chainDiagnosticMessages(fileIncludeReasons, Diagnostics.The_file_is_in_the_program_because_Colon); + const redirectInfo = file && explainIfFileIsRedirectAndImpliedFormat(file); + const chain = chainDiagnosticMessages(redirectInfo ? fileIncludeReasonDetails ? [fileIncludeReasonDetails, ...redirectInfo] : redirectInfo : fileIncludeReasonDetails, diagnostic, ...args || emptyArray); return location && isReferenceFileLocation(location) ? - ts.createFileDiagnosticFromMessageChain(location.file, location.pos, location.end - location.pos, chain, relatedInfo) : - ts.createCompilerDiagnosticFromMessageChain(chain, relatedInfo); + createFileDiagnosticFromMessageChain(location.file, location.pos, location.end - location.pos, chain, relatedInfo) : + createCompilerDiagnosticFromMessageChain(chain, relatedInfo); - function processReason(reason: ts.FileIncludeReason) { - (fileIncludeReasons ||= []).push(ts.fileIncludeReasonToDiagnostics(program, reason)); + function processReason(reason: FileIncludeReason) { + (fileIncludeReasons ||= []).push(fileIncludeReasonToDiagnostics(program, reason)); if (!locationReason && isReferencedFile(reason)) { // Report error at first reference file or file currently in processing and dont report in related information locationReason = reason; } else if (locationReason !== reason) { - relatedInfo = ts.append(relatedInfo, fileIncludeReasonToRelatedInformation(reason)); + relatedInfo = append(relatedInfo, fileIncludeReasonToRelatedInformation(reason)); } // Remove fileProcessingReason if its already included in fileReasons of the program if (reason === fileProcessingReason) fileProcessingReason = undefined; } } - function addFilePreprocessingFileExplainingDiagnostic(file: ts.SourceFile | undefined, fileProcessingReason: ts.FileIncludeReason, diagnostic: ts.DiagnosticMessage, args?: (string | number | undefined)[]) { + function addFilePreprocessingFileExplainingDiagnostic(file: SourceFile | undefined, fileProcessingReason: FileIncludeReason, diagnostic: DiagnosticMessage, args?: (string | number | undefined)[]) { (fileProcessingDiagnostics ||= []).push({ - kind: ts.FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic, + kind: FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic, file: file && file.path, fileProcessingReason, diagnostic, @@ -3762,31 +3823,31 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP }); } - function addProgramDiagnosticExplainingFile(file: ts.SourceFile, diagnostic: ts.DiagnosticMessage, args?: (string | number | undefined)[]) { + function addProgramDiagnosticExplainingFile(file: SourceFile, diagnostic: DiagnosticMessage, args?: (string | number | undefined)[]) { programDiagnostics.add(createDiagnosticExplainingFile(file, /*fileProcessingReason*/ undefined, diagnostic, args)); } - function fileIncludeReasonToRelatedInformation(reason: ts.FileIncludeReason): ts.DiagnosticWithLocation | undefined { + function fileIncludeReasonToRelatedInformation(reason: FileIncludeReason): DiagnosticWithLocation | undefined { if (isReferencedFile(reason)) { const referenceLocation = getReferencedFileLocation(getSourceFileByPath, reason); - let message: ts.DiagnosticMessage; + let message: DiagnosticMessage; switch (reason.kind) { - case ts.FileIncludeKind.Import: - message = ts.Diagnostics.File_is_included_via_import_here; + case FileIncludeKind.Import: + message = Diagnostics.File_is_included_via_import_here; break; - case ts.FileIncludeKind.ReferenceFile: - message = ts.Diagnostics.File_is_included_via_reference_here; + case FileIncludeKind.ReferenceFile: + message = Diagnostics.File_is_included_via_reference_here; break; - case ts.FileIncludeKind.TypeReferenceDirective: - message = ts.Diagnostics.File_is_included_via_type_library_reference_here; + case FileIncludeKind.TypeReferenceDirective: + message = Diagnostics.File_is_included_via_type_library_reference_here; break; - case ts.FileIncludeKind.LibReferenceDirective: - message = ts.Diagnostics.File_is_included_via_library_reference_here; + case FileIncludeKind.LibReferenceDirective: + message = Diagnostics.File_is_included_via_library_reference_here; break; default: - ts.Debug.assertNever(reason); + Debug.assertNever(reason); } - return isReferenceFileLocation(referenceLocation) ? ts.createFileDiagnostic( + return isReferenceFileLocation(referenceLocation) ? createFileDiagnostic( referenceLocation.file, referenceLocation.pos, referenceLocation.end - referenceLocation.pos, @@ -3795,62 +3856,62 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } if (!options.configFile) return undefined; - let configFileNode: ts.Node | undefined; - let message: ts.DiagnosticMessage; + let configFileNode: Node | undefined; + let message: DiagnosticMessage; switch (reason.kind) { - case ts.FileIncludeKind.RootFile: + case FileIncludeKind.RootFile: if (!options.configFile.configFileSpecs) return undefined; - const fileName = ts.getNormalizedAbsolutePath(rootNames[reason.index], currentDirectory); - const matchedByFiles = ts.getMatchedFileSpec(program, fileName); + const fileName = getNormalizedAbsolutePath(rootNames[reason.index], currentDirectory); + const matchedByFiles = getMatchedFileSpec(program, fileName); if (matchedByFiles) { - configFileNode = ts.getTsConfigPropArrayElementValue(options.configFile, "files", matchedByFiles); - message = ts.Diagnostics.File_is_matched_by_files_list_specified_here; + configFileNode = getTsConfigPropArrayElementValue(options.configFile, "files", matchedByFiles); + message = Diagnostics.File_is_matched_by_files_list_specified_here; break; } - const matchedByInclude = ts.getMatchedIncludeSpec(program, fileName); + const matchedByInclude = getMatchedIncludeSpec(program, fileName); // Could be additional files specified as roots - if (!matchedByInclude || !ts.isString(matchedByInclude)) return undefined; - configFileNode = ts.getTsConfigPropArrayElementValue(options.configFile, "include", matchedByInclude); - message = ts.Diagnostics.File_is_matched_by_include_pattern_specified_here; + if (!matchedByInclude || !isString(matchedByInclude)) return undefined; + configFileNode = getTsConfigPropArrayElementValue(options.configFile, "include", matchedByInclude); + message = Diagnostics.File_is_matched_by_include_pattern_specified_here; break; - case ts.FileIncludeKind.SourceFromProjectReference: - case ts.FileIncludeKind.OutputFromProjectReference: - const referencedResolvedRef = ts.Debug.checkDefined(resolvedProjectReferences?.[reason.index]); + case FileIncludeKind.SourceFromProjectReference: + case FileIncludeKind.OutputFromProjectReference: + const referencedResolvedRef = Debug.checkDefined(resolvedProjectReferences?.[reason.index]); const referenceInfo = forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, parent, index) => resolvedRef === referencedResolvedRef ? { sourceFile: parent?.sourceFile || options.configFile!, index } : undefined ); if (!referenceInfo) return undefined; const { sourceFile, index } = referenceInfo; - const referencesSyntax = ts.firstDefined(ts.getTsConfigPropArray(sourceFile as ts.TsConfigSourceFile, "references"), - property => ts.isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); + const referencesSyntax = firstDefined(getTsConfigPropArray(sourceFile as TsConfigSourceFile, "references"), + property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); return referencesSyntax && referencesSyntax.elements.length > index ? - ts.createDiagnosticForNodeInSourceFile( + createDiagnosticForNodeInSourceFile( sourceFile, referencesSyntax.elements[index], - reason.kind === ts.FileIncludeKind.OutputFromProjectReference ? - ts.Diagnostics.File_is_output_from_referenced_project_specified_here : - ts.Diagnostics.File_is_source_from_referenced_project_specified_here, + reason.kind === FileIncludeKind.OutputFromProjectReference ? + Diagnostics.File_is_output_from_referenced_project_specified_here : + Diagnostics.File_is_source_from_referenced_project_specified_here, ) : undefined; - case ts.FileIncludeKind.AutomaticTypeDirectiveFile: + case FileIncludeKind.AutomaticTypeDirectiveFile: if (!options.types) return undefined; configFileNode = getOptionsSyntaxByArrayElementValue("types", reason.typeReference); - message = ts.Diagnostics.File_is_entry_point_of_type_library_specified_here; + message = Diagnostics.File_is_entry_point_of_type_library_specified_here; break; - case ts.FileIncludeKind.LibFile: + case FileIncludeKind.LibFile: if (reason.index !== undefined) { configFileNode = getOptionsSyntaxByArrayElementValue("lib", options.lib![reason.index]); - message = ts.Diagnostics.File_is_library_specified_here; + message = Diagnostics.File_is_library_specified_here; break; } - const target = ts.forEachEntry(ts.targetOptionDeclaration.type, (value, key) => value === ts.getEmitScriptTarget(options) ? key : undefined); + const target = forEachEntry(targetOptionDeclaration.type, (value, key) => value === getEmitScriptTarget(options) ? key : undefined); configFileNode = target ? getOptionsSyntaxByValue("target", target) : undefined; - message = ts.Diagnostics.File_is_default_library_for_target_specified_here; + message = Diagnostics.File_is_default_library_for_target_specified_here; break; default: - ts.Debug.assertNever(reason); + Debug.assertNever(reason); } - return configFileNode && ts.createDiagnosticForNodeInSourceFile( + return configFileNode && createDiagnosticForNodeInSourceFile( options.configFile, configFileNode, message, @@ -3858,12 +3919,12 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } function verifyProjectReferences() { - const buildInfoPath = !options.suppressOutputPathCheck ? ts.getTsBuildInfoEmitOutputFilePath(options) : undefined; + const buildInfoPath = !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined; forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, parent, index) => { const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index]; - const parentFile = parent && parent.sourceFile as ts.JsonSourceFile; + const parentFile = parent && parent.sourceFile as JsonSourceFile; if (!resolvedRef) { - createDiagnosticForReference(parentFile, index, ts.Diagnostics.File_0_not_found, ref.path); + createDiagnosticForReference(parentFile, index, Diagnostics.File_0_not_found, ref.path); return; } const options = resolvedRef.commandLine.options; @@ -3871,37 +3932,37 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP // ok to not have composite if the current program is container only const inputs = parent ? parent.commandLine.fileNames : rootNames; if (inputs.length) { - if (!options.composite) createDiagnosticForReference(parentFile, index, ts.Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path); - if (options.noEmit) createDiagnosticForReference(parentFile, index, ts.Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path); + if (!options.composite) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path); + if (options.noEmit) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path); } } if (ref.prepend) { - const out = ts.outFile(options); + const out = outFile(options); if (out) { if (!host.fileExists(out)) { - createDiagnosticForReference(parentFile, index, ts.Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path); + createDiagnosticForReference(parentFile, index, Diagnostics.Output_file_0_from_project_1_does_not_exist, out, ref.path); } } else { - createDiagnosticForReference(parentFile, index, ts.Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path); + createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_prepend_project_0_because_it_does_not_have_outFile_set, ref.path); } } - if (!parent && buildInfoPath && buildInfoPath === ts.getTsBuildInfoEmitOutputFilePath(options)) { - createDiagnosticForReference(parentFile, index, ts.Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path); + if (!parent && buildInfoPath && buildInfoPath === getTsBuildInfoEmitOutputFilePath(options)) { + createDiagnosticForReference(parentFile, index, Diagnostics.Cannot_write_file_0_because_it_will_overwrite_tsbuildinfo_file_generated_by_referenced_project_1, buildInfoPath, ref.path); hasEmitBlockingDiagnostics.set(toPath(buildInfoPath), true); } }); } - function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number) { + function createDiagnosticForOptionPathKeyValue(key: string, valueIndex: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number) { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { - if (ts.isObjectLiteralExpression(pathProp.initializer)) { - for (const keyProps of ts.getPropertyAssignment(pathProp.initializer, key)) { + if (isObjectLiteralExpression(pathProp.initializer)) { + for (const keyProps of getPropertyAssignment(pathProp.initializer, key)) { const initializer = keyProps.initializer; - if (ts.isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) { - programDiagnostics.add(ts.createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, arg0, arg1, arg2)); + if (isArrayLiteralExpression(initializer) && initializer.elements.length > valueIndex) { + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, initializer.elements[valueIndex], message, arg0, arg1, arg2)); needCompilerDiagnostic = false; } } @@ -3909,15 +3970,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } if (needCompilerDiagnostic) { - programDiagnostics.add(ts.createCompilerDiagnostic(message, arg0, arg1, arg2)); + programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1, arg2)); } } - function createDiagnosticForOptionPaths(onKey: boolean, key: string, message: ts.DiagnosticMessage, arg0: string | number) { + function createDiagnosticForOptionPaths(onKey: boolean, key: string, message: DiagnosticMessage, arg0: string | number) { let needCompilerDiagnostic = true; const pathsSyntax = getOptionPathsSyntax(); for (const pathProp of pathsSyntax) { - if (ts.isObjectLiteralExpression(pathProp.initializer) && + if (isObjectLiteralExpression(pathProp.initializer) && createOptionDiagnosticInObjectLiteralSyntax( pathProp.initializer, onKey, key, /*key2*/ undefined, message, arg0)) { @@ -3925,65 +3986,65 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } } if (needCompilerDiagnostic) { - programDiagnostics.add(ts.createCompilerDiagnostic(message, arg0)); + programDiagnostics.add(createCompilerDiagnostic(message, arg0)); } } function getOptionsSyntaxByName(name: string) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); - return compilerOptionsObjectLiteralSyntax && ts.getPropertyAssignment(compilerOptionsObjectLiteralSyntax, name); + return compilerOptionsObjectLiteralSyntax && getPropertyAssignment(compilerOptionsObjectLiteralSyntax, name); } function getOptionPathsSyntax() { - return getOptionsSyntaxByName("paths") || ts.emptyArray; + return getOptionsSyntaxByName("paths") || emptyArray; } function getOptionsSyntaxByValue(name: string, value: string) { const syntaxByName = getOptionsSyntaxByName(name); - return syntaxByName && ts.firstDefined(syntaxByName, property => ts.isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer : undefined); + return syntaxByName && firstDefined(syntaxByName, property => isStringLiteral(property.initializer) && property.initializer.text === value ? property.initializer : undefined); } function getOptionsSyntaxByArrayElementValue(name: string, value: string) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); - return compilerOptionsObjectLiteralSyntax && ts.getPropertyArrayElementValue(compilerOptionsObjectLiteralSyntax, name, value); + return compilerOptionsObjectLiteralSyntax && getPropertyArrayElementValue(compilerOptionsObjectLiteralSyntax, name, value); } - function createDiagnosticForOptionName(message: ts.DiagnosticMessage, option1: string, option2?: string, option3?: string) { + function createDiagnosticForOptionName(message: DiagnosticMessage, option1: string, option2?: string, option3?: string) { createDiagnosticForOption(/*onKey*/ true, option1, option2, message, option1, option2, option3); } - function createOptionValueDiagnostic(option1: string, message: ts.DiagnosticMessage, arg0?: string, arg1?: string) { + function createOptionValueDiagnostic(option1: string, message: DiagnosticMessage, arg0?: string, arg1?: string) { createDiagnosticForOption(/*onKey*/ false, option1, /*option2*/ undefined, message, arg0, arg1); } - function createDiagnosticForReference(sourceFile: ts.JsonSourceFile | undefined, index: number, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number) { - const referencesSyntax = ts.firstDefined(ts.getTsConfigPropArray(sourceFile || options.configFile, "references"), - property => ts.isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); + function createDiagnosticForReference(sourceFile: JsonSourceFile | undefined, index: number, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number) { + const referencesSyntax = firstDefined(getTsConfigPropArray(sourceFile || options.configFile, "references"), + property => isArrayLiteralExpression(property.initializer) ? property.initializer : undefined); if (referencesSyntax && referencesSyntax.elements.length > index) { - programDiagnostics.add(ts.createDiagnosticForNodeInSourceFile(sourceFile || options.configFile!, referencesSyntax.elements[index], message, arg0, arg1)); + programDiagnostics.add(createDiagnosticForNodeInSourceFile(sourceFile || options.configFile!, referencesSyntax.elements[index], message, arg0, arg1)); } else { - programDiagnostics.add(ts.createCompilerDiagnostic(message, arg0, arg1)); + programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1)); } } - function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number) { + function createDiagnosticForOption(onKey: boolean, option1: string, option2: string | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number) { const compilerOptionsObjectLiteralSyntax = getCompilerOptionsObjectLiteralSyntax(); const needCompilerDiagnostic = !compilerOptionsObjectLiteralSyntax || !createOptionDiagnosticInObjectLiteralSyntax(compilerOptionsObjectLiteralSyntax, onKey, option1, option2, message, arg0, arg1, arg2); if (needCompilerDiagnostic) { - programDiagnostics.add(ts.createCompilerDiagnostic(message, arg0, arg1, arg2)); + programDiagnostics.add(createCompilerDiagnostic(message, arg0, arg1, arg2)); } } function getCompilerOptionsObjectLiteralSyntax() { if (_compilerOptionsObjectLiteralSyntax === undefined) { _compilerOptionsObjectLiteralSyntax = false; - const jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(options.configFile); + const jsonObjectLiteral = getTsConfigObjectLiteralExpression(options.configFile); if (jsonObjectLiteral) { - for (const prop of ts.getPropertyAssignment(jsonObjectLiteral, "compilerOptions")) { - if (ts.isObjectLiteralExpression(prop.initializer)) { + for (const prop of getPropertyAssignment(jsonObjectLiteral, "compilerOptions")) { + if (isObjectLiteralExpression(prop.initializer)) { _compilerOptionsObjectLiteralSyntax = prop.initializer; break; } @@ -3993,15 +4054,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP return _compilerOptionsObjectLiteralSyntax || undefined; } - function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ts.ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: ts.DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): boolean { - const props = ts.getPropertyAssignment(objectLiteral, key1, key2); + function createOptionDiagnosticInObjectLiteralSyntax(objectLiteral: ObjectLiteralExpression, onKey: boolean, key1: string, key2: string | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): boolean { + const props = getPropertyAssignment(objectLiteral, key1, key2); for (const prop of props) { - programDiagnostics.add(ts.createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2)); + programDiagnostics.add(createDiagnosticForNodeInSourceFile(options.configFile!, onKey ? prop.name : prop.initializer, message, arg0, arg1, arg2)); } return !!props.length; } - function blockEmittingOfFile(emitFileName: string, diag: ts.Diagnostic) { + function blockEmittingOfFile(emitFileName: string, diag: Diagnostic) { hasEmitBlockingDiagnostics.set(toPath(emitFileName), true); programDiagnostics.add(diag); } @@ -4018,40 +4079,40 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } // If options have --outFile or --out just check that - const out = ts.outFile(options); + const out = outFile(options); if (out) { - return isSameFile(filePath, out) || isSameFile(filePath, ts.removeFileExtension(out) + ts.Extension.Dts); + return isSameFile(filePath, out) || isSameFile(filePath, removeFileExtension(out) + Extension.Dts); } // If declarationDir is specified, return if its a file in that directory - if (options.declarationDir && ts.containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames())) { + if (options.declarationDir && containsPath(options.declarationDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames())) { return true; } // If --outDir, check if file is in that directory if (options.outDir) { - return ts.containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); + return containsPath(options.outDir, filePath, currentDirectory, !host.useCaseSensitiveFileNames()); } - if (ts.fileExtensionIsOneOf(filePath, ts.supportedJSExtensionsFlat) || ts.isDeclarationFileName(filePath)) { + if (fileExtensionIsOneOf(filePath, supportedJSExtensionsFlat) || isDeclarationFileName(filePath)) { // Otherwise just check if sourceFile with the name exists - const filePathWithoutExtension = ts.removeFileExtension(filePath); - return !!getSourceFileByPath((filePathWithoutExtension + ts.Extension.Ts) as ts.Path) || - !!getSourceFileByPath((filePathWithoutExtension + ts.Extension.Tsx) as ts.Path); + const filePathWithoutExtension = removeFileExtension(filePath); + return !!getSourceFileByPath((filePathWithoutExtension + Extension.Ts) as Path) || + !!getSourceFileByPath((filePathWithoutExtension + Extension.Tsx) as Path); } return false; } function isSameFile(file1: string, file2: string) { - return ts.comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === ts.Comparison.EqualTo; + return comparePaths(file1, file2, currentDirectory, !host.useCaseSensitiveFileNames()) === Comparison.EqualTo; } - function getSymlinkCache(): ts.SymlinkCache { + function getSymlinkCache(): SymlinkCache { if (host.getSymlinkCache) { return host.getSymlinkCache(); } if (!symlinks) { - symlinks = ts.createSymlinkCache(currentDirectory, getCanonicalFileName); + symlinks = createSymlinkCache(currentDirectory, getCanonicalFileName); } if (files && resolvedTypeReferenceDirectives && !symlinks.hasProcessedResolutions()) { symlinks.setSymlinksFromResolutions(files, resolvedTypeReferenceDirectives); @@ -4061,23 +4122,23 @@ export function createProgram(rootNamesOrOptions: readonly string[] | ts.CreateP } interface HostForUseSourceOfProjectReferenceRedirect { - compilerHost: ts.CompilerHost; - getSymlinkCache: () => ts.SymlinkCache; + compilerHost: CompilerHost; + getSymlinkCache: () => SymlinkCache; useSourceOfProjectReferenceRedirect: boolean; - toPath(fileName: string): ts.Path; - getResolvedProjectReferences(): readonly (ts.ResolvedProjectReference | undefined)[] | undefined; - getSourceOfProjectReferenceRedirect(path: ts.Path): ts.SourceOfProjectReferenceRedirect | undefined; - forEachResolvedProjectReference(cb: (resolvedProjectReference: ts.ResolvedProjectReference) => T | undefined): T | undefined; + toPath(fileName: string): Path; + getResolvedProjectReferences(): readonly (ResolvedProjectReference | undefined)[] | undefined; + getSourceOfProjectReferenceRedirect(path: Path): SourceOfProjectReferenceRedirect | undefined; + forEachResolvedProjectReference(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined; } function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSourceOfProjectReferenceRedirect) { - let setOfDeclarationDirectories: ts.Set | undefined; + let setOfDeclarationDirectories: Set | undefined; const originalFileExists = host.compilerHost.fileExists; const originalDirectoryExists = host.compilerHost.directoryExists; const originalGetDirectories = host.compilerHost.getDirectories; const originalRealpath = host.compilerHost.realpath; - if (!host.useSourceOfProjectReferenceRedirect) return { onProgramCreateComplete: ts.noop, fileExists }; + if (!host.useSourceOfProjectReferenceRedirect) return { onProgramCreateComplete: noop, fileExists }; host.compilerHost.fileExists = fileExists; @@ -4095,11 +4156,11 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource if (!host.getResolvedProjectReferences()) return false; if (!setOfDeclarationDirectories) { - setOfDeclarationDirectories = new ts.Set(); + setOfDeclarationDirectories = new Set(); host.forEachResolvedProjectReference(ref => { - const out = ts.outFile(ref.commandLine.options); + const out = outFile(ref.commandLine.options); if (out) { - setOfDeclarationDirectories!.add(ts.getDirectoryPath(host.toPath(out))); + setOfDeclarationDirectories!.add(getDirectoryPath(host.toPath(out))); } else { // Set declaration's in different locations only, if they are next to source the directory present doesnt change @@ -4146,7 +4207,7 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource function fileExists(file: string) { if (originalFileExists.call(host.compilerHost, file)) return true; if (!host.getResolvedProjectReferences()) return false; - if (!ts.isDeclarationFileName(file)) return false; + if (!isDeclarationFileName(file)) return false; // Project references go to source file instead of .d.ts file return fileOrDirectoryExistsUsingSource(file, /*isFile*/ true); @@ -4155,43 +4216,43 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource function fileExistsIfProjectReferenceDts(file: string) { const source = host.getSourceOfProjectReferenceRedirect(host.toPath(file)); return source !== undefined ? - ts.isString(source) ? originalFileExists.call(host.compilerHost, source) as boolean : true : + isString(source) ? originalFileExists.call(host.compilerHost, source) as boolean : true : undefined; } function directoryExistsIfProjectReferenceDeclDir(dir: string) { const dirPath = host.toPath(dir); - const dirPathWithTrailingDirectorySeparator = `${dirPath}${ts.directorySeparator}`; - return ts.forEachKey( + const dirPathWithTrailingDirectorySeparator = `${dirPath}${directorySeparator}`; + return forEachKey( setOfDeclarationDirectories!, declDirPath => dirPath === declDirPath || // Any parent directory of declaration dir - ts.startsWith(declDirPath, dirPathWithTrailingDirectorySeparator) || + startsWith(declDirPath, dirPathWithTrailingDirectorySeparator) || // Any directory inside declaration dir - ts.startsWith(dirPath, `${declDirPath}/`) + startsWith(dirPath, `${declDirPath}/`) ); } function handleDirectoryCouldBeSymlink(directory: string) { - if (!host.getResolvedProjectReferences() || ts.containsIgnoredPath(directory)) return; + if (!host.getResolvedProjectReferences() || containsIgnoredPath(directory)) return; // Because we already watch node_modules, handle symlinks in there - if (!originalRealpath || !ts.stringContains(directory, ts.nodeModulesPathPart)) return; + if (!originalRealpath || !stringContains(directory, nodeModulesPathPart)) return; const symlinkCache = host.getSymlinkCache(); - const directoryPath = ts.ensureTrailingDirectorySeparator(host.toPath(directory)); + const directoryPath = ensureTrailingDirectorySeparator(host.toPath(directory)); if (symlinkCache.getSymlinkedDirectories()?.has(directoryPath)) return; - const real = ts.normalizePath(originalRealpath.call(host.compilerHost, directory)); - let realPath: ts.Path; + const real = normalizePath(originalRealpath.call(host.compilerHost, directory)); + let realPath: Path; if (real === directory || - (realPath = ts.ensureTrailingDirectorySeparator(host.toPath(real))) === directoryPath) { + (realPath = ensureTrailingDirectorySeparator(host.toPath(real))) === directoryPath) { // not symlinked symlinkCache.setSymlinkedDirectory(directoryPath, false); return; } symlinkCache.setSymlinkedDirectory(directory, { - real: ts.ensureTrailingDirectorySeparator(real), + real: ensureTrailingDirectorySeparator(real), realPath }); } @@ -4208,18 +4269,18 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource const symlinkedDirectories = symlinkCache.getSymlinkedDirectories(); if (!symlinkedDirectories) return false; const fileOrDirectoryPath = host.toPath(fileOrDirectory); - if (!ts.stringContains(fileOrDirectoryPath, ts.nodeModulesPathPart)) return false; + if (!stringContains(fileOrDirectoryPath, nodeModulesPathPart)) return false; if (isFile && symlinkCache.getSymlinkedFiles()?.has(fileOrDirectoryPath)) return true; // If it contains node_modules check if its one of the symlinked path we know of - return ts.firstDefinedIterator( + return firstDefinedIterator( symlinkedDirectories.entries(), ([directoryPath, symlinkedDirectory]) => { - if (!symlinkedDirectory || !ts.startsWith(fileOrDirectoryPath, directoryPath)) return undefined; + if (!symlinkedDirectory || !startsWith(fileOrDirectoryPath, directoryPath)) return undefined; const result = fileOrDirectoryExistsUsingSource(fileOrDirectoryPath.replace(directoryPath, symlinkedDirectory.realPath)); if (isFile && result) { // Store the real path for the file' - const absolutePath = ts.getNormalizedAbsolutePath(fileOrDirectory, host.compilerHost.getCurrentDirectory()); + const absolutePath = getNormalizedAbsolutePath(fileOrDirectory, host.compilerHost.getCurrentDirectory()); symlinkCache.setSymlinkedFile( fileOrDirectoryPath, `${symlinkedDirectory.real}${absolutePath.replace(new RegExp(directoryPath, "i"), "")}` @@ -4232,20 +4293,20 @@ function updateHostForUseSourceOfProjectReferenceRedirect(host: HostForUseSource } /*@internal*/ -export const emitSkippedWithNoDiagnostics: ts.EmitResult = { diagnostics: ts.emptyArray, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; +export const emitSkippedWithNoDiagnostics: EmitResult = { diagnostics: emptyArray, sourceMaps: undefined, emittedFiles: undefined, emitSkipped: true }; /*@internal*/ -export function handleNoEmitOptions( - program: ts.Program | T, - sourceFile: ts.SourceFile | undefined, - writeFile: ts.WriteFileCallback | undefined, - cancellationToken: ts.CancellationToken | undefined -): ts.EmitResult | undefined { +export function handleNoEmitOptions( + program: Program | T, + sourceFile: SourceFile | undefined, + writeFile: WriteFileCallback | undefined, + cancellationToken: CancellationToken | undefined +): EmitResult | undefined { const options = program.getCompilerOptions(); if (options.noEmit) { // Cache the semantic diagnostics program.getSemanticDiagnostics(sourceFile, cancellationToken); - return sourceFile || ts.outFile(options) ? + return sourceFile || outFile(options) ? emitSkippedWithNoDiagnostics : program.emitBuildInfo(writeFile, cancellationToken); } @@ -4254,20 +4315,20 @@ export function handleNoEmitOptions( // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we // get any preEmit diagnostics, not just the ones if (!options.noEmitOnError) return undefined; - let diagnostics: readonly ts.Diagnostic[] = [ + let diagnostics: readonly Diagnostic[] = [ ...program.getOptionsDiagnostics(cancellationToken), ...program.getSyntacticDiagnostics(sourceFile, cancellationToken), ...program.getGlobalDiagnostics(cancellationToken), ...program.getSemanticDiagnostics(sourceFile, cancellationToken) ]; - if (diagnostics.length === 0 && ts.getEmitDeclarations(program.getCompilerOptions())) { + if (diagnostics.length === 0 && getEmitDeclarations(program.getCompilerOptions())) { diagnostics = program.getDeclarationDiagnostics(/*sourceFile*/ undefined, cancellationToken); } if (!diagnostics.length) return undefined; let emittedFiles: string[] | undefined; - if (!sourceFile && !ts.outFile(options)) { + if (!sourceFile && !outFile(options)) { const emitResult = program.emitBuildInfo(writeFile, cancellationToken); if (emitResult.diagnostics) diagnostics = [...diagnostics, ...emitResult.diagnostics]; emittedFiles = emitResult.emittedFiles; @@ -4276,8 +4337,8 @@ export function handleNoEmitOptions( } /*@internal*/ -export function filterSemanticDiagnostics(diagnostic: readonly ts.Diagnostic[], option: ts.CompilerOptions): readonly ts.Diagnostic[] { - return ts.filter(diagnostic, d => !d.skippedOn || !option[d.skippedOn]); +export function filterSemanticDiagnostics(diagnostic: readonly Diagnostic[], option: CompilerOptions): readonly Diagnostic[] { + return filter(diagnostic, d => !d.skippedOn || !option[d.skippedOn]); } /*@internal*/ @@ -4288,21 +4349,21 @@ interface CompilerHostLike { readFile(fileName: string): string | undefined; readDirectory?(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[], depth?: number): string[]; trace?(s: string): void; - onUnRecoverableConfigFileDiagnostic?: ts.DiagnosticReporter; + onUnRecoverableConfigFileDiagnostic?: DiagnosticReporter; } /* @internal */ -export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, directoryStructureHost: ts.DirectoryStructureHost = host): ts.ParseConfigFileHost { +export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, directoryStructureHost: DirectoryStructureHost = host): ParseConfigFileHost { return { fileExists: f => directoryStructureHost.fileExists(f), readDirectory(root, extensions, excludes, includes, depth) { - ts.Debug.assertIsDefined(directoryStructureHost.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + Debug.assertIsDefined(directoryStructureHost.readDirectory, "'CompilerHost.readDirectory' must be implemented to correctly process 'projectReferences'"); return directoryStructureHost.readDirectory(root, extensions, excludes, includes, depth); }, readFile: f => directoryStructureHost.readFile(f), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(), getCurrentDirectory: () => host.getCurrentDirectory(), - onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic || ts.returnUndefined, + onUnRecoverableConfigFileDiagnostic: host.onUnRecoverableConfigFileDiagnostic || returnUndefined, trace: host.trace ? (s) => host.trace!(s) : undefined }; } @@ -4314,37 +4375,37 @@ export function parseConfigHostFromCompilerHostLike(host: CompilerHostLike, dire /* @internal */ export function createPrependNodes( - projectReferences: readonly ts.ProjectReference[] | undefined, - getCommandLine: (ref: ts.ProjectReference, index: number) => ts.ParsedCommandLine | undefined, + projectReferences: readonly ProjectReference[] | undefined, + getCommandLine: (ref: ProjectReference, index: number) => ParsedCommandLine | undefined, readFile: (path: string) => string | undefined, - host: ts.CompilerHost, + host: CompilerHost, ) { - if (!projectReferences) return ts.emptyArray; - let nodes: ts.InputFiles[] | undefined; + if (!projectReferences) return emptyArray; + let nodes: InputFiles[] | undefined; for (let i = 0; i < projectReferences.length; i++) { const ref = projectReferences[i]; const resolvedRefOpts = getCommandLine(ref, i); if (ref.prepend && resolvedRefOpts && resolvedRefOpts.options) { - const out = ts.outFile(resolvedRefOpts.options); + const out = outFile(resolvedRefOpts.options); // Upstream project didn't have outFile set -- skip (error will have been issued earlier) if (!out) continue; - const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = ts.getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true); - const node = ts.createInputFilesWithFilePaths(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath, host, resolvedRefOpts.options); + const { jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, buildInfoPath } = getOutputPathsForBundle(resolvedRefOpts.options, /*forceDtsPaths*/ true); + const node = createInputFilesWithFilePaths(readFile, jsFilePath!, sourceMapFilePath, declarationFilePath!, declarationMapPath, buildInfoPath, host, resolvedRefOpts.options); (nodes || (nodes = [])).push(node); } } - return nodes || ts.emptyArray; + return nodes || emptyArray; } /** * Returns the target config filename of a project reference. * Note: The file might not exist. */ -export function resolveProjectReferencePath(ref: ts.ProjectReference): ts.ResolvedConfigFileName; -/** @deprecated */ export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ts.ProjectReference): ts.ResolvedConfigFileName; -export function resolveProjectReferencePath(hostOrRef: ResolveProjectReferencePathHost | ts.ProjectReference, ref?: ts.ProjectReference): ts.ResolvedConfigFileName { - const passedInRef = ref ? ref : hostOrRef as ts.ProjectReference; - return ts.resolveConfigFileProjectName(passedInRef.path); +export function resolveProjectReferencePath(ref: ProjectReference): ResolvedConfigFileName; +/** @deprecated */ export function resolveProjectReferencePath(host: ResolveProjectReferencePathHost, ref: ProjectReference): ResolvedConfigFileName; +export function resolveProjectReferencePath(hostOrRef: ResolveProjectReferencePathHost | ProjectReference, ref?: ProjectReference): ResolvedConfigFileName { + const passedInRef = ref ? ref : hostOrRef as ProjectReference; + return resolveConfigFileProjectName(passedInRef.path); } /* @internal */ @@ -4353,37 +4414,37 @@ export function resolveProjectReferencePath(hostOrRef: ResolveProjectReferencePa * The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to. * This returns a diagnostic even if the module will be an untyped module. */ -export function getResolutionDiagnostic(options: ts.CompilerOptions, { extension }: ts.ResolvedModuleFull): ts.DiagnosticMessage | undefined { +export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModuleFull): DiagnosticMessage | undefined { switch (extension) { - case ts.Extension.Ts: - case ts.Extension.Dts: + case Extension.Ts: + case Extension.Dts: // These are always allowed. return undefined; - case ts.Extension.Tsx: + case Extension.Tsx: return needJsx(); - case ts.Extension.Jsx: + case Extension.Jsx: return needJsx() || needAllowJs(); - case ts.Extension.Js: + case Extension.Js: return needAllowJs(); - case ts.Extension.Json: + case Extension.Json: return needResolveJsonModule(); } function needJsx() { - return options.jsx ? undefined : ts.Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set; + return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set; } function needAllowJs() { - return ts.getAllowJSCompilerOption(options) || !ts.getStrictOptionValue(options, "noImplicitAny") ? undefined : ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; + return getAllowJSCompilerOption(options) || !getStrictOptionValue(options, "noImplicitAny") ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; } function needResolveJsonModule() { - return options.resolveJsonModule ? undefined : ts.Diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used; + return options.resolveJsonModule ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used; } } -function getModuleNames({ imports, moduleAugmentations }: ts.SourceFile): string[] { +function getModuleNames({ imports, moduleAugmentations }: SourceFile): string[] { const res = imports.map(i => i.text); for (const aug of moduleAugmentations) { - if (aug.kind === ts.SyntaxKind.StringLiteral) { + if (aug.kind === SyntaxKind.StringLiteral) { res.push(aug.text); } // Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`. @@ -4392,15 +4453,15 @@ function getModuleNames({ imports, moduleAugmentations }: ts.SourceFile): string } /* @internal */ -export function getModuleNameStringLiteralAt({ imports, moduleAugmentations }: SourceFileImportsList, index: number): ts.StringLiteralLike { +export function getModuleNameStringLiteralAt({ imports, moduleAugmentations }: SourceFileImportsList, index: number): StringLiteralLike { if (index < imports.length) return imports[index]; let augIndex = imports.length; for (const aug of moduleAugmentations) { - if (aug.kind === ts.SyntaxKind.StringLiteral) { + if (aug.kind === SyntaxKind.StringLiteral) { if (index === augIndex) return aug; augIndex++; } // Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`. } - ts.Debug.fail("should never ask for module name at index higher than possible module name"); + Debug.fail("should never ask for module name at index higher than possible module name"); } diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index e32370b6b7a97..1a1c5bcc760fb 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -1,32 +1,49 @@ import * as ts from "./_namespaces/ts"; +import { + arrayToMap, CachedDirectoryStructureHost, CacheWithRedirects, CharacterCodes, clearMap, closeFileWatcher, + closeFileWatcherOf, CompilerOptions, contains, createCacheWithRedirects, createModeAwareCache, + createModuleResolutionCache, createMultiMap, createTypeReferenceDirectiveResolutionCache, Debug, Diagnostics, + directorySeparator, DirectoryWatcherCallback, emptyArray, emptyIterator, endsWith, ESMap, Extension, extensionIsTS, + fileExtensionIs, fileExtensionIsOneOf, FileReference, FileWatcher, FileWatcherCallback, firstDefinedIterator, + GetCanonicalFileName, getDirectoryPath, getEffectiveTypeRoots, getModeForFileReference, getModeForResolutionAtIndex, + getNormalizedAbsolutePath, getRootLength, HasInvalidatedResolutions, ignoredPaths, inferredTypesContainingFile, + isEmittedFileOfProgram, isExternalModuleNameRelative, isExternalOrCommonJsModule, isNodeModulesDirectory, + isRootedDiskPath, isString, isTraceEnabled, length, loadModuleFromGlobalCache, Map, memoize, + MinimalResolutionCacheHost, ModeAwareCache, ModuleKind, ModuleResolutionCache, ModuleResolutionHost, mutateMap, + noopFileWatcher, normalizePath, PackageId, packageIdToString, parseNodeModuleFromPath, Path, + pathContainsNodeModules, PerModuleNameCache, Program, ReadonlyESMap, removeSuffix, removeTrailingDirectorySeparator, + resolutionExtensionIsTSOrJson, ResolvedModuleFull, ResolvedModuleWithFailedLookupLocations, + ResolvedProjectReference, ResolvedTypeReferenceDirective, ResolvedTypeReferenceDirectiveWithFailedLookupLocations, + returnTrue, Set, some, SourceFile, startsWith, stringContains, trace, unorderedRemoveItem, WatchDirectoryFlags, +} from "./_namespaces/ts"; /** @internal */ /** This is the cache of module/typedirectives resolution that can be retained across program */ export interface ResolutionCache { startRecordingFilesWithChangedResolutions(): void; - finishRecordingFilesWithChangedResolutions(): ts.Path[] | undefined; + finishRecordingFilesWithChangedResolutions(): Path[] | undefined; - resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ts.ResolvedProjectReference, containingSourceFile?: ts.SourceFile): (ts.ResolvedModuleFull | undefined)[]; - getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): CachedResolvedModuleWithFailedLookupLocations | undefined; - resolveTypeReferenceDirectives(typeDirectiveNames: string[] | readonly ts.FileReference[], containingFile: string, redirectedReference?: ts.ResolvedProjectReference, containingFileMode?: ts.SourceFile["impliedNodeFormat"]): (ts.ResolvedTypeReferenceDirective | undefined)[]; + resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile): (ResolvedModuleFull | undefined)[]; + getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): CachedResolvedModuleWithFailedLookupLocations | undefined; + resolveTypeReferenceDirectives(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference?: ResolvedProjectReference, containingFileMode?: SourceFile["impliedNodeFormat"]): (ResolvedTypeReferenceDirective | undefined)[]; invalidateResolutionsOfFailedLookupLocations(): boolean; - invalidateResolutionOfFile(filePath: ts.Path): void; - removeResolutionsOfFile(filePath: ts.Path): void; - removeResolutionsFromProjectReferenceRedirects(filePath: ts.Path): void; - setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: ts.ESMap): void; - createHasInvalidatedResolutions(customHasInvalidatedResolutions: ts.HasInvalidatedResolutions): ts.HasInvalidatedResolutions; + invalidateResolutionOfFile(filePath: Path): void; + removeResolutionsOfFile(filePath: Path): void; + removeResolutionsFromProjectReferenceRedirects(filePath: Path): void; + setFilesWithInvalidatedNonRelativeUnresolvedImports(filesWithUnresolvedImports: ESMap): void; + createHasInvalidatedResolutions(customHasInvalidatedResolutions: HasInvalidatedResolutions): HasInvalidatedResolutions; hasChangedAutomaticTypeDirectiveNames(): boolean; - isFileWithInvalidatedNonRelativeUnresolvedImports(path: ts.Path): boolean; + isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean; startCachingPerDirectoryResolution(): void; - finishCachingPerDirectoryResolution(newProgram: ts.Program | undefined, oldProgram: ts.Program | undefined): void; + finishCachingPerDirectoryResolution(newProgram: Program | undefined, oldProgram: Program | undefined): void; updateTypeRootsWatch(): void; closeTypeRootsWatch(): void; - getModuleResolutionCache(): ts.ModuleResolutionCache; + getModuleResolutionCache(): ModuleResolutionCache; clear(): void; } @@ -37,52 +54,52 @@ interface ResolutionWithFailedLookupLocations { isInvalidated?: boolean; refCount?: number; // Files that have this resolution using - files?: ts.Path[]; + files?: Path[]; } interface ResolutionWithResolvedFileName { resolvedFileName: string | undefined; - packagetId?: ts.PackageId; + packagetId?: PackageId; } -interface CachedResolvedModuleWithFailedLookupLocations extends ts.ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations { +interface CachedResolvedModuleWithFailedLookupLocations extends ResolvedModuleWithFailedLookupLocations, ResolutionWithFailedLookupLocations { } -interface CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations extends ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolutionWithFailedLookupLocations { +interface CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations extends ResolvedTypeReferenceDirectiveWithFailedLookupLocations, ResolutionWithFailedLookupLocations { } /** @internal */ -export interface ResolutionCacheHost extends ts.MinimalResolutionCacheHost { - toPath(fileName: string): ts.Path; - getCanonicalFileName: ts.GetCanonicalFileName; - getCompilationSettings(): ts.CompilerOptions; - watchDirectoryOfFailedLookupLocation(directory: string, cb: ts.DirectoryWatcherCallback, flags: ts.WatchDirectoryFlags): ts.FileWatcher; - watchAffectingFileLocation(file: string, cb: ts.FileWatcherCallback): ts.FileWatcher; +export interface ResolutionCacheHost extends MinimalResolutionCacheHost { + toPath(fileName: string): Path; + getCanonicalFileName: GetCanonicalFileName; + getCompilationSettings(): CompilerOptions; + watchDirectoryOfFailedLookupLocation(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher; + watchAffectingFileLocation(file: string, cb: FileWatcherCallback): FileWatcher; onInvalidatedResolution(): void; - watchTypeRootsDirectory(directory: string, cb: ts.DirectoryWatcherCallback, flags: ts.WatchDirectoryFlags): ts.FileWatcher; + watchTypeRootsDirectory(directory: string, cb: DirectoryWatcherCallback, flags: WatchDirectoryFlags): FileWatcher; onChangedAutomaticTypeDirectiveNames(): void; scheduleInvalidateResolutionsOfFailedLookupLocations(): void; - getCachedDirectoryStructureHost(): ts.CachedDirectoryStructureHost | undefined; + getCachedDirectoryStructureHost(): CachedDirectoryStructureHost | undefined; projectName?: string; getGlobalCache?(): string | undefined; globalCacheResolutionModuleName?(externalModuleName: string): string; writeLog(s: string): void; - getCurrentProgram(): ts.Program | undefined; - fileIsOpen(filePath: ts.Path): boolean; + getCurrentProgram(): Program | undefined; + fileIsOpen(filePath: Path): boolean; onDiscoveredSymlink?(): void; } interface FileWatcherOfAffectingLocation { /** watcher for the lookup */ - watcher: ts.FileWatcher; + watcher: FileWatcher; resolutions: number; files: number; - paths: ts.Set; + paths: Set; } interface DirectoryWatchesOfFailedLookup { /** watcher for the lookup */ - watcher: ts.FileWatcher; + watcher: FileWatcher; /** ref count keeping this watch alive */ refCount: number; /** is the directory watched being non recursive */ @@ -91,18 +108,18 @@ interface DirectoryWatchesOfFailedLookup { interface DirectoryOfFailedLookupWatch { dir: string; - dirPath: ts.Path; + dirPath: Path; nonRecursive?: boolean; } /** @internal */ -export function removeIgnoredPath(path: ts.Path): ts.Path | undefined { +export function removeIgnoredPath(path: Path): Path | undefined { // Consider whole staging folder as if node_modules changed. - if (ts.endsWith(path, "/node_modules/.staging")) { - return ts.removeSuffix(path, "/.staging") as ts.Path; + if (endsWith(path, "/node_modules/.staging")) { + return removeSuffix(path, "/.staging") as Path; } - return ts.some(ts.ignoredPaths, searchPath => ts.stringContains(path, searchPath)) ? + return some(ignoredPaths, searchPath => stringContains(path, searchPath)) ? undefined : path; } @@ -114,25 +131,25 @@ export function removeIgnoredPath(path: ts.Path): ts.Path | undefined { * "c:/", "c:/users", "c:/users/username", "c:/users/username/folderAtRoot", "c:/folderAtRoot" * @param dirPath */ -export function canWatchDirectoryOrFile(dirPath: ts.Path) { - const rootLength = ts.getRootLength(dirPath); +export function canWatchDirectoryOrFile(dirPath: Path) { + const rootLength = getRootLength(dirPath); if (dirPath.length === rootLength) { // Ignore "/", "c:/" return false; } - let nextDirectorySeparator = dirPath.indexOf(ts.directorySeparator, rootLength); + let nextDirectorySeparator = dirPath.indexOf(directorySeparator, rootLength); if (nextDirectorySeparator === -1) { // ignore "/user", "c:/users" or "c:/folderAtRoot" return false; } let pathPartForUserCheck = dirPath.substring(rootLength, nextDirectorySeparator + 1); - const isNonDirectorySeparatorRoot = rootLength > 1 || dirPath.charCodeAt(0) !== ts.CharacterCodes.slash; + const isNonDirectorySeparatorRoot = rootLength > 1 || dirPath.charCodeAt(0) !== CharacterCodes.slash; if (isNonDirectorySeparatorRoot && dirPath.search(/[a-zA-Z]:/) !== 0 && // Non dos style paths pathPartForUserCheck.search(/[a-zA-Z]\$\//) === 0) { // Dos style nextPart - nextDirectorySeparator = dirPath.indexOf(ts.directorySeparator, nextDirectorySeparator + 1); + nextDirectorySeparator = dirPath.indexOf(directorySeparator, nextDirectorySeparator + 1); if (nextDirectorySeparator === -1) { // ignore "//vda1cs4850/c$/folderAtRoot" return false; @@ -148,7 +165,7 @@ export function canWatchDirectoryOrFile(dirPath: ts.Path) { } for (let searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) { - searchIndex = dirPath.indexOf(ts.directorySeparator, searchIndex) + 1; + searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1; if (searchIndex === 0) { // Folder isnt at expected minimum levels return false; @@ -162,33 +179,33 @@ type GetResolutionWithResolvedFileName | undefined; - let filesWithInvalidatedNonRelativeUnresolvedImports: ts.ReadonlyESMap | undefined; - const nonRelativeExternalModuleResolutions = ts.createMultiMap(); + let filesWithChangedSetOfUnresolvedImports: Path[] | undefined; + let filesWithInvalidatedResolutions: Set | undefined; + let filesWithInvalidatedNonRelativeUnresolvedImports: ReadonlyESMap | undefined; + const nonRelativeExternalModuleResolutions = createMultiMap(); const resolutionsWithFailedLookups: ResolutionWithFailedLookupLocations[] = []; const resolutionsWithOnlyAffectingLocations: ResolutionWithFailedLookupLocations[] = []; - const resolvedFileToResolution = ts.createMultiMap(); - const impliedFormatPackageJsons = new ts.Map(); + const resolvedFileToResolution = createMultiMap(); + const impliedFormatPackageJsons = new Map(); let hasChangedAutomaticTypeDirectiveNames = false; - let affectingPathChecksForFile: ts.Set | undefined; - let affectingPathChecks: ts.Set | undefined; - let failedLookupChecks: ts.Set | undefined; - let startsWithPathChecks: ts.Set | undefined; - let isInDirectoryChecks: ts.Set | undefined; + let affectingPathChecksForFile: Set | undefined; + let affectingPathChecks: Set | undefined; + let failedLookupChecks: Set | undefined; + let startsWithPathChecks: Set | undefined; + let isInDirectoryChecks: Set | undefined; - const getCurrentDirectory = ts.memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217 + const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217 const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); // The resolvedModuleNames and resolvedTypeReferenceDirectives are the cache of resolutions per file. // The key in the map is source file's path. // The values are Map of resolutions with key being name lookedup. - const resolvedModuleNames = new ts.Map>(); - const perDirectoryResolvedModuleNames: ts.CacheWithRedirects> = ts.createCacheWithRedirects(); - const nonRelativeModuleNameCache: ts.CacheWithRedirects = ts.createCacheWithRedirects(); - const moduleResolutionCache = ts.createModuleResolutionCache( + const resolvedModuleNames = new Map>(); + const perDirectoryResolvedModuleNames: CacheWithRedirects> = createCacheWithRedirects(); + const nonRelativeModuleNameCache: CacheWithRedirects = createCacheWithRedirects(); + const moduleResolutionCache = createModuleResolutionCache( getCurrentDirectory(), resolutionHost.getCanonicalFileName, /*options*/ undefined, @@ -196,9 +213,9 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD nonRelativeModuleNameCache, ); - const resolvedTypeReferenceDirectives = new ts.Map>(); - const perDirectoryResolvedTypeReferenceDirectives: ts.CacheWithRedirects> = ts.createCacheWithRedirects(); - const typeReferenceDirectiveResolutionCache = ts.createTypeReferenceDirectiveResolutionCache( + const resolvedTypeReferenceDirectives = new Map>(); + const perDirectoryResolvedTypeReferenceDirectives: CacheWithRedirects> = createCacheWithRedirects(); + const typeReferenceDirectiveResolutionCache = createTypeReferenceDirectiveResolutionCache( getCurrentDirectory(), resolutionHost.getCanonicalFileName, /*options*/ undefined, @@ -212,17 +229,17 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD * This helps in not having to comb through all resolutions when files are added/removed * Note that .d.ts file also has .d.ts extension hence will be part of default extensions */ - const failedLookupDefaultExtensions = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Js, ts.Extension.Jsx, ts.Extension.Json]; - const customFailedLookupPaths = new ts.Map(); + const failedLookupDefaultExtensions = [Extension.Ts, Extension.Tsx, Extension.Js, Extension.Jsx, Extension.Json]; + const customFailedLookupPaths = new Map(); - const directoryWatchesOfFailedLookups = new ts.Map(); - const fileWatchesOfAffectingLocations = new ts.Map(); - const rootDir = rootDirForResolution && ts.removeTrailingDirectorySeparator(ts.getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory())); - const rootPath = (rootDir && resolutionHost.toPath(rootDir)) as ts.Path; // TODO: GH#18217 - const rootSplitLength = rootPath !== undefined ? rootPath.split(ts.directorySeparator).length : 0; + const directoryWatchesOfFailedLookups = new Map(); + const fileWatchesOfAffectingLocations = new Map(); + const rootDir = rootDirForResolution && removeTrailingDirectorySeparator(getNormalizedAbsolutePath(rootDirForResolution, getCurrentDirectory())); + const rootPath = (rootDir && resolutionHost.toPath(rootDir)) as Path; // TODO: GH#18217 + const rootSplitLength = rootPath !== undefined ? rootPath.split(directorySeparator).length : 0; // TypeRoot watches for the types that get added as part of getAutomaticTypeDirectiveNames - const typeRootsWatches = new ts.Map(); + const typeRootsWatches = new Map(); return { getModuleResolutionCache: () => moduleResolutionCache, @@ -256,16 +273,16 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return resolution.resolvedTypeReferenceDirective; } - function isInDirectoryPath(dir: ts.Path | undefined, file: ts.Path) { + function isInDirectoryPath(dir: Path | undefined, file: Path) { if (dir === undefined || file.length <= dir.length) { return false; } - return ts.startsWith(file, dir) && file[dir.length] === ts.directorySeparator; + return startsWith(file, dir) && file[dir.length] === directorySeparator; } function clear() { - ts.clearMap(directoryWatchesOfFailedLookups, ts.closeFileWatcherOf); - ts.clearMap(fileWatchesOfAffectingLocations, ts.closeFileWatcherOf); + clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf); + clearMap(fileWatchesOfAffectingLocations, closeFileWatcherOf); customFailedLookupPaths.clear(); nonRelativeExternalModuleResolutions.clear(); closeTypeRootsWatch(); @@ -295,7 +312,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return collected; } - function isFileWithInvalidatedNonRelativeUnresolvedImports(path: ts.Path): boolean { + function isFileWithInvalidatedNonRelativeUnresolvedImports(path: Path): boolean { if (!filesWithInvalidatedNonRelativeUnresolvedImports) { return false; } @@ -305,7 +322,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return !!value && !!value.length; } - function createHasInvalidatedResolutions(customHasInvalidatedResolutions: ts.HasInvalidatedResolutions): ts.HasInvalidatedResolutions { + function createHasInvalidatedResolutions(customHasInvalidatedResolutions: HasInvalidatedResolutions): HasInvalidatedResolutions { // Ensure pending resolutions are applied invalidateResolutionsOfFailedLookupLocations(); const collected = filesWithInvalidatedResolutions; @@ -324,15 +341,15 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD nonRelativeExternalModuleResolutions.clear(); } - function finishCachingPerDirectoryResolution(newProgram: ts.Program | undefined, oldProgram: ts.Program | undefined) { + function finishCachingPerDirectoryResolution(newProgram: Program | undefined, oldProgram: Program | undefined) { filesWithInvalidatedNonRelativeUnresolvedImports = undefined; nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions); nonRelativeExternalModuleResolutions.clear(); // Update file watches if (newProgram !== oldProgram) { newProgram?.getSourceFiles().forEach(newFile => { - const expected = ts.isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations?.length ?? 0 : 0; - const existing = impliedFormatPackageJsons.get(newFile.path) ?? ts.emptyArray; + const expected = isExternalOrCommonJsModule(newFile) ? newFile.packageJsonLocations?.length ?? 0 : 0; + const existing = impliedFormatPackageJsons.get(newFile.path) ?? emptyArray; for (let i = existing.length; i < expected; i++) { createFileWatcherOfAffectingLocation(newFile.packageJsonLocations![i], /*forResolution*/ false); } @@ -367,7 +384,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD hasChangedAutomaticTypeDirectiveNames = false; } - function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: ts.CompilerOptions, host: ts.ModuleResolutionHost, redirectedReference?: ts.ResolvedProjectReference, _containingSourceFile?: never, mode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined): CachedResolvedModuleWithFailedLookupLocations { + function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, _containingSourceFile?: never, mode?: ModuleKind.CommonJS | ModuleKind.ESNext | undefined): CachedResolvedModuleWithFailedLookupLocations { const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference, mode); // return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts if (!resolutionHost.getGlobalCache) { @@ -376,11 +393,11 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // otherwise try to load typings from @types const globalCache = resolutionHost.getGlobalCache(); - if (globalCache !== undefined && !ts.isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && ts.extensionIsTS(primaryResult.resolvedModule.extension))) { + if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) { // create different collection of failed lookup locations for second pass // if it will fail and we've already found something during the first pass - we don't want to pollute its results - const { resolvedModule, failedLookupLocations, affectingLocations } = ts.loadModuleFromGlobalCache( - ts.Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), + const { resolvedModule, failedLookupLocations, affectingLocations } = loadModuleFromGlobalCache( + Debug.checkDefined(resolutionHost.globalCacheResolutionModuleName)(moduleName), resolutionHost.projectName, compilerOptions, host, @@ -400,23 +417,23 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return primaryResult; } - function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: ts.CompilerOptions, host: ts.ModuleResolutionHost, redirectedReference?: ts.ResolvedProjectReference, _containingSourceFile?: ts.SourceFile, resolutionMode?: ts.SourceFile["impliedNodeFormat"] | undefined): CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations { + function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, _containingSourceFile?: SourceFile, resolutionMode?: SourceFile["impliedNodeFormat"] | undefined): CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations { return ts.resolveTypeReferenceDirective(typeReferenceDirectiveName, containingFile, options, host, redirectedReference, typeReferenceDirectiveResolutionCache, resolutionMode); } interface ResolveNamesWithLocalCacheInput { - names: readonly string[] | readonly ts.FileReference[]; + names: readonly string[] | readonly FileReference[]; containingFile: string; - redirectedReference: ts.ResolvedProjectReference | undefined; - cache: ts.ESMap>; - perDirectoryCacheWithRedirects: ts.CacheWithRedirects>; - loader: (name: string, containingFile: string, options: ts.CompilerOptions, host: ts.ModuleResolutionHost, redirectedReference?: ts.ResolvedProjectReference, containingSourceFile?: ts.SourceFile, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined) => T; + redirectedReference: ResolvedProjectReference | undefined; + cache: ESMap>; + perDirectoryCacheWithRedirects: CacheWithRedirects>; + loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext | undefined) => T; getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName; shouldRetryResolution: (t: T) => boolean; reusedNames?: readonly string[]; logChanges?: boolean; - containingSourceFile?: ts.SourceFile; - containingSourceFileMode?: ts.SourceFile["impliedNodeFormat"]; + containingSourceFile?: SourceFile; + containingSourceFileMode?: SourceFile["impliedNodeFormat"]; } function resolveNamesWithLocalCache({ names, containingFile, redirectedReference, @@ -425,12 +442,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD shouldRetryResolution, reusedNames, logChanges, containingSourceFile, containingSourceFileMode }: ResolveNamesWithLocalCacheInput): (R | undefined)[] { const path = resolutionHost.toPath(containingFile); - const resolutionsInFile = cache.get(path) || cache.set(path, ts.createModeAwareCache()).get(path)!; - const dirPath = ts.getDirectoryPath(path); + const resolutionsInFile = cache.get(path) || cache.set(path, createModeAwareCache()).get(path)!; + const dirPath = getDirectoryPath(path); const perDirectoryCache = perDirectoryCacheWithRedirects.getOrCreateMapOfCacheRedirects(redirectedReference); let perDirectoryResolution = perDirectoryCache.get(dirPath); if (!perDirectoryResolution) { - perDirectoryResolution = ts.createModeAwareCache(); + perDirectoryResolution = createModeAwareCache(); perDirectoryCache.set(dirPath, perDirectoryResolution); } const resolvedModules: (R | undefined)[] = []; @@ -444,49 +461,49 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD !redirectedReference || redirectedReference.sourceFile.path !== oldRedirect.sourceFile.path : !!redirectedReference; - const seenNamesInFile = ts.createModeAwareCache(); + const seenNamesInFile = createModeAwareCache(); let i = 0; for (const entry of names) { - const name = ts.isString(entry) ? entry : entry.fileName.toLowerCase(); + const name = isString(entry) ? entry : entry.fileName.toLowerCase(); // Imports supply a `containingSourceFile` but no `containingSourceFileMode` - it would be redundant // they require calculating the mode for a given import from it's position in the resolution table, since a given // import's syntax may override the file's default mode. // Type references instead supply a `containingSourceFileMode` and a non-string entry which contains // a default file mode override if applicable. - const mode = !ts.isString(entry) ? ts.getModeForFileReference(entry, containingSourceFileMode) : - containingSourceFile ? ts.getModeForResolutionAtIndex(containingSourceFile, i) : undefined; + const mode = !isString(entry) ? getModeForFileReference(entry, containingSourceFileMode) : + containingSourceFile ? getModeForResolutionAtIndex(containingSourceFile, i) : undefined; i++; let resolution = resolutionsInFile.get(name, mode); // Resolution is valid if it is present and not invalidated if (!seenNamesInFile.has(name, mode) && unmatchedRedirects || !resolution || resolution.isInvalidated || // If the name is unresolved import that was invalidated, recalculate - (hasInvalidatedNonRelativeUnresolvedImport && !ts.isExternalModuleNameRelative(name) && shouldRetryResolution(resolution))) { + (hasInvalidatedNonRelativeUnresolvedImport && !isExternalModuleNameRelative(name) && shouldRetryResolution(resolution))) { const existingResolution = resolution; const resolutionInDirectory = perDirectoryResolution.get(name, mode); if (resolutionInDirectory) { resolution = resolutionInDirectory; const host = resolutionHost.getCompilerHost?.() || resolutionHost; - if (ts.isTraceEnabled(compilerOptions, host)) { + if (isTraceEnabled(compilerOptions, host)) { const resolved = getResolutionWithResolvedFileName(resolution); - ts.trace( + trace( host, loader === resolveModuleName as unknown ? resolved?.resolvedFileName ? resolved.packagetId ? - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3_with_Package_ID_4: - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3: - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_not_resolved : + Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3_with_Package_ID_4: + Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3: + Diagnostics.Reusing_resolution_of_module_0_from_1_found_in_cache_from_location_2_it_was_not_resolved : resolved?.resolvedFileName ? resolved.packagetId ? - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3_with_Package_ID_4 : - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3 : - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_not_resolved, + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3_with_Package_ID_4 : + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_successfully_resolved_to_3 : + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_found_in_cache_from_location_2_it_was_not_resolved, name, containingFile, - ts.getDirectoryPath(containingFile), + getDirectoryPath(containingFile), resolved?.resolvedFileName, - resolved?.packagetId && ts.packageIdToString(resolved.packagetId) + resolved?.packagetId && packageIdToString(resolved.packagetId) ); } } @@ -511,36 +528,36 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } else { const host = resolutionHost.getCompilerHost?.() || resolutionHost; - if (ts.isTraceEnabled(compilerOptions, host) && !seenNamesInFile.has(name, mode)) { + if (isTraceEnabled(compilerOptions, host) && !seenNamesInFile.has(name, mode)) { const resolved = getResolutionWithResolvedFileName(resolution); - ts.trace( + trace( host, loader === resolveModuleName as unknown ? resolved?.resolvedFileName ? resolved.packagetId ? - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - ts.Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved : + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : + Diagnostics.Reusing_resolution_of_module_0_from_1_of_old_program_it_was_not_resolved : resolved?.resolvedFileName ? resolved.packagetId ? - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : - ts.Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_not_resolved, + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2_with_Package_ID_3 : + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_successfully_resolved_to_2 : + Diagnostics.Reusing_resolution_of_type_reference_directive_0_from_1_of_old_program_it_was_not_resolved, name, containingFile, resolved?.resolvedFileName, - resolved?.packagetId && ts.packageIdToString(resolved.packagetId) + resolved?.packagetId && packageIdToString(resolved.packagetId) ); } } - ts.Debug.assert(resolution !== undefined && !resolution.isInvalidated); + Debug.assert(resolution !== undefined && !resolution.isInvalidated); seenNamesInFile.set(name, mode, true); resolvedModules.push(getResolutionWithResolvedFileName(resolution)); } // Stop watching and remove the unused name resolutionsInFile.forEach((resolution, name, mode) => { - if (!seenNamesInFile.has(name, mode) && !ts.contains(reusedNames, name)) { + if (!seenNamesInFile.has(name, mode) && !contains(reusedNames, name)) { stopWatchFailedLookupLocationOfResolution(resolution, path, getResolutionWithResolvedFileName); resolutionsInFile.delete(name, mode); } @@ -567,8 +584,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } - function resolveTypeReferenceDirectives(typeDirectiveNames: string[] | readonly ts.FileReference[], containingFile: string, redirectedReference?: ts.ResolvedProjectReference, containingFileMode?: ts.SourceFile["impliedNodeFormat"]): (ts.ResolvedTypeReferenceDirective | undefined)[] { - return resolveNamesWithLocalCache({ + function resolveTypeReferenceDirectives(typeDirectiveNames: string[] | readonly FileReference[], containingFile: string, redirectedReference?: ResolvedProjectReference, containingFileMode?: SourceFile["impliedNodeFormat"]): (ResolvedTypeReferenceDirective | undefined)[] { + return resolveNamesWithLocalCache({ names: typeDirectiveNames, containingFile, redirectedReference, @@ -581,8 +598,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD }); } - function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ts.ResolvedProjectReference, containingSourceFile?: ts.SourceFile): (ts.ResolvedModuleFull | undefined)[] { - return resolveNamesWithLocalCache({ + function resolveModuleNames(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference?: ResolvedProjectReference, containingSourceFile?: SourceFile): (ResolvedModuleFull | undefined)[] { + return resolveNamesWithLocalCache({ names: moduleNames, containingFile, redirectedReference, @@ -590,35 +607,35 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD perDirectoryCacheWithRedirects: perDirectoryResolvedModuleNames, loader: resolveModuleName, getResolutionWithResolvedFileName: getResolvedModule, - shouldRetryResolution: resolution => !resolution.resolvedModule || !ts.resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), + shouldRetryResolution: resolution => !resolution.resolvedModule || !resolutionExtensionIsTSOrJson(resolution.resolvedModule.extension), reusedNames, logChanges: logChangesWhenResolvingModule, containingSourceFile, }); } - function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): CachedResolvedModuleWithFailedLookupLocations | undefined { + function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): CachedResolvedModuleWithFailedLookupLocations | undefined { const cache = resolvedModuleNames.get(resolutionHost.toPath(containingFile)); if (!cache) return undefined; return cache.get(moduleName, resolutionMode); } - function isNodeModulesAtTypesDirectory(dirPath: ts.Path) { - return ts.endsWith(dirPath, "/node_modules/@types"); + function isNodeModulesAtTypesDirectory(dirPath: Path) { + return endsWith(dirPath, "/node_modules/@types"); } - function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: ts.Path): DirectoryOfFailedLookupWatch | undefined { + function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch | undefined { if (isInDirectoryPath(rootPath, failedLookupLocationPath)) { // Ensure failed look up is normalized path - failedLookupLocation = ts.isRootedDiskPath(failedLookupLocation) ? ts.normalizePath(failedLookupLocation) : ts.getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory()); - const failedLookupPathSplit = failedLookupLocationPath.split(ts.directorySeparator); - const failedLookupSplit = failedLookupLocation.split(ts.directorySeparator); - ts.Debug.assert(failedLookupSplit.length === failedLookupPathSplit.length, `FailedLookup: ${failedLookupLocation} failedLookupLocationPath: ${failedLookupLocationPath}`); + failedLookupLocation = isRootedDiskPath(failedLookupLocation) ? normalizePath(failedLookupLocation) : getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory()); + const failedLookupPathSplit = failedLookupLocationPath.split(directorySeparator); + const failedLookupSplit = failedLookupLocation.split(directorySeparator); + Debug.assert(failedLookupSplit.length === failedLookupPathSplit.length, `FailedLookup: ${failedLookupLocation} failedLookupLocationPath: ${failedLookupLocationPath}`); if (failedLookupPathSplit.length > rootSplitLength + 1) { // Instead of watching root, watch directory in root to avoid watching excluded directories not needed for module resolution return { - dir: failedLookupSplit.slice(0, rootSplitLength + 1).join(ts.directorySeparator), - dirPath: failedLookupPathSplit.slice(0, rootSplitLength + 1).join(ts.directorySeparator) as ts.Path + dir: failedLookupSplit.slice(0, rootSplitLength + 1).join(directorySeparator), + dirPath: failedLookupPathSplit.slice(0, rootSplitLength + 1).join(directorySeparator) as Path }; } else { @@ -632,29 +649,29 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } return getDirectoryToWatchFromFailedLookupLocationDirectory( - ts.getDirectoryPath(ts.getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())), - ts.getDirectoryPath(failedLookupLocationPath) + getDirectoryPath(getNormalizedAbsolutePath(failedLookupLocation, getCurrentDirectory())), + getDirectoryPath(failedLookupLocationPath) ); } - function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: ts.Path): DirectoryOfFailedLookupWatch | undefined { + function getDirectoryToWatchFromFailedLookupLocationDirectory(dir: string, dirPath: Path): DirectoryOfFailedLookupWatch | undefined { // If directory path contains node module, get the most parent node_modules directory for watching - while (ts.pathContainsNodeModules(dirPath)) { - dir = ts.getDirectoryPath(dir); - dirPath = ts.getDirectoryPath(dirPath); + while (pathContainsNodeModules(dirPath)) { + dir = getDirectoryPath(dir); + dirPath = getDirectoryPath(dirPath); } // If the directory is node_modules use it to watch, always watch it recursively - if (ts.isNodeModulesDirectory(dirPath)) { - return canWatchDirectoryOrFile(ts.getDirectoryPath(dirPath)) ? { dir, dirPath } : undefined; + if (isNodeModulesDirectory(dirPath)) { + return canWatchDirectoryOrFile(getDirectoryPath(dirPath)) ? { dir, dirPath } : undefined; } let nonRecursive = true; // Use some ancestor of the root directory - let subDirectoryPath: ts.Path | undefined, subDirectory: string | undefined; + let subDirectoryPath: Path | undefined, subDirectory: string | undefined; if (rootPath !== undefined) { while (!isInDirectoryPath(dirPath, rootPath)) { - const parentPath = ts.getDirectoryPath(dirPath); + const parentPath = getDirectoryPath(dirPath); if (parentPath === dirPath) { break; } @@ -662,31 +679,31 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD subDirectoryPath = dirPath; subDirectory = dir; dirPath = parentPath; - dir = ts.getDirectoryPath(dir); + dir = getDirectoryPath(dir); } } return canWatchDirectoryOrFile(dirPath) ? { dir: subDirectory || dir, dirPath: subDirectoryPath || dirPath, nonRecursive } : undefined; } - function isPathWithDefaultFailedLookupExtension(path: ts.Path) { - return ts.fileExtensionIsOneOf(path, failedLookupDefaultExtensions); + function isPathWithDefaultFailedLookupExtension(path: Path) { + return fileExtensionIsOneOf(path, failedLookupDefaultExtensions); } function watchFailedLookupLocationsOfExternalModuleResolutions( name: string, resolution: T, - filePath: ts.Path, + filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, ) { if (resolution.refCount) { resolution.refCount++; - ts.Debug.assertIsDefined(resolution.files); + Debug.assertIsDefined(resolution.files); } else { resolution.refCount = 1; - ts.Debug.assert(ts.length(resolution.files) === 0); // This resolution shouldnt be referenced by any file yet - if (ts.isExternalModuleNameRelative(name)) { + Debug.assert(length(resolution.files) === 0); // This resolution shouldnt be referenced by any file yet + if (isExternalModuleNameRelative(name)) { watchFailedLookupLocationOfResolution(resolution); } else { @@ -701,7 +718,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) { - ts.Debug.assert(!!resolution.refCount); + Debug.assert(!!resolution.refCount); const { failedLookupLocations, affectingLocations } = resolution; if (!failedLookupLocations.length && !affectingLocations.length) return; @@ -720,7 +737,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1); } if (dirPath === rootPath) { - ts.Debug.assert(!nonRecursive); + Debug.assert(!nonRecursive); setAtRoot = true; } else { @@ -737,7 +754,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } function watchAffectingLocationsOfResolution(resolution: ResolutionWithFailedLookupLocations, addToResolutionsWithOnlyAffectingLocations: boolean) { - ts.Debug.assert(!!resolution.refCount); + Debug.assert(!!resolution.refCount); const { affectingLocations } = resolution; if (!affectingLocations.length) return; if (addToResolutionsWithOnlyAffectingLocations) resolutionsWithOnlyAffectingLocations.push(resolution); @@ -768,25 +785,25 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } } - const paths = new ts.Set(); + const paths = new Set(); paths.add(locationToWatch); let actualWatcher = canWatchDirectoryOrFile(resolutionHost.toPath(locationToWatch)) ? resolutionHost.watchAffectingFileLocation(locationToWatch, (fileName, eventKind) => { cachedDirectoryStructureHost?.addOrDeleteFile(fileName, resolutionHost.toPath(locationToWatch), eventKind); const packageJsonMap = moduleResolutionCache.getPackageJsonInfoCache().getInternalMap(); paths.forEach(path => { - if (watcher.resolutions) (affectingPathChecks ??= new ts.Set()).add(path); - if (watcher.files) (affectingPathChecksForFile ??= new ts.Set()).add(path); + if (watcher.resolutions) (affectingPathChecks ??= new Set()).add(path); + if (watcher.files) (affectingPathChecksForFile ??= new Set()).add(path); packageJsonMap?.delete(resolutionHost.toPath(path)); }); resolutionHost.scheduleInvalidateResolutionsOfFailedLookupLocations(); - }) : ts.noopFileWatcher; + }) : noopFileWatcher; const watcher: FileWatcherOfAffectingLocation = { - watcher: actualWatcher !== ts.noopFileWatcher ? { + watcher: actualWatcher !== noopFileWatcher ? { close: () => { actualWatcher.close(); // Ensure when watching symlinked package.json, we can close the actual file watcher only once - actualWatcher = ts.noopFileWatcher; + actualWatcher = noopFileWatcher; } } : actualWatcher, resolutions: forResolution ? 1 : 0, @@ -810,10 +827,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } - function setDirectoryWatcher(dir: string, dirPath: ts.Path, nonRecursive?: boolean) { + function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) { const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); if (dirWatcher) { - ts.Debug.assert(!!nonRecursive === !!dirWatcher.nonRecursive); + Debug.assert(!!nonRecursive === !!dirWatcher.nonRecursive); dirWatcher.refCount++; } else { @@ -823,10 +840,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function stopWatchFailedLookupLocationOfResolution( resolution: T, - filePath: ts.Path, + filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, ) { - ts.unorderedRemoveItem(ts.Debug.checkDefined(resolution.files), filePath); + unorderedRemoveItem(Debug.checkDefined(resolution.files), filePath); resolution.refCount!--; if (resolution.refCount) { return; @@ -837,7 +854,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } const { failedLookupLocations, affectingLocations } = resolution; - if (ts.unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) { + if (unorderedRemoveItem(resolutionsWithFailedLookups, resolution)) { let removeAtRoot = false; for (const failedLookupLocation of failedLookupLocations) { const failedLookupLocationPath = resolutionHost.toPath(failedLookupLocation); @@ -850,7 +867,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD customFailedLookupPaths.delete(failedLookupLocationPath); } else { - ts.Debug.assert(refCount > 1); + Debug.assert(refCount > 1); customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1); } } @@ -868,7 +885,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } else if (affectingLocations.length) { - ts.unorderedRemoveItem(resolutionsWithOnlyAffectingLocations, resolution); + unorderedRemoveItem(resolutionsWithOnlyAffectingLocations, resolution); } for (const affectingLocation of affectingLocations) { @@ -883,7 +900,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD dirWatcher.refCount--; } - function createDirectoryWatcher(directory: string, dirPath: ts.Path, nonRecursive: boolean | undefined) { + function createDirectoryWatcher(directory: string, dirPath: Path, nonRecursive: boolean | undefined) { return resolutionHost.watchDirectoryOfFailedLookupLocation(directory, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); if (cachedDirectoryStructureHost) { @@ -892,12 +909,12 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath); - }, nonRecursive ? ts.WatchDirectoryFlags.None : ts.WatchDirectoryFlags.Recursive); + }, nonRecursive ? WatchDirectoryFlags.None : WatchDirectoryFlags.Recursive); } function removeResolutionsOfFileFromCache( - cache: ts.ESMap>, - filePath: ts.Path, + cache: ESMap>, + filePath: Path, getResolutionWithResolvedFileName: GetResolutionWithResolvedFileName, ) { // Deleted file, stop watching failed lookups for all the resolutions in the file @@ -908,8 +925,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } } - function removeResolutionsFromProjectReferenceRedirects(filePath: ts.Path) { - if (!ts.fileExtensionIs(filePath, ts.Extension.Json)) return; + function removeResolutionsFromProjectReferenceRedirects(filePath: Path) { + if (!fileExtensionIs(filePath, Extension.Json)) return; const program = resolutionHost.getCurrentProgram(); if (!program) return; @@ -922,7 +939,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD resolvedProjectReference.commandLine.fileNames.forEach(f => removeResolutionsOfFile(resolutionHost.toPath(f))); } - function removeResolutionsOfFile(filePath: ts.Path) { + function removeResolutionsOfFile(filePath: Path) { removeResolutionsOfFileFromCache(resolvedModuleNames, filePath, getResolvedModule); removeResolutionsOfFileFromCache(resolvedTypeReferenceDirectives, filePath, getResolvedTypeReferenceDirective); } @@ -933,36 +950,36 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD for (const resolution of resolutions) { if (resolution.isInvalidated || !canInvalidate(resolution)) continue; resolution.isInvalidated = invalidated = true; - for (const containingFilePath of ts.Debug.checkDefined(resolution.files)) { - (filesWithInvalidatedResolutions ??= new ts.Set()).add(containingFilePath); + for (const containingFilePath of Debug.checkDefined(resolution.files)) { + (filesWithInvalidatedResolutions ??= new Set()).add(containingFilePath); // When its a file with inferred types resolution, invalidate type reference directive resolution - hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || ts.endsWith(containingFilePath, ts.inferredTypesContainingFile); + hasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames || endsWith(containingFilePath, inferredTypesContainingFile); } } return invalidated; } - function invalidateResolutionOfFile(filePath: ts.Path) { + function invalidateResolutionOfFile(filePath: Path) { removeResolutionsOfFile(filePath); // Resolution is invalidated if the resulting file name is same as the deleted file path const prevHasChangedAutomaticTypeDirectiveNames = hasChangedAutomaticTypeDirectiveNames; - if (invalidateResolutions(resolvedFileToResolution.get(filePath), ts.returnTrue) && + if (invalidateResolutions(resolvedFileToResolution.get(filePath), returnTrue) && hasChangedAutomaticTypeDirectiveNames && !prevHasChangedAutomaticTypeDirectiveNames) { resolutionHost.onChangedAutomaticTypeDirectiveNames(); } } - function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: ts.ReadonlyESMap) { - ts.Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined); + function setFilesWithInvalidatedNonRelativeUnresolvedImports(filesMap: ReadonlyESMap) { + Debug.assert(filesWithInvalidatedNonRelativeUnresolvedImports === filesMap || filesWithInvalidatedNonRelativeUnresolvedImports === undefined); filesWithInvalidatedNonRelativeUnresolvedImports = filesMap; } - function scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath: ts.Path, isCreatingWatchedDirectory: boolean) { + function scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath: Path, isCreatingWatchedDirectory: boolean) { if (isCreatingWatchedDirectory) { // Watching directory is created // Invalidate any resolution has failed lookup in this directory - (isInDirectoryChecks ||= new ts.Set()).add(fileOrDirectoryPath); + (isInDirectoryChecks ||= new Set()).add(fileOrDirectoryPath); } else { // If something to do with folder/file starting with "." in node_modules folder, skip it @@ -977,29 +994,29 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // Some file or directory in the watching directory is created // Return early if it does not have any of the watching extension or not the custom failed lookup path - const dirOfFileOrDirectory = ts.getDirectoryPath(fileOrDirectoryPath); - if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || ts.isNodeModulesDirectory(fileOrDirectoryPath) || - isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || ts.isNodeModulesDirectory(dirOfFileOrDirectory)) { + const dirOfFileOrDirectory = getDirectoryPath(fileOrDirectoryPath); + if (isNodeModulesAtTypesDirectory(fileOrDirectoryPath) || isNodeModulesDirectory(fileOrDirectoryPath) || + isNodeModulesAtTypesDirectory(dirOfFileOrDirectory) || isNodeModulesDirectory(dirOfFileOrDirectory)) { // Invalidate any resolution from this directory - (failedLookupChecks ||= new ts.Set()).add(fileOrDirectoryPath); - (startsWithPathChecks ||= new ts.Set()).add(fileOrDirectoryPath); + (failedLookupChecks ||= new Set()).add(fileOrDirectoryPath); + (startsWithPathChecks ||= new Set()).add(fileOrDirectoryPath); } else { if (!isPathWithDefaultFailedLookupExtension(fileOrDirectoryPath) && !customFailedLookupPaths.has(fileOrDirectoryPath)) { return false; } // Ignore emits from the program - if (ts.isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectoryPath)) { + if (isEmittedFileOfProgram(resolutionHost.getCurrentProgram(), fileOrDirectoryPath)) { return false; } // Resolution need to be invalidated if failed lookup location is same as the file or directory getting created - (failedLookupChecks ||= new ts.Set()).add(fileOrDirectoryPath); + (failedLookupChecks ||= new Set()).add(fileOrDirectoryPath); // If the invalidated file is from a node_modules package, invalidate everything else // in the package since we might not get notifications for other files in the package. // This hardens our logic against unreliable file watchers. - const packagePath = ts.parseNodeModuleFromPath(fileOrDirectoryPath); - if (packagePath) (startsWithPathChecks ||= new ts.Set()).add(packagePath as ts.Path); + const packagePath = parseNodeModuleFromPath(fileOrDirectoryPath); + if (packagePath) (startsWithPathChecks ||= new Set()).add(packagePath as Path); } } resolutionHost.scheduleInvalidateResolutionsOfFailedLookupLocations(); @@ -1009,8 +1026,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD let invalidated = false; if (affectingPathChecksForFile) { resolutionHost.getCurrentProgram()?.getSourceFiles().forEach(f => { - if (ts.some(f.packageJsonLocations, location => affectingPathChecksForFile!.has(location))) { - (filesWithInvalidatedResolutions ??= new ts.Set()).add(f.path); + if (some(f.packageJsonLocations, location => affectingPathChecksForFile!.has(location))) { + (filesWithInvalidatedResolutions ??= new Set()).add(f.path); invalidated = true; } }); @@ -1040,10 +1057,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return resolution.failedLookupLocations.some(location => isInvalidatedFailedLookup(resolutionHost.toPath(location))); } - function isInvalidatedFailedLookup(locationPath: ts.Path) { + function isInvalidatedFailedLookup(locationPath: Path) { return failedLookupChecks?.has(locationPath) || - ts.firstDefinedIterator(startsWithPathChecks?.keys() || ts.emptyIterator, fileOrDirectoryPath => ts.startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || - ts.firstDefinedIterator(isInDirectoryChecks?.keys() || ts.emptyIterator, fileOrDirectoryPath => isInDirectoryPath(fileOrDirectoryPath, locationPath) ? true : undefined); + firstDefinedIterator(startsWithPathChecks?.keys() || emptyIterator, fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || + firstDefinedIterator(isInDirectoryChecks?.keys() || emptyIterator, fileOrDirectoryPath => isInDirectoryPath(fileOrDirectoryPath, locationPath) ? true : undefined); } function canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution: ResolutionWithFailedLookupLocations) { @@ -1051,10 +1068,10 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD } function closeTypeRootsWatch() { - ts.clearMap(typeRootsWatches, ts.closeFileWatcher); + clearMap(typeRootsWatches, closeFileWatcher); } - function getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot: string, typeRootPath: ts.Path): ts.Path | undefined { + function getDirectoryToWatchFailedLookupLocationFromTypeRoot(typeRoot: string, typeRootPath: Path): Path | undefined { if (isInDirectoryPath(rootPath, typeRootPath)) { return rootPath; } @@ -1062,7 +1079,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD return toWatch && directoryWatchesOfFailedLookups.has(toWatch.dirPath) ? toWatch.dirPath : undefined; } - function createTypeRootsWatch(typeRootPath: ts.Path, typeRoot: string): ts.FileWatcher { + function createTypeRootsWatch(typeRootPath: Path, typeRoot: string): FileWatcher { // Create new watch and recursive info return resolutionHost.watchTypeRootsDirectory(typeRoot, fileOrDirectory => { const fileOrDirectoryPath = resolutionHost.toPath(fileOrDirectory); @@ -1083,7 +1100,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD if (dirPath) { scheduleInvalidateResolutionOfFailedLookupLocation(fileOrDirectoryPath, dirPath === fileOrDirectoryPath); } - }, ts.WatchDirectoryFlags.Recursive); + }, WatchDirectoryFlags.Recursive); } /** @@ -1101,14 +1118,14 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD // we need to assume the directories exist to ensure that we can get all the type root directories that get included // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them - const typeRoots = ts.getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory }); + const typeRoots = getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory }); if (typeRoots) { - ts.mutateMap( + mutateMap( typeRootsWatches, - ts.arrayToMap(typeRoots, tr => resolutionHost.toPath(tr)), + arrayToMap(typeRoots, tr => resolutionHost.toPath(tr)), { createNewValue: createTypeRootsWatch, - onDeleteValue: ts.closeFileWatcher + onDeleteValue: closeFileWatcher } ); } @@ -1123,7 +1140,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD * Hence return true for all directories except root directories which are filtered from watching */ function directoryExistsForTypeRootWatch(nodeTypesDirectory: string) { - const dir = ts.getDirectoryPath(ts.getDirectoryPath(nodeTypesDirectory)); + const dir = getDirectoryPath(getDirectoryPath(nodeTypesDirectory)); const dirPath = resolutionHost.toPath(dir); return dirPath === rootPath || canWatchDirectoryOrFile(dirPath); } @@ -1131,7 +1148,7 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function resolutionIsSymlink(resolution: ResolutionWithFailedLookupLocations) { return !!( - (resolution as ts.ResolvedModuleWithFailedLookupLocations).resolvedModule?.originalPath || - (resolution as ts.ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective?.originalPath + (resolution as ResolvedModuleWithFailedLookupLocations).resolvedModule?.originalPath || + (resolution as ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective?.originalPath ); } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 0552d246894f6..107b1680480cd 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -1,20 +1,25 @@ -import * as ts from "./_namespaces/ts"; +import { + append, arraysEqual, binarySearch, CharacterCodes, CommentDirective, CommentDirectiveType, CommentKind, + CommentRange, compareValues, Debug, DiagnosticMessage, Diagnostics, ESMap, getEntries, identity, JSDocSyntaxKind, + JsxTokenSyntaxKind, KeywordSyntaxKind, LanguageVariant, LineAndCharacter, Map, MapLike, parsePseudoBigInt, + positionIsSynthesized, ScriptTarget, SourceFileLike, SyntaxKind, TokenFlags, trimStringStart, +} from "./_namespaces/ts"; -export type ErrorCallback = (message: ts.DiagnosticMessage, length: number) => void; +export type ErrorCallback = (message: DiagnosticMessage, length: number) => void; /* @internal */ -export function tokenIsIdentifierOrKeyword(token: ts.SyntaxKind): boolean { - return token >= ts.SyntaxKind.Identifier; +export function tokenIsIdentifierOrKeyword(token: SyntaxKind): boolean { + return token >= SyntaxKind.Identifier; } /* @internal */ -export function tokenIsIdentifierOrKeywordOrGreaterThan(token: ts.SyntaxKind): boolean { - return token === ts.SyntaxKind.GreaterThanToken || tokenIsIdentifierOrKeyword(token); +export function tokenIsIdentifierOrKeywordOrGreaterThan(token: SyntaxKind): boolean { + return token === SyntaxKind.GreaterThanToken || tokenIsIdentifierOrKeyword(token); } export interface Scanner { getStartPos(): number; - getToken(): ts.SyntaxKind; + getToken(): SyntaxKind; getTextPos(): number; getTokenPos(): number; getTokenText(): string; @@ -28,27 +33,27 @@ export interface Scanner { isReservedWord(): boolean; isUnterminated(): boolean; /* @internal */ - getNumericLiteralFlags(): ts.TokenFlags; + getNumericLiteralFlags(): TokenFlags; /* @internal */ - getCommentDirectives(): ts.CommentDirective[] | undefined; + getCommentDirectives(): CommentDirective[] | undefined; /* @internal */ - getTokenFlags(): ts.TokenFlags; - reScanGreaterToken(): ts.SyntaxKind; - reScanSlashToken(): ts.SyntaxKind; - reScanAsteriskEqualsToken(): ts.SyntaxKind; - reScanTemplateToken(isTaggedTemplate: boolean): ts.SyntaxKind; - reScanTemplateHeadOrNoSubstitutionTemplate(): ts.SyntaxKind; - scanJsxIdentifier(): ts.SyntaxKind; - scanJsxAttributeValue(): ts.SyntaxKind; - reScanJsxAttributeValue(): ts.SyntaxKind; - reScanJsxToken(allowMultilineJsxText?: boolean): ts.JsxTokenSyntaxKind; - reScanLessThanToken(): ts.SyntaxKind; - reScanHashToken(): ts.SyntaxKind; - reScanQuestionToken(): ts.SyntaxKind; - reScanInvalidIdentifier(): ts.SyntaxKind; - scanJsxToken(): ts.JsxTokenSyntaxKind; - scanJsDocToken(): ts.JSDocSyntaxKind; - scan(): ts.SyntaxKind; + getTokenFlags(): TokenFlags; + reScanGreaterToken(): SyntaxKind; + reScanSlashToken(): SyntaxKind; + reScanAsteriskEqualsToken(): SyntaxKind; + reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind; + reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind; + scanJsxIdentifier(): SyntaxKind; + scanJsxAttributeValue(): SyntaxKind; + reScanJsxAttributeValue(): SyntaxKind; + reScanJsxToken(allowMultilineJsxText?: boolean): JsxTokenSyntaxKind; + reScanLessThanToken(): SyntaxKind; + reScanHashToken(): SyntaxKind; + reScanQuestionToken(): SyntaxKind; + reScanInvalidIdentifier(): SyntaxKind; + scanJsxToken(): JsxTokenSyntaxKind; + scanJsDocToken(): JSDocSyntaxKind; + scan(): SyntaxKind; getText(): string; /* @internal */ @@ -57,8 +62,8 @@ export interface Scanner { // can be provided to have the scanner only scan a portion of the text. setText(text: string | undefined, start?: number, length?: number): void; setOnError(onError: ErrorCallback | undefined): void; - setScriptTarget(scriptTarget: ts.ScriptTarget): void; - setLanguageVariant(variant: ts.LanguageVariant): void; + setScriptTarget(scriptTarget: ScriptTarget): void; + setLanguageVariant(variant: LanguageVariant): void; setTextPos(textPos: number): void; /* @internal */ setInJSDocType(inType: boolean): void; @@ -79,156 +84,156 @@ export interface Scanner { } /** @internal */ -export const textToKeywordObj: ts.MapLike = { - abstract: ts.SyntaxKind.AbstractKeyword, - accessor: ts.SyntaxKind.AccessorKeyword, - any: ts.SyntaxKind.AnyKeyword, - as: ts.SyntaxKind.AsKeyword, - asserts: ts.SyntaxKind.AssertsKeyword, - assert: ts.SyntaxKind.AssertKeyword, - bigint: ts.SyntaxKind.BigIntKeyword, - boolean: ts.SyntaxKind.BooleanKeyword, - break: ts.SyntaxKind.BreakKeyword, - case: ts.SyntaxKind.CaseKeyword, - catch: ts.SyntaxKind.CatchKeyword, - class: ts.SyntaxKind.ClassKeyword, - continue: ts.SyntaxKind.ContinueKeyword, - const: ts.SyntaxKind.ConstKeyword, - ["" + "constructor"]: ts.SyntaxKind.ConstructorKeyword, - debugger: ts.SyntaxKind.DebuggerKeyword, - declare: ts.SyntaxKind.DeclareKeyword, - default: ts.SyntaxKind.DefaultKeyword, - delete: ts.SyntaxKind.DeleteKeyword, - do: ts.SyntaxKind.DoKeyword, - else: ts.SyntaxKind.ElseKeyword, - enum: ts.SyntaxKind.EnumKeyword, - export: ts.SyntaxKind.ExportKeyword, - extends: ts.SyntaxKind.ExtendsKeyword, - false: ts.SyntaxKind.FalseKeyword, - finally: ts.SyntaxKind.FinallyKeyword, - for: ts.SyntaxKind.ForKeyword, - from: ts.SyntaxKind.FromKeyword, - function: ts.SyntaxKind.FunctionKeyword, - get: ts.SyntaxKind.GetKeyword, - if: ts.SyntaxKind.IfKeyword, - implements: ts.SyntaxKind.ImplementsKeyword, - import: ts.SyntaxKind.ImportKeyword, - in: ts.SyntaxKind.InKeyword, - infer: ts.SyntaxKind.InferKeyword, - instanceof: ts.SyntaxKind.InstanceOfKeyword, - interface: ts.SyntaxKind.InterfaceKeyword, - intrinsic: ts.SyntaxKind.IntrinsicKeyword, - is: ts.SyntaxKind.IsKeyword, - keyof: ts.SyntaxKind.KeyOfKeyword, - let: ts.SyntaxKind.LetKeyword, - module: ts.SyntaxKind.ModuleKeyword, - namespace: ts.SyntaxKind.NamespaceKeyword, - never: ts.SyntaxKind.NeverKeyword, - new: ts.SyntaxKind.NewKeyword, - null: ts.SyntaxKind.NullKeyword, - number: ts.SyntaxKind.NumberKeyword, - object: ts.SyntaxKind.ObjectKeyword, - package: ts.SyntaxKind.PackageKeyword, - private: ts.SyntaxKind.PrivateKeyword, - protected: ts.SyntaxKind.ProtectedKeyword, - public: ts.SyntaxKind.PublicKeyword, - override: ts.SyntaxKind.OverrideKeyword, - out: ts.SyntaxKind.OutKeyword, - readonly: ts.SyntaxKind.ReadonlyKeyword, - require: ts.SyntaxKind.RequireKeyword, - global: ts.SyntaxKind.GlobalKeyword, - return: ts.SyntaxKind.ReturnKeyword, - satisfies: ts.SyntaxKind.SatisfiesKeyword, - set: ts.SyntaxKind.SetKeyword, - static: ts.SyntaxKind.StaticKeyword, - string: ts.SyntaxKind.StringKeyword, - super: ts.SyntaxKind.SuperKeyword, - switch: ts.SyntaxKind.SwitchKeyword, - symbol: ts.SyntaxKind.SymbolKeyword, - this: ts.SyntaxKind.ThisKeyword, - throw: ts.SyntaxKind.ThrowKeyword, - true: ts.SyntaxKind.TrueKeyword, - try: ts.SyntaxKind.TryKeyword, - type: ts.SyntaxKind.TypeKeyword, - typeof: ts.SyntaxKind.TypeOfKeyword, - undefined: ts.SyntaxKind.UndefinedKeyword, - unique: ts.SyntaxKind.UniqueKeyword, - unknown: ts.SyntaxKind.UnknownKeyword, - var: ts.SyntaxKind.VarKeyword, - void: ts.SyntaxKind.VoidKeyword, - while: ts.SyntaxKind.WhileKeyword, - with: ts.SyntaxKind.WithKeyword, - yield: ts.SyntaxKind.YieldKeyword, - async: ts.SyntaxKind.AsyncKeyword, - await: ts.SyntaxKind.AwaitKeyword, - of: ts.SyntaxKind.OfKeyword, +export const textToKeywordObj: MapLike = { + abstract: SyntaxKind.AbstractKeyword, + accessor: SyntaxKind.AccessorKeyword, + any: SyntaxKind.AnyKeyword, + as: SyntaxKind.AsKeyword, + asserts: SyntaxKind.AssertsKeyword, + assert: SyntaxKind.AssertKeyword, + bigint: SyntaxKind.BigIntKeyword, + boolean: SyntaxKind.BooleanKeyword, + break: SyntaxKind.BreakKeyword, + case: SyntaxKind.CaseKeyword, + catch: SyntaxKind.CatchKeyword, + class: SyntaxKind.ClassKeyword, + continue: SyntaxKind.ContinueKeyword, + const: SyntaxKind.ConstKeyword, + ["" + "constructor"]: SyntaxKind.ConstructorKeyword, + debugger: SyntaxKind.DebuggerKeyword, + declare: SyntaxKind.DeclareKeyword, + default: SyntaxKind.DefaultKeyword, + delete: SyntaxKind.DeleteKeyword, + do: SyntaxKind.DoKeyword, + else: SyntaxKind.ElseKeyword, + enum: SyntaxKind.EnumKeyword, + export: SyntaxKind.ExportKeyword, + extends: SyntaxKind.ExtendsKeyword, + false: SyntaxKind.FalseKeyword, + finally: SyntaxKind.FinallyKeyword, + for: SyntaxKind.ForKeyword, + from: SyntaxKind.FromKeyword, + function: SyntaxKind.FunctionKeyword, + get: SyntaxKind.GetKeyword, + if: SyntaxKind.IfKeyword, + implements: SyntaxKind.ImplementsKeyword, + import: SyntaxKind.ImportKeyword, + in: SyntaxKind.InKeyword, + infer: SyntaxKind.InferKeyword, + instanceof: SyntaxKind.InstanceOfKeyword, + interface: SyntaxKind.InterfaceKeyword, + intrinsic: SyntaxKind.IntrinsicKeyword, + is: SyntaxKind.IsKeyword, + keyof: SyntaxKind.KeyOfKeyword, + let: SyntaxKind.LetKeyword, + module: SyntaxKind.ModuleKeyword, + namespace: SyntaxKind.NamespaceKeyword, + never: SyntaxKind.NeverKeyword, + new: SyntaxKind.NewKeyword, + null: SyntaxKind.NullKeyword, + number: SyntaxKind.NumberKeyword, + object: SyntaxKind.ObjectKeyword, + package: SyntaxKind.PackageKeyword, + private: SyntaxKind.PrivateKeyword, + protected: SyntaxKind.ProtectedKeyword, + public: SyntaxKind.PublicKeyword, + override: SyntaxKind.OverrideKeyword, + out: SyntaxKind.OutKeyword, + readonly: SyntaxKind.ReadonlyKeyword, + require: SyntaxKind.RequireKeyword, + global: SyntaxKind.GlobalKeyword, + return: SyntaxKind.ReturnKeyword, + satisfies: SyntaxKind.SatisfiesKeyword, + set: SyntaxKind.SetKeyword, + static: SyntaxKind.StaticKeyword, + string: SyntaxKind.StringKeyword, + super: SyntaxKind.SuperKeyword, + switch: SyntaxKind.SwitchKeyword, + symbol: SyntaxKind.SymbolKeyword, + this: SyntaxKind.ThisKeyword, + throw: SyntaxKind.ThrowKeyword, + true: SyntaxKind.TrueKeyword, + try: SyntaxKind.TryKeyword, + type: SyntaxKind.TypeKeyword, + typeof: SyntaxKind.TypeOfKeyword, + undefined: SyntaxKind.UndefinedKeyword, + unique: SyntaxKind.UniqueKeyword, + unknown: SyntaxKind.UnknownKeyword, + var: SyntaxKind.VarKeyword, + void: SyntaxKind.VoidKeyword, + while: SyntaxKind.WhileKeyword, + with: SyntaxKind.WithKeyword, + yield: SyntaxKind.YieldKeyword, + async: SyntaxKind.AsyncKeyword, + await: SyntaxKind.AwaitKeyword, + of: SyntaxKind.OfKeyword, }; -const textToKeyword = new ts.Map(ts.getEntries(textToKeywordObj)); +const textToKeyword = new Map(getEntries(textToKeywordObj)); -const textToToken = new ts.Map(ts.getEntries({ +const textToToken = new Map(getEntries({ ...textToKeywordObj, - "{": ts.SyntaxKind.OpenBraceToken, - "}": ts.SyntaxKind.CloseBraceToken, - "(": ts.SyntaxKind.OpenParenToken, - ")": ts.SyntaxKind.CloseParenToken, - "[": ts.SyntaxKind.OpenBracketToken, - "]": ts.SyntaxKind.CloseBracketToken, - ".": ts.SyntaxKind.DotToken, - "...": ts.SyntaxKind.DotDotDotToken, - ";": ts.SyntaxKind.SemicolonToken, - ",": ts.SyntaxKind.CommaToken, - "<": ts.SyntaxKind.LessThanToken, - ">": ts.SyntaxKind.GreaterThanToken, - "<=": ts.SyntaxKind.LessThanEqualsToken, - ">=": ts.SyntaxKind.GreaterThanEqualsToken, - "==": ts.SyntaxKind.EqualsEqualsToken, - "!=": ts.SyntaxKind.ExclamationEqualsToken, - "===": ts.SyntaxKind.EqualsEqualsEqualsToken, - "!==": ts.SyntaxKind.ExclamationEqualsEqualsToken, - "=>": ts.SyntaxKind.EqualsGreaterThanToken, - "+": ts.SyntaxKind.PlusToken, - "-": ts.SyntaxKind.MinusToken, - "**": ts.SyntaxKind.AsteriskAsteriskToken, - "*": ts.SyntaxKind.AsteriskToken, - "/": ts.SyntaxKind.SlashToken, - "%": ts.SyntaxKind.PercentToken, - "++": ts.SyntaxKind.PlusPlusToken, - "--": ts.SyntaxKind.MinusMinusToken, - "<<": ts.SyntaxKind.LessThanLessThanToken, - ">": ts.SyntaxKind.GreaterThanGreaterThanToken, - ">>>": ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken, - "&": ts.SyntaxKind.AmpersandToken, - "|": ts.SyntaxKind.BarToken, - "^": ts.SyntaxKind.CaretToken, - "!": ts.SyntaxKind.ExclamationToken, - "~": ts.SyntaxKind.TildeToken, - "&&": ts.SyntaxKind.AmpersandAmpersandToken, - "||": ts.SyntaxKind.BarBarToken, - "?": ts.SyntaxKind.QuestionToken, - "??": ts.SyntaxKind.QuestionQuestionToken, - "?.": ts.SyntaxKind.QuestionDotToken, - ":": ts.SyntaxKind.ColonToken, - "=": ts.SyntaxKind.EqualsToken, - "+=": ts.SyntaxKind.PlusEqualsToken, - "-=": ts.SyntaxKind.MinusEqualsToken, - "*=": ts.SyntaxKind.AsteriskEqualsToken, - "**=": ts.SyntaxKind.AsteriskAsteriskEqualsToken, - "/=": ts.SyntaxKind.SlashEqualsToken, - "%=": ts.SyntaxKind.PercentEqualsToken, - "<<=": ts.SyntaxKind.LessThanLessThanEqualsToken, - ">>=": ts.SyntaxKind.GreaterThanGreaterThanEqualsToken, - ">>>=": ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken, - "&=": ts.SyntaxKind.AmpersandEqualsToken, - "|=": ts.SyntaxKind.BarEqualsToken, - "^=": ts.SyntaxKind.CaretEqualsToken, - "||=": ts.SyntaxKind.BarBarEqualsToken, - "&&=": ts.SyntaxKind.AmpersandAmpersandEqualsToken, - "??=": ts.SyntaxKind.QuestionQuestionEqualsToken, - "@": ts.SyntaxKind.AtToken, - "#": ts.SyntaxKind.HashToken, - "`": ts.SyntaxKind.BacktickToken, + "{": SyntaxKind.OpenBraceToken, + "}": SyntaxKind.CloseBraceToken, + "(": SyntaxKind.OpenParenToken, + ")": SyntaxKind.CloseParenToken, + "[": SyntaxKind.OpenBracketToken, + "]": SyntaxKind.CloseBracketToken, + ".": SyntaxKind.DotToken, + "...": SyntaxKind.DotDotDotToken, + ";": SyntaxKind.SemicolonToken, + ",": SyntaxKind.CommaToken, + "<": SyntaxKind.LessThanToken, + ">": SyntaxKind.GreaterThanToken, + "<=": SyntaxKind.LessThanEqualsToken, + ">=": SyntaxKind.GreaterThanEqualsToken, + "==": SyntaxKind.EqualsEqualsToken, + "!=": SyntaxKind.ExclamationEqualsToken, + "===": SyntaxKind.EqualsEqualsEqualsToken, + "!==": SyntaxKind.ExclamationEqualsEqualsToken, + "=>": SyntaxKind.EqualsGreaterThanToken, + "+": SyntaxKind.PlusToken, + "-": SyntaxKind.MinusToken, + "**": SyntaxKind.AsteriskAsteriskToken, + "*": SyntaxKind.AsteriskToken, + "/": SyntaxKind.SlashToken, + "%": SyntaxKind.PercentToken, + "++": SyntaxKind.PlusPlusToken, + "--": SyntaxKind.MinusMinusToken, + "<<": SyntaxKind.LessThanLessThanToken, + ">": SyntaxKind.GreaterThanGreaterThanToken, + ">>>": SyntaxKind.GreaterThanGreaterThanGreaterThanToken, + "&": SyntaxKind.AmpersandToken, + "|": SyntaxKind.BarToken, + "^": SyntaxKind.CaretToken, + "!": SyntaxKind.ExclamationToken, + "~": SyntaxKind.TildeToken, + "&&": SyntaxKind.AmpersandAmpersandToken, + "||": SyntaxKind.BarBarToken, + "?": SyntaxKind.QuestionToken, + "??": SyntaxKind.QuestionQuestionToken, + "?.": SyntaxKind.QuestionDotToken, + ":": SyntaxKind.ColonToken, + "=": SyntaxKind.EqualsToken, + "+=": SyntaxKind.PlusEqualsToken, + "-=": SyntaxKind.MinusEqualsToken, + "*=": SyntaxKind.AsteriskEqualsToken, + "**=": SyntaxKind.AsteriskAsteriskEqualsToken, + "/=": SyntaxKind.SlashEqualsToken, + "%=": SyntaxKind.PercentEqualsToken, + "<<=": SyntaxKind.LessThanLessThanEqualsToken, + ">>=": SyntaxKind.GreaterThanGreaterThanEqualsToken, + ">>>=": SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken, + "&=": SyntaxKind.AmpersandEqualsToken, + "|=": SyntaxKind.BarEqualsToken, + "^=": SyntaxKind.CaretEqualsToken, + "||=": SyntaxKind.BarBarEqualsToken, + "&&=": SyntaxKind.AmpersandAmpersandEqualsToken, + "??=": SyntaxKind.QuestionQuestionEqualsToken, + "@": SyntaxKind.AtToken, + "#": SyntaxKind.HashToken, + "`": SyntaxKind.BacktickToken, })); /* @@ -328,21 +333,21 @@ function lookupInUnicodeMap(code: number, map: readonly number[]): boolean { return false; } -/* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ts.ScriptTarget | undefined) { - return languageVersion! >= ts.ScriptTarget.ES2015 ? +/* @internal */ export function isUnicodeIdentifierStart(code: number, languageVersion: ScriptTarget | undefined) { + return languageVersion! >= ScriptTarget.ES2015 ? lookupInUnicodeMap(code, unicodeESNextIdentifierStart) : - languageVersion === ts.ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : + languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierStart) : lookupInUnicodeMap(code, unicodeES3IdentifierStart); } -function isUnicodeIdentifierPart(code: number, languageVersion: ts.ScriptTarget | undefined) { - return languageVersion! >= ts.ScriptTarget.ES2015 ? +function isUnicodeIdentifierPart(code: number, languageVersion: ScriptTarget | undefined) { + return languageVersion! >= ScriptTarget.ES2015 ? lookupInUnicodeMap(code, unicodeESNextIdentifierPart) : - languageVersion === ts.ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : + languageVersion === ScriptTarget.ES5 ? lookupInUnicodeMap(code, unicodeES5IdentifierPart) : lookupInUnicodeMap(code, unicodeES3IdentifierPart); } -function makeReverseMap(source: ts.ESMap): string[] { +function makeReverseMap(source: ESMap): string[] { const result: string[] = []; source.forEach((value, name) => { result[value] = name; @@ -351,12 +356,12 @@ function makeReverseMap(source: ts.ESMap): string[] { } const tokenStrings = makeReverseMap(textToToken); -export function tokenToString(t: ts.SyntaxKind): string | undefined { +export function tokenToString(t: SyntaxKind): string | undefined { return tokenStrings[t]; } /* @internal */ -export function stringToToken(s: string): ts.SyntaxKind | undefined { +export function stringToToken(s: string): SyntaxKind | undefined { return textToToken.get(s); } @@ -369,17 +374,17 @@ export function computeLineStarts(text: string): number[] { const ch = text.charCodeAt(pos); pos++; switch (ch) { - case ts.CharacterCodes.carriageReturn: - if (text.charCodeAt(pos) === ts.CharacterCodes.lineFeed) { + case CharacterCodes.carriageReturn: + if (text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } // falls through - case ts.CharacterCodes.lineFeed: + case CharacterCodes.lineFeed: result.push(lineStart); lineStart = pos; break; default: - if (ch > ts.CharacterCodes.maxAsciiCharacter && isLineBreak(ch)) { + if (ch > CharacterCodes.maxAsciiCharacter && isLineBreak(ch)) { result.push(lineStart); lineStart = pos; } @@ -390,10 +395,10 @@ export function computeLineStarts(text: string): number[] { return result; } -export function getPositionOfLineAndCharacter(sourceFile: ts.SourceFileLike, line: number, character: number): number; +export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number): number; /* @internal */ -export function getPositionOfLineAndCharacter(sourceFile: ts.SourceFileLike, line: number, character: number, allowEdits?: true): number; // eslint-disable-line @typescript-eslint/unified-signatures -export function getPositionOfLineAndCharacter(sourceFile: ts.SourceFileLike, line: number, character: number, allowEdits?: true): number { +export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number; // eslint-disable-line @typescript-eslint/unified-signatures +export function getPositionOfLineAndCharacter(sourceFile: SourceFileLike, line: number, character: number, allowEdits?: true): number { return sourceFile.getPositionOfLineAndCharacter ? sourceFile.getPositionOfLineAndCharacter(line, character, allowEdits) : computePositionOfLineAndCharacter(getLineStarts(sourceFile), line, character, sourceFile.text, allowEdits); @@ -407,7 +412,7 @@ export function computePositionOfLineAndCharacter(lineStarts: readonly number[], line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line; } else { - ts.Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? ts.arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`); + Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`); } } @@ -419,21 +424,21 @@ export function computePositionOfLineAndCharacter(lineStarts: readonly number[], return res > lineStarts[line + 1] ? lineStarts[line + 1] : typeof debugText === "string" && res > debugText.length ? debugText.length : res; } if (line < lineStarts.length - 1) { - ts.Debug.assert(res < lineStarts[line + 1]); + Debug.assert(res < lineStarts[line + 1]); } else if (debugText !== undefined) { - ts.Debug.assert(res <= debugText.length); // Allow single character overflow for trailing newline + Debug.assert(res <= debugText.length); // Allow single character overflow for trailing newline } return res; } /* @internal */ -export function getLineStarts(sourceFile: ts.SourceFileLike): readonly number[] { +export function getLineStarts(sourceFile: SourceFileLike): readonly number[] { return sourceFile.lineMap || (sourceFile.lineMap = computeLineStarts(sourceFile.text)); } /* @internal */ -export function computeLineAndCharacterOfPosition(lineStarts: readonly number[], position: number): ts.LineAndCharacter { +export function computeLineAndCharacterOfPosition(lineStarts: readonly number[], position: number): LineAndCharacter { const lineNumber = computeLineOfPosition(lineStarts, position); return { line: lineNumber, @@ -446,7 +451,7 @@ export function computeLineAndCharacterOfPosition(lineStarts: readonly number[], * We assume the first line starts at position 0 and 'position' is non-negative. */ export function computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number) { - let lineNumber = ts.binarySearch(lineStarts, position, ts.identity, ts.compareValues, lowerBound); + let lineNumber = binarySearch(lineStarts, position, identity, compareValues, lowerBound); if (lineNumber < 0) { // If the actual position was not found, // the binary search returns the 2's-complement of the next line start @@ -456,13 +461,13 @@ export function computeLineOfPosition(lineStarts: readonly number[], position: n // We want the index of the previous line start, so we subtract 1. // Review 2's-complement if this is confusing. lineNumber = ~lineNumber - 1; - ts.Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); + Debug.assert(lineNumber !== -1, "position cannot precede the beginning of the file"); } return lineNumber; } /** @internal */ -export function getLinesBetweenPositions(sourceFile: ts.SourceFileLike, pos1: number, pos2: number) { +export function getLinesBetweenPositions(sourceFile: SourceFileLike, pos1: number, pos2: number) { if (pos1 === pos2) return 0; const lineStarts = getLineStarts(sourceFile); const lower = Math.min(pos1, pos2); @@ -473,7 +478,7 @@ export function getLinesBetweenPositions(sourceFile: ts.SourceFileLike, pos1: nu return isNegative ? lowerLine - upperLine : upperLine - lowerLine; } -export function getLineAndCharacterOfPosition(sourceFile: ts.SourceFileLike, position: number): ts.LineAndCharacter { +export function getLineAndCharacterOfPosition(sourceFile: SourceFileLike, position: number): LineAndCharacter { return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position); } @@ -485,18 +490,18 @@ export function isWhiteSpaceLike(ch: number): boolean { export function isWhiteSpaceSingleLine(ch: number): boolean { // Note: nextLine is in the Zs space, and should be considered to be a whitespace. // It is explicitly not a line-break as it isn't in the exact set specified by EcmaScript. - return ch === ts.CharacterCodes.space || - ch === ts.CharacterCodes.tab || - ch === ts.CharacterCodes.verticalTab || - ch === ts.CharacterCodes.formFeed || - ch === ts.CharacterCodes.nonBreakingSpace || - ch === ts.CharacterCodes.nextLine || - ch === ts.CharacterCodes.ogham || - ch >= ts.CharacterCodes.enQuad && ch <= ts.CharacterCodes.zeroWidthSpace || - ch === ts.CharacterCodes.narrowNoBreakSpace || - ch === ts.CharacterCodes.mathematicalSpace || - ch === ts.CharacterCodes.ideographicSpace || - ch === ts.CharacterCodes.byteOrderMark; + return ch === CharacterCodes.space || + ch === CharacterCodes.tab || + ch === CharacterCodes.verticalTab || + ch === CharacterCodes.formFeed || + ch === CharacterCodes.nonBreakingSpace || + ch === CharacterCodes.nextLine || + ch === CharacterCodes.ogham || + ch >= CharacterCodes.enQuad && ch <= CharacterCodes.zeroWidthSpace || + ch === CharacterCodes.narrowNoBreakSpace || + ch === CharacterCodes.mathematicalSpace || + ch === CharacterCodes.ideographicSpace || + ch === CharacterCodes.byteOrderMark; } export function isLineBreak(ch: number): boolean { @@ -511,18 +516,18 @@ export function isLineBreak(ch: number): boolean { // Only the characters in Table 3 are treated as line terminators. Other new line or line // breaking characters are treated as white space but not as line terminators. - return ch === ts.CharacterCodes.lineFeed || - ch === ts.CharacterCodes.carriageReturn || - ch === ts.CharacterCodes.lineSeparator || - ch === ts.CharacterCodes.paragraphSeparator; + return ch === CharacterCodes.lineFeed || + ch === CharacterCodes.carriageReturn || + ch === CharacterCodes.lineSeparator || + ch === CharacterCodes.paragraphSeparator; } function isDigit(ch: number): boolean { - return ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9; + return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } function isHexDigit(ch: number): boolean { - return isDigit(ch) || ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.F || ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.f; + return isDigit(ch) || ch >= CharacterCodes.A && ch <= CharacterCodes.F || ch >= CharacterCodes.a && ch <= CharacterCodes.f; } function isCodePoint(code: number): boolean { @@ -531,39 +536,39 @@ function isCodePoint(code: number): boolean { /* @internal */ export function isOctalDigit(ch: number): boolean { - return ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._7; + return ch >= CharacterCodes._0 && ch <= CharacterCodes._7; } export function couldStartTrivia(text: string, pos: number): boolean { // Keep in sync with skipTrivia const ch = text.charCodeAt(pos); switch (ch) { - case ts.CharacterCodes.carriageReturn: - case ts.CharacterCodes.lineFeed: - case ts.CharacterCodes.tab: - case ts.CharacterCodes.verticalTab: - case ts.CharacterCodes.formFeed: - case ts.CharacterCodes.space: - case ts.CharacterCodes.slash: + case CharacterCodes.carriageReturn: + case CharacterCodes.lineFeed: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: + case CharacterCodes.slash: // starts of normal trivia // falls through - case ts.CharacterCodes.lessThan: - case ts.CharacterCodes.bar: - case ts.CharacterCodes.equals: - case ts.CharacterCodes.greaterThan: + case CharacterCodes.lessThan: + case CharacterCodes.bar: + case CharacterCodes.equals: + case CharacterCodes.greaterThan: // Starts of conflict marker trivia return true; - case ts.CharacterCodes.hash: + case CharacterCodes.hash: // Only if its the beginning can we have #! trivia return pos === 0; default: - return ch > ts.CharacterCodes.maxAsciiCharacter; + return ch > CharacterCodes.maxAsciiCharacter; } } /* @internal */ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean, stopAtComments?: boolean, inJSDoc?: boolean): number { - if (ts.positionIsSynthesized(pos)) { + if (positionIsSynthesized(pos)) { return pos; } @@ -572,29 +577,29 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole while (true) { const ch = text.charCodeAt(pos); switch (ch) { - case ts.CharacterCodes.carriageReturn: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.lineFeed) { + case CharacterCodes.carriageReturn: + if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { pos++; } // falls through - case ts.CharacterCodes.lineFeed: + case CharacterCodes.lineFeed: pos++; if (stopAfterLineBreak) { return pos; } canConsumeStar = !!inJSDoc; continue; - case ts.CharacterCodes.tab: - case ts.CharacterCodes.verticalTab: - case ts.CharacterCodes.formFeed: - case ts.CharacterCodes.space: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: pos++; continue; - case ts.CharacterCodes.slash: + case CharacterCodes.slash: if (stopAtComments) { break; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { @@ -605,10 +610,10 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole canConsumeStar = false; continue; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.asterisk) { + if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; while (pos < text.length) { - if (text.charCodeAt(pos) === ts.CharacterCodes.asterisk && text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; break; } @@ -619,10 +624,10 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole } break; - case ts.CharacterCodes.lessThan: - case ts.CharacterCodes.bar: - case ts.CharacterCodes.equals: - case ts.CharacterCodes.greaterThan: + case CharacterCodes.lessThan: + case CharacterCodes.bar: + case CharacterCodes.equals: + case CharacterCodes.greaterThan: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos); canConsumeStar = false; @@ -630,7 +635,7 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole } break; - case ts.CharacterCodes.hash: + case CharacterCodes.hash: if (pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); canConsumeStar = false; @@ -638,7 +643,7 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole } break; - case ts.CharacterCodes.asterisk: + case CharacterCodes.asterisk: if (canConsumeStar) { pos++; canConsumeStar = false; @@ -647,7 +652,7 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole break; default: - if (ch > ts.CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { pos++; continue; } @@ -662,7 +667,7 @@ export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boole const mergeConflictMarkerLength = "<<<<<<<".length; function isConflictMarkerTrivia(text: string, pos: number) { - ts.Debug.assert(pos >= 0); + Debug.assert(pos >= 0); // Conflict markers must be at the start of a line. if (pos === 0 || isLineBreak(text.charCodeAt(pos - 1))) { @@ -675,34 +680,34 @@ function isConflictMarkerTrivia(text: string, pos: number) { } } - return ch === ts.CharacterCodes.equals || - text.charCodeAt(pos + mergeConflictMarkerLength) === ts.CharacterCodes.space; + return ch === CharacterCodes.equals || + text.charCodeAt(pos + mergeConflictMarkerLength) === CharacterCodes.space; } } return false; } -function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: ts.DiagnosticMessage, pos?: number, len?: number) => void) { +function scanConflictMarkerTrivia(text: string, pos: number, error?: (diag: DiagnosticMessage, pos?: number, len?: number) => void) { if (error) { - error(ts.Diagnostics.Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength); + error(Diagnostics.Merge_conflict_marker_encountered, pos, mergeConflictMarkerLength); } const ch = text.charCodeAt(pos); const len = text.length; - if (ch === ts.CharacterCodes.lessThan || ch === ts.CharacterCodes.greaterThan) { + if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) { while (pos < len && !isLineBreak(text.charCodeAt(pos))) { pos++; } } else { - ts.Debug.assert(ch === ts.CharacterCodes.bar || ch === ts.CharacterCodes.equals); + Debug.assert(ch === CharacterCodes.bar || ch === CharacterCodes.equals); // Consume everything from the start of a ||||||| or ======= marker to the start // of the next ======= or >>>>>>> marker. while (pos < len) { const currentChar = text.charCodeAt(pos); - if ((currentChar === ts.CharacterCodes.equals || currentChar === ts.CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { + if ((currentChar === CharacterCodes.equals || currentChar === CharacterCodes.greaterThan) && currentChar !== ch && isConflictMarkerTrivia(text, pos)) { break; } @@ -718,7 +723,7 @@ const shebangTriviaRegex = /^#!.*/; /*@internal*/ export function isShebangTrivia(text: string, pos: number) { // Shebangs check must only be done at the start of the file - ts.Debug.assert(pos === 0); + Debug.assert(pos === 0); return shebangTriviaRegex.test(text); } @@ -749,10 +754,10 @@ export function scanShebangTrivia(text: string, pos: number) { * @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy * return value of the callback. */ -function iterateCommentRanges(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined { +function iterateCommentRanges(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U | undefined) => U, state: T, initial?: U): U | undefined { let pendingPos!: number; let pendingEnd!: number; - let pendingKind!: ts.CommentKind; + let pendingKind!: CommentKind; let pendingHasTrailingNewLine!: boolean; let hasPendingCommentRange = false; let collecting = trailing; @@ -767,12 +772,12 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, scan: while (pos >= 0 && pos < text.length) { const ch = text.charCodeAt(pos); switch (ch) { - case ts.CharacterCodes.carriageReturn: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.lineFeed) { + case CharacterCodes.carriageReturn: + if (text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { pos++; } // falls through - case ts.CharacterCodes.lineFeed: + case CharacterCodes.lineFeed: pos++; if (trailing) { break scan; @@ -784,20 +789,20 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, } continue; - case ts.CharacterCodes.tab: - case ts.CharacterCodes.verticalTab: - case ts.CharacterCodes.formFeed: - case ts.CharacterCodes.space: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: pos++; continue; - case ts.CharacterCodes.slash: + case CharacterCodes.slash: const nextChar = text.charCodeAt(pos + 1); let hasTrailingNewLine = false; - if (nextChar === ts.CharacterCodes.slash || nextChar === ts.CharacterCodes.asterisk) { - const kind = nextChar === ts.CharacterCodes.slash ? ts.SyntaxKind.SingleLineCommentTrivia : ts.SyntaxKind.MultiLineCommentTrivia; + if (nextChar === CharacterCodes.slash || nextChar === CharacterCodes.asterisk) { + const kind = nextChar === CharacterCodes.slash ? SyntaxKind.SingleLineCommentTrivia : SyntaxKind.MultiLineCommentTrivia; const startPos = pos; pos += 2; - if (nextChar === ts.CharacterCodes.slash) { + if (nextChar === CharacterCodes.slash) { while (pos < text.length) { if (isLineBreak(text.charCodeAt(pos))) { hasTrailingNewLine = true; @@ -808,7 +813,7 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, } else { while (pos < text.length) { - if (text.charCodeAt(pos) === ts.CharacterCodes.asterisk && text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; break; } @@ -836,7 +841,7 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, } break scan; default: - if (ch > ts.CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { + if (ch > CharacterCodes.maxAsciiCharacter && (isWhiteSpaceLike(ch))) { if (hasPendingCommentRange && isLineBreak(ch)) { pendingHasTrailingNewLine = true; } @@ -854,27 +859,27 @@ function iterateCommentRanges(reduce: boolean, text: string, pos: number, return accumulator; } -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; -export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { +export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; +export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; +export function forEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state); } -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; -export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { +export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean) => U): U | undefined; +export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state: T): U | undefined; +export function forEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T): U | undefined { return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state); } -export function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) { +export function reduceEachLeadingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) { return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial); } -export function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) { +export function reduceEachTrailingCommentRange(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) { return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial); } -function appendCommentRange(pos: number, end: number, kind: ts.CommentKind, hasTrailingNewLine: boolean, _state: any, comments: ts.CommentRange[]) { +function appendCommentRange(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) { if (!comments) { comments = []; } @@ -883,11 +888,11 @@ function appendCommentRange(pos: number, end: number, kind: ts.CommentKind, hasT return comments; } -export function getLeadingCommentRanges(text: string, pos: number): ts.CommentRange[] | undefined { +export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined { return reduceEachLeadingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } -export function getTrailingCommentRanges(text: string, pos: number): ts.CommentRange[] | undefined { +export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined { return reduceEachTrailingCommentRange(text, pos, appendCommentRange, /*state*/ undefined, /*initial*/ undefined); } @@ -899,22 +904,22 @@ export function getShebang(text: string): string | undefined { } } -export function isIdentifierStart(ch: number, languageVersion: ts.ScriptTarget | undefined): boolean { - return ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.Z || ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.z || - ch === ts.CharacterCodes.$ || ch === ts.CharacterCodes._ || - ch > ts.CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion); +export function isIdentifierStart(ch: number, languageVersion: ScriptTarget | undefined): boolean { + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || + ch === CharacterCodes.$ || ch === CharacterCodes._ || + ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion); } -export function isIdentifierPart(ch: number, languageVersion: ts.ScriptTarget | undefined, identifierVariant?: ts.LanguageVariant): boolean { - return ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.Z || ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.z || - ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9 || ch === ts.CharacterCodes.$ || ch === ts.CharacterCodes._ || +export function isIdentifierPart(ch: number, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean { + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z || + ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ || // "-" and ":" are valid in JSX Identifiers - (identifierVariant === ts.LanguageVariant.JSX ? (ch === ts.CharacterCodes.minus || ch === ts.CharacterCodes.colon) : false) || - ch > ts.CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); + (identifierVariant === LanguageVariant.JSX ? (ch === CharacterCodes.minus || ch === CharacterCodes.colon) : false) || + ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion); } /* @internal */ -export function isIdentifierText(name: string, languageVersion: ts.ScriptTarget | undefined, identifierVariant?: ts.LanguageVariant): boolean { +export function isIdentifierText(name: string, languageVersion: ScriptTarget | undefined, identifierVariant?: LanguageVariant): boolean { let ch = codePointAt(name, 0); if (!isIdentifierStart(ch, languageVersion)) { return false; @@ -930,9 +935,9 @@ export function isIdentifierText(name: string, languageVersion: ts.ScriptTarget } // Creates a scanner over a (possibly unspecified) range of a piece of text. -export function createScanner(languageVersion: ts.ScriptTarget, +export function createScanner(languageVersion: ScriptTarget, skipTrivia: boolean, - languageVariant = ts.LanguageVariant.Standard, + languageVariant = LanguageVariant.Standard, textInitial?: string, onError?: ErrorCallback, start?: number, @@ -953,11 +958,11 @@ export function createScanner(languageVersion: ts.ScriptTarget, // Start position of text of current token let tokenPos: number; - let token: ts.SyntaxKind; + let token: SyntaxKind; let tokenValue!: string; - let tokenFlags: ts.TokenFlags; + let tokenFlags: TokenFlags; - let commentDirectives: ts.CommentDirective[] | undefined; + let commentDirectives: CommentDirective[] | undefined; let inJSDocType = 0; setText(text, start, length); @@ -969,15 +974,15 @@ export function createScanner(languageVersion: ts.ScriptTarget, getTokenPos: () => tokenPos, getTokenText: () => text.substring(tokenPos, pos), getTokenValue: () => tokenValue, - hasUnicodeEscape: () => (tokenFlags & ts.TokenFlags.UnicodeEscape) !== 0, - hasExtendedUnicodeEscape: () => (tokenFlags & ts.TokenFlags.ExtendedUnicodeEscape) !== 0, - hasPrecedingLineBreak: () => (tokenFlags & ts.TokenFlags.PrecedingLineBreak) !== 0, - hasPrecedingJSDocComment: () => (tokenFlags & ts.TokenFlags.PrecedingJSDocComment) !== 0, - isIdentifier: () => token === ts.SyntaxKind.Identifier || token > ts.SyntaxKind.LastReservedWord, - isReservedWord: () => token >= ts.SyntaxKind.FirstReservedWord && token <= ts.SyntaxKind.LastReservedWord, - isUnterminated: () => (tokenFlags & ts.TokenFlags.Unterminated) !== 0, + hasUnicodeEscape: () => (tokenFlags & TokenFlags.UnicodeEscape) !== 0, + hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0, + hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0, + hasPrecedingJSDocComment: () => (tokenFlags & TokenFlags.PrecedingJSDocComment) !== 0, + isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord, + isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord, + isUnterminated: () => (tokenFlags & TokenFlags.Unterminated) !== 0, getCommentDirectives: () => commentDirectives, - getNumericLiteralFlags: () => tokenFlags & ts.TokenFlags.NumericLiteralFlags, + getNumericLiteralFlags: () => tokenFlags & TokenFlags.NumericLiteralFlags, getTokenFlags: () => tokenFlags, reScanGreaterToken, reScanAsteriskEqualsToken, @@ -1008,7 +1013,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, scanRange, }; - if (ts.Debug.isDebugging) { + if (Debug.isDebugging) { Object.defineProperty(scanner, "__debugShowCurrentPositionInText", { get: () => { const text = scanner.getText(); @@ -1019,9 +1024,9 @@ export function createScanner(languageVersion: ts.ScriptTarget, return scanner; - function error(message: ts.DiagnosticMessage): void; - function error(message: ts.DiagnosticMessage, errPos: number, length: number): void; - function error(message: ts.DiagnosticMessage, errPos: number = pos, length?: number): void { + function error(message: DiagnosticMessage): void; + function error(message: DiagnosticMessage, errPos: number, length: number): void; + function error(message: DiagnosticMessage, errPos: number = pos, length?: number): void { if (onError) { const oldPos = pos; pos = errPos; @@ -1037,18 +1042,18 @@ export function createScanner(languageVersion: ts.ScriptTarget, let result = ""; while (true) { const ch = text.charCodeAt(pos); - if (ch === ts.CharacterCodes._) { - tokenFlags |= ts.TokenFlags.ContainsSeparator; + if (ch === CharacterCodes._) { + tokenFlags |= TokenFlags.ContainsSeparator; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; result += text.substring(start, pos); } else if (isPreviousTokenSeparator) { - error(ts.Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); + error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); } else { - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); } pos++; start = pos; @@ -1062,30 +1067,30 @@ export function createScanner(languageVersion: ts.ScriptTarget, } break; } - if (text.charCodeAt(pos - 1) === ts.CharacterCodes._) { - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); + if (text.charCodeAt(pos - 1) === CharacterCodes._) { + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return result + text.substring(start, pos); } - function scanNumber(): { type: ts.SyntaxKind, value: string } { + function scanNumber(): { type: SyntaxKind, value: string } { const start = pos; const mainFragment = scanNumberFragment(); let decimalFragment: string | undefined; let scientificFragment: string | undefined; - if (text.charCodeAt(pos) === ts.CharacterCodes.dot) { + if (text.charCodeAt(pos) === CharacterCodes.dot) { pos++; decimalFragment = scanNumberFragment(); } let end = pos; - if (text.charCodeAt(pos) === ts.CharacterCodes.E || text.charCodeAt(pos) === ts.CharacterCodes.e) { + if (text.charCodeAt(pos) === CharacterCodes.E || text.charCodeAt(pos) === CharacterCodes.e) { pos++; - tokenFlags |= ts.TokenFlags.Scientific; - if (text.charCodeAt(pos) === ts.CharacterCodes.plus || text.charCodeAt(pos) === ts.CharacterCodes.minus) pos++; + tokenFlags |= TokenFlags.Scientific; + if (text.charCodeAt(pos) === CharacterCodes.plus || text.charCodeAt(pos) === CharacterCodes.minus) pos++; const preNumericPart = pos; const finalFragment = scanNumberFragment(); if (!finalFragment) { - error(ts.Diagnostics.Digit_expected); + error(Diagnostics.Digit_expected); } else { scientificFragment = text.substring(end, preNumericPart) + finalFragment; @@ -1093,7 +1098,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, } } let result: string; - if (tokenFlags & ts.TokenFlags.ContainsSeparator) { + if (tokenFlags & TokenFlags.ContainsSeparator) { result = mainFragment; if (decimalFragment) { result += "." + decimalFragment; @@ -1106,10 +1111,10 @@ export function createScanner(languageVersion: ts.ScriptTarget, result = text.substring(start, end); // No need to use all the fragments; no _ removal needed } - if (decimalFragment !== undefined || tokenFlags & ts.TokenFlags.Scientific) { - checkForIdentifierStartAfterNumericLiteral(start, decimalFragment === undefined && !!(tokenFlags & ts.TokenFlags.Scientific)); + if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) { + checkForIdentifierStartAfterNumericLiteral(start, decimalFragment === undefined && !!(tokenFlags & TokenFlags.Scientific)); return { - type: ts.SyntaxKind.NumericLiteral, + type: SyntaxKind.NumericLiteral, value: "" + +result // if value is not an integer, it can be safely coerced to a number }; } @@ -1131,14 +1136,14 @@ export function createScanner(languageVersion: ts.ScriptTarget, if (length === 1 && text[identifierStart] === "n") { if (isScientific) { - error(ts.Diagnostics.A_bigint_literal_cannot_use_exponential_notation, numericStart, identifierStart - numericStart + 1); + error(Diagnostics.A_bigint_literal_cannot_use_exponential_notation, numericStart, identifierStart - numericStart + 1); } else { - error(ts.Diagnostics.A_bigint_literal_must_be_an_integer, numericStart, identifierStart - numericStart + 1); + error(Diagnostics.A_bigint_literal_must_be_an_integer, numericStart, identifierStart - numericStart + 1); } } else { - error(ts.Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length); + error(Diagnostics.An_identifier_or_keyword_cannot_immediately_follow_a_numeric_literal, identifierStart, length); pos = identifierStart; } } @@ -1174,27 +1179,27 @@ export function createScanner(languageVersion: ts.ScriptTarget, let isPreviousTokenSeparator = false; while (valueChars.length < minCount || scanAsManyAsPossible) { let ch = text.charCodeAt(pos); - if (canHaveSeparators && ch === ts.CharacterCodes._) { - tokenFlags |= ts.TokenFlags.ContainsSeparator; + if (canHaveSeparators && ch === CharacterCodes._) { + tokenFlags |= TokenFlags.ContainsSeparator; if (allowSeparator) { allowSeparator = false; isPreviousTokenSeparator = true; } else if (isPreviousTokenSeparator) { - error(ts.Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); + error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); } else { - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); } pos++; continue; } allowSeparator = canHaveSeparators; - if (ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.F) { - ch += ts.CharacterCodes.a - ts.CharacterCodes.A; // standardize hex literals to lowercase + if (ch >= CharacterCodes.A && ch <= CharacterCodes.F) { + ch += CharacterCodes.a - CharacterCodes.A; // standardize hex literals to lowercase } - else if (!((ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9) || - (ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.f) + else if (!((ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || + (ch >= CharacterCodes.a && ch <= CharacterCodes.f) )) { break; } @@ -1205,8 +1210,8 @@ export function createScanner(languageVersion: ts.ScriptTarget, if (valueChars.length < minCount) { valueChars = []; } - if (text.charCodeAt(pos - 1) === ts.CharacterCodes._) { - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); + if (text.charCodeAt(pos - 1) === CharacterCodes._) { + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return String.fromCharCode(...valueChars); } @@ -1219,8 +1224,8 @@ export function createScanner(languageVersion: ts.ScriptTarget, while (true) { if (pos >= end) { result += text.substring(start, pos); - tokenFlags |= ts.TokenFlags.Unterminated; - error(ts.Diagnostics.Unterminated_string_literal); + tokenFlags |= TokenFlags.Unterminated; + error(Diagnostics.Unterminated_string_literal); break; } const ch = text.charCodeAt(pos); @@ -1229,7 +1234,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, pos++; break; } - if (ch === ts.CharacterCodes.backslash && !jsxAttributeString) { + if (ch === CharacterCodes.backslash && !jsxAttributeString) { result += text.substring(start, pos); result += scanEscapeSequence(); start = pos; @@ -1237,8 +1242,8 @@ export function createScanner(languageVersion: ts.ScriptTarget, } if (isLineBreak(ch) && !jsxAttributeString) { result += text.substring(start, pos); - tokenFlags |= ts.TokenFlags.Unterminated; - error(ts.Diagnostics.Unterminated_string_literal); + tokenFlags |= TokenFlags.Unterminated; + error(Diagnostics.Unterminated_string_literal); break; } pos++; @@ -1250,43 +1255,43 @@ export function createScanner(languageVersion: ts.ScriptTarget, * Sets the current 'tokenValue' and returns a NoSubstitutionTemplateLiteral or * a literal component of a TemplateExpression. */ - function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean): ts.SyntaxKind { - const startedWithBacktick = text.charCodeAt(pos) === ts.CharacterCodes.backtick; + function scanTemplateAndSetTokenValue(isTaggedTemplate: boolean): SyntaxKind { + const startedWithBacktick = text.charCodeAt(pos) === CharacterCodes.backtick; pos++; let start = pos; let contents = ""; - let resultingToken: ts.SyntaxKind; + let resultingToken: SyntaxKind; while (true) { if (pos >= end) { contents += text.substring(start, pos); - tokenFlags |= ts.TokenFlags.Unterminated; - error(ts.Diagnostics.Unterminated_template_literal); - resultingToken = startedWithBacktick ? ts.SyntaxKind.NoSubstitutionTemplateLiteral : ts.SyntaxKind.TemplateTail; + tokenFlags |= TokenFlags.Unterminated; + error(Diagnostics.Unterminated_template_literal); + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; break; } const currChar = text.charCodeAt(pos); // '`' - if (currChar === ts.CharacterCodes.backtick) { + if (currChar === CharacterCodes.backtick) { contents += text.substring(start, pos); pos++; - resultingToken = startedWithBacktick ? ts.SyntaxKind.NoSubstitutionTemplateLiteral : ts.SyntaxKind.TemplateTail; + resultingToken = startedWithBacktick ? SyntaxKind.NoSubstitutionTemplateLiteral : SyntaxKind.TemplateTail; break; } // '${' - if (currChar === ts.CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === ts.CharacterCodes.openBrace) { + if (currChar === CharacterCodes.$ && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.openBrace) { contents += text.substring(start, pos); pos += 2; - resultingToken = startedWithBacktick ? ts.SyntaxKind.TemplateHead : ts.SyntaxKind.TemplateMiddle; + resultingToken = startedWithBacktick ? SyntaxKind.TemplateHead : SyntaxKind.TemplateMiddle; break; } // Escape character - if (currChar === ts.CharacterCodes.backslash) { + if (currChar === CharacterCodes.backslash) { contents += text.substring(start, pos); contents += scanEscapeSequence(isTaggedTemplate); start = pos; @@ -1295,11 +1300,11 @@ export function createScanner(languageVersion: ts.ScriptTarget, // Speculated ECMAScript 6 Spec 11.8.6.1: // and LineTerminatorSequences are normalized to for Template Values - if (currChar === ts.CharacterCodes.carriageReturn) { + if (currChar === CharacterCodes.carriageReturn) { contents += text.substring(start, pos); pos++; - if (pos < end && text.charCodeAt(pos) === ts.CharacterCodes.lineFeed) { + if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } @@ -1311,7 +1316,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, pos++; } - ts.Debug.assert(resultingToken !== undefined); + Debug.assert(resultingToken !== undefined); tokenValue = contents; return resultingToken; @@ -1321,54 +1326,54 @@ export function createScanner(languageVersion: ts.ScriptTarget, const start = pos; pos++; if (pos >= end) { - error(ts.Diagnostics.Unexpected_end_of_text); + error(Diagnostics.Unexpected_end_of_text); return ""; } const ch = text.charCodeAt(pos); pos++; switch (ch) { - case ts.CharacterCodes._0: + case CharacterCodes._0: // '\01' if (isTaggedTemplate && pos < end && isDigit(text.charCodeAt(pos))) { pos++; - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } return "\0"; - case ts.CharacterCodes.b: + case CharacterCodes.b: return "\b"; - case ts.CharacterCodes.t: + case CharacterCodes.t: return "\t"; - case ts.CharacterCodes.n: + case CharacterCodes.n: return "\n"; - case ts.CharacterCodes.v: + case CharacterCodes.v: return "\v"; - case ts.CharacterCodes.f: + case CharacterCodes.f: return "\f"; - case ts.CharacterCodes.r: + case CharacterCodes.r: return "\r"; - case ts.CharacterCodes.singleQuote: + case CharacterCodes.singleQuote: return "\'"; - case ts.CharacterCodes.doubleQuote: + case CharacterCodes.doubleQuote: return "\""; - case ts.CharacterCodes.u: + case CharacterCodes.u: if (isTaggedTemplate) { // '\u' or '\u0' or '\u00' or '\u000' for (let escapePos = pos; escapePos < pos + 4; escapePos++) { - if (escapePos < end && !isHexDigit(text.charCodeAt(escapePos)) && text.charCodeAt(escapePos) !== ts.CharacterCodes.openBrace) { + if (escapePos < end && !isHexDigit(text.charCodeAt(escapePos)) && text.charCodeAt(escapePos) !== CharacterCodes.openBrace) { pos = escapePos; - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } } } // '\u{DDDDDDDD}' - if (pos < end && text.charCodeAt(pos) === ts.CharacterCodes.openBrace) { + if (pos < end && text.charCodeAt(pos) === CharacterCodes.openBrace) { pos++; // '\u{' if (isTaggedTemplate && !isHexDigit(text.charCodeAt(pos))) { - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } @@ -1378,31 +1383,31 @@ export function createScanner(languageVersion: ts.ScriptTarget, const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1; // '\u{Not Code Point' or '\u{CodePoint' - if (!isCodePoint(escapedValue) || text.charCodeAt(pos) !== ts.CharacterCodes.closeBrace) { - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + if (!isCodePoint(escapedValue) || text.charCodeAt(pos) !== CharacterCodes.closeBrace) { + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } else { pos = savePos; } } - tokenFlags |= ts.TokenFlags.ExtendedUnicodeEscape; + tokenFlags |= TokenFlags.ExtendedUnicodeEscape; return scanExtendedUnicodeEscape(); } - tokenFlags |= ts.TokenFlags.UnicodeEscape; + tokenFlags |= TokenFlags.UnicodeEscape; // '\uDDDD' return scanHexadecimalEscape(/*numDigits*/ 4); - case ts.CharacterCodes.x: + case CharacterCodes.x: if (isTaggedTemplate) { if (!isHexDigit(text.charCodeAt(pos))) { - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } else if (!isHexDigit(text.charCodeAt(pos + 1))) { pos++; - tokenFlags |= ts.TokenFlags.ContainsInvalidEscape; + tokenFlags |= TokenFlags.ContainsInvalidEscape; return text.substring(start, pos); } } @@ -1411,14 +1416,14 @@ export function createScanner(languageVersion: ts.ScriptTarget, // when encountering a LineContinuation (i.e. a backslash and a line terminator sequence), // the line terminator is interpreted to be "the empty code unit sequence". - case ts.CharacterCodes.carriageReturn: - if (pos < end && text.charCodeAt(pos) === ts.CharacterCodes.lineFeed) { + case CharacterCodes.carriageReturn: + if (pos < end && text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } // falls through - case ts.CharacterCodes.lineFeed: - case ts.CharacterCodes.lineSeparator: - case ts.CharacterCodes.paragraphSeparator: + case CharacterCodes.lineFeed: + case CharacterCodes.lineSeparator: + case CharacterCodes.paragraphSeparator: return ""; default: return String.fromCharCode(ch); @@ -1432,7 +1437,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, return String.fromCharCode(escapedValue); } else { - error(ts.Diagnostics.Hexadecimal_digit_expected); + error(Diagnostics.Hexadecimal_digit_expected); return ""; } } @@ -1444,24 +1449,24 @@ export function createScanner(languageVersion: ts.ScriptTarget, // Validate the value of the digit if (escapedValue < 0) { - error(ts.Diagnostics.Hexadecimal_digit_expected); + error(Diagnostics.Hexadecimal_digit_expected); isInvalidExtendedEscape = true; } else if (escapedValue > 0x10FFFF) { - error(ts.Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); + error(Diagnostics.An_extended_Unicode_escape_value_must_be_between_0x0_and_0x10FFFF_inclusive); isInvalidExtendedEscape = true; } if (pos >= end) { - error(ts.Diagnostics.Unexpected_end_of_text); + error(Diagnostics.Unexpected_end_of_text); isInvalidExtendedEscape = true; } - else if (text.charCodeAt(pos) === ts.CharacterCodes.closeBrace) { + else if (text.charCodeAt(pos) === CharacterCodes.closeBrace) { // Only swallow the following character up if it's a '}'. pos++; } else { - error(ts.Diagnostics.Unterminated_Unicode_escape_sequence); + error(Diagnostics.Unterminated_Unicode_escape_sequence); isInvalidExtendedEscape = true; } @@ -1475,7 +1480,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, // Current character is known to be a backslash. Check for Unicode escape of the form '\uXXXX' // and return code point value if valid Unicode escape is found. Otherwise return -1. function peekUnicodeEscape(): number { - if (pos + 5 < end && text.charCodeAt(pos + 1) === ts.CharacterCodes.u) { + if (pos + 5 < end && text.charCodeAt(pos + 1) === CharacterCodes.u) { const start = pos; pos += 2; const value = scanExactNumberOfHexDigits(4, /*canHaveSeparators*/ false); @@ -1487,7 +1492,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, function peekExtendedUnicodeEscape(): number { - if (codePointAt(text, pos + 1) === ts.CharacterCodes.u && codePointAt(text, pos + 2) === ts.CharacterCodes.openBrace) { + if (codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace) { const start = pos; pos += 3; const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false); @@ -1506,11 +1511,11 @@ export function createScanner(languageVersion: ts.ScriptTarget, if (isIdentifierPart(ch, languageVersion)) { pos += charSize(ch); } - else if (ch === ts.CharacterCodes.backslash) { + else if (ch === CharacterCodes.backslash) { ch = peekExtendedUnicodeEscape(); if (ch >= 0 && isIdentifierPart(ch, languageVersion)) { pos += 3; - tokenFlags |= ts.TokenFlags.ExtendedUnicodeEscape; + tokenFlags |= TokenFlags.ExtendedUnicodeEscape; result += scanExtendedUnicodeEscape(); start = pos; continue; @@ -1519,7 +1524,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, if (!(ch >= 0 && isIdentifierPart(ch, languageVersion))) { break; } - tokenFlags |= ts.TokenFlags.UnicodeEscape; + tokenFlags |= TokenFlags.UnicodeEscape; result += text.substring(start, pos); result += utf16EncodeAsString(ch); // Valid Unicode escape is always six characters @@ -1534,19 +1539,19 @@ export function createScanner(languageVersion: ts.ScriptTarget, return result; } - function getIdentifierToken(): ts.SyntaxKind.Identifier | ts.KeywordSyntaxKind { + function getIdentifierToken(): SyntaxKind.Identifier | KeywordSyntaxKind { // Reserved words are between 2 and 12 characters long and start with a lowercase letter const len = tokenValue.length; if (len >= 2 && len <= 12) { const ch = tokenValue.charCodeAt(0); - if (ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.z) { + if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) { const keyword = textToKeyword.get(tokenValue); if (keyword !== undefined) { return token = keyword; } } } - return token = ts.SyntaxKind.Identifier; + return token = SyntaxKind.Identifier; } function scanBinaryOrOctalDigits(base: 2 | 8): string { @@ -1558,120 +1563,120 @@ export function createScanner(languageVersion: ts.ScriptTarget, while (true) { const ch = text.charCodeAt(pos); // Numeric separators are allowed anywhere within a numeric literal, except not at the beginning, or following another separator - if (ch === ts.CharacterCodes._) { - tokenFlags |= ts.TokenFlags.ContainsSeparator; + if (ch === CharacterCodes._) { + tokenFlags |= TokenFlags.ContainsSeparator; if (separatorAllowed) { separatorAllowed = false; isPreviousTokenSeparator = true; } else if (isPreviousTokenSeparator) { - error(ts.Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); + error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1); } else { - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1); } pos++; continue; } separatorAllowed = true; - if (!isDigit(ch) || ch - ts.CharacterCodes._0 >= base) { + if (!isDigit(ch) || ch - CharacterCodes._0 >= base) { break; } value += text[pos]; pos++; isPreviousTokenSeparator = false; } - if (text.charCodeAt(pos - 1) === ts.CharacterCodes._) { + if (text.charCodeAt(pos - 1) === CharacterCodes._) { // Literal ends with underscore - not allowed - error(ts.Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); + error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1); } return value; } - function checkBigIntSuffix(): ts.SyntaxKind { - if (text.charCodeAt(pos) === ts.CharacterCodes.n) { + function checkBigIntSuffix(): SyntaxKind { + if (text.charCodeAt(pos) === CharacterCodes.n) { tokenValue += "n"; // Use base 10 instead of base 2 or base 8 for shorter literals - if (tokenFlags & ts.TokenFlags.BinaryOrOctalSpecifier) { - tokenValue = ts.parsePseudoBigInt(tokenValue) + "n"; + if (tokenFlags & TokenFlags.BinaryOrOctalSpecifier) { + tokenValue = parsePseudoBigInt(tokenValue) + "n"; } pos++; - return ts.SyntaxKind.BigIntLiteral; + return SyntaxKind.BigIntLiteral; } else { // not a bigint, so can convert to number in simplified form // Number() may not support 0b or 0o, so use parseInt() instead - const numericValue = tokenFlags & ts.TokenFlags.BinarySpecifier + const numericValue = tokenFlags & TokenFlags.BinarySpecifier ? parseInt(tokenValue.slice(2), 2) // skip "0b" - : tokenFlags & ts.TokenFlags.OctalSpecifier + : tokenFlags & TokenFlags.OctalSpecifier ? parseInt(tokenValue.slice(2), 8) // skip "0o" : +tokenValue; tokenValue = "" + numericValue; - return ts.SyntaxKind.NumericLiteral; + return SyntaxKind.NumericLiteral; } } - function scan(): ts.SyntaxKind { + function scan(): SyntaxKind { startPos = pos; - tokenFlags = ts.TokenFlags.None; + tokenFlags = TokenFlags.None; let asteriskSeen = false; while (true) { tokenPos = pos; if (pos >= end) { - return token = ts.SyntaxKind.EndOfFileToken; + return token = SyntaxKind.EndOfFileToken; } const ch = codePointAt(text, pos); // Special handling for shebang - if (ch === ts.CharacterCodes.hash && pos === 0 && isShebangTrivia(text, pos)) { + if (ch === CharacterCodes.hash && pos === 0 && isShebangTrivia(text, pos)) { pos = scanShebangTrivia(text, pos); if (skipTrivia) { continue; } else { - return token = ts.SyntaxKind.ShebangTrivia; + return token = SyntaxKind.ShebangTrivia; } } switch (ch) { - case ts.CharacterCodes.lineFeed: - case ts.CharacterCodes.carriageReturn: - tokenFlags |= ts.TokenFlags.PrecedingLineBreak; + case CharacterCodes.lineFeed: + case CharacterCodes.carriageReturn: + tokenFlags |= TokenFlags.PrecedingLineBreak; if (skipTrivia) { pos++; continue; } else { - if (ch === ts.CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === ts.CharacterCodes.lineFeed) { + if (ch === CharacterCodes.carriageReturn && pos + 1 < end && text.charCodeAt(pos + 1) === CharacterCodes.lineFeed) { // consume both CR and LF pos += 2; } else { pos++; } - return token = ts.SyntaxKind.NewLineTrivia; + return token = SyntaxKind.NewLineTrivia; } - case ts.CharacterCodes.tab: - case ts.CharacterCodes.verticalTab: - case ts.CharacterCodes.formFeed: - case ts.CharacterCodes.space: - case ts.CharacterCodes.nonBreakingSpace: - case ts.CharacterCodes.ogham: - case ts.CharacterCodes.enQuad: - case ts.CharacterCodes.emQuad: - case ts.CharacterCodes.enSpace: - case ts.CharacterCodes.emSpace: - case ts.CharacterCodes.threePerEmSpace: - case ts.CharacterCodes.fourPerEmSpace: - case ts.CharacterCodes.sixPerEmSpace: - case ts.CharacterCodes.figureSpace: - case ts.CharacterCodes.punctuationSpace: - case ts.CharacterCodes.thinSpace: - case ts.CharacterCodes.hairSpace: - case ts.CharacterCodes.zeroWidthSpace: - case ts.CharacterCodes.narrowNoBreakSpace: - case ts.CharacterCodes.mathematicalSpace: - case ts.CharacterCodes.ideographicSpace: - case ts.CharacterCodes.byteOrderMark: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: + case CharacterCodes.nonBreakingSpace: + case CharacterCodes.ogham: + case CharacterCodes.enQuad: + case CharacterCodes.emQuad: + case CharacterCodes.enSpace: + case CharacterCodes.emSpace: + case CharacterCodes.threePerEmSpace: + case CharacterCodes.fourPerEmSpace: + case CharacterCodes.sixPerEmSpace: + case CharacterCodes.figureSpace: + case CharacterCodes.punctuationSpace: + case CharacterCodes.thinSpace: + case CharacterCodes.hairSpace: + case CharacterCodes.zeroWidthSpace: + case CharacterCodes.narrowNoBreakSpace: + case CharacterCodes.mathematicalSpace: + case CharacterCodes.ideographicSpace: + case CharacterCodes.byteOrderMark: if (skipTrivia) { pos++; continue; @@ -1680,98 +1685,98 @@ export function createScanner(languageVersion: ts.ScriptTarget, while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = ts.SyntaxKind.WhitespaceTrivia; + return token = SyntaxKind.WhitespaceTrivia; } - case ts.CharacterCodes.exclamation: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.ExclamationEqualsEqualsToken; + case CharacterCodes.exclamation: + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.ExclamationEqualsEqualsToken; } - return pos += 2, token = ts.SyntaxKind.ExclamationEqualsToken; + return pos += 2, token = SyntaxKind.ExclamationEqualsToken; } pos++; - return token = ts.SyntaxKind.ExclamationToken; - case ts.CharacterCodes.doubleQuote: - case ts.CharacterCodes.singleQuote: + return token = SyntaxKind.ExclamationToken; + case CharacterCodes.doubleQuote: + case CharacterCodes.singleQuote: tokenValue = scanString(); - return token = ts.SyntaxKind.StringLiteral; - case ts.CharacterCodes.backtick: + return token = SyntaxKind.StringLiteral; + case CharacterCodes.backtick: return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ false); - case ts.CharacterCodes.percent: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.PercentEqualsToken; + case CharacterCodes.percent: + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.PercentEqualsToken; } pos++; - return token = ts.SyntaxKind.PercentToken; - case ts.CharacterCodes.ampersand: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.ampersand) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.AmpersandAmpersandEqualsToken; + return token = SyntaxKind.PercentToken; + case CharacterCodes.ampersand: + if (text.charCodeAt(pos + 1) === CharacterCodes.ampersand) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.AmpersandAmpersandEqualsToken; } - return pos += 2, token = ts.SyntaxKind.AmpersandAmpersandToken; + return pos += 2, token = SyntaxKind.AmpersandAmpersandToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.AmpersandEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.AmpersandEqualsToken; } pos++; - return token = ts.SyntaxKind.AmpersandToken; - case ts.CharacterCodes.openParen: + return token = SyntaxKind.AmpersandToken; + case CharacterCodes.openParen: pos++; - return token = ts.SyntaxKind.OpenParenToken; - case ts.CharacterCodes.closeParen: + return token = SyntaxKind.OpenParenToken; + case CharacterCodes.closeParen: pos++; - return token = ts.SyntaxKind.CloseParenToken; - case ts.CharacterCodes.asterisk: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.AsteriskEqualsToken; + return token = SyntaxKind.CloseParenToken; + case CharacterCodes.asterisk: + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.AsteriskEqualsToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.asterisk) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.AsteriskAsteriskEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.AsteriskAsteriskEqualsToken; } - return pos += 2, token = ts.SyntaxKind.AsteriskAsteriskToken; + return pos += 2, token = SyntaxKind.AsteriskAsteriskToken; } pos++; - if (inJSDocType && !asteriskSeen && (tokenFlags & ts.TokenFlags.PrecedingLineBreak)) { + if (inJSDocType && !asteriskSeen && (tokenFlags & TokenFlags.PrecedingLineBreak)) { // decoration at the start of a JSDoc comment line asteriskSeen = true; continue; } - return token = ts.SyntaxKind.AsteriskToken; - case ts.CharacterCodes.plus: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.plus) { - return pos += 2, token = ts.SyntaxKind.PlusPlusToken; + return token = SyntaxKind.AsteriskToken; + case CharacterCodes.plus: + if (text.charCodeAt(pos + 1) === CharacterCodes.plus) { + return pos += 2, token = SyntaxKind.PlusPlusToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.PlusEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.PlusEqualsToken; } pos++; - return token = ts.SyntaxKind.PlusToken; - case ts.CharacterCodes.comma: + return token = SyntaxKind.PlusToken; + case CharacterCodes.comma: pos++; - return token = ts.SyntaxKind.CommaToken; - case ts.CharacterCodes.minus: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.minus) { - return pos += 2, token = ts.SyntaxKind.MinusMinusToken; + return token = SyntaxKind.CommaToken; + case CharacterCodes.minus: + if (text.charCodeAt(pos + 1) === CharacterCodes.minus) { + return pos += 2, token = SyntaxKind.MinusMinusToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.MinusEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.MinusEqualsToken; } pos++; - return token = ts.SyntaxKind.MinusToken; - case ts.CharacterCodes.dot: + return token = SyntaxKind.MinusToken; + case CharacterCodes.dot: if (isDigit(text.charCodeAt(pos + 1))) { tokenValue = scanNumber().value; - return token = ts.SyntaxKind.NumericLiteral; + return token = SyntaxKind.NumericLiteral; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.dot && text.charCodeAt(pos + 2) === ts.CharacterCodes.dot) { - return pos += 3, token = ts.SyntaxKind.DotDotDotToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.dot && text.charCodeAt(pos + 2) === CharacterCodes.dot) { + return pos += 3, token = SyntaxKind.DotDotDotToken; } pos++; - return token = ts.SyntaxKind.DotToken; - case ts.CharacterCodes.slash: + return token = SyntaxKind.DotToken; + case CharacterCodes.slash: // Single-line comment - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; while (pos < end) { @@ -1792,14 +1797,14 @@ export function createScanner(languageVersion: ts.ScriptTarget, continue; } else { - return token = ts.SyntaxKind.SingleLineCommentTrivia; + return token = SyntaxKind.SingleLineCommentTrivia; } } // Multi-line comment - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.asterisk) { + if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { pos += 2; - if (text.charCodeAt(pos) === ts.CharacterCodes.asterisk && text.charCodeAt(pos + 1) !== ts.CharacterCodes.slash) { - tokenFlags |= ts.TokenFlags.PrecedingJSDocComment; + if (text.charCodeAt(pos) === CharacterCodes.asterisk && text.charCodeAt(pos + 1) !== CharacterCodes.slash) { + tokenFlags |= TokenFlags.PrecedingJSDocComment; } let commentClosed = false; @@ -1807,7 +1812,7 @@ export function createScanner(languageVersion: ts.ScriptTarget, while (pos < end) { const ch = text.charCodeAt(pos); - if (ch === ts.CharacterCodes.asterisk && text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (ch === CharacterCodes.asterisk && text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; commentClosed = true; break; @@ -1817,14 +1822,14 @@ export function createScanner(languageVersion: ts.ScriptTarget, if (isLineBreak(ch)) { lastLineStart = pos; - tokenFlags |= ts.TokenFlags.PrecedingLineBreak; + tokenFlags |= TokenFlags.PrecedingLineBreak; } } commentDirectives = appendIfCommentDirective(commentDirectives, text.slice(lastLineStart, pos), commentDirectiveRegExMultiLine, lastLineStart); if (!commentClosed) { - error(ts.Diagnostics.Asterisk_Slash_expected); + error(Diagnostics.Asterisk_Slash_expected); } if (skipTrivia) { @@ -1832,205 +1837,205 @@ export function createScanner(languageVersion: ts.ScriptTarget, } else { if (!commentClosed) { - tokenFlags |= ts.TokenFlags.Unterminated; + tokenFlags |= TokenFlags.Unterminated; } - return token = ts.SyntaxKind.MultiLineCommentTrivia; + return token = SyntaxKind.MultiLineCommentTrivia; } } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.SlashEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.SlashEqualsToken; } pos++; - return token = ts.SyntaxKind.SlashToken; + return token = SyntaxKind.SlashToken; - case ts.CharacterCodes._0: - if (pos + 2 < end && (text.charCodeAt(pos + 1) === ts.CharacterCodes.X || text.charCodeAt(pos + 1) === ts.CharacterCodes.x)) { + case CharacterCodes._0: + if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.X || text.charCodeAt(pos + 1) === CharacterCodes.x)) { pos += 2; tokenValue = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ true); if (!tokenValue) { - error(ts.Diagnostics.Hexadecimal_digit_expected); + error(Diagnostics.Hexadecimal_digit_expected); tokenValue = "0"; } tokenValue = "0x" + tokenValue; - tokenFlags |= ts.TokenFlags.HexSpecifier; + tokenFlags |= TokenFlags.HexSpecifier; return token = checkBigIntSuffix(); } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === ts.CharacterCodes.B || text.charCodeAt(pos + 1) === ts.CharacterCodes.b)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.B || text.charCodeAt(pos + 1) === CharacterCodes.b)) { pos += 2; tokenValue = scanBinaryOrOctalDigits(/* base */ 2); if (!tokenValue) { - error(ts.Diagnostics.Binary_digit_expected); + error(Diagnostics.Binary_digit_expected); tokenValue = "0"; } tokenValue = "0b" + tokenValue; - tokenFlags |= ts.TokenFlags.BinarySpecifier; + tokenFlags |= TokenFlags.BinarySpecifier; return token = checkBigIntSuffix(); } - else if (pos + 2 < end && (text.charCodeAt(pos + 1) === ts.CharacterCodes.O || text.charCodeAt(pos + 1) === ts.CharacterCodes.o)) { + else if (pos + 2 < end && (text.charCodeAt(pos + 1) === CharacterCodes.O || text.charCodeAt(pos + 1) === CharacterCodes.o)) { pos += 2; tokenValue = scanBinaryOrOctalDigits(/* base */ 8); if (!tokenValue) { - error(ts.Diagnostics.Octal_digit_expected); + error(Diagnostics.Octal_digit_expected); tokenValue = "0"; } tokenValue = "0o" + tokenValue; - tokenFlags |= ts.TokenFlags.OctalSpecifier; + tokenFlags |= TokenFlags.OctalSpecifier; return token = checkBigIntSuffix(); } // Try to parse as an octal if (pos + 1 < end && isOctalDigit(text.charCodeAt(pos + 1))) { tokenValue = "" + scanOctalDigits(); - tokenFlags |= ts.TokenFlags.Octal; - return token = ts.SyntaxKind.NumericLiteral; + tokenFlags |= TokenFlags.Octal; + return token = SyntaxKind.NumericLiteral; } // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do). // falls through - case ts.CharacterCodes._1: - case ts.CharacterCodes._2: - case ts.CharacterCodes._3: - case ts.CharacterCodes._4: - case ts.CharacterCodes._5: - case ts.CharacterCodes._6: - case ts.CharacterCodes._7: - case ts.CharacterCodes._8: - case ts.CharacterCodes._9: + case CharacterCodes._1: + case CharacterCodes._2: + case CharacterCodes._3: + case CharacterCodes._4: + case CharacterCodes._5: + case CharacterCodes._6: + case CharacterCodes._7: + case CharacterCodes._8: + case CharacterCodes._9: ({ type: token, value: tokenValue } = scanNumber()); return token; - case ts.CharacterCodes.colon: + case CharacterCodes.colon: pos++; - return token = ts.SyntaxKind.ColonToken; - case ts.CharacterCodes.semicolon: + return token = SyntaxKind.ColonToken; + case CharacterCodes.semicolon: pos++; - return token = ts.SyntaxKind.SemicolonToken; - case ts.CharacterCodes.lessThan: + return token = SyntaxKind.SemicolonToken; + case CharacterCodes.lessThan: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = ts.SyntaxKind.ConflictMarkerTrivia; + return token = SyntaxKind.ConflictMarkerTrivia; } } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.lessThan) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.LessThanLessThanEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.lessThan) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.LessThanLessThanEqualsToken; } - return pos += 2, token = ts.SyntaxKind.LessThanLessThanToken; + return pos += 2, token = SyntaxKind.LessThanLessThanToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.LessThanEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.LessThanEqualsToken; } - if (languageVariant === ts.LanguageVariant.JSX && - text.charCodeAt(pos + 1) === ts.CharacterCodes.slash && - text.charCodeAt(pos + 2) !== ts.CharacterCodes.asterisk) { - return pos += 2, token = ts.SyntaxKind.LessThanSlashToken; + if (languageVariant === LanguageVariant.JSX && + text.charCodeAt(pos + 1) === CharacterCodes.slash && + text.charCodeAt(pos + 2) !== CharacterCodes.asterisk) { + return pos += 2, token = SyntaxKind.LessThanSlashToken; } pos++; - return token = ts.SyntaxKind.LessThanToken; - case ts.CharacterCodes.equals: + return token = SyntaxKind.LessThanToken; + case CharacterCodes.equals: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = ts.SyntaxKind.ConflictMarkerTrivia; + return token = SyntaxKind.ConflictMarkerTrivia; } } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.EqualsEqualsEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.EqualsEqualsEqualsToken; } - return pos += 2, token = ts.SyntaxKind.EqualsEqualsToken; + return pos += 2, token = SyntaxKind.EqualsEqualsToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.greaterThan) { - return pos += 2, token = ts.SyntaxKind.EqualsGreaterThanToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) { + return pos += 2, token = SyntaxKind.EqualsGreaterThanToken; } pos++; - return token = ts.SyntaxKind.EqualsToken; - case ts.CharacterCodes.greaterThan: + return token = SyntaxKind.EqualsToken; + case CharacterCodes.greaterThan: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = ts.SyntaxKind.ConflictMarkerTrivia; + return token = SyntaxKind.ConflictMarkerTrivia; } } pos++; - return token = ts.SyntaxKind.GreaterThanToken; - case ts.CharacterCodes.question: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.dot && !isDigit(text.charCodeAt(pos + 2))) { - return pos += 2, token = ts.SyntaxKind.QuestionDotToken; + return token = SyntaxKind.GreaterThanToken; + case CharacterCodes.question: + if (text.charCodeAt(pos + 1) === CharacterCodes.dot && !isDigit(text.charCodeAt(pos + 2))) { + return pos += 2, token = SyntaxKind.QuestionDotToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.question) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.QuestionQuestionEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.question) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.QuestionQuestionEqualsToken; } - return pos += 2, token = ts.SyntaxKind.QuestionQuestionToken; + return pos += 2, token = SyntaxKind.QuestionQuestionToken; } pos++; - return token = ts.SyntaxKind.QuestionToken; - case ts.CharacterCodes.openBracket: + return token = SyntaxKind.QuestionToken; + case CharacterCodes.openBracket: pos++; - return token = ts.SyntaxKind.OpenBracketToken; - case ts.CharacterCodes.closeBracket: + return token = SyntaxKind.OpenBracketToken; + case CharacterCodes.closeBracket: pos++; - return token = ts.SyntaxKind.CloseBracketToken; - case ts.CharacterCodes.caret: - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.CaretEqualsToken; + return token = SyntaxKind.CloseBracketToken; + case CharacterCodes.caret: + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.CaretEqualsToken; } pos++; - return token = ts.SyntaxKind.CaretToken; - case ts.CharacterCodes.openBrace: + return token = SyntaxKind.CaretToken; + case CharacterCodes.openBrace: pos++; - return token = ts.SyntaxKind.OpenBraceToken; - case ts.CharacterCodes.bar: + return token = SyntaxKind.OpenBraceToken; + case CharacterCodes.bar: if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); if (skipTrivia) { continue; } else { - return token = ts.SyntaxKind.ConflictMarkerTrivia; + return token = SyntaxKind.ConflictMarkerTrivia; } } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.bar) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.BarBarEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.bar) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.BarBarEqualsToken; } - return pos += 2, token = ts.SyntaxKind.BarBarToken; + return pos += 2, token = SyntaxKind.BarBarToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.BarEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.BarEqualsToken; } pos++; - return token = ts.SyntaxKind.BarToken; - case ts.CharacterCodes.closeBrace: + return token = SyntaxKind.BarToken; + case CharacterCodes.closeBrace: pos++; - return token = ts.SyntaxKind.CloseBraceToken; - case ts.CharacterCodes.tilde: + return token = SyntaxKind.CloseBraceToken; + case CharacterCodes.tilde: pos++; - return token = ts.SyntaxKind.TildeToken; - case ts.CharacterCodes.at: + return token = SyntaxKind.TildeToken; + case CharacterCodes.at: pos++; - return token = ts.SyntaxKind.AtToken; - case ts.CharacterCodes.backslash: + return token = SyntaxKind.AtToken; + case CharacterCodes.backslash: const extendedCookedChar = peekExtendedUnicodeEscape(); if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; - tokenFlags |= ts.TokenFlags.ExtendedUnicodeEscape; + tokenFlags |= TokenFlags.ExtendedUnicodeEscape; tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts(); return token = getIdentifierToken(); } @@ -2038,38 +2043,38 @@ export function createScanner(languageVersion: ts.ScriptTarget, const cookedChar = peekUnicodeEscape(); if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) { pos += 6; - tokenFlags |= ts.TokenFlags.UnicodeEscape; + tokenFlags |= TokenFlags.UnicodeEscape; tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts(); return token = getIdentifierToken(); } - error(ts.Diagnostics.Invalid_character); + error(Diagnostics.Invalid_character); pos++; - return token = ts.SyntaxKind.Unknown; - case ts.CharacterCodes.hash: + return token = SyntaxKind.Unknown; + case CharacterCodes.hash: if (pos !== 0 && text[pos + 1] === "!") { - error(ts.Diagnostics.can_only_be_used_at_the_start_of_a_file); + error(Diagnostics.can_only_be_used_at_the_start_of_a_file); pos++; - return token = ts.SyntaxKind.Unknown; + return token = SyntaxKind.Unknown; } const charAfterHash = codePointAt(text, pos + 1); - if (charAfterHash === ts.CharacterCodes.backslash) { + if (charAfterHash === CharacterCodes.backslash) { pos++; const extendedCookedChar = peekExtendedUnicodeEscape(); if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; - tokenFlags |= ts.TokenFlags.ExtendedUnicodeEscape; + tokenFlags |= TokenFlags.ExtendedUnicodeEscape; tokenValue = "#" + scanExtendedUnicodeEscape() + scanIdentifierParts(); - return token = ts.SyntaxKind.PrivateIdentifier; + return token = SyntaxKind.PrivateIdentifier; } const cookedChar = peekUnicodeEscape(); if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) { pos += 6; - tokenFlags |= ts.TokenFlags.UnicodeEscape; + tokenFlags |= TokenFlags.UnicodeEscape; tokenValue = "#" + String.fromCharCode(cookedChar) + scanIdentifierParts(); - return token = ts.SyntaxKind.PrivateIdentifier; + return token = SyntaxKind.PrivateIdentifier; } pos--; } @@ -2085,9 +2090,9 @@ export function createScanner(languageVersion: ts.ScriptTarget, } else { tokenValue = "#"; - error(ts.Diagnostics.Invalid_character, pos++, charSize(ch)); + error(Diagnostics.Invalid_character, pos++, charSize(ch)); } - return token = ts.SyntaxKind.PrivateIdentifier; + return token = SyntaxKind.PrivateIdentifier; default: const identifierKind = scanIdentifier(ch, languageVersion); if (identifierKind) { @@ -2098,24 +2103,24 @@ export function createScanner(languageVersion: ts.ScriptTarget, continue; } else if (isLineBreak(ch)) { - tokenFlags |= ts.TokenFlags.PrecedingLineBreak; + tokenFlags |= TokenFlags.PrecedingLineBreak; pos += charSize(ch); continue; } const size = charSize(ch); - error(ts.Diagnostics.Invalid_character, pos, size); + error(Diagnostics.Invalid_character, pos, size); pos += size; - return token = ts.SyntaxKind.Unknown; + return token = SyntaxKind.Unknown; } } } - function reScanInvalidIdentifier(): ts.SyntaxKind { - ts.Debug.assert(token === ts.SyntaxKind.Unknown, "'reScanInvalidIdentifier' should only be called when the current token is 'SyntaxKind.Unknown'."); + function reScanInvalidIdentifier(): SyntaxKind { + Debug.assert(token === SyntaxKind.Unknown, "'reScanInvalidIdentifier' should only be called when the current token is 'SyntaxKind.Unknown'."); pos = tokenPos = startPos; tokenFlags = 0; const ch = codePointAt(text, pos); - const identifierKind = scanIdentifier(ch, ts.ScriptTarget.ESNext); + const identifierKind = scanIdentifier(ch, ScriptTarget.ESNext); if (identifierKind) { return token = identifierKind; } @@ -2123,50 +2128,50 @@ export function createScanner(languageVersion: ts.ScriptTarget, return token; // Still `SyntaKind.Unknown` } - function scanIdentifier(startCharacter: number, languageVersion: ts.ScriptTarget) { + function scanIdentifier(startCharacter: number, languageVersion: ScriptTarget) { let ch = startCharacter; if (isIdentifierStart(ch, languageVersion)) { pos += charSize(ch); while (pos < end && isIdentifierPart(ch = codePointAt(text, pos), languageVersion)) pos += charSize(ch); tokenValue = text.substring(tokenPos, pos); - if (ch === ts.CharacterCodes.backslash) { + if (ch === CharacterCodes.backslash) { tokenValue += scanIdentifierParts(); } return getIdentifierToken(); } } - function reScanGreaterToken(): ts.SyntaxKind { - if (token === ts.SyntaxKind.GreaterThanToken) { - if (text.charCodeAt(pos) === ts.CharacterCodes.greaterThan) { - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.greaterThan) { - if (text.charCodeAt(pos + 2) === ts.CharacterCodes.equals) { - return pos += 3, token = ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken; + function reScanGreaterToken(): SyntaxKind { + if (token === SyntaxKind.GreaterThanToken) { + if (text.charCodeAt(pos) === CharacterCodes.greaterThan) { + if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) { + if (text.charCodeAt(pos + 2) === CharacterCodes.equals) { + return pos += 3, token = SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken; } - return pos += 2, token = ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken; + return pos += 2, token = SyntaxKind.GreaterThanGreaterThanGreaterThanToken; } - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.equals) { - return pos += 2, token = ts.SyntaxKind.GreaterThanGreaterThanEqualsToken; + if (text.charCodeAt(pos + 1) === CharacterCodes.equals) { + return pos += 2, token = SyntaxKind.GreaterThanGreaterThanEqualsToken; } pos++; - return token = ts.SyntaxKind.GreaterThanGreaterThanToken; + return token = SyntaxKind.GreaterThanGreaterThanToken; } - if (text.charCodeAt(pos) === ts.CharacterCodes.equals) { + if (text.charCodeAt(pos) === CharacterCodes.equals) { pos++; - return token = ts.SyntaxKind.GreaterThanEqualsToken; + return token = SyntaxKind.GreaterThanEqualsToken; } } return token; } - function reScanAsteriskEqualsToken(): ts.SyntaxKind { - ts.Debug.assert(token === ts.SyntaxKind.AsteriskEqualsToken, "'reScanAsteriskEqualsToken' should only be called on a '*='"); + function reScanAsteriskEqualsToken(): SyntaxKind { + Debug.assert(token === SyntaxKind.AsteriskEqualsToken, "'reScanAsteriskEqualsToken' should only be called on a '*='"); pos = tokenPos + 1; - return token = ts.SyntaxKind.EqualsToken; + return token = SyntaxKind.EqualsToken; } - function reScanSlashToken(): ts.SyntaxKind { - if (token === ts.SyntaxKind.SlashToken || token === ts.SyntaxKind.SlashEqualsToken) { + function reScanSlashToken(): SyntaxKind { + if (token === SyntaxKind.SlashToken || token === SyntaxKind.SlashEqualsToken) { let p = tokenPos + 1; let inEscape = false; let inCharacterClass = false; @@ -2174,15 +2179,15 @@ export function createScanner(languageVersion: ts.ScriptTarget, // If we reach the end of a file, or hit a newline, then this is an unterminated // regex. Report error and return what we have so far. if (p >= end) { - tokenFlags |= ts.TokenFlags.Unterminated; - error(ts.Diagnostics.Unterminated_regular_expression_literal); + tokenFlags |= TokenFlags.Unterminated; + error(Diagnostics.Unterminated_regular_expression_literal); break; } const ch = text.charCodeAt(p); if (isLineBreak(ch)) { - tokenFlags |= ts.TokenFlags.Unterminated; - error(ts.Diagnostics.Unterminated_regular_expression_literal); + tokenFlags |= TokenFlags.Unterminated; + error(Diagnostics.Unterminated_regular_expression_literal); break; } @@ -2191,19 +2196,19 @@ export function createScanner(languageVersion: ts.ScriptTarget, // reset the flag and just advance to the next char. inEscape = false; } - else if (ch === ts.CharacterCodes.slash && !inCharacterClass) { + else if (ch === CharacterCodes.slash && !inCharacterClass) { // A slash within a character class is permissible, // but in general it signals the end of the regexp literal. p++; break; } - else if (ch === ts.CharacterCodes.openBracket) { + else if (ch === CharacterCodes.openBracket) { inCharacterClass = true; } - else if (ch === ts.CharacterCodes.backslash) { + else if (ch === CharacterCodes.backslash) { inEscape = true; } - else if (ch === ts.CharacterCodes.closeBracket) { + else if (ch === CharacterCodes.closeBracket) { inCharacterClass = false; } p++; @@ -2214,23 +2219,23 @@ export function createScanner(languageVersion: ts.ScriptTarget, } pos = p; tokenValue = text.substring(tokenPos, pos); - token = ts.SyntaxKind.RegularExpressionLiteral; + token = SyntaxKind.RegularExpressionLiteral; } return token; } function appendIfCommentDirective( - commentDirectives: ts.CommentDirective[] | undefined, + commentDirectives: CommentDirective[] | undefined, text: string, commentDirectiveRegEx: RegExp, lineStart: number, ) { - const type = getDirectiveFromComment(ts.trimStringStart(text), commentDirectiveRegEx); + const type = getDirectiveFromComment(trimStringStart(text), commentDirectiveRegEx); if (type === undefined) { return commentDirectives; } - return ts.append( + return append( commentDirectives, { range: { pos: lineStart, end: pos }, @@ -2247,10 +2252,10 @@ export function createScanner(languageVersion: ts.ScriptTarget, switch (match[1]) { case "ts-expect-error": - return ts.CommentDirectiveType.ExpectError; + return CommentDirectiveType.ExpectError; case "ts-ignore": - return ts.CommentDirectiveType.Ignore; + return CommentDirectiveType.Ignore; } return undefined; @@ -2259,64 +2264,64 @@ export function createScanner(languageVersion: ts.ScriptTarget, /** * Unconditionally back up and scan a template expression portion. */ - function reScanTemplateToken(isTaggedTemplate: boolean): ts.SyntaxKind { - ts.Debug.assert(token === ts.SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'"); + function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind { + Debug.assert(token === SyntaxKind.CloseBraceToken, "'reScanTemplateToken' should only be called on a '}'"); pos = tokenPos; return token = scanTemplateAndSetTokenValue(isTaggedTemplate); } - function reScanTemplateHeadOrNoSubstitutionTemplate(): ts.SyntaxKind { + function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind { pos = tokenPos; return token = scanTemplateAndSetTokenValue(/* isTaggedTemplate */ true); } - function reScanJsxToken(allowMultilineJsxText = true): ts.JsxTokenSyntaxKind { + function reScanJsxToken(allowMultilineJsxText = true): JsxTokenSyntaxKind { pos = tokenPos = startPos; return token = scanJsxToken(allowMultilineJsxText); } - function reScanLessThanToken(): ts.SyntaxKind { - if (token === ts.SyntaxKind.LessThanLessThanToken) { + function reScanLessThanToken(): SyntaxKind { + if (token === SyntaxKind.LessThanLessThanToken) { pos = tokenPos + 1; - return token = ts.SyntaxKind.LessThanToken; + return token = SyntaxKind.LessThanToken; } return token; } - function reScanHashToken(): ts.SyntaxKind { - if (token === ts.SyntaxKind.PrivateIdentifier) { + function reScanHashToken(): SyntaxKind { + if (token === SyntaxKind.PrivateIdentifier) { pos = tokenPos + 1; - return token = ts.SyntaxKind.HashToken; + return token = SyntaxKind.HashToken; } return token; } - function reScanQuestionToken(): ts.SyntaxKind { - ts.Debug.assert(token === ts.SyntaxKind.QuestionQuestionToken, "'reScanQuestionToken' should only be called on a '??'"); + function reScanQuestionToken(): SyntaxKind { + Debug.assert(token === SyntaxKind.QuestionQuestionToken, "'reScanQuestionToken' should only be called on a '??'"); pos = tokenPos + 1; - return token = ts.SyntaxKind.QuestionToken; + return token = SyntaxKind.QuestionToken; } - function scanJsxToken(allowMultilineJsxText = true): ts.JsxTokenSyntaxKind { + function scanJsxToken(allowMultilineJsxText = true): JsxTokenSyntaxKind { startPos = tokenPos = pos; if (pos >= end) { - return token = ts.SyntaxKind.EndOfFileToken; + return token = SyntaxKind.EndOfFileToken; } let char = text.charCodeAt(pos); - if (char === ts.CharacterCodes.lessThan) { - if (text.charCodeAt(pos + 1) === ts.CharacterCodes.slash) { + if (char === CharacterCodes.lessThan) { + if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { pos += 2; - return token = ts.SyntaxKind.LessThanSlashToken; + return token = SyntaxKind.LessThanSlashToken; } pos++; - return token = ts.SyntaxKind.LessThanToken; + return token = SyntaxKind.LessThanToken; } - if (char === ts.CharacterCodes.openBrace) { + if (char === CharacterCodes.openBrace) { pos++; - return token = ts.SyntaxKind.OpenBraceToken; + return token = SyntaxKind.OpenBraceToken; } // First non-whitespace character on this line. @@ -2327,21 +2332,21 @@ export function createScanner(languageVersion: ts.ScriptTarget, while (pos < end) { char = text.charCodeAt(pos); - if (char === ts.CharacterCodes.openBrace) { + if (char === CharacterCodes.openBrace) { break; } - if (char === ts.CharacterCodes.lessThan) { + if (char === CharacterCodes.lessThan) { if (isConflictMarkerTrivia(text, pos)) { pos = scanConflictMarkerTrivia(text, pos, error); - return token = ts.SyntaxKind.ConflictMarkerTrivia; + return token = SyntaxKind.ConflictMarkerTrivia; } break; } - if (char === ts.CharacterCodes.greaterThan) { - error(ts.Diagnostics.Unexpected_token_Did_you_mean_or_gt, pos, 1); + if (char === CharacterCodes.greaterThan) { + error(Diagnostics.Unexpected_token_Did_you_mean_or_gt, pos, 1); } - if (char === ts.CharacterCodes.closeBrace) { - error(ts.Diagnostics.Unexpected_token_Did_you_mean_or_rbrace, pos, 1); + if (char === CharacterCodes.closeBrace) { + error(Diagnostics.Unexpected_token_Did_you_mean_or_rbrace, pos, 1); } // FirstNonWhitespace is 0, then we only see whitespaces so far. If we see a linebreak, we want to ignore that whitespaces. @@ -2367,12 +2372,12 @@ export function createScanner(languageVersion: ts.ScriptTarget, tokenValue = text.substring(startPos, pos); - return firstNonWhitespace === -1 ? ts.SyntaxKind.JsxTextAllWhiteSpaces : ts.SyntaxKind.JsxText; + return firstNonWhitespace === -1 ? SyntaxKind.JsxTextAllWhiteSpaces : SyntaxKind.JsxText; } // Scans a JSX identifier; these differ from normal identifiers in that // they allow dashes - function scanJsxIdentifier(): ts.SyntaxKind { + function scanJsxIdentifier(): SyntaxKind { if (tokenIsIdentifierOrKeyword(token)) { // An identifier or keyword has already been parsed - check for a `-` or a single instance of `:` and then append it and // everything after it to the token @@ -2381,16 +2386,16 @@ export function createScanner(languageVersion: ts.ScriptTarget, let namespaceSeparator = false; while (pos < end) { const ch = text.charCodeAt(pos); - if (ch === ts.CharacterCodes.minus) { + if (ch === CharacterCodes.minus) { tokenValue += "-"; pos++; continue; } - else if (ch === ts.CharacterCodes.colon && !namespaceSeparator) { + else if (ch === CharacterCodes.colon && !namespaceSeparator) { tokenValue += ":"; pos++; namespaceSeparator = true; - token = ts.SyntaxKind.Identifier; // swap from keyword kind to identifier kind + token = SyntaxKind.Identifier; // swap from keyword kind to identifier kind continue; } const oldPos = pos; @@ -2409,83 +2414,83 @@ export function createScanner(languageVersion: ts.ScriptTarget, return token; } - function scanJsxAttributeValue(): ts.SyntaxKind { + function scanJsxAttributeValue(): SyntaxKind { startPos = pos; switch (text.charCodeAt(pos)) { - case ts.CharacterCodes.doubleQuote: - case ts.CharacterCodes.singleQuote: + case CharacterCodes.doubleQuote: + case CharacterCodes.singleQuote: tokenValue = scanString(/*jsxAttributeString*/ true); - return token = ts.SyntaxKind.StringLiteral; + return token = SyntaxKind.StringLiteral; default: // If this scans anything other than `{`, it's a parse error. return scan(); } } - function reScanJsxAttributeValue(): ts.SyntaxKind { + function reScanJsxAttributeValue(): SyntaxKind { pos = tokenPos = startPos; return scanJsxAttributeValue(); } - function scanJsDocToken(): ts.JSDocSyntaxKind { + function scanJsDocToken(): JSDocSyntaxKind { startPos = tokenPos = pos; - tokenFlags = ts.TokenFlags.None; + tokenFlags = TokenFlags.None; if (pos >= end) { - return token = ts.SyntaxKind.EndOfFileToken; + return token = SyntaxKind.EndOfFileToken; } const ch = codePointAt(text, pos); pos += charSize(ch); switch (ch) { - case ts.CharacterCodes.tab: - case ts.CharacterCodes.verticalTab: - case ts.CharacterCodes.formFeed: - case ts.CharacterCodes.space: + case CharacterCodes.tab: + case CharacterCodes.verticalTab: + case CharacterCodes.formFeed: + case CharacterCodes.space: while (pos < end && isWhiteSpaceSingleLine(text.charCodeAt(pos))) { pos++; } - return token = ts.SyntaxKind.WhitespaceTrivia; - case ts.CharacterCodes.at: - return token = ts.SyntaxKind.AtToken; - case ts.CharacterCodes.carriageReturn: - if (text.charCodeAt(pos) === ts.CharacterCodes.lineFeed) { + return token = SyntaxKind.WhitespaceTrivia; + case CharacterCodes.at: + return token = SyntaxKind.AtToken; + case CharacterCodes.carriageReturn: + if (text.charCodeAt(pos) === CharacterCodes.lineFeed) { pos++; } // falls through - case ts.CharacterCodes.lineFeed: - tokenFlags |= ts.TokenFlags.PrecedingLineBreak; - return token = ts.SyntaxKind.NewLineTrivia; - case ts.CharacterCodes.asterisk: - return token = ts.SyntaxKind.AsteriskToken; - case ts.CharacterCodes.openBrace: - return token = ts.SyntaxKind.OpenBraceToken; - case ts.CharacterCodes.closeBrace: - return token = ts.SyntaxKind.CloseBraceToken; - case ts.CharacterCodes.openBracket: - return token = ts.SyntaxKind.OpenBracketToken; - case ts.CharacterCodes.closeBracket: - return token = ts.SyntaxKind.CloseBracketToken; - case ts.CharacterCodes.lessThan: - return token = ts.SyntaxKind.LessThanToken; - case ts.CharacterCodes.greaterThan: - return token = ts.SyntaxKind.GreaterThanToken; - case ts.CharacterCodes.equals: - return token = ts.SyntaxKind.EqualsToken; - case ts.CharacterCodes.comma: - return token = ts.SyntaxKind.CommaToken; - case ts.CharacterCodes.dot: - return token = ts.SyntaxKind.DotToken; - case ts.CharacterCodes.backtick: - return token = ts.SyntaxKind.BacktickToken; - case ts.CharacterCodes.hash: - return token = ts.SyntaxKind.HashToken; - case ts.CharacterCodes.backslash: + case CharacterCodes.lineFeed: + tokenFlags |= TokenFlags.PrecedingLineBreak; + return token = SyntaxKind.NewLineTrivia; + case CharacterCodes.asterisk: + return token = SyntaxKind.AsteriskToken; + case CharacterCodes.openBrace: + return token = SyntaxKind.OpenBraceToken; + case CharacterCodes.closeBrace: + return token = SyntaxKind.CloseBraceToken; + case CharacterCodes.openBracket: + return token = SyntaxKind.OpenBracketToken; + case CharacterCodes.closeBracket: + return token = SyntaxKind.CloseBracketToken; + case CharacterCodes.lessThan: + return token = SyntaxKind.LessThanToken; + case CharacterCodes.greaterThan: + return token = SyntaxKind.GreaterThanToken; + case CharacterCodes.equals: + return token = SyntaxKind.EqualsToken; + case CharacterCodes.comma: + return token = SyntaxKind.CommaToken; + case CharacterCodes.dot: + return token = SyntaxKind.DotToken; + case CharacterCodes.backtick: + return token = SyntaxKind.BacktickToken; + case CharacterCodes.hash: + return token = SyntaxKind.HashToken; + case CharacterCodes.backslash: pos--; const extendedCookedChar = peekExtendedUnicodeEscape(); if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) { pos += 3; - tokenFlags |= ts.TokenFlags.ExtendedUnicodeEscape; + tokenFlags |= TokenFlags.ExtendedUnicodeEscape; tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts(); return token = getIdentifierToken(); } @@ -2493,25 +2498,25 @@ export function createScanner(languageVersion: ts.ScriptTarget, const cookedChar = peekUnicodeEscape(); if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) { pos += 6; - tokenFlags |= ts.TokenFlags.UnicodeEscape; + tokenFlags |= TokenFlags.UnicodeEscape; tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts(); return token = getIdentifierToken(); } pos++; - return token = ts.SyntaxKind.Unknown; + return token = SyntaxKind.Unknown; } if (isIdentifierStart(ch, languageVersion)) { let char = ch; - while (pos < end && isIdentifierPart(char = codePointAt(text, pos), languageVersion) || text.charCodeAt(pos) === ts.CharacterCodes.minus) pos += charSize(char); + while (pos < end && isIdentifierPart(char = codePointAt(text, pos), languageVersion) || text.charCodeAt(pos) === CharacterCodes.minus) pos += charSize(char); tokenValue = text.substring(tokenPos, pos); - if (char === ts.CharacterCodes.backslash) { + if (char === CharacterCodes.backslash) { tokenValue += scanIdentifierParts(); } return token = getIdentifierToken(); } else { - return token = ts.SyntaxKind.Unknown; + return token = SyntaxKind.Unknown; } } @@ -2588,22 +2593,22 @@ export function createScanner(languageVersion: ts.ScriptTarget, onError = errorCallback; } - function setScriptTarget(scriptTarget: ts.ScriptTarget) { + function setScriptTarget(scriptTarget: ScriptTarget) { languageVersion = scriptTarget; } - function setLanguageVariant(variant: ts.LanguageVariant) { + function setLanguageVariant(variant: LanguageVariant) { languageVariant = variant; } function setTextPos(textPos: number) { - ts.Debug.assert(textPos >= 0); + Debug.assert(textPos >= 0); pos = textPos; startPos = textPos; tokenPos = textPos; - token = ts.SyntaxKind.Unknown; + token = SyntaxKind.Unknown; tokenValue = undefined!; - tokenFlags = ts.TokenFlags.None; + tokenFlags = TokenFlags.None; } function setInJSDocType(inType: boolean) { @@ -2642,7 +2647,7 @@ function charSize(ch: number) { // Derived from the 10.1.1 UTF16Encoding of the ES6 Spec. function utf16EncodeAsStringFallback(codePoint: number) { - ts.Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF); + Debug.assert(0x0 <= codePoint && codePoint <= 0x10FFFF); if (codePoint <= 65535) { return String.fromCharCode(codePoint); diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts index d187fa4e0221c..0500ba87f827b 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -1,4 +1,6 @@ -import * as ts from "./_namespaces/ts"; +import { + compareStringsCaseSensitive, compareValues, Comparison, Debug, emptyArray, every, isArray, map, some, trimString, +} from "./_namespaces/ts"; // https://semver.org/#spec-item-2 // > A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative @@ -45,19 +47,19 @@ export class Version { constructor(major: number, minor?: number, patch?: number, prerelease?: string | readonly string[], build?: string | readonly string[]); constructor(major: number | string, minor = 0, patch = 0, prerelease: string | readonly string[] = "", build: string | readonly string[] = "") { if (typeof major === "string") { - const result = ts.Debug.checkDefined(tryParseComponents(major), "Invalid version"); + const result = Debug.checkDefined(tryParseComponents(major), "Invalid version"); ({ major, minor, patch, prerelease, build } = result); } - ts.Debug.assert(major >= 0, "Invalid argument: major"); - ts.Debug.assert(minor >= 0, "Invalid argument: minor"); - ts.Debug.assert(patch >= 0, "Invalid argument: patch"); + Debug.assert(major >= 0, "Invalid argument: major"); + Debug.assert(minor >= 0, "Invalid argument: minor"); + Debug.assert(patch >= 0, "Invalid argument: patch"); - const prereleaseArray = prerelease ? ts.isArray(prerelease) ? prerelease : prerelease.split(".") : ts.emptyArray; - const buildArray = build ? ts.isArray(build) ? build : build.split(".") : ts.emptyArray; + const prereleaseArray = prerelease ? isArray(prerelease) ? prerelease : prerelease.split(".") : emptyArray; + const buildArray = build ? isArray(build) ? build : build.split(".") : emptyArray; - ts.Debug.assert(ts.every(prereleaseArray, s => prereleasePartRegExp.test(s)), "Invalid argument: prerelease"); - ts.Debug.assert(ts.every(buildArray, s => buildPartRegExp.test(s)), "Invalid argument: build"); + Debug.assert(every(prereleaseArray, s => prereleasePartRegExp.test(s)), "Invalid argument: prerelease"); + Debug.assert(every(buildArray, s => buildPartRegExp.test(s)), "Invalid argument: build"); this.major = major; this.minor = minor; @@ -87,11 +89,11 @@ export class Version { // // https://semver.org/#spec-item-11 // > Build metadata does not figure into precedence - if (this === other) return ts.Comparison.EqualTo; - if (other === undefined) return ts.Comparison.GreaterThan; - return ts.compareValues(this.major, other.major) - || ts.compareValues(this.minor, other.minor) - || ts.compareValues(this.patch, other.patch) + if (this === other) return Comparison.EqualTo; + if (other === undefined) return Comparison.GreaterThan; + return compareValues(this.major, other.major) + || compareValues(this.minor, other.minor) + || compareValues(this.patch, other.patch) || comparePrereleaseIdentifiers(this.prerelease, other.prerelease); } @@ -100,7 +102,7 @@ export class Version { case "major": return new Version(this.major + 1, 0, 0); case "minor": return new Version(this.major, this.minor + 1, 0); case "patch": return new Version(this.major, this.minor, this.patch + 1); - default: return ts.Debug.assertNever(field); + default: return Debug.assertNever(field); } } @@ -117,8 +119,8 @@ export class Version { toString() { let result = `${this.major}.${this.minor}.${this.patch}`; - if (ts.some(this.prerelease)) result += `-${this.prerelease.join(".")}`; - if (ts.some(this.build)) result += `+${this.build.join(".")}`; + if (some(this.prerelease)) result += `-${this.prerelease.join(".")}`; + if (some(this.build)) result += `+${this.build.join(".")}`; return result; } } @@ -143,9 +145,9 @@ function comparePrereleaseIdentifiers(left: readonly string[], right: readonly s // https://semver.org/#spec-item-11 // > When major, minor, and patch are equal, a pre-release version has lower precedence // > than a normal version. - if (left === right) return ts.Comparison.EqualTo; - if (left.length === 0) return right.length === 0 ? ts.Comparison.EqualTo : ts.Comparison.GreaterThan; - if (right.length === 0) return ts.Comparison.LessThan; + if (left === right) return Comparison.EqualTo; + if (left.length === 0) return right.length === 0 ? Comparison.EqualTo : Comparison.GreaterThan; + if (right.length === 0) return Comparison.LessThan; // https://semver.org/#spec-item-11 // > Precedence for two pre-release versions with the same major, minor, and patch version @@ -162,17 +164,17 @@ function comparePrereleaseIdentifiers(left: readonly string[], right: readonly s if (leftIsNumeric || rightIsNumeric) { // https://semver.org/#spec-item-11 // > Numeric identifiers always have lower precedence than non-numeric identifiers. - if (leftIsNumeric !== rightIsNumeric) return leftIsNumeric ? ts.Comparison.LessThan : ts.Comparison.GreaterThan; + if (leftIsNumeric !== rightIsNumeric) return leftIsNumeric ? Comparison.LessThan : Comparison.GreaterThan; // https://semver.org/#spec-item-11 // > identifiers consisting of only digits are compared numerically - const result = ts.compareValues(+leftIdentifier, +rightIdentifier); + const result = compareValues(+leftIdentifier, +rightIdentifier); if (result) return result; } else { // https://semver.org/#spec-item-11 // > identifiers with letters or hyphens are compared lexically in ASCII sort order. - const result = ts.compareStringsCaseSensitive(leftIdentifier, rightIdentifier); + const result = compareStringsCaseSensitive(leftIdentifier, rightIdentifier); if (result) return result; } } @@ -180,7 +182,7 @@ function comparePrereleaseIdentifiers(left: readonly string[], right: readonly s // https://semver.org/#spec-item-11 // > A larger set of pre-release fields has a higher precedence than a smaller set, if all // > of the preceding identifiers are equal. - return ts.compareValues(left.length, right.length); + return compareValues(left.length, right.length); } /** @internal */ @@ -191,7 +193,7 @@ export class VersionRange { private _alternatives: readonly (readonly Comparator[])[]; constructor(spec: string) { - this._alternatives = spec ? ts.Debug.checkDefined(parseRange(spec), "Invalid range spec.") : ts.emptyArray; + this._alternatives = spec ? Debug.checkDefined(parseRange(spec), "Invalid range spec.") : emptyArray; } static tryParse(text: string) { @@ -258,17 +260,17 @@ const rangeRegExp = /^(~|\^|<|<=|>|>=|=)?\s*([a-z0-9-+.*]+)$/i; function parseRange(text: string) { const alternatives: Comparator[][] = []; - for (let range of ts.trimString(text).split(logicalOrRegExp)) { + for (let range of trimString(text).split(logicalOrRegExp)) { if (!range) continue; const comparators: Comparator[] = []; - range = ts.trimString(range); + range = trimString(range); const match = hyphenRegExp.exec(range); if (match) { if (!parseHyphen(match[1], match[2], comparators)) return undefined; } else { for (const simple of range.split(whitespaceRegExp)) { - const match = rangeRegExp.exec(ts.trimString(simple)); + const match = rangeRegExp.exec(trimString(simple)); if (!match || !parseComparator(match[1], match[2], comparators)) return undefined; } } @@ -400,16 +402,16 @@ function testComparator(version: Version, operator: Comparator["operator"], oper case ">": return cmp > 0; case ">=": return cmp >= 0; case "=": return cmp === 0; - default: return ts.Debug.assertNever(operator); + default: return Debug.assertNever(operator); } } function formatDisjunction(alternatives: readonly (readonly Comparator[])[]) { - return ts.map(alternatives, formatAlternative).join(" || ") || "*"; + return map(alternatives, formatAlternative).join(" || ") || "*"; } function formatAlternative(comparators: readonly Comparator[]) { - return ts.map(comparators, formatComparator).join(" "); + return map(comparators, formatComparator).join(" "); } function formatComparator(comparator: Comparator) { diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 0eb2cafd45ae4..6cab9ab9876e2 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -1,4 +1,11 @@ import * as ts from "./_namespaces/ts"; +import { + arrayFrom, binarySearchKey, CharacterCodes, combinePaths, compareValues, Debug, DocumentPosition, + DocumentPositionMapper, DocumentPositionMapperHost, EmitHost, emptyArray, ESMap, every, getDirectoryPath, + getNormalizedAbsolutePath, getPositionOfLineAndCharacter, getRelativePathToDirectoryOrUrl, identity, isArray, + isString, Iterator, LineAndCharacter, Map, RawSourceMap, some, sortAndDeduplicate, SortedReadonlyArray, + SourceMapGenerator, trimStringEnd, +} from "./_namespaces/ts"; /** @internal */ export interface SourceMapGeneratorOptions { @@ -6,7 +13,7 @@ export interface SourceMapGeneratorOptions { } /** @internal */ -export function createSourceMapGenerator(host: ts.EmitHost, file: string, sourceRoot: string, sourcesDirectoryPath: string, generatorOptions: SourceMapGeneratorOptions): ts.SourceMapGenerator { +export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoot: string, sourcesDirectoryPath: string, generatorOptions: SourceMapGeneratorOptions): SourceMapGenerator { const { enter, exit } = generatorOptions.extendedDiagnostics ? ts.performance.createTimer("Source Map", "beforeSourcemap", "afterSourcemap") : ts.performance.nullTimer; @@ -14,11 +21,11 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source // Current source map file and its index in the sources list const rawSources: string[] = []; const sources: string[] = []; - const sourceToSourceIndexMap = new ts.Map(); + const sourceToSourceIndexMap = new Map(); let sourcesContent: (string | null)[] | undefined; const names: string[] = []; - let nameToNameIndexMap: ts.ESMap | undefined; + let nameToNameIndexMap: ESMap | undefined; const mappingCharCodes: number[] = []; let mappings = ""; @@ -54,7 +61,7 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source function addSource(fileName: string) { enter(); - const source = ts.getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, + const source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath, fileName, host.getCurrentDirectory(), host.getCanonicalFileName, @@ -87,7 +94,7 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source function addName(name: string) { enter(); - if (!nameToNameIndexMap) nameToNameIndexMap = new ts.Map(); + if (!nameToNameIndexMap) nameToNameIndexMap = new Map(); let nameIndex = nameToNameIndexMap.get(name); if (nameIndex === undefined) { nameIndex = names.length; @@ -114,11 +121,11 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source } function addMapping(generatedLine: number, generatedCharacter: number, sourceIndex?: number, sourceLine?: number, sourceCharacter?: number, nameIndex?: number) { - ts.Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); - ts.Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); - ts.Debug.assert(sourceIndex === undefined || sourceIndex >= 0, "sourceIndex cannot be negative"); - ts.Debug.assert(sourceLine === undefined || sourceLine >= 0, "sourceLine cannot be negative"); - ts.Debug.assert(sourceCharacter === undefined || sourceCharacter >= 0, "sourceCharacter cannot be negative"); + Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); + Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); + Debug.assert(sourceIndex === undefined || sourceIndex >= 0, "sourceIndex cannot be negative"); + Debug.assert(sourceLine === undefined || sourceLine >= 0, "sourceLine cannot be negative"); + Debug.assert(sourceCharacter === undefined || sourceCharacter >= 0, "sourceCharacter cannot be negative"); enter(); // If this location wasn't recorded or the location in source is going backwards, record the mapping if (isNewGeneratedPosition(generatedLine, generatedCharacter) || @@ -144,9 +151,9 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source exit(); } - function appendSourceMap(generatedLine: number, generatedCharacter: number, map: ts.RawSourceMap, sourceMapPath: string, start?: ts.LineAndCharacter, end?: ts.LineAndCharacter) { - ts.Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); - ts.Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); + function appendSourceMap(generatedLine: number, generatedCharacter: number, map: RawSourceMap, sourceMapPath: string, start?: LineAndCharacter, end?: LineAndCharacter) { + Debug.assert(generatedLine >= pendingGeneratedLine, "generatedLine cannot backtrack"); + Debug.assert(generatedCharacter >= 0, "generatedCharacter cannot be negative"); enter(); // First, decode the old component sourcemap const sourceIndexToNewSourceIndexMap: number[] = []; @@ -175,8 +182,8 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source if (newSourceIndex === undefined) { // Apply offsets to each position and fixup source entries const rawPath = map.sources[raw.sourceIndex]; - const relativePath = map.sourceRoot ? ts.combinePaths(map.sourceRoot, rawPath) : rawPath; - const combinedPath = ts.combinePaths(ts.getDirectoryPath(sourceMapPath), relativePath); + const relativePath = map.sourceRoot ? combinePaths(map.sourceRoot, rawPath) : rawPath; + const combinedPath = combinePaths(getDirectoryPath(sourceMapPath), relativePath); sourceIndexToNewSourceIndexMap[raw.sourceIndex] = newSourceIndex = addSource(combinedPath); if (map.sourcesContent && typeof map.sourcesContent[raw.sourceIndex] === "string") { setSourceContent(newSourceIndex, map.sourcesContent[raw.sourceIndex]); @@ -233,7 +240,7 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source if (lastGeneratedLine < pendingGeneratedLine) { // Emit line delimiters do { - appendMappingCharCode(ts.CharacterCodes.semicolon); + appendMappingCharCode(CharacterCodes.semicolon); lastGeneratedLine++; } while (lastGeneratedLine < pendingGeneratedLine); @@ -241,10 +248,10 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source lastGeneratedCharacter = 0; } else { - ts.Debug.assertEqual(lastGeneratedLine, pendingGeneratedLine, "generatedLine cannot backtrack"); + Debug.assertEqual(lastGeneratedLine, pendingGeneratedLine, "generatedLine cannot backtrack"); // Emit comma to separate the entry if (hasLast) { - appendMappingCharCode(ts.CharacterCodes.comma); + appendMappingCharCode(CharacterCodes.comma); } } @@ -283,7 +290,7 @@ export function createSourceMapGenerator(host: ts.EmitHost, file: string, source } } - function toJSON(): ts.RawSourceMap { + function toJSON(): RawSourceMap { commitPendingMapping(); flushMappingBuffer(); return { @@ -355,7 +362,7 @@ export function tryGetSourceMappingURL(lineInfo: LineInfo) { const line = lineInfo.getLineText(index); const comment = sourceMapCommentRegExp.exec(line); if (comment) { - return ts.trimStringEnd(comment[1]); + return trimStringEnd(comment[1]); } // If we see a non-whitespace/map comment-like line, break, to avoid scanning up the entire file else if (!line.match(whitespaceOrMapCommentRegExp)) { @@ -370,16 +377,16 @@ function isStringOrNull(x: any) { } /** @internal */ -export function isRawSourceMap(x: any): x is ts.RawSourceMap { +export function isRawSourceMap(x: any): x is RawSourceMap { return x !== null && typeof x === "object" && x.version === 3 && typeof x.file === "string" && typeof x.mappings === "string" - && ts.isArray(x.sources) && ts.every(x.sources, ts.isString) + && isArray(x.sources) && every(x.sources, isString) && (x.sourceRoot === undefined || x.sourceRoot === null || typeof x.sourceRoot === "string") - && (x.sourcesContent === undefined || x.sourcesContent === null || ts.isArray(x.sourcesContent) && ts.every(x.sourcesContent, isStringOrNull)) - && (x.names === undefined || x.names === null || ts.isArray(x.names) && ts.every(x.names, ts.isString)); + && (x.sourcesContent === undefined || x.sourcesContent === null || isArray(x.sourcesContent) && every(x.sourcesContent, isStringOrNull)) + && (x.names === undefined || x.names === null || isArray(x.names) && every(x.names, isString)); } /* eslint-enable no-null/no-null */ @@ -399,7 +406,7 @@ export function tryParseRawSourceMap(text: string) { } /** @internal */ -export interface MappingsDecoder extends ts.Iterator { +export interface MappingsDecoder extends Iterator { readonly pos: number; readonly error: string | undefined; readonly state: Required; @@ -441,7 +448,7 @@ export function decodeMappings(mappings: string): MappingsDecoder { next() { while (!done && pos < mappings.length) { const ch = mappings.charCodeAt(pos); - if (ch === ts.CharacterCodes.semicolon) { + if (ch === CharacterCodes.semicolon) { // new line generatedLine++; generatedCharacter = 0; @@ -449,7 +456,7 @@ export function decodeMappings(mappings: string): MappingsDecoder { continue; } - if (ch === ts.CharacterCodes.comma) { + if (ch === CharacterCodes.comma) { // Next entry is on same line - no action needed pos++; continue; @@ -531,8 +538,8 @@ export function decodeMappings(mappings: string): MappingsDecoder { function isSourceMappingSegmentEnd() { return (pos === mappings.length || - mappings.charCodeAt(pos) === ts.CharacterCodes.comma || - mappings.charCodeAt(pos) === ts.CharacterCodes.semicolon); + mappings.charCodeAt(pos) === CharacterCodes.comma || + mappings.charCodeAt(pos) === CharacterCodes.semicolon); } function base64VLQFormatDecode(): number { @@ -589,20 +596,20 @@ export function isSourceMapping(mapping: Mapping): mapping is SourceMapping { } function base64FormatEncode(value: number) { - return value >= 0 && value < 26 ? ts.CharacterCodes.A + value : - value >= 26 && value < 52 ? ts.CharacterCodes.a + value - 26 : - value >= 52 && value < 62 ? ts.CharacterCodes._0 + value - 52 : - value === 62 ? ts.CharacterCodes.plus : - value === 63 ? ts.CharacterCodes.slash : - ts.Debug.fail(`${value}: not a base64 value`); + return value >= 0 && value < 26 ? CharacterCodes.A + value : + value >= 26 && value < 52 ? CharacterCodes.a + value - 26 : + value >= 52 && value < 62 ? CharacterCodes._0 + value - 52 : + value === 62 ? CharacterCodes.plus : + value === 63 ? CharacterCodes.slash : + Debug.fail(`${value}: not a base64 value`); } function base64FormatDecode(ch: number) { - return ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.Z ? ch - ts.CharacterCodes.A : - ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.z ? ch - ts.CharacterCodes.a + 26 : - ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9 ? ch - ts.CharacterCodes._0 + 52 : - ch === ts.CharacterCodes.plus ? 62 : - ch === ts.CharacterCodes.slash ? 63 : + return ch >= CharacterCodes.A && ch <= CharacterCodes.Z ? ch - CharacterCodes.A : + ch >= CharacterCodes.a && ch <= CharacterCodes.z ? ch - CharacterCodes.a + 26 : + ch >= CharacterCodes._0 && ch <= CharacterCodes._9 ? ch - CharacterCodes._0 + 52 : + ch === CharacterCodes.plus ? 62 : + ch === CharacterCodes.slash ? 63 : -1; } @@ -634,12 +641,12 @@ function sameMappedPosition(left: MappedPosition, right: MappedPosition) { function compareSourcePositions(left: SourceMappedPosition, right: SourceMappedPosition) { // Compares sourcePosition without comparing sourceIndex // since the mappings are grouped by sourceIndex - ts.Debug.assert(left.sourceIndex === right.sourceIndex); - return ts.compareValues(left.sourcePosition, right.sourcePosition); + Debug.assert(left.sourceIndex === right.sourceIndex); + return compareValues(left.sourcePosition, right.sourcePosition); } function compareGeneratedPositions(left: MappedPosition, right: MappedPosition) { - return ts.compareValues(left.generatedPosition, right.generatedPosition); + return compareValues(left.generatedPosition, right.generatedPosition); } function getSourcePositionOfMapping(value: SourceMappedPosition) { @@ -651,16 +658,16 @@ function getGeneratedPositionOfMapping(value: MappedPosition) { } /** @internal */ -export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost, map: ts.RawSourceMap, mapPath: string): ts.DocumentPositionMapper { - const mapDirectory = ts.getDirectoryPath(mapPath); - const sourceRoot = map.sourceRoot ? ts.getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory; - const generatedAbsoluteFilePath = ts.getNormalizedAbsolutePath(map.file, mapDirectory); +export function createDocumentPositionMapper(host: DocumentPositionMapperHost, map: RawSourceMap, mapPath: string): DocumentPositionMapper { + const mapDirectory = getDirectoryPath(mapPath); + const sourceRoot = map.sourceRoot ? getNormalizedAbsolutePath(map.sourceRoot, mapDirectory) : mapDirectory; + const generatedAbsoluteFilePath = getNormalizedAbsolutePath(map.file, mapDirectory); const generatedFile = host.getSourceFileLike(generatedAbsoluteFilePath); - const sourceFileAbsolutePaths = map.sources.map(source => ts.getNormalizedAbsolutePath(source, sourceRoot)); - const sourceToSourceIndexMap = new ts.Map(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i])); + const sourceFileAbsolutePaths = map.sources.map(source => getNormalizedAbsolutePath(source, sourceRoot)); + const sourceToSourceIndexMap = new Map(sourceFileAbsolutePaths.map((source, i) => [host.getCanonicalFileName(source), i])); let decodedMappings: readonly MappedPosition[] | undefined; - let generatedMappings: ts.SortedReadonlyArray | undefined; - let sourceMappings: readonly ts.SortedReadonlyArray[] | undefined; + let generatedMappings: SortedReadonlyArray | undefined; + let sourceMappings: readonly SortedReadonlyArray[] | undefined; return { getSourcePosition, @@ -669,7 +676,7 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost function processMapping(mapping: Mapping): MappedPosition { const generatedPosition = generatedFile !== undefined - ? ts.getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter, /*allowEdits*/ true) + ? getPositionOfLineAndCharacter(generatedFile, mapping.generatedLine, mapping.generatedCharacter, /*allowEdits*/ true) : -1; let source: string | undefined; let sourcePosition: number | undefined; @@ -677,7 +684,7 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost const sourceFile = host.getSourceFileLike(sourceFileAbsolutePaths[mapping.sourceIndex]); source = map.sources[mapping.sourceIndex]; sourcePosition = sourceFile !== undefined - ? ts.getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter, /*allowEdits*/ true) + ? getPositionOfLineAndCharacter(sourceFile, mapping.sourceLine, mapping.sourceCharacter, /*allowEdits*/ true) : -1; } return { @@ -692,12 +699,12 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost function getDecodedMappings() { if (decodedMappings === undefined) { const decoder = decodeMappings(map.mappings); - const mappings = ts.arrayFrom(decoder, processMapping); + const mappings = arrayFrom(decoder, processMapping); if (decoder.error !== undefined) { if (host.log) { host.log(`Encountered error while decoding sourcemap: ${decoder.error}`); } - decodedMappings = ts.emptyArray; + decodedMappings = emptyArray; } else { decodedMappings = mappings; @@ -715,7 +722,7 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost if (!list) lists[mapping.sourceIndex] = list = []; list.push(mapping); } - sourceMappings = lists.map(list => ts.sortAndDeduplicate(list, compareSourcePositions, sameMappedPosition)); + sourceMappings = lists.map(list => sortAndDeduplicate(list, compareSourcePositions, sameMappedPosition)); } return sourceMappings[sourceIndex]; } @@ -726,19 +733,19 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost for (const mapping of getDecodedMappings()) { list.push(mapping); } - generatedMappings = ts.sortAndDeduplicate(list, compareGeneratedPositions, sameMappedPosition); + generatedMappings = sortAndDeduplicate(list, compareGeneratedPositions, sameMappedPosition); } return generatedMappings; } - function getGeneratedPosition(loc: ts.DocumentPosition): ts.DocumentPosition { + function getGeneratedPosition(loc: DocumentPosition): DocumentPosition { const sourceIndex = sourceToSourceIndexMap.get(host.getCanonicalFileName(loc.fileName)); if (sourceIndex === undefined) return loc; const sourceMappings = getSourceMappings(sourceIndex); - if (!ts.some(sourceMappings)) return loc; + if (!some(sourceMappings)) return loc; - let targetIndex = ts.binarySearchKey(sourceMappings, loc.pos, getSourcePositionOfMapping, ts.compareValues); + let targetIndex = binarySearchKey(sourceMappings, loc.pos, getSourcePositionOfMapping, compareValues); if (targetIndex < 0) { // if no exact match, closest is 2's complement of result targetIndex = ~targetIndex; @@ -752,11 +759,11 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost return { fileName: generatedAbsoluteFilePath, pos: mapping.generatedPosition }; // Closest pos } - function getSourcePosition(loc: ts.DocumentPosition): ts.DocumentPosition { + function getSourcePosition(loc: DocumentPosition): DocumentPosition { const generatedMappings = getGeneratedMappings(); - if (!ts.some(generatedMappings)) return loc; + if (!some(generatedMappings)) return loc; - let targetIndex = ts.binarySearchKey(generatedMappings, loc.pos, getGeneratedPositionOfMapping, ts.compareValues); + let targetIndex = binarySearchKey(generatedMappings, loc.pos, getGeneratedPositionOfMapping, compareValues); if (targetIndex < 0) { // if no exact match, closest is 2's complement of result targetIndex = ~targetIndex; @@ -772,7 +779,7 @@ export function createDocumentPositionMapper(host: ts.DocumentPositionMapperHost } /** @internal */ -export const identitySourceMapConsumer: ts.DocumentPositionMapper = { - getSourcePosition: ts.identity, - getGeneratedPosition: ts.identity +export const identitySourceMapConsumer: DocumentPositionMapper = { + getSourcePosition: identity, + getGeneratedPosition: identity }; diff --git a/src/compiler/symbolWalker.ts b/src/compiler/symbolWalker.ts index b3e00e7bf4441..905443939fd94 100644 --- a/src/compiler/symbolWalker.ts +++ b/src/compiler/symbolWalker.ts @@ -1,50 +1,54 @@ -import * as ts from "./_namespaces/ts"; +import { + clear, EntityNameOrEntityNameExpression, forEach, getOwnValues, getSymbolId, Identifier, IndexedAccessType, + IndexType, InterfaceType, MappedType, Node, ObjectFlags, ObjectType, ResolvedType, Signature, Symbol, SymbolWalker, + SyntaxKind, Type, TypeFlags, TypeParameter, TypePredicate, TypeQueryNode, TypeReference, UnionOrIntersectionType, +} from "./_namespaces/ts"; /** @internal */ /** @internal */ export function createGetSymbolWalker( - getRestTypeOfSignature: (sig: ts.Signature) => ts.Type, - getTypePredicateOfSignature: (sig: ts.Signature) => ts.TypePredicate | undefined, - getReturnTypeOfSignature: (sig: ts.Signature) => ts.Type, - getBaseTypes: (type: ts.Type) => ts.Type[], - resolveStructuredTypeMembers: (type: ts.ObjectType) => ts.ResolvedType, - getTypeOfSymbol: (sym: ts.Symbol) => ts.Type, - getResolvedSymbol: (node: ts.Node) => ts.Symbol, - getConstraintOfTypeParameter: (typeParameter: ts.TypeParameter) => ts.Type | undefined, - getFirstIdentifier: (node: ts.EntityNameOrEntityNameExpression) => ts.Identifier, - getTypeArguments: (type: ts.TypeReference) => readonly ts.Type[]) { + getRestTypeOfSignature: (sig: Signature) => Type, + getTypePredicateOfSignature: (sig: Signature) => TypePredicate | undefined, + getReturnTypeOfSignature: (sig: Signature) => Type, + getBaseTypes: (type: Type) => Type[], + resolveStructuredTypeMembers: (type: ObjectType) => ResolvedType, + getTypeOfSymbol: (sym: Symbol) => Type, + getResolvedSymbol: (node: Node) => Symbol, + getConstraintOfTypeParameter: (typeParameter: TypeParameter) => Type | undefined, + getFirstIdentifier: (node: EntityNameOrEntityNameExpression) => Identifier, + getTypeArguments: (type: TypeReference) => readonly Type[]) { return getSymbolWalker; - function getSymbolWalker(accept: (symbol: ts.Symbol) => boolean = () => true): ts.SymbolWalker { - const visitedTypes: ts.Type[] = []; // Sparse array from id to type - const visitedSymbols: ts.Symbol[] = []; // Sparse array from id to symbol + function getSymbolWalker(accept: (symbol: Symbol) => boolean = () => true): SymbolWalker { + const visitedTypes: Type[] = []; // Sparse array from id to type + const visitedSymbols: Symbol[] = []; // Sparse array from id to symbol return { walkType: type => { try { visitType(type); - return { visitedTypes: ts.getOwnValues(visitedTypes), visitedSymbols: ts.getOwnValues(visitedSymbols) }; + return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) }; } finally { - ts.clear(visitedTypes); - ts.clear(visitedSymbols); + clear(visitedTypes); + clear(visitedSymbols); } }, walkSymbol: symbol => { try { visitSymbol(symbol); - return { visitedTypes: ts.getOwnValues(visitedTypes), visitedSymbols: ts.getOwnValues(visitedSymbols) }; + return { visitedTypes: getOwnValues(visitedTypes), visitedSymbols: getOwnValues(visitedSymbols) }; } finally { - ts.clear(visitedTypes); - ts.clear(visitedSymbols); + clear(visitedTypes); + clear(visitedSymbols); } }, }; - function visitType(type: ts.Type | undefined): void { + function visitType(type: Type | undefined): void { if (!type) { return; } @@ -60,72 +64,72 @@ export function createGetSymbolWalker( if (shouldBail) return; // Visit the type's related types, if any - if (type.flags & ts.TypeFlags.Object) { - const objectType = type as ts.ObjectType; + if (type.flags & TypeFlags.Object) { + const objectType = type as ObjectType; const objectFlags = objectType.objectFlags; - if (objectFlags & ts.ObjectFlags.Reference) { - visitTypeReference(type as ts.TypeReference); + if (objectFlags & ObjectFlags.Reference) { + visitTypeReference(type as TypeReference); } - if (objectFlags & ts.ObjectFlags.Mapped) { - visitMappedType(type as ts.MappedType); + if (objectFlags & ObjectFlags.Mapped) { + visitMappedType(type as MappedType); } - if (objectFlags & (ts.ObjectFlags.Class | ts.ObjectFlags.Interface)) { - visitInterfaceType(type as ts.InterfaceType); + if (objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)) { + visitInterfaceType(type as InterfaceType); } - if (objectFlags & (ts.ObjectFlags.Tuple | ts.ObjectFlags.Anonymous)) { + if (objectFlags & (ObjectFlags.Tuple | ObjectFlags.Anonymous)) { visitObjectType(objectType); } } - if (type.flags & ts.TypeFlags.TypeParameter) { - visitTypeParameter(type as ts.TypeParameter); + if (type.flags & TypeFlags.TypeParameter) { + visitTypeParameter(type as TypeParameter); } - if (type.flags & ts.TypeFlags.UnionOrIntersection) { - visitUnionOrIntersectionType(type as ts.UnionOrIntersectionType); + if (type.flags & TypeFlags.UnionOrIntersection) { + visitUnionOrIntersectionType(type as UnionOrIntersectionType); } - if (type.flags & ts.TypeFlags.Index) { - visitIndexType(type as ts.IndexType); + if (type.flags & TypeFlags.Index) { + visitIndexType(type as IndexType); } - if (type.flags & ts.TypeFlags.IndexedAccess) { - visitIndexedAccessType(type as ts.IndexedAccessType); + if (type.flags & TypeFlags.IndexedAccess) { + visitIndexedAccessType(type as IndexedAccessType); } } - function visitTypeReference(type: ts.TypeReference): void { + function visitTypeReference(type: TypeReference): void { visitType(type.target); - ts.forEach(getTypeArguments(type), visitType); + forEach(getTypeArguments(type), visitType); } - function visitTypeParameter(type: ts.TypeParameter): void { + function visitTypeParameter(type: TypeParameter): void { visitType(getConstraintOfTypeParameter(type)); } - function visitUnionOrIntersectionType(type: ts.UnionOrIntersectionType): void { - ts.forEach(type.types, visitType); + function visitUnionOrIntersectionType(type: UnionOrIntersectionType): void { + forEach(type.types, visitType); } - function visitIndexType(type: ts.IndexType): void { + function visitIndexType(type: IndexType): void { visitType(type.type); } - function visitIndexedAccessType(type: ts.IndexedAccessType): void { + function visitIndexedAccessType(type: IndexedAccessType): void { visitType(type.objectType); visitType(type.indexType); visitType(type.constraint); } - function visitMappedType(type: ts.MappedType): void { + function visitMappedType(type: MappedType): void { visitType(type.typeParameter); visitType(type.constraintType); visitType(type.templateType); visitType(type.modifiersType); } - function visitSignature(signature: ts.Signature): void { + function visitSignature(signature: Signature): void { const typePredicate = getTypePredicateOfSignature(signature); if (typePredicate) { visitType(typePredicate.type); } - ts.forEach(signature.typeParameters, visitType); + forEach(signature.typeParameters, visitType); for (const parameter of signature.parameters) { visitSymbol(parameter); @@ -134,14 +138,14 @@ export function createGetSymbolWalker( visitType(getReturnTypeOfSignature(signature)); } - function visitInterfaceType(interfaceT: ts.InterfaceType): void { + function visitInterfaceType(interfaceT: InterfaceType): void { visitObjectType(interfaceT); - ts.forEach(interfaceT.typeParameters, visitType); - ts.forEach(getBaseTypes(interfaceT), visitType); + forEach(interfaceT.typeParameters, visitType); + forEach(getBaseTypes(interfaceT), visitType); visitType(interfaceT.thisType); } - function visitObjectType(type: ts.ObjectType): void { + function visitObjectType(type: ObjectType): void { const resolved = resolveStructuredTypeMembers(type); for (const info of resolved.indexInfos) { visitType(info.keyType); @@ -158,11 +162,11 @@ export function createGetSymbolWalker( } } - function visitSymbol(symbol: ts.Symbol | undefined): boolean { + function visitSymbol(symbol: Symbol | undefined): boolean { if (!symbol) { return false; } - const symbolId = ts.getSymbolId(symbol); + const symbolId = getSymbolId(symbol); if (visitedSymbols[symbolId]) { return false; } @@ -175,13 +179,13 @@ export function createGetSymbolWalker( if (symbol.exports) { symbol.exports.forEach(visitSymbol); } - ts.forEach(symbol.declarations, d => { + forEach(symbol.declarations, d => { // Type queries are too far resolved when we just visit the symbol's type // (their type resolved directly to the member deeply referenced) // So to get the intervening symbols, we need to check if there's a type // query node on any of the symbol's declarations and get symbols there - if ((d as any).type && (d as any).type.kind === ts.SyntaxKind.TypeQuery) { - const query = (d as any).type as ts.TypeQueryNode; + if ((d as any).type && (d as any).type.kind === SyntaxKind.TypeQuery) { + const query = (d as any).type as TypeQueryNode; const entity = getResolvedSymbol(getFirstIdentifier(query.exprName)); visitSymbol(entity); } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index f96f3df585efb..45404e759648f 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1,4 +1,12 @@ -import * as ts from "./_namespaces/ts"; +import { + AssertionLevel, closeFileWatcher, closeFileWatcherOf, combinePaths, Comparison, contains, containsPath, + createGetCanonicalFileName, createMultiMap, Debug, directorySeparator, emptyArray, emptyFileSystemEntries, endsWith, + enumerateInsertsAndDeletes, ESMap, FileSystemEntries, getDirectoryPath, getFallbackOptions, + getNormalizedAbsolutePath, getRelativePathToDirectoryOrUrl, getRootLength, getStringComparer, isArray, isString, + Map, mapDefined, matchesExclude, matchFiles, memoize, noop, normalizePath, normalizeSlashes, orderedRemoveItem, + Path, perfLogger, PollingWatchKind, RequireResult, resolveJSModule, some, startsWith, stringContains, timestamp, + unorderedRemoveItem, WatchDirectoryKind, WatchFileKind, WatchOptions, writeFileEnsuringDirectories, +} from "./_namespaces/ts"; declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any; declare function clearTimeout(handle: any): void; @@ -50,9 +58,9 @@ export enum PollingInterval { } /* @internal */ -export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: ts.WatchOptions | undefined) => FileWatcher; +export type HostWatchFile = (fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined) => FileWatcher; /* @internal */ -export type HostWatchDirectory = (fileName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: ts.WatchOptions | undefined) => FileWatcher; +export type HostWatchDirectory = (fileName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined) => FileWatcher; /* @internal */ export const missingFileModifiedTime = new Date(0); // Any subsequent modification will occur after this time @@ -222,7 +230,7 @@ function createDynamicPriorityPollingWatchFile(host: { close: () => { file.isClosed = true; // Remove from watchedFiles - ts.unorderedRemoveItem(watchedFiles, file); + unorderedRemoveItem(watchedFiles, file); // Do not update polling interval queue since that will happen as part of polling } }; @@ -243,7 +251,7 @@ function createDynamicPriorityPollingWatchFile(host: { scheduleNextPoll(queue.pollingInterval); } else { - ts.Debug.assert(queue.pollIndex === 0); + Debug.assert(queue.pollIndex === 0); queue.pollScheduled = false; } } @@ -330,17 +338,17 @@ function createDynamicPriorityPollingWatchFile(host: { function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSensitiveFileNames: boolean): HostWatchFile { // One file can have multiple watchers - const fileWatcherCallbacks = ts.createMultiMap(); - const dirWatchers = new ts.Map(); - const toCanonicalName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const fileWatcherCallbacks = createMultiMap(); + const dirWatchers = new Map(); + const toCanonicalName = createGetCanonicalFileName(useCaseSensitiveFileNames); return nonPollingWatchFile; - function nonPollingWatchFile(fileName: string, callback: FileWatcherCallback, _pollingInterval: PollingInterval, fallbackOptions: ts.WatchOptions | undefined): FileWatcher { + function nonPollingWatchFile(fileName: string, callback: FileWatcherCallback, _pollingInterval: PollingInterval, fallbackOptions: WatchOptions | undefined): FileWatcher { const filePath = toCanonicalName(fileName); fileWatcherCallbacks.add(filePath, callback); - const dirPath = ts.getDirectoryPath(filePath) || "."; + const dirPath = getDirectoryPath(filePath) || "."; const watcher = dirWatchers.get(dirPath) || - createDirectoryWatcher(ts.getDirectoryPath(fileName) || ".", dirPath, fallbackOptions); + createDirectoryWatcher(getDirectoryPath(fileName) || ".", dirPath, fallbackOptions); watcher.referenceCount++; return { close: () => { @@ -356,14 +364,14 @@ function createUseFsEventsOnParentDirectoryWatchFile(fsWatch: FsWatch, useCaseSe }; } - function createDirectoryWatcher(dirName: string, dirPath: string, fallbackOptions: ts.WatchOptions | undefined) { + function createDirectoryWatcher(dirName: string, dirPath: string, fallbackOptions: WatchOptions | undefined) { const watcher = fsWatch( dirName, FileSystemEntryKind.Directory, (_eventName: string, relativeFileName, modifiedTime) => { // When files are deleted from disk, the triggered "rename" event would have a relativefileName of "undefined" - if (!ts.isString(relativeFileName)) return; - const fileName = ts.getNormalizedAbsolutePath(relativeFileName, dirName); + if (!isString(relativeFileName)) return; + const fileName = getNormalizedAbsolutePath(relativeFileName, dirName); // Some applications save a working file via rename operations const callbacks = fileName && fileWatcherCallbacks.get(toCanonicalName(fileName)); if (callbacks) { @@ -402,7 +410,7 @@ function createFixedChunkSizePollingWatchFile(host: { return { close: () => { file.isClosed = true; - ts.unorderedRemoveItem(watchedFiles, file); + unorderedRemoveItem(watchedFiles, file); } }; } @@ -424,13 +432,13 @@ interface SingleFileWatcher{ callbacks: T[]; } function createSingleWatcherPerName( - cache: ts.Map>, + cache: Map>, useCaseSensitiveFileNames: boolean, name: string, callback: T, createWatcher: (callback: T) => FileWatcher, ): FileWatcher { - const toCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const toCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); const path = toCanonicalFileName(name); const existing = cache.get(path); if (existing) { @@ -452,9 +460,9 @@ function createSingleWatcherPerName void = ts.noop; // eslint-disable-line prefer-const +let curSysLog: (s: string) => void = noop; // eslint-disable-line prefer-const /*@internal*/ export function sysLog(s: string) { @@ -535,13 +543,13 @@ function createDirectoryWatcherSupportingRecursive({ refCount: number; } - const cache = new ts.Map(); - const callbackCache = ts.createMultiMap(); - const cacheToUpdateChildWatches = new ts.Map(); + const cache = new Map(); + const callbackCache = createMultiMap(); + const cacheToUpdateChildWatches = new Map(); let timerToUpdateChildWatches: any; - const filePathComparer = ts.getStringComparer(!useCaseSensitiveFileNames); - const toCanonicalFilePath = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const filePathComparer = getStringComparer(!useCaseSensitiveFileNames); + const toCanonicalFilePath = createGetCanonicalFileName(useCaseSensitiveFileNames); return (dirName, callback, recursive, options) => recursive ? createDirectoryWatcher(dirName, options, callback) : @@ -550,8 +558,8 @@ function createDirectoryWatcherSupportingRecursive({ /** * Create the directory watcher for the dirPath. */ - function createDirectoryWatcher(dirName: string, options: ts.WatchOptions | undefined, callback?: DirectoryWatcherCallback): ChildDirectoryWatcher { - const dirPath = toCanonicalFilePath(dirName) as ts.Path; + function createDirectoryWatcher(dirName: string, options: WatchOptions | undefined, callback?: DirectoryWatcherCallback): ChildDirectoryWatcher { + const dirPath = toCanonicalFilePath(dirName) as Path; let directoryWatcher = cache.get(dirPath); if (directoryWatcher) { directoryWatcher.refCount++; @@ -573,7 +581,7 @@ function createDirectoryWatcherSupportingRecursive({ } }, /*recursive*/ false, options), refCount: 1, - childWatches: ts.emptyArray + childWatches: emptyArray }; cache.set(dirPath, directoryWatcher); updateChildWatches(dirName, dirPath, options); @@ -587,26 +595,26 @@ function createDirectoryWatcherSupportingRecursive({ return { dirName, close: () => { - const directoryWatcher = ts.Debug.checkDefined(cache.get(dirPath)); + const directoryWatcher = Debug.checkDefined(cache.get(dirPath)); if (callbackToAdd) callbackCache.remove(dirPath, callbackToAdd); directoryWatcher.refCount--; if (directoryWatcher.refCount) return; cache.delete(dirPath); - ts.closeFileWatcherOf(directoryWatcher); - directoryWatcher.childWatches.forEach(ts.closeFileWatcher); + closeFileWatcherOf(directoryWatcher); + directoryWatcher.childWatches.forEach(closeFileWatcher); } }; } - type InvokeMap = ts.ESMap; - function invokeCallbacks(dirPath: ts.Path, fileName: string): void; - function invokeCallbacks(dirPath: ts.Path, invokeMap: InvokeMap, fileNames: string[] | undefined): void; - function invokeCallbacks(dirPath: ts.Path, fileNameOrInvokeMap: string | InvokeMap, fileNames?: string[]) { + type InvokeMap = ESMap; + function invokeCallbacks(dirPath: Path, fileName: string): void; + function invokeCallbacks(dirPath: Path, invokeMap: InvokeMap, fileNames: string[] | undefined): void; + function invokeCallbacks(dirPath: Path, fileNameOrInvokeMap: string | InvokeMap, fileNames?: string[]) { let fileName: string | undefined; let invokeMap: InvokeMap | undefined; - if (ts.isString(fileNameOrInvokeMap)) { + if (isString(fileNameOrInvokeMap)) { fileName = fileNameOrInvokeMap; } else { @@ -615,7 +623,7 @@ function createDirectoryWatcherSupportingRecursive({ // Call the actual callback callbackCache.forEach((callbacks, rootDirName) => { if (invokeMap && invokeMap.get(rootDirName) === true) return; - if (rootDirName === dirPath || (ts.startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === ts.directorySeparator)) { + if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) { if (invokeMap) { if (fileNames) { const existing = invokeMap.get(rootDirName); @@ -637,7 +645,7 @@ function createDirectoryWatcherSupportingRecursive({ }); } - function nonSyncUpdateChildWatches(dirName: string, dirPath: ts.Path, fileName: string, options: ts.WatchOptions | undefined) { + function nonSyncUpdateChildWatches(dirName: string, dirPath: Path, fileName: string, options: WatchOptions | undefined) { // Iterate through existing children and update the watches if needed const parentWatcher = cache.get(dirPath); if (parentWatcher && fileSystemEntryExists(dirName, FileSystemEntryKind.Directory)) { @@ -651,7 +659,7 @@ function createDirectoryWatcherSupportingRecursive({ removeChildWatches(parentWatcher); } - function scheduleUpdateChildWatches(dirName: string, dirPath: ts.Path, fileName: string, options: ts.WatchOptions | undefined) { + function scheduleUpdateChildWatches(dirName: string, dirPath: Path, fileName: string, options: WatchOptions | undefined) { const existing = cacheToUpdateChildWatches.get(dirPath); if (existing) { existing.fileNames.push(fileName); @@ -669,12 +677,12 @@ function createDirectoryWatcherSupportingRecursive({ function onTimerToUpdateChildWatches() { timerToUpdateChildWatches = undefined; sysLog(`sysLog:: onTimerToUpdateChildWatches:: ${cacheToUpdateChildWatches.size}`); - const start = ts.timestamp(); - const invokeMap = new ts.Map(); + const start = timestamp(); + const invokeMap = new Map(); while (!timerToUpdateChildWatches && cacheToUpdateChildWatches.size) { const result = cacheToUpdateChildWatches.entries().next(); - ts.Debug.assert(!result.done); + Debug.assert(!result.done); const { value: [dirPath, { dirName, options, fileNames }] } = result; cacheToUpdateChildWatches.delete(dirPath); // Because the child refresh is fresh, we would need to invalidate whole root directory being watched @@ -683,12 +691,12 @@ function createDirectoryWatcherSupportingRecursive({ invokeCallbacks(dirPath, invokeMap, hasChanges ? undefined : fileNames); } - sysLog(`sysLog:: invokingWatchers:: Elapsed:: ${ts.timestamp() - start}ms:: ${cacheToUpdateChildWatches.size}`); + sysLog(`sysLog:: invokingWatchers:: Elapsed:: ${timestamp() - start}ms:: ${cacheToUpdateChildWatches.size}`); callbackCache.forEach((callbacks, rootDirName) => { const existing = invokeMap.get(rootDirName); if (existing) { callbacks.forEach(({ callback, dirName }) => { - if (ts.isArray(existing)) { + if (isArray(existing)) { existing.forEach(callback); } else { @@ -698,39 +706,39 @@ function createDirectoryWatcherSupportingRecursive({ } }); - const elapsed = ts.timestamp() - start; + const elapsed = timestamp() - start; sysLog(`sysLog:: Elapsed:: ${elapsed}ms:: onTimerToUpdateChildWatches:: ${cacheToUpdateChildWatches.size} ${timerToUpdateChildWatches}`); } function removeChildWatches(parentWatcher: HostDirectoryWatcher | undefined) { if (!parentWatcher) return; const existingChildWatches = parentWatcher.childWatches; - parentWatcher.childWatches = ts.emptyArray; + parentWatcher.childWatches = emptyArray; for (const childWatcher of existingChildWatches) { childWatcher.close(); removeChildWatches(cache.get(toCanonicalFilePath(childWatcher.dirName))); } } - function updateChildWatches(parentDir: string, parentDirPath: ts.Path, options: ts.WatchOptions | undefined) { + function updateChildWatches(parentDir: string, parentDirPath: Path, options: WatchOptions | undefined) { // Iterate through existing children and update the watches if needed const parentWatcher = cache.get(parentDirPath); if (!parentWatcher) return false; let newChildWatches: ChildDirectoryWatcher[] | undefined; - const hasChanges = ts.enumerateInsertsAndDeletes( - fileSystemEntryExists(parentDir, FileSystemEntryKind.Directory) ? ts.mapDefined(getAccessibleSortedChildDirectories(parentDir), child => { - const childFullName = ts.getNormalizedAbsolutePath(child, parentDir); + const hasChanges = enumerateInsertsAndDeletes( + fileSystemEntryExists(parentDir, FileSystemEntryKind.Directory) ? mapDefined(getAccessibleSortedChildDirectories(parentDir), child => { + const childFullName = getNormalizedAbsolutePath(child, parentDir); // Filter our the symbolic link directories since those arent included in recursive watch // which is same behaviour when recursive: true is passed to fs.watch - return !isIgnoredPath(childFullName, options) && filePathComparer(childFullName, ts.normalizePath(realpath(childFullName))) === ts.Comparison.EqualTo ? childFullName : undefined; - }) : ts.emptyArray, + return !isIgnoredPath(childFullName, options) && filePathComparer(childFullName, normalizePath(realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined; + }) : emptyArray, parentWatcher.childWatches, (child, childWatcher) => filePathComparer(child, childWatcher.dirName), createAndAddChildDirectoryWatcher, - ts.closeFileWatcher, + closeFileWatcher, addChildDirectoryWatcher ); - parentWatcher.childWatches = newChildWatches || ts.emptyArray; + parentWatcher.childWatches = newChildWatches || emptyArray; return hasChanges; /** @@ -749,22 +757,22 @@ function createDirectoryWatcherSupportingRecursive({ } } - function isIgnoredPath(path: string, options: ts.WatchOptions | undefined) { - return ts.some(ignoredPaths, searchPath => isInPath(path, searchPath)) || + function isIgnoredPath(path: string, options: WatchOptions | undefined) { + return some(ignoredPaths, searchPath => isInPath(path, searchPath)) || isIgnoredByWatchOptions(path, options, useCaseSensitiveFileNames, getCurrentDirectory); } function isInPath(path: string, searchPath: string) { - if (ts.stringContains(path, searchPath)) return true; + if (stringContains(path, searchPath)) return true; if (useCaseSensitiveFileNames) return false; - return ts.stringContains(toCanonicalFilePath(path), searchPath); + return stringContains(toCanonicalFilePath(path), searchPath); } } /*@internal*/ export type FsWatchCallback = (eventName: "rename" | "change", relativeFileName: string | undefined, modifiedTime?: Date) => void; /*@internal*/ -export type FsWatch = (fileOrDirectory: string, entryKind: FileSystemEntryKind, callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, fallbackOptions: ts.WatchOptions | undefined) => FileWatcher; +export type FsWatch = (fileOrDirectory: string, entryKind: FileSystemEntryKind, callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, fallbackOptions: WatchOptions | undefined) => FileWatcher; /*@internal*/ export interface FsWatchWorkerWatcher extends FileWatcher { on(eventName: string, listener: () => void): void; @@ -801,20 +809,20 @@ function createFsWatchCallbackForFileWatcherCallback( function isIgnoredByWatchOptions( pathToCheck: string, - options: ts.WatchOptions | undefined, + options: WatchOptions | undefined, useCaseSensitiveFileNames: boolean, getCurrentDirectory: System["getCurrentDirectory"], ) { return (options?.excludeDirectories || options?.excludeFiles) && ( - ts.matchesExclude(pathToCheck, options?.excludeFiles, useCaseSensitiveFileNames, getCurrentDirectory()) || - ts.matchesExclude(pathToCheck, options?.excludeDirectories, useCaseSensitiveFileNames, getCurrentDirectory()) + matchesExclude(pathToCheck, options?.excludeFiles, useCaseSensitiveFileNames, getCurrentDirectory()) || + matchesExclude(pathToCheck, options?.excludeDirectories, useCaseSensitiveFileNames, getCurrentDirectory()) ); } function createFsWatchCallbackForDirectoryWatcherCallback( directoryName: string, callback: DirectoryWatcherCallback, - options: ts.WatchOptions | undefined, + options: WatchOptions | undefined, useCaseSensitiveFileNames: boolean, getCurrentDirectory: System["getCurrentDirectory"], ): FsWatchCallback { @@ -824,7 +832,7 @@ function createFsWatchCallbackForDirectoryWatcherCallback( // event name is "change") if (eventName === "rename") { // When deleting a file, the passed baseFileName is null - const fileName = !relativeFileName ? directoryName : ts.normalizePath(ts.combinePaths(directoryName, relativeFileName)); + const fileName = !relativeFileName ? directoryName : normalizePath(combinePaths(directoryName, relativeFileName)); if (!relativeFileName || !isIgnoredByWatchOptions(fileName, options, useCaseSensitiveFileNames, getCurrentDirectory)) { callback(fileName); } @@ -878,9 +886,9 @@ export function createSystemWatchFunctions({ inodeWatching, sysLog, }: CreateSystemWatchFunctions): { watchFile: HostWatchFile; watchDirectory: HostWatchDirectory; } { - const pollingWatches = new ts.Map>(); - const fsWatches = new ts.Map>(); - const fsWatchesRecursive = new ts.Map>(); + const pollingWatches = new Map>(); + const fsWatches = new Map>(); + const fsWatchesRecursive = new Map>(); let dynamicPollingWatchFile: HostWatchFile | undefined; let fixedChunkSizePollingWatchFile: HostWatchFile | undefined; let nonPollingWatchFile: HostWatchFile | undefined; @@ -891,34 +899,34 @@ export function createSystemWatchFunctions({ watchDirectory }; - function watchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: ts.WatchOptions | undefined): FileWatcher { + function watchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined): FileWatcher { options = updateOptionsForWatchFile(options, useNonPollingWatchers); - const watchFileKind = ts.Debug.checkDefined(options.watchFile); + const watchFileKind = Debug.checkDefined(options.watchFile); switch (watchFileKind) { - case ts.WatchFileKind.FixedPollingInterval: + case WatchFileKind.FixedPollingInterval: return pollingWatchFile(fileName, callback, PollingInterval.Low, /*options*/ undefined); - case ts.WatchFileKind.PriorityPollingInterval: + case WatchFileKind.PriorityPollingInterval: return pollingWatchFile(fileName, callback, pollingInterval, /*options*/ undefined); - case ts.WatchFileKind.DynamicPriorityPolling: + case WatchFileKind.DynamicPriorityPolling: return ensureDynamicPollingWatchFile()(fileName, callback, pollingInterval, /*options*/ undefined); - case ts.WatchFileKind.FixedChunkSizePolling: + case WatchFileKind.FixedChunkSizePolling: return ensureFixedChunkSizePollingWatchFile()(fileName, callback, /* pollingInterval */ undefined!, /*options*/ undefined); - case ts.WatchFileKind.UseFsEvents: + case WatchFileKind.UseFsEvents: return fsWatch( fileName, FileSystemEntryKind.File, createFsWatchCallbackForFileWatcherCallback(fileName, callback, getModifiedTime), /*recursive*/ false, pollingInterval, - ts.getFallbackOptions(options) + getFallbackOptions(options) ); - case ts.WatchFileKind.UseFsEventsOnParentDirectory: + case WatchFileKind.UseFsEventsOnParentDirectory: if (!nonPollingWatchFile) { nonPollingWatchFile = createUseFsEventsOnParentDirectoryWatchFile(fsWatch, useCaseSensitiveFileNames); } - return nonPollingWatchFile(fileName, callback, pollingInterval, ts.getFallbackOptions(options)); + return nonPollingWatchFile(fileName, callback, pollingInterval, getFallbackOptions(options)); default: - ts.Debug.assertNever(watchFileKind); + Debug.assertNever(watchFileKind); } } @@ -930,38 +938,38 @@ export function createSystemWatchFunctions({ return fixedChunkSizePollingWatchFile ||= createFixedChunkSizePollingWatchFile({ getModifiedTime, setTimeout }); } - function updateOptionsForWatchFile(options: ts.WatchOptions | undefined, useNonPollingWatchers?: boolean): ts.WatchOptions { + function updateOptionsForWatchFile(options: WatchOptions | undefined, useNonPollingWatchers?: boolean): WatchOptions { if (options && options.watchFile !== undefined) return options; switch (tscWatchFile) { case "PriorityPollingInterval": // Use polling interval based on priority when create watch using host.watchFile - return { watchFile: ts.WatchFileKind.PriorityPollingInterval }; + return { watchFile: WatchFileKind.PriorityPollingInterval }; case "DynamicPriorityPolling": // Use polling interval but change the interval depending on file changes and their default polling interval - return { watchFile: ts.WatchFileKind.DynamicPriorityPolling }; + return { watchFile: WatchFileKind.DynamicPriorityPolling }; case "UseFsEvents": // Use notifications from FS to watch with falling back to fs.watchFile - return generateWatchFileOptions(ts.WatchFileKind.UseFsEvents, ts.PollingWatchKind.PriorityInterval, options); + return generateWatchFileOptions(WatchFileKind.UseFsEvents, PollingWatchKind.PriorityInterval, options); case "UseFsEventsWithFallbackDynamicPolling": // Use notifications from FS to watch with falling back to dynamic watch file - return generateWatchFileOptions(ts.WatchFileKind.UseFsEvents, ts.PollingWatchKind.DynamicPriority, options); + return generateWatchFileOptions(WatchFileKind.UseFsEvents, PollingWatchKind.DynamicPriority, options); case "UseFsEventsOnParentDirectory": useNonPollingWatchers = true; // fall through default: return useNonPollingWatchers ? // Use notifications from FS to watch with falling back to fs.watchFile - generateWatchFileOptions(ts.WatchFileKind.UseFsEventsOnParentDirectory, ts.PollingWatchKind.PriorityInterval, options) : + generateWatchFileOptions(WatchFileKind.UseFsEventsOnParentDirectory, PollingWatchKind.PriorityInterval, options) : // Default to using fs events - { watchFile: ts.WatchFileKind.UseFsEvents }; + { watchFile: WatchFileKind.UseFsEvents }; } } function generateWatchFileOptions( - watchFile: ts.WatchFileKind, - fallbackPolling: ts.PollingWatchKind, - options: ts.WatchOptions | undefined - ): ts.WatchOptions { + watchFile: WatchFileKind, + fallbackPolling: PollingWatchKind, + options: WatchOptions | undefined + ): WatchOptions { const defaultFallbackPolling = options?.fallbackPolling; return { watchFile, @@ -971,7 +979,7 @@ export function createSystemWatchFunctions({ }; } - function watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: ts.WatchOptions | undefined): FileWatcher { + function watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined): FileWatcher { if (fsSupportsRecursiveFsWatch) { return fsWatch( directoryName, @@ -979,7 +987,7 @@ export function createSystemWatchFunctions({ createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback, options, useCaseSensitiveFileNames, getCurrentDirectory), recursive, PollingInterval.Medium, - ts.getFallbackOptions(options) + getFallbackOptions(options) ); } @@ -998,59 +1006,59 @@ export function createSystemWatchFunctions({ return hostRecursiveDirectoryWatcher(directoryName, callback, recursive, options); } - function nonRecursiveWatchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: ts.WatchOptions | undefined): FileWatcher { - ts.Debug.assert(!recursive); + function nonRecursiveWatchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean, options: WatchOptions | undefined): FileWatcher { + Debug.assert(!recursive); const watchDirectoryOptions = updateOptionsForWatchDirectory(options); - const watchDirectoryKind = ts.Debug.checkDefined(watchDirectoryOptions.watchDirectory); + const watchDirectoryKind = Debug.checkDefined(watchDirectoryOptions.watchDirectory); switch (watchDirectoryKind) { - case ts.WatchDirectoryKind.FixedPollingInterval: + case WatchDirectoryKind.FixedPollingInterval: return pollingWatchFile( directoryName, () => callback(directoryName), PollingInterval.Medium, /*options*/ undefined ); - case ts.WatchDirectoryKind.DynamicPriorityPolling: + case WatchDirectoryKind.DynamicPriorityPolling: return ensureDynamicPollingWatchFile()( directoryName, () => callback(directoryName), PollingInterval.Medium, /*options*/ undefined ); - case ts.WatchDirectoryKind.FixedChunkSizePolling: + case WatchDirectoryKind.FixedChunkSizePolling: return ensureFixedChunkSizePollingWatchFile()( directoryName, () => callback(directoryName), /* pollingInterval */ undefined!, /*options*/ undefined ); - case ts.WatchDirectoryKind.UseFsEvents: + case WatchDirectoryKind.UseFsEvents: return fsWatch( directoryName, FileSystemEntryKind.Directory, createFsWatchCallbackForDirectoryWatcherCallback(directoryName, callback, options, useCaseSensitiveFileNames, getCurrentDirectory), recursive, PollingInterval.Medium, - ts.getFallbackOptions(watchDirectoryOptions) + getFallbackOptions(watchDirectoryOptions) ); default: - ts.Debug.assertNever(watchDirectoryKind); + Debug.assertNever(watchDirectoryKind); } } - function updateOptionsForWatchDirectory(options: ts.WatchOptions | undefined): ts.WatchOptions { + function updateOptionsForWatchDirectory(options: WatchOptions | undefined): WatchOptions { if (options && options.watchDirectory !== undefined) return options; switch (tscWatchDirectory) { case "RecursiveDirectoryUsingFsWatchFile": // Use polling interval based on priority when create watch using host.watchFile - return { watchDirectory: ts.WatchDirectoryKind.FixedPollingInterval }; + return { watchDirectory: WatchDirectoryKind.FixedPollingInterval }; case "RecursiveDirectoryUsingDynamicPriorityPolling": // Use polling interval but change the interval depending on file changes and their default polling interval - return { watchDirectory: ts.WatchDirectoryKind.DynamicPriorityPolling }; + return { watchDirectory: WatchDirectoryKind.DynamicPriorityPolling }; default: const defaultFallbackPolling = options?.fallbackPolling; return { - watchDirectory: ts.WatchDirectoryKind.UseFsEvents, + watchDirectory: WatchDirectoryKind.UseFsEvents, fallbackPolling: defaultFallbackPolling !== undefined ? defaultFallbackPolling : undefined @@ -1058,7 +1066,7 @@ export function createSystemWatchFunctions({ } } - function pollingWatchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: ts.WatchOptions | undefined) { + function pollingWatchFile(fileName: string, callback: FileWatcherCallback, pollingInterval: PollingInterval, options: WatchOptions | undefined) { return createSingleWatcherPerName( pollingWatches, useCaseSensitiveFileNames, @@ -1073,7 +1081,7 @@ export function createSystemWatchFunctions({ callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, - fallbackOptions: ts.WatchOptions | undefined + fallbackOptions: WatchOptions | undefined ): FileWatcher { return createSingleWatcherPerName( recursive ? fsWatchesRecursive : fsWatches, @@ -1090,13 +1098,13 @@ export function createSystemWatchFunctions({ callback: FsWatchCallback, recursive: boolean, fallbackPollingInterval: PollingInterval, - fallbackOptions: ts.WatchOptions | undefined + fallbackOptions: WatchOptions | undefined ): FileWatcher { let lastDirectoryPartWithDirectorySeparator: string | undefined; let lastDirectoryPart: string | undefined; if (inodeWatching) { - lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substring(fileOrDirectory.lastIndexOf(ts.directorySeparator)); - lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(ts.directorySeparator.length); + lastDirectoryPartWithDirectorySeparator = fileOrDirectory.substring(fileOrDirectory.lastIndexOf(directorySeparator)); + lastDirectoryPart = lastDirectoryPartWithDirectorySeparator.slice(directorySeparator.length); } /** Watcher for the file system entry depending on whether it is missing or present */ let watcher: FileWatcher | undefined = !fileSystemEntryExists(fileOrDirectory, entryKind) ? @@ -1162,7 +1170,7 @@ export function createSystemWatchFunctions({ // The worst is we have fired event that was not needed but we wont miss any changes // especially in cases where file goes missing and watches wrong inode let originalRelativeName: string | undefined; - if (relativeName && ts.endsWith(relativeName, "~")) { + if (relativeName && endsWith(relativeName, "~")) { originalRelativeName = relativeName; relativeName = relativeName.slice(0, relativeName.length - 1); } @@ -1171,7 +1179,7 @@ export function createSystemWatchFunctions({ if (event === "rename" && (!relativeName || relativeName === lastDirectoryPart || - ts.endsWith(relativeName, lastDirectoryPartWithDirectorySeparator!))) { + endsWith(relativeName, lastDirectoryPartWithDirectorySeparator!))) { const modifiedTime = getModifiedTime(fileOrDirectory) || missingFileModifiedTime; if (originalRelativeName) callback(event, originalRelativeName, modifiedTime); callback(event, relativeName, modifiedTime); @@ -1236,7 +1244,7 @@ export function patchWriteFileEnsuringDirectory(sys: System) { // patch writefile to create folder before writing the file const originalWriteFile = sys.writeFile; sys.writeFile = (path, data, writeBom) => - ts.writeFileEnsuringDirectories( + writeFileEnsuringDirectories( path, data, !!writeBom, @@ -1343,8 +1351,8 @@ export interface System { * @pollingInterval - this parameter is used in polling-based watchers and ignored in watchers that * use native OS file watching */ - watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: ts.WatchOptions): FileWatcher; - watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: ts.WatchOptions): FileWatcher; + watchFile?(path: string, callback: FileWatcherCallback, pollingInterval?: number, options?: WatchOptions): FileWatcher; + watchDirectory?(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher; resolvePath(path: string): string; fileExists(path: string): boolean; directoryExists(path: string): boolean; @@ -1378,7 +1386,7 @@ export interface System { base64decode?(input: string): string; base64encode?(input: string): string; /*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer; - /*@internal*/ require?(baseDir: string, moduleName: string): ts.RequireResult; + /*@internal*/ require?(baseDir: string, moduleName: string): RequireResult; // For testing /*@internal*/ now?(): Date; @@ -1453,7 +1461,7 @@ export let sys: System = (() => { const fsRealpath = !!_fs.realpathSync.native ? process.platform === "win32" ? fsRealPathHandlingLongPath : _fs.realpathSync.native : _fs.realpathSync; const fsSupportsRecursiveFsWatch = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin"); - const getCurrentDirectory = ts.memoize(() => process.cwd()); + const getCurrentDirectory = memoize(() => process.cwd()); const { watchFile, watchDirectory } = createSystemWatchFunctions({ pollingWatchFileWorker: fsWatchFileWorker, getModifiedTime, @@ -1544,9 +1552,9 @@ export let sys: System = (() => { }, enableCPUProfiler, disableCPUProfiler, - cpuProfilingEnabled: () => !!activeSession || ts.contains(process.execArgv, "--cpu-prof") || ts.contains(process.execArgv, "--prof"), + cpuProfilingEnabled: () => !!activeSession || contains(process.execArgv, "--cpu-prof") || contains(process.execArgv, "--prof"), realpath, - debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || ts.some(process.execArgv as string[], arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)), + debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv as string[], arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)), tryEnableSourceMapsForHost() { try { require("source-map-support").install(); @@ -1570,7 +1578,7 @@ export let sys: System = (() => { base64encode: input => bufferFrom(input).toString("base64"), require: (baseDir, moduleName) => { try { - const modulePath = ts.resolveJSModule(moduleName, baseDir, nodeSystem); + const modulePath = resolveJSModule(moduleName, baseDir, nodeSystem); return { module: require(modulePath), modulePath, error: undefined }; } catch (error) { @@ -1623,15 +1631,15 @@ export let sys: System = (() => { */ function cleanupPaths(profile: import("inspector").Profiler.Profile) { let externalFileCounter = 0; - const remappedPaths = new ts.Map(); - const normalizedDir = ts.normalizeSlashes(__dirname); + const remappedPaths = new Map(); + const normalizedDir = normalizeSlashes(__dirname); // Windows rooted dir names need an extra `/` prepended to be valid file:/// urls - const fileUrlRoot = `file://${ts.getRootLength(normalizedDir) === 1 ? "" : "/"}${normalizedDir}`; + const fileUrlRoot = `file://${getRootLength(normalizedDir) === 1 ? "" : "/"}${normalizedDir}`; for (const node of profile.nodes) { if (node.callFrame.url) { - const url = ts.normalizeSlashes(node.callFrame.url); - if (ts.containsPath(fileUrlRoot, url, useCaseSensitiveFileNames)) { - node.callFrame.url = ts.getRelativePathToDirectoryOrUrl(fileUrlRoot, url, fileUrlRoot, ts.createGetCanonicalFileName(useCaseSensitiveFileNames), /*isAbsolutePathAnUrl*/ true); + const url = normalizeSlashes(node.callFrame.url); + if (containsPath(fileUrlRoot, url, useCaseSensitiveFileNames)) { + node.callFrame.url = getRelativePathToDirectoryOrUrl(fileUrlRoot, url, fileUrlRoot, createGetCanonicalFileName(useCaseSensitiveFileNames), /*isAbsolutePathAnUrl*/ true); } else if (!nativePattern.test(url)) { node.callFrame.url = (remappedPaths.has(url) ? remappedPaths : remappedPaths.set(url, `external${externalFileCounter}.js`)).get(url)!; @@ -1781,14 +1789,14 @@ export let sys: System = (() => { } function readFile(fileName: string, _encoding?: string): string | undefined { - ts.perfLogger.logStartReadFile(fileName); + perfLogger.logStartReadFile(fileName); const file = readFileWorker(fileName, _encoding); - ts.perfLogger.logStopReadFile(); + perfLogger.logStopReadFile(); return file; } function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { - ts.perfLogger.logEvent("WriteFile: " + fileName); + perfLogger.logEvent("WriteFile: " + fileName); // If a BOM is required, emit one if (writeByteOrderMark) { data = byteOrderMarkIndicator + data; @@ -1807,8 +1815,8 @@ export let sys: System = (() => { } } - function getAccessibleFileSystemEntries(path: string): ts.FileSystemEntries { - ts.perfLogger.logEvent("ReadDir: " + (path || ".")); + function getAccessibleFileSystemEntries(path: string): FileSystemEntries { + perfLogger.logEvent("ReadDir: " + (path || ".")); try { const entries = _fs.readdirSync(path || ".", { withFileTypes: true }); const files: string[] = []; @@ -1825,7 +1833,7 @@ export let sys: System = (() => { let stat: any; if (typeof dirent === "string" || dirent.isSymbolicLink()) { - const name = ts.combinePaths(path, entry); + const name = combinePaths(path, entry); try { stat = statSync(name); @@ -1853,12 +1861,12 @@ export let sys: System = (() => { return { files, directories }; } catch (e) { - return ts.emptyFileSystemEntries; + return emptyFileSystemEntries; } } function readDirectory(path: string, extensions?: readonly string[], excludes?: readonly string[], includes?: readonly string[], depth?: number): string[] { - return ts.matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); + return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); } function fileSystemEntryExists(path: string, entryKind: FileSystemEntryKind): boolean { @@ -1972,10 +1980,10 @@ export function setSys(s: System) { if (sys && sys.getEnvironmentVariable) { setCustomPollingValues(sys); - ts.Debug.setAssertionLevel(/^development$/i.test(sys.getEnvironmentVariable("NODE_ENV")) - ? ts.AssertionLevel.Normal - : ts.AssertionLevel.None); + Debug.setAssertionLevel(/^development$/i.test(sys.getEnvironmentVariable("NODE_ENV")) + ? AssertionLevel.Normal + : AssertionLevel.None); } if (sys && sys.debugMode) { - ts.Debug.isDebugging = true; + Debug.isDebugging = true; } diff --git a/src/compiler/tracing.ts b/src/compiler/tracing.ts index 5e0a2302d5ebe..b7234531b100d 100644 --- a/src/compiler/tracing.ts +++ b/src/compiler/tracing.ts @@ -1,4 +1,9 @@ import * as ts from "./_namespaces/ts"; +import { + combinePaths, ConditionalType, Debug, EvolvingArrayType, getLineAndCharacterOfPosition, getSourceFileOfNode, + IndexedAccessType, IndexType, IntersectionType, LineAndCharacter, Map, Node, ObjectFlags, Path, ReverseMappedType, + SubstitutionType, timestamp, Type, TypeFlags, TypeReference, unescapeLeadingUnderscores, UnionType, +} from "./_namespaces/ts"; /* Tracing events for the compiler. */ @@ -19,7 +24,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file let mode: Mode; - const typeCatalog: ts.Type[] = []; // NB: id is index + 1 + const typeCatalog: Type[] = []; // NB: id is index + 1 let legendPath: string | undefined; const legend: TraceRecord[] = []; @@ -31,7 +36,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file /** Starts tracing for the given project. */ export function startTracing(tracingMode: Mode, traceDir: string, configFilePath?: string) { - ts.Debug.assert(!tracing, "Tracing already started"); + Debug.assert(!tracing, "Tracing already started"); if (fs === undefined) { try { @@ -46,7 +51,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file typeCatalog.length = 0; if (legendPath === undefined) { - legendPath = ts.combinePaths(traceDir, "legend.json"); + legendPath = combinePaths(traceDir, "legend.json"); } // Note that writing will fail later on if it exists and is not a directory @@ -58,8 +63,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file mode === "build" ? `.${process.pid}-${++traceCount}` : mode === "server" ? `.${process.pid}` : ``; - const tracePath = ts.combinePaths(traceDir, `trace${countPart}.json`); - const typesPath = ts.combinePaths(traceDir, `types${countPart}.json`); + const tracePath = combinePaths(traceDir, `trace${countPart}.json`); + const typesPath = combinePaths(traceDir, `types${countPart}.json`); legend.push({ configFilePath, @@ -71,7 +76,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file tracing = tracingEnabled; // only when traceFd is properly set // Start with a prefix that contains some metadata that the devtools profiler expects (also avoids a warning on import) - const meta = { cat: "__metadata", ph: "M", ts: 1000 * ts.timestamp(), pid: 1, tid: 1 }; + const meta = { cat: "__metadata", ph: "M", ts: 1000 * timestamp(), pid: 1, tid: 1 }; fs.writeSync(traceFd, "[\n" + [{ name: "process_name", args: { name: "tsc" }, ...meta }, @@ -82,8 +87,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file /** Stops tracing for the in-progress project and dumps the type catalog. */ export function stopTracing() { - ts.Debug.assert(tracing, "Tracing is not in progress"); - ts.Debug.assert(!!typeCatalog.length === (mode !== "server")); // Have a type catalog iff not in server mode + Debug.assert(tracing, "Tracing is not in progress"); + Debug.assert(!!typeCatalog.length === (mode !== "server")); // Have a type catalog iff not in server mode fs.writeSync(traceFd, `\n]\n`); fs.closeSync(traceFd); @@ -99,7 +104,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } } - export function recordType(type: ts.Type): void { + export function recordType(type: Type): void { if (mode !== "server") { typeCatalog.push(type); } @@ -131,15 +136,15 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file if (separateBeginAndEnd) { writeEvent("B", phase, name, args); } - eventStack.push({ phase, name, args, time: 1000 * ts.timestamp(), separateBeginAndEnd }); + eventStack.push({ phase, name, args, time: 1000 * timestamp(), separateBeginAndEnd }); } export function pop(results?: Args) { - ts.Debug.assert(eventStack.length > 0); - writeStackEvent(eventStack.length - 1, 1000 * ts.timestamp(), results); + Debug.assert(eventStack.length > 0); + writeStackEvent(eventStack.length - 1, 1000 * timestamp(), results); eventStack.length--; } export function popAll() { - const endTime = 1000 * ts.timestamp(); + const endTime = 1000 * timestamp(); for (let i = eventStack.length - 1; i >= 0; i--) { writeStackEvent(i, endTime); } @@ -150,7 +155,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file function writeStackEvent(index: number, endTime: number, results?: Args) { const { phase, name, args, time, separateBeginAndEnd } = eventStack[index]; if (separateBeginAndEnd) { - ts.Debug.assert(!results, "`results` are not supported for events with `separateBeginAndEnd`"); + Debug.assert(!results, "`results` are not supported for events with `separateBeginAndEnd`"); writeEvent("E", phase, name, args, /*extras*/ undefined, endTime); } // test if [time,endTime) straddles a sampling point @@ -160,7 +165,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } function writeEvent(eventType: string, phase: Phase, name: string, args: Args | undefined, extras?: string, - time: number = 1000 * ts.timestamp()) { + time: number = 1000 * timestamp()) { // In server mode, there's no easy way to dump type information, so we drop events that would require it. if (mode === "server" && phase === Phase.CheckTypes) return; @@ -174,17 +179,17 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file ts.performance.measure("Tracing", "beginTracing", "endTracing"); } - function getLocation(node: ts.Node | undefined) { - const file = ts.getSourceFileOfNode(node); + function getLocation(node: Node | undefined) { + const file = getSourceFileOfNode(node); return !file ? undefined : { path: file.path, - start: indexFromOne(ts.getLineAndCharacterOfPosition(file, node!.pos)), - end: indexFromOne(ts.getLineAndCharacterOfPosition(file, node!.end)), + start: indexFromOne(getLineAndCharacterOfPosition(file, node!.pos)), + end: indexFromOne(getLineAndCharacterOfPosition(file, node!.end)), }; - function indexFromOne(lc: ts.LineAndCharacter): ts.LineAndCharacter { + function indexFromOne(lc: LineAndCharacter): LineAndCharacter { return { line: lc.line + 1, character: lc.character + 1, @@ -192,13 +197,13 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } } - function dumpTypes(types: readonly ts.Type[]) { + function dumpTypes(types: readonly Type[]) { ts.performance.mark("beginDumpTypes"); const typesPath = legend[legend.length - 1].typesPath!; const typesFd = fs.openSync(typesPath, "w"); - const recursionIdentityMap = new ts.Map(); + const recursionIdentityMap = new Map(); // Cleverness: no line break here so that the type ID will match the line number fs.writeSync(typesFd, "["); @@ -211,7 +216,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file // It's slow to compute the display text, so skip it unless it's really valuable (or cheap) let display: string | undefined; - if ((objectFlags & ts.ObjectFlags.Anonymous) | (type.flags & ts.TypeFlags.Literal)) { + if ((objectFlags & ObjectFlags.Anonymous) | (type.flags & TypeFlags.Literal)) { try { display = type.checker?.typeToString(type); } @@ -221,8 +226,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let indexedAccessProperties: object = {}; - if (type.flags & ts.TypeFlags.IndexedAccess) { - const indexedAccessType = type as ts.IndexedAccessType; + if (type.flags & TypeFlags.IndexedAccess) { + const indexedAccessType = type as IndexedAccessType; indexedAccessProperties = { indexedAccessObjectType: indexedAccessType.objectType?.id, indexedAccessIndexType: indexedAccessType.indexType?.id, @@ -230,8 +235,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let referenceProperties: object = {}; - if (objectFlags & ts.ObjectFlags.Reference) { - const referenceType = type as ts.TypeReference; + if (objectFlags & ObjectFlags.Reference) { + const referenceType = type as TypeReference; referenceProperties = { instantiatedType: referenceType.target?.id, typeArguments: referenceType.resolvedTypeArguments?.map(t => t.id), @@ -240,8 +245,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let conditionalProperties: object = {}; - if (type.flags & ts.TypeFlags.Conditional) { - const conditionalType = type as ts.ConditionalType; + if (type.flags & TypeFlags.Conditional) { + const conditionalType = type as ConditionalType; conditionalProperties = { conditionalCheckType: conditionalType.checkType?.id, conditionalExtendsType: conditionalType.extendsType?.id, @@ -251,8 +256,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let substitutionProperties: object = {}; - if (type.flags & ts.TypeFlags.Substitution) { - const substitutionType = type as ts.SubstitutionType; + if (type.flags & TypeFlags.Substitution) { + const substitutionType = type as SubstitutionType; substitutionProperties = { substitutionBaseType: substitutionType.baseType?.id, constraintType: substitutionType.constraint?.id, @@ -260,8 +265,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let reverseMappedProperties: object = {}; - if (objectFlags & ts.ObjectFlags.ReverseMapped) { - const reverseMappedType = type as ts.ReverseMappedType; + if (objectFlags & ObjectFlags.ReverseMapped) { + const reverseMappedType = type as ReverseMappedType; reverseMappedProperties = { reverseMappedSourceType: reverseMappedType.source?.id, reverseMappedMappedType: reverseMappedType.mappedType?.id, @@ -270,8 +275,8 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file } let evolvingArrayProperties: object = {}; - if (objectFlags & ts.ObjectFlags.EvolvingArray) { - const evolvingArrayType = type as ts.EvolvingArrayType; + if (objectFlags & ObjectFlags.EvolvingArray) { + const evolvingArrayType = type as EvolvingArrayType; evolvingArrayProperties = { evolvingArrayElementType: evolvingArrayType.elementType.id, evolvingArrayFinalType: evolvingArrayType.finalArrayType?.id, @@ -293,13 +298,13 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file const descriptor = { id: type.id, intrinsicName: (type as any).intrinsicName, - symbolName: symbol?.escapedName && ts.unescapeLeadingUnderscores(symbol.escapedName), + symbolName: symbol?.escapedName && unescapeLeadingUnderscores(symbol.escapedName), recursionId: recursionToken, - isTuple: objectFlags & ts.ObjectFlags.Tuple ? true : undefined, - unionTypes: (type.flags & ts.TypeFlags.Union) ? (type as ts.UnionType).types?.map(t => t.id) : undefined, - intersectionTypes: (type.flags & ts.TypeFlags.Intersection) ? (type as ts.IntersectionType).types.map(t => t.id) : undefined, + isTuple: objectFlags & ObjectFlags.Tuple ? true : undefined, + unionTypes: (type.flags & TypeFlags.Union) ? (type as UnionType).types?.map(t => t.id) : undefined, + intersectionTypes: (type.flags & TypeFlags.Intersection) ? (type as IntersectionType).types.map(t => t.id) : undefined, aliasTypeArguments: type.aliasTypeArguments?.map(t => t.id), - keyofType: (type.flags & ts.TypeFlags.Index) ? (type as ts.IndexType).type?.id : undefined, + keyofType: (type.flags & TypeFlags.Index) ? (type as IndexType).type?.id : undefined, ...indexedAccessProperties, ...referenceProperties, ...conditionalProperties, @@ -308,7 +313,7 @@ namespace tracingEnabled { // eslint-disable-line local/one-namespace-per-file ...evolvingArrayProperties, destructuringPattern: getLocation(type.pattern), firstDeclaration: getLocation(symbol?.declarations?.[0]), - flags: ts.Debug.formatTypeFlags(type.flags).split("|"), + flags: Debug.formatTypeFlags(type.flags).split("|"), display, }; @@ -349,5 +354,5 @@ export const dumpTracingLegend = tracingEnabled.dumpLegend; /** @internal */ export interface TracingNode { - tracingPath?: ts.Path; + tracingPath?: Path; } diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 42b2fb94ebf56..78f9ba9c67147 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -1,19 +1,32 @@ import * as ts from "./_namespaces/ts"; - -function getModuleTransformer(moduleKind: ts.ModuleKind): ts.TransformerFactory { +import { + addRange, append, Bundle, chainBundle, CompilerOptions, createEmitHelperFactory, CustomTransformer, + CustomTransformerFactory, CustomTransformers, Debug, DiagnosticWithLocation, disposeEmitNodes, EmitFlags, + EmitHelper, EmitHint, EmitHost, EmitOnly, EmitResolver, EmitTransformers, emptyArray, factory, FunctionDeclaration, + getEmitFlags, getEmitModuleKind, getEmitScriptTarget, getJSXTransformEnabled, getParseTreeNode, getSourceFileOfNode, + Identifier, isBundle, isSourceFile, LexicalEnvironmentFlags, map, memoize, ModuleKind, Node, NodeFactory, NodeFlags, + noop, notImplemented, returnUndefined, ScriptTarget, setEmitFlags, some, SourceFile, Statement, SyntaxKind, tracing, + TransformationContext, TransformationResult, transformClassFields, transformDeclarations, transformECMAScriptModule, + Transformer, TransformerFactory, transformES2015, transformES2016, transformES2017, transformES2018, + transformES2019, transformES2020, transformES2021, transformES5, transformESNext, transformGenerators, transformJsx, + transformLegacyDecorators, transformModule, transformNodeModule, transformSystemModule, transformTypeScript, + VariableDeclaration, +} from "./_namespaces/ts"; + +function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory { switch (moduleKind) { - case ts.ModuleKind.ESNext: - case ts.ModuleKind.ES2022: - case ts.ModuleKind.ES2020: - case ts.ModuleKind.ES2015: - return ts.transformECMAScriptModule; - case ts.ModuleKind.System: - return ts.transformSystemModule; - case ts.ModuleKind.Node16: - case ts.ModuleKind.NodeNext: - return ts.transformNodeModule; + case ModuleKind.ESNext: + case ModuleKind.ES2022: + case ModuleKind.ES2020: + case ModuleKind.ES2015: + return transformECMAScriptModule; + case ModuleKind.System: + return transformSystemModule; + case ModuleKind.Node16: + case ModuleKind.NodeNext: + return transformNodeModule; default: - return ts.transformModule; + return transformModule; } } @@ -30,96 +43,96 @@ const enum SyntaxKindFeatureFlags { } /** @internal */ -export const noTransformers: ts.EmitTransformers = { scriptTransformers: ts.emptyArray, declarationTransformers: ts.emptyArray }; +export const noTransformers: EmitTransformers = { scriptTransformers: emptyArray, declarationTransformers: emptyArray }; /** @internal */ -export function getTransformers(compilerOptions: ts.CompilerOptions, customTransformers?: ts.CustomTransformers, emitOnly?: boolean | ts.EmitOnly): ts.EmitTransformers { +export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly): EmitTransformers { return { scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnly), declarationTransformers: getDeclarationTransformers(customTransformers), }; } -function getScriptTransformers(compilerOptions: ts.CompilerOptions, customTransformers?: ts.CustomTransformers, emitOnly?: boolean | ts.EmitOnly) { - if (emitOnly) return ts.emptyArray; +function getScriptTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnly?: boolean | EmitOnly) { + if (emitOnly) return emptyArray; - const languageVersion = ts.getEmitScriptTarget(compilerOptions); - const moduleKind = ts.getEmitModuleKind(compilerOptions); - const transformers: ts.TransformerFactory[] = []; + const languageVersion = getEmitScriptTarget(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); + const transformers: TransformerFactory[] = []; - ts.addRange(transformers, customTransformers && ts.map(customTransformers.before, wrapScriptTransformerFactory)); + addRange(transformers, customTransformers && map(customTransformers.before, wrapScriptTransformerFactory)); - transformers.push(ts.transformTypeScript); - transformers.push(ts.transformLegacyDecorators); - transformers.push(ts.transformClassFields); + transformers.push(transformTypeScript); + transformers.push(transformLegacyDecorators); + transformers.push(transformClassFields); - if (ts.getJSXTransformEnabled(compilerOptions)) { - transformers.push(ts.transformJsx); + if (getJSXTransformEnabled(compilerOptions)) { + transformers.push(transformJsx); } - if (languageVersion < ts.ScriptTarget.ESNext) { - transformers.push(ts.transformESNext); + if (languageVersion < ScriptTarget.ESNext) { + transformers.push(transformESNext); } - if (languageVersion < ts.ScriptTarget.ES2021) { - transformers.push(ts.transformES2021); + if (languageVersion < ScriptTarget.ES2021) { + transformers.push(transformES2021); } - if (languageVersion < ts.ScriptTarget.ES2020) { - transformers.push(ts.transformES2020); + if (languageVersion < ScriptTarget.ES2020) { + transformers.push(transformES2020); } - if (languageVersion < ts.ScriptTarget.ES2019) { - transformers.push(ts.transformES2019); + if (languageVersion < ScriptTarget.ES2019) { + transformers.push(transformES2019); } - if (languageVersion < ts.ScriptTarget.ES2018) { - transformers.push(ts.transformES2018); + if (languageVersion < ScriptTarget.ES2018) { + transformers.push(transformES2018); } - if (languageVersion < ts.ScriptTarget.ES2017) { - transformers.push(ts.transformES2017); + if (languageVersion < ScriptTarget.ES2017) { + transformers.push(transformES2017); } - if (languageVersion < ts.ScriptTarget.ES2016) { - transformers.push(ts.transformES2016); + if (languageVersion < ScriptTarget.ES2016) { + transformers.push(transformES2016); } - if (languageVersion < ts.ScriptTarget.ES2015) { - transformers.push(ts.transformES2015); - transformers.push(ts.transformGenerators); + if (languageVersion < ScriptTarget.ES2015) { + transformers.push(transformES2015); + transformers.push(transformGenerators); } transformers.push(getModuleTransformer(moduleKind)); // The ES5 transformer is last so that it can substitute expressions like `exports.default` // for ES3. - if (languageVersion < ts.ScriptTarget.ES5) { - transformers.push(ts.transformES5); + if (languageVersion < ScriptTarget.ES5) { + transformers.push(transformES5); } - ts.addRange(transformers, customTransformers && ts.map(customTransformers.after, wrapScriptTransformerFactory)); + addRange(transformers, customTransformers && map(customTransformers.after, wrapScriptTransformerFactory)); return transformers; } -function getDeclarationTransformers(customTransformers?: ts.CustomTransformers) { - const transformers: ts.TransformerFactory[] = []; - transformers.push(ts.transformDeclarations); - ts.addRange(transformers, customTransformers && ts.map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); +function getDeclarationTransformers(customTransformers?: CustomTransformers) { + const transformers: TransformerFactory[] = []; + transformers.push(transformDeclarations); + addRange(transformers, customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); return transformers; } /** * Wrap a custom script or declaration transformer object in a `Transformer` callback with fallback support for transforming bundles. */ -function wrapCustomTransformer(transformer: ts.CustomTransformer): ts.Transformer { - return node => ts.isBundle(node) ? transformer.transformBundle(node) : transformer.transformSourceFile(node); +function wrapCustomTransformer(transformer: CustomTransformer): Transformer { + return node => isBundle(node) ? transformer.transformBundle(node) : transformer.transformSourceFile(node); } /** * Wrap a transformer factory that may return a custom script or declaration transformer object. */ -function wrapCustomTransformerFactory(transformer: ts.TransformerFactory | ts.CustomTransformerFactory, handleDefault: (context: ts.TransformationContext, tx: ts.Transformer) => ts.Transformer): ts.TransformerFactory { +function wrapCustomTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory, handleDefault: (context: TransformationContext, tx: Transformer) => Transformer): TransformerFactory { return context => { const customTransformer = transformer(context); return typeof customTransformer === "function" @@ -128,21 +141,21 @@ function wrapCustomTransformerFactory(trans }; } -function wrapScriptTransformerFactory(transformer: ts.TransformerFactory | ts.CustomTransformerFactory): ts.TransformerFactory { - return wrapCustomTransformerFactory(transformer, ts.chainBundle); +function wrapScriptTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory): TransformerFactory { + return wrapCustomTransformerFactory(transformer, chainBundle); } -function wrapDeclarationTransformerFactory(transformer: ts.TransformerFactory | ts.CustomTransformerFactory): ts.TransformerFactory { +function wrapDeclarationTransformerFactory(transformer: TransformerFactory | CustomTransformerFactory): TransformerFactory { return wrapCustomTransformerFactory(transformer, (_, node) => node); } /** @internal */ -export function noEmitSubstitution(_hint: ts.EmitHint, node: ts.Node) { +export function noEmitSubstitution(_hint: EmitHint, node: Node) { return node; } /** @internal */ -export function noEmitNotification(hint: ts.EmitHint, node: ts.Node, callback: (hint: ts.EmitHint, node: ts.Node) => void) { +export function noEmitNotification(hint: EmitHint, node: Node, callback: (hint: EmitHint, node: Node) => void) { callback(hint, node); } @@ -157,35 +170,35 @@ export function noEmitNotification(hint: ts.EmitHint, node: ts.Node, callback: ( * @param transforms An array of `TransformerFactory` callbacks. * @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files. */ -export function transformNodes(resolver: ts.EmitResolver | undefined, host: ts.EmitHost | undefined, factory: ts.NodeFactory, options: ts.CompilerOptions, nodes: readonly T[], transformers: readonly ts.TransformerFactory[], allowDtsFiles: boolean): ts.TransformationResult { - const enabledSyntaxKindFeatures = new Array(ts.SyntaxKind.Count); - let lexicalEnvironmentVariableDeclarations: ts.VariableDeclaration[]; - let lexicalEnvironmentFunctionDeclarations: ts.FunctionDeclaration[]; - let lexicalEnvironmentStatements: ts.Statement[]; - let lexicalEnvironmentFlags = ts.LexicalEnvironmentFlags.None; - let lexicalEnvironmentVariableDeclarationsStack: ts.VariableDeclaration[][] = []; - let lexicalEnvironmentFunctionDeclarationsStack: ts.FunctionDeclaration[][] = []; - let lexicalEnvironmentStatementsStack: ts.Statement[][] = []; - let lexicalEnvironmentFlagsStack: ts.LexicalEnvironmentFlags[] = []; +export function transformNodes(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory[], allowDtsFiles: boolean): TransformationResult { + const enabledSyntaxKindFeatures = new Array(SyntaxKind.Count); + let lexicalEnvironmentVariableDeclarations: VariableDeclaration[]; + let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[]; + let lexicalEnvironmentStatements: Statement[]; + let lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; + let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = []; + let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = []; + let lexicalEnvironmentStatementsStack: Statement[][] = []; + let lexicalEnvironmentFlagsStack: LexicalEnvironmentFlags[] = []; let lexicalEnvironmentStackOffset = 0; let lexicalEnvironmentSuspended = false; - let blockScopedVariableDeclarationsStack: ts.Identifier[][] = []; + let blockScopedVariableDeclarationsStack: Identifier[][] = []; let blockScopeStackOffset = 0; - let blockScopedVariableDeclarations: ts.Identifier[]; - let emitHelpers: ts.EmitHelper[] | undefined; - let onSubstituteNode: ts.TransformationContext["onSubstituteNode"] = noEmitSubstitution; - let onEmitNode: ts.TransformationContext["onEmitNode"] = noEmitNotification; + let blockScopedVariableDeclarations: Identifier[]; + let emitHelpers: EmitHelper[] | undefined; + let onSubstituteNode: TransformationContext["onSubstituteNode"] = noEmitSubstitution; + let onEmitNode: TransformationContext["onEmitNode"] = noEmitNotification; let state = TransformationState.Uninitialized; - const diagnostics: ts.DiagnosticWithLocation[] = []; + const diagnostics: DiagnosticWithLocation[] = []; // The transformation context is provided to each transformer as part of transformer // initialization. - const context: ts.TransformationContext = { + const context: TransformationContext = { factory, getCompilerOptions: () => options, getEmitResolver: () => resolver!, // TODO: GH#18217 getEmitHost: () => host!, // TODO: GH#18217 - getEmitHelperFactory: ts.memoize(() => ts.createEmitHelperFactory(context)), + getEmitHelperFactory: memoize(() => createEmitHelperFactory(context)), startLexicalEnvironment, suspendLexicalEnvironment, resumeLexicalEnvironment, @@ -206,14 +219,14 @@ export function transformNodes(resolver: ts.EmitResolver | un isEmitNotificationEnabled, get onSubstituteNode() { return onSubstituteNode; }, set onSubstituteNode(value) { - ts.Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); - ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); + Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); + Debug.assert(value !== undefined, "Value must not be 'undefined'"); onSubstituteNode = value; }, get onEmitNode() { return onEmitNode; }, set onEmitNode(value) { - ts.Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); - ts.Debug.assert(value !== undefined, "Value must not be 'undefined'"); + Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed."); + Debug.assert(value !== undefined, "Value must not be 'undefined'"); onEmitNode = value; }, addDiagnostic(diag) { @@ -223,7 +236,7 @@ export function transformNodes(resolver: ts.EmitResolver | un // Ensure the parse tree is clean before applying transformations for (const node of nodes) { - ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); + disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node))); } ts.performance.mark("beforeTransform"); @@ -243,9 +256,9 @@ export function transformNodes(resolver: ts.EmitResolver | un // Transform each node. const transformed: T[] = []; for (const node of nodes) { - ts.tracing?.push(ts.tracing.Phase.Emit, "transformNodes", node.kind === ts.SyntaxKind.SourceFile ? { path: (node as any as ts.SourceFile).path } : { kind: node.kind, pos: node.pos, end: node.end }); + tracing?.push(tracing.Phase.Emit, "transformNodes", node.kind === SyntaxKind.SourceFile ? { path: (node as any as SourceFile).path } : { kind: node.kind, pos: node.pos, end: node.end }); transformed.push((allowDtsFiles ? transformation : transformRoot)(node)); - ts.tracing?.pop(); + tracing?.pop(); } // prevent modification of the lexical environment. @@ -264,23 +277,23 @@ export function transformNodes(resolver: ts.EmitResolver | un }; function transformRoot(node: T) { - return node && (!ts.isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; + return node && (!isSourceFile(node) || !node.isDeclarationFile) ? transformation(node) : node; } /** * Enables expression substitutions in the pretty printer for the provided SyntaxKind. */ - function enableSubstitution(kind: ts.SyntaxKind) { - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + function enableSubstitution(kind: SyntaxKind) { + Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution; } /** * Determines whether expression substitutions are enabled for the provided node. */ - function isSubstitutionEnabled(node: ts.Node) { + function isSubstitutionEnabled(node: Node) { return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.Substitution) !== 0 - && (ts.getEmitFlags(node) & ts.EmitFlags.NoSubstitution) === 0; + && (getEmitFlags(node) & EmitFlags.NoSubstitution) === 0; } /** @@ -290,16 +303,16 @@ export function transformNodes(resolver: ts.EmitResolver | un * @param node The node to emit. * @param emitCallback The callback used to emit the node or its substitute. */ - function substituteNode(hint: ts.EmitHint, node: ts.Node) { - ts.Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed."); + function substituteNode(hint: EmitHint, node: Node) { + Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed."); return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node; } /** * Enables before/after emit notifications in the pretty printer for the provided SyntaxKind. */ - function enableEmitNotification(kind: ts.SyntaxKind) { - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + function enableEmitNotification(kind: SyntaxKind) { + Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications; } @@ -307,9 +320,9 @@ export function transformNodes(resolver: ts.EmitResolver | un * Determines whether before/after emit notifications should be raised in the pretty * printer when it emits a node. */ - function isEmitNotificationEnabled(node: ts.Node) { + function isEmitNotificationEnabled(node: Node) { return (enabledSyntaxKindFeatures[node.kind] & SyntaxKindFeatureFlags.EmitNotifications) !== 0 - || (ts.getEmitFlags(node) & ts.EmitFlags.AdviseOnEmitNode) !== 0; + || (getEmitFlags(node) & EmitFlags.AdviseOnEmitNode) !== 0; } /** @@ -319,8 +332,8 @@ export function transformNodes(resolver: ts.EmitResolver | un * @param node The node to emit. * @param emitCallback The callback used to emit the node. */ - function emitNodeWithNotification(hint: ts.EmitHint, node: ts.Node, emitCallback: (hint: ts.EmitHint, node: ts.Node) => void) { - ts.Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed."); + function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { + Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed."); if (node) { // TODO: Remove check and unconditionally use onEmitNode when API is breakingly changed // (see https://github.com/microsoft/TypeScript/pull/36248/files/5062623f39120171b98870c71344b3242eb03d23#r369766739) @@ -336,28 +349,28 @@ export function transformNodes(resolver: ts.EmitResolver | un /** * Records a hoisted variable declaration for the provided name within a lexical environment. */ - function hoistVariableDeclaration(name: ts.Identifier): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - const decl = ts.setEmitFlags(factory.createVariableDeclaration(name), ts.EmitFlags.NoNestedSourceMaps); + function hoistVariableDeclaration(name: Identifier): void { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + const decl = setEmitFlags(factory.createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps); if (!lexicalEnvironmentVariableDeclarations) { lexicalEnvironmentVariableDeclarations = [decl]; } else { lexicalEnvironmentVariableDeclarations.push(decl); } - if (lexicalEnvironmentFlags & ts.LexicalEnvironmentFlags.InParameters) { - lexicalEnvironmentFlags |= ts.LexicalEnvironmentFlags.VariablesHoistedInParameters; + if (lexicalEnvironmentFlags & LexicalEnvironmentFlags.InParameters) { + lexicalEnvironmentFlags |= LexicalEnvironmentFlags.VariablesHoistedInParameters; } } /** * Records a hoisted function declaration within a lexical environment. */ - function hoistFunctionDeclaration(func: ts.FunctionDeclaration): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.setEmitFlags(func, ts.EmitFlags.CustomPrologue); + function hoistFunctionDeclaration(func: FunctionDeclaration): void { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + setEmitFlags(func, EmitFlags.CustomPrologue); if (!lexicalEnvironmentFunctionDeclarations) { lexicalEnvironmentFunctionDeclarations = [func]; } @@ -369,10 +382,10 @@ export function transformNodes(resolver: ts.EmitResolver | un /** * Adds an initialization statement to the top of the lexical environment. */ - function addInitializationStatement(node: ts.Statement): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.setEmitFlags(node, ts.EmitFlags.CustomPrologue); + function addInitializationStatement(node: Statement): void { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + setEmitFlags(node, EmitFlags.CustomPrologue); if (!lexicalEnvironmentStatements) { lexicalEnvironmentStatements = [node]; } @@ -386,9 +399,9 @@ export function transformNodes(resolver: ts.EmitResolver | un * are pushed onto a stack, and the related storage variables are reset. */ function startLexicalEnvironment(): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); // Save the current lexical environment. Rather than resizing the array we adjust the // stack size variable. This allows us to reuse existing array slots we've @@ -402,22 +415,22 @@ export function transformNodes(resolver: ts.EmitResolver | un lexicalEnvironmentVariableDeclarations = undefined!; lexicalEnvironmentFunctionDeclarations = undefined!; lexicalEnvironmentStatements = undefined!; - lexicalEnvironmentFlags = ts.LexicalEnvironmentFlags.None; + lexicalEnvironmentFlags = LexicalEnvironmentFlags.None; } /** Suspends the current lexical environment, usually after visiting a parameter list. */ function suspendLexicalEnvironment(): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended."); lexicalEnvironmentSuspended = true; } /** Resumes a suspended lexical environment, usually before visiting a function body. */ function resumeLexicalEnvironment(): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended."); lexicalEnvironmentSuspended = false; } @@ -425,12 +438,12 @@ export function transformNodes(resolver: ts.EmitResolver | un * Ends a lexical environment. The previous set of hoisted declarations are restored and * any hoisted declarations added in this environment are returned. */ - function endLexicalEnvironment(): ts.Statement[] | undefined { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); - ts.Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); + function endLexicalEnvironment(): Statement[] | undefined { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed."); + Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended."); - let statements: ts.Statement[] | undefined; + let statements: Statement[] | undefined; if (lexicalEnvironmentVariableDeclarations || lexicalEnvironmentFunctionDeclarations || lexicalEnvironmentStatements) { @@ -444,7 +457,7 @@ export function transformNodes(resolver: ts.EmitResolver | un factory.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations) ); - ts.setEmitFlags(statement, ts.EmitFlags.CustomPrologue); + setEmitFlags(statement, EmitFlags.CustomPrologue); if (!statements) { statements = [statement]; @@ -479,13 +492,13 @@ export function transformNodes(resolver: ts.EmitResolver | un return statements; } - function setLexicalEnvironmentFlags(flags: ts.LexicalEnvironmentFlags, value: boolean): void { + function setLexicalEnvironmentFlags(flags: LexicalEnvironmentFlags, value: boolean): void { lexicalEnvironmentFlags = value ? lexicalEnvironmentFlags | flags : lexicalEnvironmentFlags & ~flags; } - function getLexicalEnvironmentFlags(): ts.LexicalEnvironmentFlags { + function getLexicalEnvironmentFlags(): LexicalEnvironmentFlags { return lexicalEnvironmentFlags; } @@ -493,8 +506,8 @@ export function transformNodes(resolver: ts.EmitResolver | un * Starts a block scope. Any existing block hoisted variables are pushed onto the stack and the related storage variables are reset. */ function startBlockScope() { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot start a block scope during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot start a block scope after transformation has completed."); + Debug.assert(state > TransformationState.Uninitialized, "Cannot start a block scope during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot start a block scope after transformation has completed."); blockScopedVariableDeclarationsStack[blockScopeStackOffset] = blockScopedVariableDeclarations; blockScopeStackOffset++; blockScopedVariableDeclarations = undefined!; @@ -504,15 +517,15 @@ export function transformNodes(resolver: ts.EmitResolver | un * Ends a block scope. The previous set of block hoisted variables are restored. Any hoisted declarations are returned. */ function endBlockScope() { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot end a block scope during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot end a block scope after transformation has completed."); - const statements: ts.Statement[] | undefined = ts.some(blockScopedVariableDeclarations) ? + Debug.assert(state > TransformationState.Uninitialized, "Cannot end a block scope during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot end a block scope after transformation has completed."); + const statements: Statement[] | undefined = some(blockScopedVariableDeclarations) ? [ factory.createVariableStatement( /*modifiers*/ undefined, factory.createVariableDeclarationList( blockScopedVariableDeclarations.map(identifier => factory.createVariableDeclaration(identifier)), - ts.NodeFlags.Let + NodeFlags.Let ) ) ] : undefined; @@ -524,26 +537,26 @@ export function transformNodes(resolver: ts.EmitResolver | un return statements; } - function addBlockScopedVariable(name: ts.Identifier): void { - ts.Debug.assert(blockScopeStackOffset > 0, "Cannot add a block scoped variable outside of an iteration body."); + function addBlockScopedVariable(name: Identifier): void { + Debug.assert(blockScopeStackOffset > 0, "Cannot add a block scoped variable outside of an iteration body."); (blockScopedVariableDeclarations || (blockScopedVariableDeclarations = [])).push(name); } - function requestEmitHelper(helper: ts.EmitHelper): void { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); - ts.Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); + function requestEmitHelper(helper: EmitHelper): void { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + Debug.assert(!helper.scoped, "Cannot request a scoped emit helper."); if (helper.dependencies) { for (const h of helper.dependencies) { requestEmitHelper(h); } } - emitHelpers = ts.append(emitHelpers, helper); + emitHelpers = append(emitHelpers, helper); } - function readEmitHelpers(): ts.EmitHelper[] | undefined { - ts.Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); - ts.Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); + function readEmitHelpers(): EmitHelper[] | undefined { + Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization."); + Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed."); const helpers = emitHelpers; emitHelpers = undefined; return helpers; @@ -553,7 +566,7 @@ export function transformNodes(resolver: ts.EmitResolver | un if (state < TransformationState.Disposed) { // Clean up emit nodes on parse tree for (const node of nodes) { - ts.disposeEmitNodes(ts.getSourceFileOfNode(ts.getParseTreeNode(node))); + disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node))); } // Release references to external entries for GC purposes. @@ -572,31 +585,31 @@ export function transformNodes(resolver: ts.EmitResolver | un } /** @internal */ -export const nullTransformationContext: ts.TransformationContext = { - factory: ts.factory, // eslint-disable-line object-shorthand +export const nullTransformationContext: TransformationContext = { + factory: factory, // eslint-disable-line object-shorthand getCompilerOptions: () => ({}), - getEmitResolver: ts.notImplemented, - getEmitHost: ts.notImplemented, - getEmitHelperFactory: ts.notImplemented, - startLexicalEnvironment: ts.noop, - resumeLexicalEnvironment: ts.noop, - suspendLexicalEnvironment: ts.noop, - endLexicalEnvironment: ts.returnUndefined, - setLexicalEnvironmentFlags: ts.noop, + getEmitResolver: notImplemented, + getEmitHost: notImplemented, + getEmitHelperFactory: notImplemented, + startLexicalEnvironment: noop, + resumeLexicalEnvironment: noop, + suspendLexicalEnvironment: noop, + endLexicalEnvironment: returnUndefined, + setLexicalEnvironmentFlags: noop, getLexicalEnvironmentFlags: () => 0, - hoistVariableDeclaration: ts.noop, - hoistFunctionDeclaration: ts.noop, - addInitializationStatement: ts.noop, - startBlockScope: ts.noop, - endBlockScope: ts.returnUndefined, - addBlockScopedVariable: ts.noop, - requestEmitHelper: ts.noop, - readEmitHelpers: ts.notImplemented, - enableSubstitution: ts.noop, - enableEmitNotification: ts.noop, - isSubstitutionEnabled: ts.notImplemented, - isEmitNotificationEnabled: ts.notImplemented, + hoistVariableDeclaration: noop, + hoistFunctionDeclaration: noop, + addInitializationStatement: noop, + startBlockScope: noop, + endBlockScope: returnUndefined, + addBlockScopedVariable: noop, + requestEmitHelper: noop, + readEmitHelpers: notImplemented, + enableSubstitution: noop, + enableEmitNotification: noop, + isSubstitutionEnabled: notImplemented, + isEmitNotificationEnabled: notImplemented, onSubstituteNode: noEmitSubstitution, onEmitNode: noEmitNotification, - addDiagnostic: ts.noop, + addDiagnostic: noop, }; diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index d3bf188e4c95b..1f2c3ce4c0049 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -1,4 +1,40 @@ -import * as ts from "../_namespaces/ts"; +import { + __String, AccessorDeclaration, addEmitFlags, addEmitHelpers, addRange, append, AssignmentOperator, + AssignmentPattern, AutoAccessorPropertyDeclaration, BinaryExpression, BindingOrAssignmentElement, CallExpression, + chainBundle, ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, + classOrConstructorParameterIsDecorated, ClassStaticBlockDeclaration, compact, ComputedPropertyName, + ConstructorDeclaration, createAccessorPropertyBackingField, createAccessorPropertyGetRedirector, + createAccessorPropertySetRedirector, createMemberAccessForPropertyName, Debug, ElementAccessExpression, EmitFlags, + EmitHint, ESMap, expandPreOrPostfixIncrementOrDecrementExpression, Expression, ExpressionStatement, + ExpressionWithTypeArguments, factory, filter, findSuperStatementIndex, ForStatement, GeneratedIdentifier, + GeneratedIdentifierFlags, GeneratedNamePart, GeneratedPrivateIdentifier, GetAccessorDeclaration, getCommentRange, + getEffectiveBaseTypeNode, getEmitFlags, getEmitScriptTarget, getInitializerOfBindingOrAssignmentElement, + getNameOfDeclaration, getNodeForGeneratedName, getNonAssignmentOperatorForCompoundAssignment, getOriginalNode, + getOriginalNodeId, getProperties, getSourceMapRange, getStaticPropertiesAndClassStaticBlock, + getTargetOfBindingOrAssignmentElement, getUseDefineForClassFields, hasAbstractModifier, hasAccessorModifier, + hasDecorators, hasStaticModifier, hasSyntacticModifier, Identifier, InKeyword, isAccessorModifier, + isArrayLiteralExpression, isArrowFunction, isAssignmentExpression, isAutoAccessorPropertyDeclaration, isCallChain, + isClassDeclaration, isClassElement, isClassStaticBlockDeclaration, isCompoundAssignment, isComputedPropertyName, + isConstructorDeclaration, isDestructuringAssignment, isElementAccessExpression, isExpression, isForInitializer, + isGeneratedIdentifier, isGeneratedPrivateIdentifier, isGetAccessor, isGetAccessorDeclaration, isHeritageClause, + isIdentifier, isInitializedProperty, isMethodDeclaration, isModifier, isModifierLike, + isNonStaticMethodOrAccessorWithPrivateName, isObjectBindingOrAssignmentElement, isObjectLiteralElementLike, + isParameterPropertyDeclaration, isParenthesizedExpression, isPrefixUnaryExpression, isPrivateIdentifier, + isPrivateIdentifierClassElementDeclaration, isPrivateIdentifierPropertyAccessExpression, isPropertyAccessExpression, + isPropertyAssignment, isPropertyDeclaration, isPropertyName, isSetAccessor, isSetAccessorDeclaration, + isShorthandPropertyAssignment, isSimpleCopiableExpression, isSimpleInlineableExpression, isSpreadAssignment, + isSpreadElement, isStatement, isStatic, isStaticModifier, isSuperProperty, isTemplateLiteral, isThisProperty, + LeftHandSideExpression, map, Map, MethodDeclaration, Modifier, ModifierFlags, moveRangePastModifiers, moveRangePos, + Node, NodeCheckFlags, nodeIsSynthesized, ObjectLiteralElementLike, PostfixUnaryExpression, PrefixUnaryExpression, + PrivateIdentifier, PrivateIdentifierPropertyAccessExpression, PrivateIdentifierPropertyDeclaration, + PropertyAccessExpression, PropertyDeclaration, PropertyName, ScriptTarget, SetAccessorDeclaration, setCommentRange, + setEmitFlags, setOriginalNode, setSourceMapRange, setSyntheticLeadingComments, setSyntheticTrailingComments, + setTextRange, skipOuterExpressions, skipParentheses, skipPartiallyEmittedExpressions, some, SourceFile, + startOnNewLine, Statement, SuperProperty, SyntaxKind, TaggedTemplateExpression, ThisExpression, + TransformationContext, TransformFlags, tryGetTextOfPropertyName, UnderscoreEscapedMap, unescapeLeadingUnderscores, + VariableStatement, visitArray, visitEachChild, visitFunctionBody, visitIterationBody, visitNode, visitNodes, + visitParameterList, VisitResult, +} from "../_namespaces/ts"; const enum ClassPropertySubstitutionFlags { /** @@ -27,7 +63,7 @@ interface PrivateIdentifierInfoBase { * - For instance methods or accessors: The WeakSet that will be used for brand checking. * - For static members: The constructor that will be used for brand checking. */ - brandCheckIdentifier: ts.Identifier; + brandCheckIdentifier: Identifier; /** * Stores if the identifier is static or not */ @@ -44,11 +80,11 @@ interface PrivateIdentifierAccessorInfo extends PrivateIdentifierInfoBase { /** * Identifier for a variable that will contain the private get accessor implementation, if any. */ - getterName?: ts.Identifier; + getterName?: Identifier; /** * Identifier for a variable that will contain the private set accessor implementation, if any. */ - setterName?: ts.Identifier; + setterName?: Identifier; } interface PrivateIdentifierMethodInfo extends PrivateIdentifierInfoBase { @@ -56,7 +92,7 @@ interface PrivateIdentifierMethodInfo extends PrivateIdentifierInfoBase { /** * Identifier for a variable that will contain the private method implementation. */ - methodName: ts.Identifier; + methodName: Identifier; } interface PrivateIdentifierInstanceFieldInfo extends PrivateIdentifierInfoBase { @@ -74,7 +110,7 @@ interface PrivateIdentifierStaticFieldInfo extends PrivateIdentifierInfoBase { /** * Contains the variable that will serve as the storage for the field. */ - variableName: ts.Identifier; + variableName: Identifier; } type PrivateIdentifierInfo = @@ -87,19 +123,19 @@ interface PrivateIdentifierEnvironment { /** * Used for prefixing generated variable names. */ - className?: ts.Identifier; + className?: Identifier; /** * Used for brand check on private methods. */ - weakSetName?: ts.Identifier; + weakSetName?: Identifier; /** * A mapping of private names to information needed for transformation. */ - identifiers?: ts.UnderscoreEscapedMap; + identifiers?: UnderscoreEscapedMap; /** * A mapping of generated private names to information needed for transformation. */ - generatedIdentifiers?: ts.ESMap; + generatedIdentifiers?: ESMap; } interface ClassLexicalEnvironment { @@ -107,11 +143,11 @@ interface ClassLexicalEnvironment { /** * Used for brand checks on static members, and `this` references in static initializers */ - classConstructor: ts.Identifier | undefined; + classConstructor: Identifier | undefined; /** * Used for `super` references in static initializers. */ - superClassReference: ts.Identifier | undefined; + superClassReference: Identifier | undefined; privateIdentifierEnvironment: PrivateIdentifierEnvironment | undefined; } @@ -131,7 +167,7 @@ const enum ClassFacts { * where declarations are elided and initializers are transformed as assignments in the constructor. * When --useDefineForClassFields is on, this transforms to ECMAScript semantics, with Object.defineProperty. */ -export function transformClassFields(context: ts.TransformationContext) { +export function transformClassFields(context: TransformationContext) { const { factory, hoistVariableDeclaration, @@ -142,29 +178,29 @@ export function transformClassFields(context: ts.TransformationContext) { } = context; const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); - const languageVersion = ts.getEmitScriptTarget(compilerOptions); - const useDefineForClassFields = ts.getUseDefineForClassFields(compilerOptions); + const languageVersion = getEmitScriptTarget(compilerOptions); + const useDefineForClassFields = getUseDefineForClassFields(compilerOptions); // Always transform field initializers using Set semantics when `useDefineForClassFields: false`. const shouldTransformInitializersUsingSet = !useDefineForClassFields; // Transform field initializers using Define semantics when `useDefineForClassFields: true` and target < ES2022. - const shouldTransformInitializersUsingDefine = useDefineForClassFields && languageVersion < ts.ScriptTarget.ES2022; + const shouldTransformInitializersUsingDefine = useDefineForClassFields && languageVersion < ScriptTarget.ES2022; const shouldTransformInitializers = shouldTransformInitializersUsingSet || shouldTransformInitializersUsingDefine; // We need to transform private members and class static blocks when target < ES2022. - const shouldTransformPrivateElementsOrClassStaticBlocks = languageVersion < ts.ScriptTarget.ES2022; + const shouldTransformPrivateElementsOrClassStaticBlocks = languageVersion < ScriptTarget.ES2022; // We need to transform `accessor` fields when target < ESNext - const shouldTransformAutoAccessors = languageVersion < ts.ScriptTarget.ESNext; + const shouldTransformAutoAccessors = languageVersion < ScriptTarget.ESNext; // We need to transform `this` in a static initializer into a reference to the class // when target < ES2022 since the assignment will be moved outside of the class body. - const shouldTransformThisInStaticInitializers = languageVersion < ts.ScriptTarget.ES2022; + const shouldTransformThisInStaticInitializers = languageVersion < ScriptTarget.ES2022; // We don't need to transform `super` property access when target <= ES5 because // the es2015 transformation handles those. - const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ts.ScriptTarget.ES2015; + const shouldTransformSuperInStaticInitializers = shouldTransformThisInStaticInitializers && languageVersion >= ScriptTarget.ES2015; const shouldTransformAnything = shouldTransformInitializers || @@ -179,84 +215,84 @@ export function transformClassFields(context: ts.TransformationContext) { let enabledSubstitutions: ClassPropertySubstitutionFlags; - let classAliases: ts.Identifier[]; + let classAliases: Identifier[]; /** * Tracks what computed name expressions originating from elided names must be inlined * at the next execution site, in document order */ - let pendingExpressions: ts.Expression[] | undefined; + let pendingExpressions: Expression[] | undefined; /** * Tracks what computed name expression statements and static property initializers must be * emitted at the next execution site, in document order (for decorated classes). */ - let pendingStatements: ts.Statement[] | undefined; + let pendingStatements: Statement[] | undefined; const classLexicalEnvironmentStack: (ClassLexicalEnvironment | undefined)[] = []; - const classLexicalEnvironmentMap = new ts.Map(); + const classLexicalEnvironmentMap = new Map(); let currentClassLexicalEnvironment: ClassLexicalEnvironment | undefined; - let currentClassContainer: ts.ClassLikeDeclaration | undefined; + let currentClassContainer: ClassLikeDeclaration | undefined; let currentComputedPropertyNameClassLexicalEnvironment: ClassLexicalEnvironment | undefined; - let currentStaticPropertyDeclarationOrStaticBlock: ts.PropertyDeclaration | ts.ClassStaticBlockDeclaration | undefined; + let currentStaticPropertyDeclarationOrStaticBlock: PropertyDeclaration | ClassStaticBlockDeclaration | undefined; - return ts.chainBundle(context, transformSourceFile); + return chainBundle(context, transformSourceFile); - function transformSourceFile(node: ts.SourceFile) { + function transformSourceFile(node: SourceFile) { if (node.isDeclarationFile || !shouldTransformAnything) { return node; } - const visited = ts.visitEachChild(node, visitor, context); - ts.addEmitHelpers(visited, context.readEmitHelpers()); + const visited = visitEachChild(node, visitor, context); + addEmitHelpers(visited, context.readEmitHelpers()); return visited; } - function visitor(node: ts.Node): ts.VisitResult { - if (!(node.transformFlags & ts.TransformFlags.ContainsClassFields) && - !(node.transformFlags & ts.TransformFlags.ContainsLexicalThisOrSuper)) { + function visitor(node: Node): VisitResult { + if (!(node.transformFlags & TransformFlags.ContainsClassFields) && + !(node.transformFlags & TransformFlags.ContainsLexicalThisOrSuper)) { return node; } switch (node.kind) { - case ts.SyntaxKind.AccessorKeyword: + case SyntaxKind.AccessorKeyword: return shouldTransformAutoAccessors ? undefined : node; - case ts.SyntaxKind.ClassDeclaration: - return visitClassDeclaration(node as ts.ClassDeclaration); - case ts.SyntaxKind.ClassExpression: - return visitClassExpression(node as ts.ClassExpression); - case ts.SyntaxKind.ClassStaticBlockDeclaration: - return visitClassStaticBlockDeclaration(node as ts.ClassStaticBlockDeclaration); - case ts.SyntaxKind.PropertyDeclaration: - return visitPropertyDeclaration(node as ts.PropertyDeclaration); - case ts.SyntaxKind.VariableStatement: - return visitVariableStatement(node as ts.VariableStatement); - case ts.SyntaxKind.PrivateIdentifier: - return visitPrivateIdentifier(node as ts.PrivateIdentifier); - case ts.SyntaxKind.PropertyAccessExpression: - return visitPropertyAccessExpression(node as ts.PropertyAccessExpression); - case ts.SyntaxKind.ElementAccessExpression: - return visitElementAccessExpression(node as ts.ElementAccessExpression); - case ts.SyntaxKind.PrefixUnaryExpression: - case ts.SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, /*valueIsDiscarded*/ false); - case ts.SyntaxKind.BinaryExpression: - return visitBinaryExpression(node as ts.BinaryExpression, /*valueIsDiscarded*/ false); - case ts.SyntaxKind.CallExpression: - return visitCallExpression(node as ts.CallExpression); - case ts.SyntaxKind.ExpressionStatement: - return visitExpressionStatement(node as ts.ExpressionStatement); - case ts.SyntaxKind.TaggedTemplateExpression: - return visitTaggedTemplateExpression(node as ts.TaggedTemplateExpression); - case ts.SyntaxKind.ForStatement: - return visitForStatement(node as ts.ForStatement); - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: { + case SyntaxKind.ClassDeclaration: + return visitClassDeclaration(node as ClassDeclaration); + case SyntaxKind.ClassExpression: + return visitClassExpression(node as ClassExpression); + case SyntaxKind.ClassStaticBlockDeclaration: + return visitClassStaticBlockDeclaration(node as ClassStaticBlockDeclaration); + case SyntaxKind.PropertyDeclaration: + return visitPropertyDeclaration(node as PropertyDeclaration); + case SyntaxKind.VariableStatement: + return visitVariableStatement(node as VariableStatement); + case SyntaxKind.PrivateIdentifier: + return visitPrivateIdentifier(node as PrivateIdentifier); + case SyntaxKind.PropertyAccessExpression: + return visitPropertyAccessExpression(node as PropertyAccessExpression); + case SyntaxKind.ElementAccessExpression: + return visitElementAccessExpression(node as ElementAccessExpression); + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*valueIsDiscarded*/ false); + case SyntaxKind.BinaryExpression: + return visitBinaryExpression(node as BinaryExpression, /*valueIsDiscarded*/ false); + case SyntaxKind.CallExpression: + return visitCallExpression(node as CallExpression); + case SyntaxKind.ExpressionStatement: + return visitExpressionStatement(node as ExpressionStatement); + case SyntaxKind.TaggedTemplateExpression: + return visitTaggedTemplateExpression(node as TaggedTemplateExpression); + case SyntaxKind.ForStatement: + return visitForStatement(node as ForStatement); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.Constructor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: { // If we are descending into a new scope, clear the current static property or block return setCurrentStaticPropertyDeclarationOrStaticBlockAnd( /*current*/ undefined, @@ -269,20 +305,20 @@ export function transformClassFields(context: ts.TransformationContext) { } } - function fallbackVisitor(node: ts.Node) { - return ts.visitEachChild(node, visitor, context); + function fallbackVisitor(node: Node) { + return visitEachChild(node, visitor, context); } /** * Visits a node in an expression whose result is discarded. */ - function discardedValueVisitor(node: ts.Node): ts.VisitResult { + function discardedValueVisitor(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: - case ts.SyntaxKind.PostfixUnaryExpression: - return visitPreOrPostfixUnaryExpression(node as ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, /*valueIsDiscarded*/ true); - case ts.SyntaxKind.BinaryExpression: - return visitBinaryExpression(node as ts.BinaryExpression, /*valueIsDiscarded*/ true); + case SyntaxKind.PrefixUnaryExpression: + case SyntaxKind.PostfixUnaryExpression: + return visitPreOrPostfixUnaryExpression(node as PrefixUnaryExpression | PostfixUnaryExpression, /*valueIsDiscarded*/ true); + case SyntaxKind.BinaryExpression: + return visitBinaryExpression(node as BinaryExpression, /*valueIsDiscarded*/ true); default: return visitor(node); } @@ -291,12 +327,12 @@ export function transformClassFields(context: ts.TransformationContext) { /** * Visits a node in a {@link HeritageClause}. */ - function heritageClauseVisitor(node: ts.Node): ts.VisitResult { + function heritageClauseVisitor(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.HeritageClause: - return ts.visitEachChild(node, heritageClauseVisitor, context); - case ts.SyntaxKind.ExpressionWithTypeArguments: - return visitExpressionWithTypeArgumentsInHeritageClause(node as ts.ExpressionWithTypeArguments); + case SyntaxKind.HeritageClause: + return visitEachChild(node, heritageClauseVisitor, context); + case SyntaxKind.ExpressionWithTypeArguments: + return visitExpressionWithTypeArgumentsInHeritageClause(node as ExpressionWithTypeArguments); default: return visitor(node); } @@ -305,11 +341,11 @@ export function transformClassFields(context: ts.TransformationContext) { /** * Visits the assignment target of a destructuring assignment. */ - function assignmentTargetVisitor(node: ts.Node): ts.VisitResult { + function assignmentTargetVisitor(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ArrayLiteralExpression: - return visitAssignmentPattern(node as ts.AssignmentPattern); + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ArrayLiteralExpression: + return visitAssignmentPattern(node as AssignmentPattern); default: return visitor(node); } @@ -318,25 +354,25 @@ export function transformClassFields(context: ts.TransformationContext) { /** * Visits a member of a class. */ - function classElementVisitor(node: ts.Node): ts.VisitResult { + function classElementVisitor(node: Node): VisitResult { switch (node.kind) { - case ts.SyntaxKind.Constructor: - return visitConstructorDeclaration(node as ts.ConstructorDeclaration); - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + return visitConstructorDeclaration(node as ConstructorDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: return setCurrentStaticPropertyDeclarationOrStaticBlockAnd( /*current*/ undefined, visitMethodOrAccessorDeclaration, - node as ts.MethodDeclaration | ts.AccessorDeclaration); - case ts.SyntaxKind.PropertyDeclaration: + node as MethodDeclaration | AccessorDeclaration); + case SyntaxKind.PropertyDeclaration: return setCurrentStaticPropertyDeclarationOrStaticBlockAnd( /*current*/ undefined, visitPropertyDeclaration, - node as ts.PropertyDeclaration); - case ts.SyntaxKind.ComputedPropertyName: - return visitComputedPropertyName(node as ts.ComputedPropertyName); - case ts.SyntaxKind.SemicolonClassElement: + node as PropertyDeclaration); + case SyntaxKind.ComputedPropertyName: + return visitComputedPropertyName(node as ComputedPropertyName); + case SyntaxKind.SemicolonClassElement: return node; default: return visitor(node); @@ -346,15 +382,15 @@ export function transformClassFields(context: ts.TransformationContext) { /** * Visits the results of an auto-accessor field transformation in a second pass. */ - function accessorFieldResultVisitor(node: ts.Node) { + function accessorFieldResultVisitor(node: Node) { switch (node.kind) { - case ts.SyntaxKind.PropertyDeclaration: - return transformFieldInitializer(node as ts.PropertyDeclaration); - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + return transformFieldInitializer(node as PropertyDeclaration); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: return classElementVisitor(node); default: - ts.Debug.assertMissingNode(node, "Expected node to either be a PropertyDeclaration, GetAccessorDeclaration, or SetAccessorDeclaration"); + Debug.assertMissingNode(node, "Expected node to either be a PropertyDeclaration, GetAccessorDeclaration, or SetAccessorDeclaration"); break; } } @@ -365,21 +401,21 @@ export function transformClassFields(context: ts.TransformationContext) { * unless we are in a statement position - otherwise this will not trigger * a SyntaxError. */ - function visitPrivateIdentifier(node: ts.PrivateIdentifier) { + function visitPrivateIdentifier(node: PrivateIdentifier) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { return node; } - if (ts.isStatement(node.parent)) { + if (isStatement(node.parent)) { return node; } - return ts.setOriginalNode(factory.createIdentifier(""), node); + return setOriginalNode(factory.createIdentifier(""), node); } - type PrivateIdentifierInExpression = ts.BinaryExpression & { readonly left: ts.PrivateIdentifier, readonly token: ts.InKeyword }; + type PrivateIdentifierInExpression = BinaryExpression & { readonly left: PrivateIdentifier, readonly token: InKeyword }; - function isPrivateIdentifierInExpression(node: ts.BinaryExpression): node is PrivateIdentifierInExpression { - return ts.isPrivateIdentifier(node.left) - && node.operatorToken.kind === ts.SyntaxKind.InKeyword; + function isPrivateIdentifierInExpression(node: BinaryExpression): node is PrivateIdentifierInExpression { + return isPrivateIdentifier(node.left) + && node.operatorToken.kind === SyntaxKind.InKeyword; } /** @@ -388,24 +424,24 @@ export function transformClassFields(context: ts.TransformationContext) { function transformPrivateIdentifierInInExpression(node: PrivateIdentifierInExpression) { const info = accessPrivateIdentifier(node.left); if (info) { - const receiver = ts.visitNode(node.right, visitor, ts.isExpression); + const receiver = visitNode(node.right, visitor, isExpression); - return ts.setOriginalNode( + return setOriginalNode( context.getEmitHelperFactory().createClassPrivateFieldInHelper(info.brandCheckIdentifier, receiver), node ); } // Private name has not been declared. Subsequent transformers will handle this error - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitVariableStatement(node: ts.VariableStatement) { + function visitVariableStatement(node: VariableStatement) { const savedPendingStatements = pendingStatements; pendingStatements = []; - const visitedNode = ts.visitEachChild(node, visitor, context); - const statement = ts.some(pendingStatements) ? + const visitedNode = visitEachChild(node, visitor, context); + const statement = some(pendingStatements) ? [visitedNode, ...pendingStatements] : visitedNode; @@ -413,10 +449,10 @@ export function transformClassFields(context: ts.TransformationContext) { return statement; } - function visitComputedPropertyName(node: ts.ComputedPropertyName) { - let expression = ts.visitNode(node.expression, visitor, ts.isExpression); - if (ts.some(pendingExpressions)) { - if (ts.isParenthesizedExpression(expression)) { + function visitComputedPropertyName(node: ComputedPropertyName) { + let expression = visitNode(node.expression, visitor, isExpression); + if (some(pendingExpressions)) { + if (isParenthesizedExpression(expression)) { expression = factory.updateParenthesizedExpression(expression, factory.inlineExpressions([...pendingExpressions, expression.expression])); } else { @@ -427,23 +463,23 @@ export function transformClassFields(context: ts.TransformationContext) { return factory.updateComputedPropertyName(node, expression); } - function visitConstructorDeclaration(node: ts.ConstructorDeclaration) { + function visitConstructorDeclaration(node: ConstructorDeclaration) { if (currentClassContainer) { return transformConstructor(node, currentClassContainer); } return fallbackVisitor(node); } - function visitMethodOrAccessorDeclaration(node: ts.MethodDeclaration | ts.AccessorDeclaration) { - ts.Debug.assert(!ts.hasDecorators(node)); + function visitMethodOrAccessorDeclaration(node: MethodDeclaration | AccessorDeclaration) { + Debug.assert(!hasDecorators(node)); - if (!shouldTransformPrivateElementsOrClassStaticBlocks || !ts.isPrivateIdentifier(node.name)) { - return ts.visitEachChild(node, classElementVisitor, context); + if (!shouldTransformPrivateElementsOrClassStaticBlocks || !isPrivateIdentifier(node.name)) { + return visitEachChild(node, classElementVisitor, context); } // leave invalid code untransformed const info = accessPrivateIdentifier(node.name); - ts.Debug.assert(info, "Undeclared private name for property declaration."); + Debug.assert(info, "Undeclared private name for property declaration."); if (!info.isValid) { return node; } @@ -454,13 +490,13 @@ export function transformClassFields(context: ts.TransformationContext) { factory.createAssignment( functionName, factory.createFunctionExpression( - ts.filter(node.modifiers, (m): m is ts.Modifier => ts.isModifier(m) && !ts.isStaticModifier(m) && !ts.isAccessorModifier(m)), + filter(node.modifiers, (m): m is Modifier => isModifier(m) && !isStaticModifier(m) && !isAccessorModifier(m)), node.asteriskToken, functionName, /* typeParameters */ undefined, - ts.visitParameterList(node.parameters, visitor, context), + visitParameterList(node.parameters, visitor, context), /* type */ undefined, - ts.visitFunctionBody(node.body!, visitor, context) + visitFunctionBody(node.body!, visitor, context) ) ) ); @@ -471,7 +507,7 @@ export function transformClassFields(context: ts.TransformationContext) { } function setCurrentStaticPropertyDeclarationOrStaticBlockAnd( - current: ts.ClassStaticBlockDeclaration | ts.PropertyDeclaration | undefined, + current: ClassStaticBlockDeclaration | PropertyDeclaration | undefined, visitor: (arg: T) => U, arg: T, ) { @@ -482,26 +518,26 @@ export function transformClassFields(context: ts.TransformationContext) { return result; } - function getHoistedFunctionName(node: ts.MethodDeclaration | ts.AccessorDeclaration) { - ts.Debug.assert(ts.isPrivateIdentifier(node.name)); + function getHoistedFunctionName(node: MethodDeclaration | AccessorDeclaration) { + Debug.assert(isPrivateIdentifier(node.name)); const info = accessPrivateIdentifier(node.name); - ts.Debug.assert(info, "Undeclared private name for property declaration."); + Debug.assert(info, "Undeclared private name for property declaration."); if (info.kind === PrivateIdentifierKind.Method) { return info.methodName; } if (info.kind === PrivateIdentifierKind.Accessor) { - if (ts.isGetAccessor(node)) { + if (isGetAccessor(node)) { return info.getterName; } - if (ts.isSetAccessor(node)) { + if (isSetAccessor(node)) { return info.setterName; } } } - function transformAutoAccessor(node: ts.AutoAccessorPropertyDeclaration): ts.VisitResult { + function transformAutoAccessor(node: AutoAccessorPropertyDeclaration): VisitResult { // transforms: // accessor x = 1; // into: @@ -509,62 +545,62 @@ export function transformClassFields(context: ts.TransformationContext) { // get x() { return this.#x; } // set x(value) { this.#x = value; } - ts.Debug.assertEachNode(node.modifiers, ts.isModifier); + Debug.assertEachNode(node.modifiers, isModifier); - const commentRange = ts.getCommentRange(node); - const sourceMapRange = ts.getSourceMapRange(node); + const commentRange = getCommentRange(node); + const sourceMapRange = getSourceMapRange(node); // Since we're creating two declarations where there was previously one, cache // the expression for any computed property names. const name = node.name; let getterName = name; let setterName = name; - if (ts.isComputedPropertyName(name) && !ts.isSimpleInlineableExpression(name.expression)) { + if (isComputedPropertyName(name) && !isSimpleInlineableExpression(name.expression)) { const temp = factory.createTempVariable(hoistVariableDeclaration); - ts.setSourceMapRange(temp, name.expression); - const expression = ts.visitNode(name.expression, visitor, ts.isExpression); + setSourceMapRange(temp, name.expression); + const expression = visitNode(name.expression, visitor, isExpression); const assignment = factory.createAssignment(temp, expression); - ts.setSourceMapRange(assignment, name.expression); + setSourceMapRange(assignment, name.expression); getterName = factory.updateComputedPropertyName(name, factory.inlineExpressions([assignment, temp])); setterName = factory.updateComputedPropertyName(name, temp); } - const backingField = ts.createAccessorPropertyBackingField(factory, node, node.modifiers, node.initializer); - ts.setOriginalNode(backingField, node); - ts.setEmitFlags(backingField, ts.EmitFlags.NoComments); - ts.setSourceMapRange(backingField, sourceMapRange); + const backingField = createAccessorPropertyBackingField(factory, node, node.modifiers, node.initializer); + setOriginalNode(backingField, node); + setEmitFlags(backingField, EmitFlags.NoComments); + setSourceMapRange(backingField, sourceMapRange); - const getter = ts.createAccessorPropertyGetRedirector(factory, node, node.modifiers, getterName); - ts.setOriginalNode(getter, node); - ts.setCommentRange(getter, commentRange); - ts.setSourceMapRange(getter, sourceMapRange); + const getter = createAccessorPropertyGetRedirector(factory, node, node.modifiers, getterName); + setOriginalNode(getter, node); + setCommentRange(getter, commentRange); + setSourceMapRange(getter, sourceMapRange); - const setter = ts.createAccessorPropertySetRedirector(factory, node, node.modifiers, setterName); - ts.setOriginalNode(setter, node); - ts.setEmitFlags(setter, ts.EmitFlags.NoComments); - ts.setSourceMapRange(setter, sourceMapRange); + const setter = createAccessorPropertySetRedirector(factory, node, node.modifiers, setterName); + setOriginalNode(setter, node); + setEmitFlags(setter, EmitFlags.NoComments); + setSourceMapRange(setter, sourceMapRange); - return ts.visitArray([backingField, getter, setter], accessorFieldResultVisitor, ts.isClassElement); + return visitArray([backingField, getter, setter], accessorFieldResultVisitor, isClassElement); } - function transformPrivateFieldInitializer(node: ts.PrivateIdentifierPropertyDeclaration) { + function transformPrivateFieldInitializer(node: PrivateIdentifierPropertyDeclaration) { if (shouldTransformPrivateElementsOrClassStaticBlocks) { // If we are transforming private elements into WeakMap/WeakSet, we should elide the node. const info = accessPrivateIdentifier(node.name); - ts.Debug.assert(info, "Undeclared private name for property declaration."); + Debug.assert(info, "Undeclared private name for property declaration."); // Leave invalid code untransformed; otherwise, elide the node as it is transformed elsewhere. return info.isValid ? undefined : node; } - if (shouldTransformInitializersUsingSet && !ts.isStatic(node)) { + if (shouldTransformInitializersUsingSet && !isStatic(node)) { // If we are transforming initializers using Set semantics we will elide the initializer as it will // be moved to the constructor to preserve evaluation order next to public instance fields. We don't // need to do this transformation for private static fields since public static fields can be // transformed into `static {}` blocks. return factory.updatePropertyDeclaration( node, - ts.visitNodes(node.modifiers, visitor, ts.isModifierLike), + visitNodes(node.modifiers, visitor, isModifierLike), node.name, /*questionOrExclamationToken*/ undefined, /*type*/ undefined, @@ -572,10 +608,10 @@ export function transformClassFields(context: ts.TransformationContext) { ); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function transformPublicFieldInitializer(node: ts.PropertyDeclaration) { + function transformPublicFieldInitializer(node: PropertyDeclaration) { if (shouldTransformInitializers) { // Create a temporary variable to store a computed property name (if necessary). // If it's not inlineable, then we emit an expression after the class which assigns @@ -586,21 +622,21 @@ export function transformClassFields(context: ts.TransformationContext) { getPendingExpressions().push(expr); } - if (ts.isStatic(node) && !shouldTransformPrivateElementsOrClassStaticBlocks) { + if (isStatic(node) && !shouldTransformPrivateElementsOrClassStaticBlocks) { const initializerStatement = transformPropertyOrClassStaticBlock(node, factory.createThis()); if (initializerStatement) { const staticBlock = factory.createClassStaticBlockDeclaration( factory.createBlock([initializerStatement]) ); - ts.setOriginalNode(staticBlock, node); - ts.setCommentRange(staticBlock, node); + setOriginalNode(staticBlock, node); + setCommentRange(staticBlock, node); // Set the comment range for the statement to an empty synthetic range // and drop synthetic comments from the statement to avoid printing them twice. - ts.setCommentRange(initializerStatement, { pos: -1, end: -1 }); - ts.setSyntheticLeadingComments(initializerStatement, undefined); - ts.setSyntheticTrailingComments(initializerStatement, undefined); + setCommentRange(initializerStatement, { pos: -1, end: -1 }); + setSyntheticLeadingComments(initializerStatement, undefined); + setSyntheticTrailingComments(initializerStatement, undefined); return staticBlock; } } @@ -608,32 +644,32 @@ export function transformClassFields(context: ts.TransformationContext) { return undefined; } - return ts.visitEachChild(node, classElementVisitor, context); + return visitEachChild(node, classElementVisitor, context); } - function transformFieldInitializer(node: ts.PropertyDeclaration) { - ts.Debug.assert(!ts.hasDecorators(node), "Decorators should already have been transformed and elided."); - return ts.isPrivateIdentifierClassElementDeclaration(node) ? + function transformFieldInitializer(node: PropertyDeclaration) { + Debug.assert(!hasDecorators(node), "Decorators should already have been transformed and elided."); + return isPrivateIdentifierClassElementDeclaration(node) ? transformPrivateFieldInitializer(node) : transformPublicFieldInitializer(node); } - function visitPropertyDeclaration(node: ts.PropertyDeclaration) { + function visitPropertyDeclaration(node: PropertyDeclaration) { // If this is an auto-accessor, we defer to `transformAutoAccessor`. That function // will in turn call `transformFieldInitializer` as needed. - if (shouldTransformAutoAccessors && ts.isAutoAccessorPropertyDeclaration(node)) { + if (shouldTransformAutoAccessors && isAutoAccessorPropertyDeclaration(node)) { return transformAutoAccessor(node); } return transformFieldInitializer(node); } - function createPrivateIdentifierAccess(info: PrivateIdentifierInfo, receiver: ts.Expression): ts.Expression { - return createPrivateIdentifierAccessHelper(info, ts.visitNode(receiver, visitor, ts.isExpression)); + function createPrivateIdentifierAccess(info: PrivateIdentifierInfo, receiver: Expression): Expression { + return createPrivateIdentifierAccessHelper(info, visitNode(receiver, visitor, isExpression)); } - function createPrivateIdentifierAccessHelper(info: PrivateIdentifierInfo, receiver: ts.Expression): ts.Expression { - ts.setCommentRange(receiver, ts.moveRangePos(receiver, -1)); + function createPrivateIdentifierAccessHelper(info: PrivateIdentifierInfo, receiver: Expression): Expression { + setCommentRange(receiver, moveRangePos(receiver, -1)); switch(info.kind) { case PrivateIdentifierKind.Accessor: @@ -658,16 +694,16 @@ export function transformClassFields(context: ts.TransformationContext) { info.variableName ); default: - ts.Debug.assertNever(info, "Unknown private element type"); + Debug.assertNever(info, "Unknown private element type"); } } - function visitPropertyAccessExpression(node: ts.PropertyAccessExpression) { - if (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifier(node.name)) { + function visitPropertyAccessExpression(node: PropertyAccessExpression) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifier(node.name)) { const privateIdentifierInfo = accessPrivateIdentifier(node.name); if (privateIdentifierInfo) { - return ts.setTextRange( - ts.setOriginalNode( + return setTextRange( + setOriginalNode( createPrivateIdentifierAccess(privateIdentifierInfo, node.expression), node ), @@ -676,8 +712,8 @@ export function transformClassFields(context: ts.TransformationContext) { } } if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node) && - ts.isIdentifier(node.name) && + isSuperProperty(node) && + isIdentifier(node.name) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; @@ -691,17 +727,17 @@ export function transformClassFields(context: ts.TransformationContext) { factory.createStringLiteralFromNode(node.name), classConstructor ); - ts.setOriginalNode(superProperty, node.expression); - ts.setTextRange(superProperty, node.expression); + setOriginalNode(superProperty, node.expression); + setTextRange(superProperty, node.expression); return superProperty; } } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitElementAccessExpression(node: ts.ElementAccessExpression) { + function visitElementAccessExpression(node: ElementAccessExpression) { if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node) && + isSuperProperty(node) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; @@ -713,48 +749,48 @@ export function transformClassFields(context: ts.TransformationContext) { // converts `super[x]` into `Reflect.get(_baseTemp, x, _classTemp)` const superProperty = factory.createReflectGetCall( superClassReference, - ts.visitNode(node.argumentExpression, visitor, ts.isExpression), + visitNode(node.argumentExpression, visitor, isExpression), classConstructor ); - ts.setOriginalNode(superProperty, node.expression); - ts.setTextRange(superProperty, node.expression); + setOriginalNode(superProperty, node.expression); + setTextRange(superProperty, node.expression); return superProperty; } } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitPreOrPostfixUnaryExpression(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, valueIsDiscarded: boolean) { - if (node.operator === ts.SyntaxKind.PlusPlusToken || - node.operator === ts.SyntaxKind.MinusMinusToken) { - const operand = ts.skipParentheses(node.operand); + function visitPreOrPostfixUnaryExpression(node: PrefixUnaryExpression | PostfixUnaryExpression, valueIsDiscarded: boolean) { + if (node.operator === SyntaxKind.PlusPlusToken || + node.operator === SyntaxKind.MinusMinusToken) { + const operand = skipParentheses(node.operand); if (shouldTransformPrivateElementsOrClassStaticBlocks && - ts.isPrivateIdentifierPropertyAccessExpression(operand)) { + isPrivateIdentifierPropertyAccessExpression(operand)) { let info: PrivateIdentifierInfo | undefined; if (info = accessPrivateIdentifier(operand.name)) { - const receiver = ts.visitNode(operand.expression, visitor, ts.isExpression); + const receiver = visitNode(operand.expression, visitor, isExpression); const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver); - let expression: ts.Expression = createPrivateIdentifierAccess(info, readExpression); - const temp = ts.isPrefixUnaryExpression(node) || valueIsDiscarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); - expression = ts.expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); + let expression: Expression = createPrivateIdentifierAccess(info, readExpression); + const temp = isPrefixUnaryExpression(node) || valueIsDiscarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); + expression = expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); expression = createPrivateIdentifierAssignment( info, initializeExpression || readExpression, expression, - ts.SyntaxKind.EqualsToken + SyntaxKind.EqualsToken ); - ts.setOriginalNode(expression, node); - ts.setTextRange(expression, node); + setOriginalNode(expression, node); + setTextRange(expression, node); if (temp) { expression = factory.createComma(expression, temp); - ts.setTextRange(expression, node); + setTextRange(expression, node); } return expression; } } else if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(operand) && + isSuperProperty(operand) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { // converts `++super.a` into `(Reflect.set(_baseTemp, "a", (_a = Reflect.get(_baseTemp, "a", _classTemp), _b = ++_a), _classTemp), _b)` @@ -768,68 +804,68 @@ export function transformClassFields(context: ts.TransformationContext) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; if (facts & ClassFacts.ClassWasDecorated) { const expression = visitInvalidSuperProperty(operand); - return ts.isPrefixUnaryExpression(node) ? + return isPrefixUnaryExpression(node) ? factory.updatePrefixUnaryExpression(node, expression) : factory.updatePostfixUnaryExpression(node, expression); } if (classConstructor && superClassReference) { - let setterName: ts.Expression | undefined; - let getterName: ts.Expression | undefined; - if (ts.isPropertyAccessExpression(operand)) { - if (ts.isIdentifier(operand.name)) { + let setterName: Expression | undefined; + let getterName: Expression | undefined; + if (isPropertyAccessExpression(operand)) { + if (isIdentifier(operand.name)) { getterName = setterName = factory.createStringLiteralFromNode(operand.name); } } else { - if (ts.isSimpleInlineableExpression(operand.argumentExpression)) { + if (isSimpleInlineableExpression(operand.argumentExpression)) { getterName = setterName = operand.argumentExpression; } else { getterName = factory.createTempVariable(hoistVariableDeclaration); - setterName = factory.createAssignment(getterName, ts.visitNode(operand.argumentExpression, visitor, ts.isExpression)); + setterName = factory.createAssignment(getterName, visitNode(operand.argumentExpression, visitor, isExpression)); } } if (setterName && getterName) { - let expression: ts.Expression = factory.createReflectGetCall(superClassReference, getterName, classConstructor); - ts.setTextRange(expression, operand); + let expression: Expression = factory.createReflectGetCall(superClassReference, getterName, classConstructor); + setTextRange(expression, operand); const temp = valueIsDiscarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); - expression = ts.expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); + expression = expandPreOrPostfixIncrementOrDecrementExpression(factory, node, expression, hoistVariableDeclaration, temp); expression = factory.createReflectSetCall(superClassReference, setterName, expression, classConstructor); - ts.setOriginalNode(expression, node); - ts.setTextRange(expression, node); + setOriginalNode(expression, node); + setTextRange(expression, node); if (temp) { expression = factory.createComma(expression, temp); - ts.setTextRange(expression, node); + setTextRange(expression, node); } return expression; } } } } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitForStatement(node: ts.ForStatement) { + function visitForStatement(node: ForStatement) { return factory.updateForStatement( node, - ts.visitNode(node.initializer, discardedValueVisitor, ts.isForInitializer), - ts.visitNode(node.condition, visitor, ts.isExpression), - ts.visitNode(node.incrementor, discardedValueVisitor, ts.isExpression), - ts.visitIterationBody(node.statement, visitor, context) + visitNode(node.initializer, discardedValueVisitor, isForInitializer), + visitNode(node.condition, visitor, isExpression), + visitNode(node.incrementor, discardedValueVisitor, isExpression), + visitIterationBody(node.statement, visitor, context) ); } - function visitExpressionStatement(node: ts.ExpressionStatement) { + function visitExpressionStatement(node: ExpressionStatement) { return factory.updateExpressionStatement( node, - ts.visitNode(node.expression, discardedValueVisitor, ts.isExpression) + visitNode(node.expression, discardedValueVisitor, isExpression) ); } - function createCopiableReceiverExpr(receiver: ts.Expression): { readExpression: ts.Expression; initializeExpression: ts.Expression | undefined } { - const clone = ts.nodeIsSynthesized(receiver) ? receiver : factory.cloneNode(receiver); - if (ts.isSimpleInlineableExpression(receiver)) { + function createCopiableReceiverExpr(receiver: Expression): { readExpression: Expression; initializeExpression: Expression | undefined } { + const clone = nodeIsSynthesized(receiver) ? receiver : factory.cloneNode(receiver); + if (isSimpleInlineableExpression(receiver)) { return { readExpression: clone, initializeExpression: undefined }; } const readExpression = factory.createTempVariable(hoistVariableDeclaration); @@ -837,32 +873,32 @@ export function transformClassFields(context: ts.TransformationContext) { return { readExpression, initializeExpression }; } - function visitCallExpression(node: ts.CallExpression) { + function visitCallExpression(node: CallExpression) { if (shouldTransformPrivateElementsOrClassStaticBlocks && - ts.isPrivateIdentifierPropertyAccessExpression(node.expression)) { + isPrivateIdentifierPropertyAccessExpression(node.expression)) { // obj.#x() // Transform call expressions of private names to properly bind the `this` parameter. const { thisArg, target } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion); - if (ts.isCallChain(node)) { + if (isCallChain(node)) { return factory.updateCallChain( node, - factory.createPropertyAccessChain(ts.visitNode(target, visitor), node.questionDotToken, "call"), + factory.createPropertyAccessChain(visitNode(target, visitor), node.questionDotToken, "call"), /*questionDotToken*/ undefined, /*typeArguments*/ undefined, - [ts.visitNode(thisArg, visitor, ts.isExpression), ...ts.visitNodes(node.arguments, visitor, ts.isExpression)] + [visitNode(thisArg, visitor, isExpression), ...visitNodes(node.arguments, visitor, isExpression)] ); } return factory.updateCallExpression( node, - factory.createPropertyAccessExpression(ts.visitNode(target, visitor), "call"), + factory.createPropertyAccessExpression(visitNode(target, visitor), "call"), /*typeArguments*/ undefined, - [ts.visitNode(thisArg, visitor, ts.isExpression), ...ts.visitNodes(node.arguments, visitor, ts.isExpression)] + [visitNode(thisArg, visitor, isExpression), ...visitNodes(node.arguments, visitor, isExpression)] ); } if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node.expression) && + isSuperProperty(node.expression) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment?.classConstructor) { // super.x() @@ -870,81 +906,81 @@ export function transformClassFields(context: ts.TransformationContext) { // converts `super.f(...)` into `Reflect.get(_baseTemp, "f", _classTemp).call(_classTemp, ...)` const invocation = factory.createFunctionCallCall( - ts.visitNode(node.expression, visitor, ts.isExpression), + visitNode(node.expression, visitor, isExpression), currentClassLexicalEnvironment.classConstructor, - ts.visitNodes(node.arguments, visitor, ts.isExpression) + visitNodes(node.arguments, visitor, isExpression) ); - ts.setOriginalNode(invocation, node); - ts.setTextRange(invocation, node); + setOriginalNode(invocation, node); + setTextRange(invocation, node); return invocation; } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitTaggedTemplateExpression(node: ts.TaggedTemplateExpression) { + function visitTaggedTemplateExpression(node: TaggedTemplateExpression) { if (shouldTransformPrivateElementsOrClassStaticBlocks && - ts.isPrivateIdentifierPropertyAccessExpression(node.tag)) { + isPrivateIdentifierPropertyAccessExpression(node.tag)) { // Bind the `this` correctly for tagged template literals when the tag is a private identifier property access. const { thisArg, target } = factory.createCallBinding(node.tag, hoistVariableDeclaration, languageVersion); return factory.updateTaggedTemplateExpression( node, factory.createCallExpression( - factory.createPropertyAccessExpression(ts.visitNode(target, visitor), "bind"), + factory.createPropertyAccessExpression(visitNode(target, visitor), "bind"), /*typeArguments*/ undefined, - [ts.visitNode(thisArg, visitor, ts.isExpression)] + [visitNode(thisArg, visitor, isExpression)] ), /*typeArguments*/ undefined, - ts.visitNode(node.template, visitor, ts.isTemplateLiteral) + visitNode(node.template, visitor, isTemplateLiteral) ); } if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node.tag) && + isSuperProperty(node.tag) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment?.classConstructor) { // converts `` super.f`x` `` into `` Reflect.get(_baseTemp, "f", _classTemp).bind(_classTemp)`x` `` const invocation = factory.createFunctionBindCall( - ts.visitNode(node.tag, visitor, ts.isExpression), + visitNode(node.tag, visitor, isExpression), currentClassLexicalEnvironment.classConstructor, [] ); - ts.setOriginalNode(invocation, node); - ts.setTextRange(invocation, node); + setOriginalNode(invocation, node); + setTextRange(invocation, node); return factory.updateTaggedTemplateExpression( node, invocation, /*typeArguments*/ undefined, - ts.visitNode(node.template, visitor, ts.isTemplateLiteral) + visitNode(node.template, visitor, isTemplateLiteral) ); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function transformClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function transformClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { if (shouldTransformPrivateElementsOrClassStaticBlocks) { if (currentClassLexicalEnvironment) { - classLexicalEnvironmentMap.set(ts.getOriginalNodeId(node), currentClassLexicalEnvironment); + classLexicalEnvironmentMap.set(getOriginalNodeId(node), currentClassLexicalEnvironment); } startLexicalEnvironment(); let statements = setCurrentStaticPropertyDeclarationOrStaticBlockAnd( node, - statements => ts.visitNodes(statements, visitor, ts.isStatement), + statements => visitNodes(statements, visitor, isStatement), node.body.statements ); statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); const iife = factory.createImmediatelyInvokedArrowFunction(statements); - ts.setOriginalNode(iife, node); - ts.setTextRange(iife, node); - ts.addEmitFlags(iife, ts.EmitFlags.AdviseOnEmitNode); + setOriginalNode(iife, node); + setTextRange(iife, node); + addEmitFlags(iife, EmitFlags.AdviseOnEmitNode); return iife; } } - function visitBinaryExpression(node: ts.BinaryExpression, valueIsDiscarded: boolean) { - if (ts.isDestructuringAssignment(node)) { + function visitBinaryExpression(node: BinaryExpression, valueIsDiscarded: boolean) { + if (isDestructuringAssignment(node)) { // ({ x: obj.#x } = ...) // ({ x: super.x } = ...) // ({ x: super[x] } = ...) @@ -952,24 +988,24 @@ export function transformClassFields(context: ts.TransformationContext) { pendingExpressions = undefined; node = factory.updateBinaryExpression( node, - ts.visitNode(node.left, assignmentTargetVisitor), + visitNode(node.left, assignmentTargetVisitor), node.operatorToken, - ts.visitNode(node.right, visitor) + visitNode(node.right, visitor) ); - const expr = ts.some(pendingExpressions) ? - factory.inlineExpressions(ts.compact([...pendingExpressions, node])) : + const expr = some(pendingExpressions) ? + factory.inlineExpressions(compact([...pendingExpressions, node])) : node; pendingExpressions = savedPendingExpressions; return expr; } - if (ts.isAssignmentExpression(node)) { + if (isAssignmentExpression(node)) { if (shouldTransformPrivateElementsOrClassStaticBlocks && - ts.isPrivateIdentifierPropertyAccessExpression(node.left)) { + isPrivateIdentifierPropertyAccessExpression(node.left)) { // obj.#x = ... const info = accessPrivateIdentifier(node.left.name); if (info) { - return ts.setTextRange( - ts.setOriginalNode( + return setTextRange( + setOriginalNode( createPrivateIdentifierAssignment(info, node.left.expression, node.right, node.operatorToken.kind), node ), @@ -978,7 +1014,7 @@ export function transformClassFields(context: ts.TransformationContext) { } } else if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(node.left) && + isSuperProperty(node.left) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { // super.x = ... @@ -991,12 +1027,12 @@ export function transformClassFields(context: ts.TransformationContext) { node, visitInvalidSuperProperty(node.left), node.operatorToken, - ts.visitNode(node.right, visitor, ts.isExpression)); + visitNode(node.right, visitor, isExpression)); } if (classConstructor && superClassReference) { let setterName = - ts.isElementAccessExpression(node.left) ? ts.visitNode(node.left.argumentExpression, visitor, ts.isExpression) : - ts.isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) : + isElementAccessExpression(node.left) ? visitNode(node.left.argumentExpression, visitor, isExpression) : + isIdentifier(node.left.name) ? factory.createStringLiteralFromNode(node.left.name) : undefined; if (setterName) { // converts `super.x = 1` into `(Reflect.set(_baseTemp, "x", _a = 1, _classTemp), _a)` @@ -1004,10 +1040,10 @@ export function transformClassFields(context: ts.TransformationContext) { // converts `super.x += 1` into `(Reflect.set(_baseTemp, "x", _a = Reflect.get(_baseTemp, "x", _classtemp) + 1, _classTemp), _a)` // converts `super[f()] += 1` into `(Reflect.set(_baseTemp, _a = f(), _b = Reflect.get(_baseTemp, _a, _classtemp) + 1, _classTemp), _b)` - let expression = ts.visitNode(node.right, visitor, ts.isExpression); - if (ts.isCompoundAssignment(node.operatorToken.kind)) { + let expression = visitNode(node.right, visitor, isExpression); + if (isCompoundAssignment(node.operatorToken.kind)) { let getterName = setterName; - if (!ts.isSimpleInlineableExpression(setterName)) { + if (!isSimpleInlineableExpression(setterName)) { getterName = factory.createTempVariable(hoistVariableDeclaration); setterName = factory.createAssignment(getterName, setterName); } @@ -1016,21 +1052,21 @@ export function transformClassFields(context: ts.TransformationContext) { getterName, classConstructor ); - ts.setOriginalNode(superPropertyGet, node.left); - ts.setTextRange(superPropertyGet, node.left); + setOriginalNode(superPropertyGet, node.left); + setTextRange(superPropertyGet, node.left); expression = factory.createBinaryExpression( superPropertyGet, - ts.getNonAssignmentOperatorForCompoundAssignment(node.operatorToken.kind), + getNonAssignmentOperatorForCompoundAssignment(node.operatorToken.kind), expression ); - ts.setTextRange(expression, node); + setTextRange(expression, node); } const temp = valueIsDiscarded ? undefined : factory.createTempVariable(hoistVariableDeclaration); if (temp) { expression = factory.createAssignment(temp, expression); - ts.setTextRange(temp, node); + setTextRange(temp, node); } expression = factory.createReflectSetCall( @@ -1039,12 +1075,12 @@ export function transformClassFields(context: ts.TransformationContext) { expression, classConstructor ); - ts.setOriginalNode(expression, node); - ts.setTextRange(expression, node); + setOriginalNode(expression, node); + setTextRange(expression, node); if (temp) { expression = factory.createComma(expression, temp); - ts.setTextRange(expression, node); + setTextRange(expression, node); } return expression; @@ -1057,24 +1093,24 @@ export function transformClassFields(context: ts.TransformationContext) { // #x in obj return transformPrivateIdentifierInInExpression(node); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function createPrivateIdentifierAssignment(info: PrivateIdentifierInfo, receiver: ts.Expression, right: ts.Expression, operator: ts.AssignmentOperator): ts.Expression { - receiver = ts.visitNode(receiver, visitor, ts.isExpression); - right = ts.visitNode(right, visitor, ts.isExpression); + function createPrivateIdentifierAssignment(info: PrivateIdentifierInfo, receiver: Expression, right: Expression, operator: AssignmentOperator): Expression { + receiver = visitNode(receiver, visitor, isExpression); + right = visitNode(right, visitor, isExpression); - if (ts.isCompoundAssignment(operator)) { + if (isCompoundAssignment(operator)) { const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver); receiver = initializeExpression || readExpression; right = factory.createBinaryExpression( createPrivateIdentifierAccessHelper(info, readExpression), - ts.getNonAssignmentOperatorForCompoundAssignment(operator), + getNonAssignmentOperatorForCompoundAssignment(operator), right ); } - ts.setCommentRange(receiver, ts.moveRangePos(receiver, -1)); + setCommentRange(receiver, moveRangePos(receiver, -1)); switch(info.kind) { case PrivateIdentifierKind.Accessor: @@ -1102,33 +1138,33 @@ export function transformClassFields(context: ts.TransformationContext) { info.variableName ); default: - ts.Debug.assertNever(info, "Unknown private element type"); + Debug.assertNever(info, "Unknown private element type"); } } - function getPrivateInstanceMethodsAndAccessors(node: ts.ClassLikeDeclaration) { - return ts.filter(node.members, ts.isNonStaticMethodOrAccessorWithPrivateName); + function getPrivateInstanceMethodsAndAccessors(node: ClassLikeDeclaration) { + return filter(node.members, isNonStaticMethodOrAccessorWithPrivateName); } - function getClassFacts(node: ts.ClassLikeDeclaration) { + function getClassFacts(node: ClassLikeDeclaration) { let facts = ClassFacts.None; - const original = ts.getOriginalNode(node); - if (ts.isClassDeclaration(original) && ts.classOrConstructorParameterIsDecorated(original)) { + const original = getOriginalNode(node); + if (isClassDeclaration(original) && classOrConstructorParameterIsDecorated(original)) { facts |= ClassFacts.ClassWasDecorated; } for (const member of node.members) { - if (!ts.isStatic(member)) continue; - if (member.name && (ts.isPrivateIdentifier(member.name) || ts.isAutoAccessorPropertyDeclaration(member)) && shouldTransformPrivateElementsOrClassStaticBlocks) { + if (!isStatic(member)) continue; + if (member.name && (isPrivateIdentifier(member.name) || isAutoAccessorPropertyDeclaration(member)) && shouldTransformPrivateElementsOrClassStaticBlocks) { facts |= ClassFacts.NeedsClassConstructorReference; } - if (ts.isPropertyDeclaration(member) || ts.isClassStaticBlockDeclaration(member)) { - if (shouldTransformThisInStaticInitializers && member.transformFlags & ts.TransformFlags.ContainsLexicalThis) { + if (isPropertyDeclaration(member) || isClassStaticBlockDeclaration(member)) { + if (shouldTransformThisInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalThis) { facts |= ClassFacts.NeedsSubstitutionForThisInClassStaticField; if (!(facts & ClassFacts.ClassWasDecorated)) { facts |= ClassFacts.NeedsClassConstructorReference; } } - if (shouldTransformSuperInStaticInitializers && member.transformFlags & ts.TransformFlags.ContainsLexicalSuper) { + if (shouldTransformSuperInStaticInitializers && member.transformFlags & TransformFlags.ContainsLexicalSuper) { if (!(facts & ClassFacts.ClassWasDecorated)) { facts |= ClassFacts.NeedsClassConstructorReference | ClassFacts.NeedsClassSuperReference; } @@ -1138,7 +1174,7 @@ export function transformClassFields(context: ts.TransformationContext) { return facts; } - function visitExpressionWithTypeArgumentsInHeritageClause(node: ts.ExpressionWithTypeArguments) { + function visitExpressionWithTypeArgumentsInHeritageClause(node: ExpressionWithTypeArguments) { const facts = currentClassLexicalEnvironment?.facts || ClassFacts.None; if (facts & ClassFacts.NeedsClassSuperReference) { const temp = factory.createTempVariable(hoistVariableDeclaration, /*reserveInNestedScopes*/ true); @@ -1147,15 +1183,15 @@ export function transformClassFields(context: ts.TransformationContext) { node, factory.createAssignment( temp, - ts.visitNode(node.expression, visitor, ts.isExpression) + visitNode(node.expression, visitor, isExpression) ), /*typeArguments*/ undefined ); } - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } - function visitInNewClassLexicalEnvironment(node: T, visitor: (node: T, facts: ClassFacts) => U) { + function visitInNewClassLexicalEnvironment(node: T, visitor: (node: T, facts: ClassFacts) => U) { const savedCurrentClassContainer = currentClassContainer; const savedPendingExpressions = pendingExpressions; currentClassContainer = node; @@ -1163,13 +1199,13 @@ export function transformClassFields(context: ts.TransformationContext) { startClassLexicalEnvironment(); if (shouldTransformPrivateElementsOrClassStaticBlocks) { - const name = ts.getNameOfDeclaration(node); - if (name && ts.isIdentifier(name)) { + const name = getNameOfDeclaration(node); + if (name && isIdentifier(name)) { getPrivateIdentifierEnvironment().className = name; } const privateInstanceMethodsAndAccessors = getPrivateInstanceMethodsAndAccessors(node); - if (ts.some(privateInstanceMethodsAndAccessors)) { + if (some(privateInstanceMethodsAndAccessors)) { getPrivateIdentifierEnvironment().weakSetName = createHoistedVariableForClass( "instances", privateInstanceMethodsAndAccessors[0].name @@ -1194,22 +1230,22 @@ export function transformClassFields(context: ts.TransformationContext) { } - function visitClassDeclaration(node: ts.ClassDeclaration) { + function visitClassDeclaration(node: ClassDeclaration) { return visitInNewClassLexicalEnvironment(node, visitClassDeclarationInNewClassLexicalEnvironment); } - function visitClassDeclarationInNewClassLexicalEnvironment(node: ts.ClassDeclaration, facts: ClassFacts) { + function visitClassDeclarationInNewClassLexicalEnvironment(node: ClassDeclaration, facts: ClassFacts) { // If a class has private static fields, or a static field has a `this` or `super` reference, // then we need to allocate a temp variable to hold on to that reference. - let pendingClassReferenceAssignment: ts.BinaryExpression | undefined; + let pendingClassReferenceAssignment: BinaryExpression | undefined; if (facts & ClassFacts.NeedsClassConstructorReference) { const temp = factory.createTempVariable(hoistVariableDeclaration, /*reservedInNestedScopes*/ true); getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp); pendingClassReferenceAssignment = factory.createAssignment(temp, factory.getInternalName(node)); } - const modifiers = ts.visitNodes(node.modifiers, visitor, ts.isModifierLike); - const heritageClauses = ts.visitNodes(node.heritageClauses, heritageClauseVisitor, ts.isHeritageClause); + const modifiers = visitNodes(node.modifiers, visitor, isModifierLike); + const heritageClauses = visitNodes(node.heritageClauses, heritageClauseVisitor, isHeritageClause); const { members, prologue } = transformClassMembers(node); const classDecl = factory.updateClassDeclaration( node, @@ -1220,7 +1256,7 @@ export function transformClassFields(context: ts.TransformationContext) { members ); - const statements: ts.Statement[] = []; + const statements: Statement[] = []; if (prologue) { statements.push(factory.createExpressionStatement(prologue)); } @@ -1232,7 +1268,7 @@ export function transformClassFields(context: ts.TransformationContext) { } // Write any pending expressions from elided or moved computed property names - if (ts.some(pendingExpressions)) { + if (some(pendingExpressions)) { statements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); } @@ -1243,8 +1279,8 @@ export function transformClassFields(context: ts.TransformationContext) { // HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using // a lexical declaration such as a LexicalDeclaration or a ClassDeclaration. - const staticProperties = ts.getStaticPropertiesAndClassStaticBlock(node); - if (ts.some(staticProperties)) { + const staticProperties = getStaticPropertiesAndClassStaticBlock(node); + if (some(staticProperties)) { addPropertyOrClassStaticBlockStatements(statements, staticProperties, factory.getInternalName(node)); } } @@ -1252,11 +1288,11 @@ export function transformClassFields(context: ts.TransformationContext) { return statements; } - function visitClassExpression(node: ts.ClassExpression): ts.Expression { + function visitClassExpression(node: ClassExpression): Expression { return visitInNewClassLexicalEnvironment(node, visitClassExpressionInNewClassLexicalEnvironment); } - function visitClassExpressionInNewClassLexicalEnvironment(node: ts.ClassExpression, facts: ClassFacts): ts.Expression { + function visitClassExpressionInNewClassLexicalEnvironment(node: ClassExpression, facts: ClassFacts): Expression { // If this class expression is a transformation of a decorated class declaration, // then we want to output the pendingExpressions as statements, not as inlined // expressions with the class statement. @@ -1266,14 +1302,14 @@ export function transformClassFields(context: ts.TransformationContext) { // these statements after the class expression variable statement. const isDecoratedClassDeclaration = !!(facts & ClassFacts.ClassWasDecorated); - const staticPropertiesOrClassStaticBlocks = ts.getStaticPropertiesAndClassStaticBlock(node); + const staticPropertiesOrClassStaticBlocks = getStaticPropertiesAndClassStaticBlock(node); - const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & ts.NodeCheckFlags.ClassWithConstructorReference; - let temp: ts.Identifier | undefined; + const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference; + let temp: Identifier | undefined; function createClassTempVar() { const classCheckFlags = resolver.getNodeCheckFlags(node); - const isClassWithConstructorReference = classCheckFlags & ts.NodeCheckFlags.ClassWithConstructorReference; - const requiresBlockScopedVar = classCheckFlags & ts.NodeCheckFlags.BlockScopedBindingInLoop; + const isClassWithConstructorReference = classCheckFlags & NodeCheckFlags.ClassWithConstructorReference; + const requiresBlockScopedVar = classCheckFlags & NodeCheckFlags.BlockScopedBindingInLoop; return factory.createTempVariable(requiresBlockScopedVar ? addBlockScopedVariable : hoistVariableDeclaration, !!isClassWithConstructorReference); } @@ -1282,8 +1318,8 @@ export function transformClassFields(context: ts.TransformationContext) { getClassLexicalEnvironment().classConstructor = factory.cloneNode(temp); } - const modifiers = ts.visitNodes(node.modifiers, visitor, ts.isModifierLike); - const heritageClauses = ts.visitNodes(node.heritageClauses, heritageClauseVisitor, ts.isHeritageClause); + const modifiers = visitNodes(node.modifiers, visitor, isModifierLike); + const heritageClauses = visitNodes(node.heritageClauses, heritageClauseVisitor, isHeritageClause); const { members, prologue } = transformClassMembers(node); const classExpression = factory.updateClassExpression( node, @@ -1294,7 +1330,7 @@ export function transformClassFields(context: ts.TransformationContext) { members ); - const expressions: ts.Expression[] = []; + const expressions: Expression[] = []; if (prologue) { expressions.push(prologue); } @@ -1303,33 +1339,33 @@ export function transformClassFields(context: ts.TransformationContext) { // and not also transforming static blocks. const hasTransformableStatics = shouldTransformPrivateElementsOrClassStaticBlocks && - ts.some(staticPropertiesOrClassStaticBlocks, node => - ts.isClassStaticBlockDeclaration(node) || - ts.isPrivateIdentifierClassElementDeclaration(node) || - shouldTransformInitializers && ts.isInitializedProperty(node)); + some(staticPropertiesOrClassStaticBlocks, node => + isClassStaticBlockDeclaration(node) || + isPrivateIdentifierClassElementDeclaration(node) || + shouldTransformInitializers && isInitializedProperty(node)); - if (hasTransformableStatics || ts.some(pendingExpressions)) { + if (hasTransformableStatics || some(pendingExpressions)) { if (isDecoratedClassDeclaration) { - ts.Debug.assertIsDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); + Debug.assertIsDefined(pendingStatements, "Decorated classes transformed by TypeScript are expected to be within a variable declaration."); // Write any pending expressions from elided or moved computed property names - if (pendingStatements && pendingExpressions && ts.some(pendingExpressions)) { + if (pendingStatements && pendingExpressions && some(pendingExpressions)) { pendingStatements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))); } - if (pendingStatements && ts.some(staticPropertiesOrClassStaticBlocks)) { + if (pendingStatements && some(staticPropertiesOrClassStaticBlocks)) { addPropertyOrClassStaticBlockStatements(pendingStatements, staticPropertiesOrClassStaticBlocks, factory.getInternalName(node)); } if (temp) { expressions.push( - ts.startOnNewLine(factory.createAssignment(temp, classExpression)), - ts.startOnNewLine(temp)); + startOnNewLine(factory.createAssignment(temp, classExpression)), + startOnNewLine(temp)); } else { expressions.push(classExpression); if (prologue) { - ts.startOnNewLine(classExpression); + startOnNewLine(classExpression); } } } @@ -1338,53 +1374,53 @@ export function transformClassFields(context: ts.TransformationContext) { if (isClassWithConstructorReference) { // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); - const alias = factory.cloneNode(temp) as ts.GeneratedIdentifier; - alias.autoGenerateFlags &= ~ts.GeneratedIdentifierFlags.ReservedInNestedScopes; - classAliases[ts.getOriginalNodeId(node)] = alias; + const alias = factory.cloneNode(temp) as GeneratedIdentifier; + alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + classAliases[getOriginalNodeId(node)] = alias; } // To preserve the behavior of the old emitter, we explicitly indent // the body of a class with static initializers. - ts.setEmitFlags(classExpression, ts.EmitFlags.Indented | ts.getEmitFlags(classExpression)); - expressions.push(ts.startOnNewLine(factory.createAssignment(temp, classExpression))); + setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression)); + expressions.push(startOnNewLine(factory.createAssignment(temp, classExpression))); // Add any pending expressions leftover from elided or relocated computed property names - ts.addRange(expressions, ts.map(pendingExpressions, ts.startOnNewLine)); - ts.addRange(expressions, generateInitializedPropertyExpressionsOrClassStaticBlock(staticPropertiesOrClassStaticBlocks, temp)); - expressions.push(ts.startOnNewLine(temp)); + addRange(expressions, map(pendingExpressions, startOnNewLine)); + addRange(expressions, generateInitializedPropertyExpressionsOrClassStaticBlock(staticPropertiesOrClassStaticBlocks, temp)); + expressions.push(startOnNewLine(temp)); } } else { expressions.push(classExpression); if (prologue) { - ts.startOnNewLine(classExpression); + startOnNewLine(classExpression); } } return factory.inlineExpressions(expressions); } - function visitClassStaticBlockDeclaration(node: ts.ClassStaticBlockDeclaration) { + function visitClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration) { if (!shouldTransformPrivateElementsOrClassStaticBlocks) { - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } // ClassStaticBlockDeclaration for classes are transformed in `visitClassDeclaration` or `visitClassExpression`. return undefined; } - function transformClassMembers(node: ts.ClassDeclaration | ts.ClassExpression) { + function transformClassMembers(node: ClassDeclaration | ClassExpression) { // Declare private names if (shouldTransformPrivateElementsOrClassStaticBlocks) { for (const member of node.members) { - if (ts.isPrivateIdentifierClassElementDeclaration(member)) { + if (isPrivateIdentifierClassElementDeclaration(member)) { addPrivateIdentifierToEnvironment(member, member.name, addPrivateIdentifierClassElementToEnvironment); } } - if (ts.some(getPrivateInstanceMethodsAndAccessors(node))) { + if (some(getPrivateInstanceMethodsAndAccessors(node))) { createBrandCheckWeakSetForPrivateMethods(); } if (shouldTransformAutoAccessors) { for (const member of node.members) { - if (ts.isAutoAccessorPropertyDeclaration(member)) { + if (isAutoAccessorPropertyDeclaration(member)) { const storageName = factory.getGeneratedPrivateNameForNode(member.name, /*prefix*/ undefined, "_accessor_storage"); addPrivateIdentifierToEnvironment(member, storageName, addPrivateIdentifierPropertyDeclarationToEnvironment); } @@ -1392,24 +1428,24 @@ export function transformClassFields(context: ts.TransformationContext) { } } - let members = ts.visitNodes(node.members, classElementVisitor, ts.isClassElement); + let members = visitNodes(node.members, classElementVisitor, isClassElement); // Create a synthetic constructor if necessary - let syntheticConstructor: ts.ConstructorDeclaration | undefined; - if (!ts.some(members, ts.isConstructorDeclaration)) { + let syntheticConstructor: ConstructorDeclaration | undefined; + if (!some(members, isConstructorDeclaration)) { syntheticConstructor = transformConstructor(/*constructor*/ undefined, node); } - let prologue: ts.Expression | undefined; + let prologue: Expression | undefined; // If there are pending expressions create a class static block in which to evaluate them, but only if // class static blocks are not also being transformed. This block will be injected at the top of the class // to ensure that expressions from computed property names are evaluated before any other static // initializers. - let syntheticStaticBlock: ts.ClassStaticBlockDeclaration | undefined; - if (!shouldTransformPrivateElementsOrClassStaticBlocks && ts.some(pendingExpressions)) { + let syntheticStaticBlock: ClassStaticBlockDeclaration | undefined; + if (!shouldTransformPrivateElementsOrClassStaticBlocks && some(pendingExpressions)) { let statement = factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)); - if (statement.transformFlags & ts.TransformFlags.ContainsLexicalThisOrSuper) { + if (statement.transformFlags & TransformFlags.ContainsLexicalThisOrSuper) { // If there are `this` or `super` references from computed property names, shift the expression // into an arrow function to be evaluated in the outer scope so that `this` and `super` are // properly captured. @@ -1433,11 +1469,11 @@ export function transformClassFields(context: ts.TransformationContext) { // If we created a synthetic constructor or class static block, add them to the visited members // and return a new array. if (syntheticConstructor || syntheticStaticBlock) { - let membersArray: ts.ClassElement[] | undefined; - membersArray = ts.append(membersArray, syntheticConstructor); - membersArray = ts.append(membersArray, syntheticStaticBlock); - membersArray = ts.addRange(membersArray, members); - members = ts.setTextRange(factory.createNodeArray(membersArray), /*location*/ node.members); + let membersArray: ClassElement[] | undefined; + membersArray = append(membersArray, syntheticConstructor); + membersArray = append(membersArray, syntheticStaticBlock); + membersArray = addRange(membersArray, members); + members = setTextRange(factory.createNodeArray(membersArray), /*location*/ node.members); } return { members, prologue }; @@ -1445,7 +1481,7 @@ export function transformClassFields(context: ts.TransformationContext) { function createBrandCheckWeakSetForPrivateMethods() { const { weakSetName } = getPrivateIdentifierEnvironment(); - ts.Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); + Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); getPendingExpressions().push( factory.createAssignment( @@ -1459,39 +1495,39 @@ export function transformClassFields(context: ts.TransformationContext) { ); } - function isClassElementThatRequiresConstructorStatement(member: ts.ClassElement) { - if (ts.isStatic(member) || ts.hasAbstractModifier(ts.getOriginalNode(member))) { + function isClassElementThatRequiresConstructorStatement(member: ClassElement) { + if (isStatic(member) || hasAbstractModifier(getOriginalNode(member))) { return false; } - return shouldTransformInitializersUsingDefine && ts.isPropertyDeclaration(member) || - shouldTransformInitializersUsingSet && ts.isInitializedProperty(member) || - shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifierClassElementDeclaration(member) || - shouldTransformPrivateElementsOrClassStaticBlocks && shouldTransformAutoAccessors && ts.isAutoAccessorPropertyDeclaration(member); + return shouldTransformInitializersUsingDefine && isPropertyDeclaration(member) || + shouldTransformInitializersUsingSet && isInitializedProperty(member) || + shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifierClassElementDeclaration(member) || + shouldTransformPrivateElementsOrClassStaticBlocks && shouldTransformAutoAccessors && isAutoAccessorPropertyDeclaration(member); } - function transformConstructor(constructor: ts.ConstructorDeclaration | undefined, container: ts.ClassDeclaration | ts.ClassExpression) { - constructor = ts.visitNode(constructor, visitor, ts.isConstructorDeclaration); - if (!ts.some(container.members, isClassElementThatRequiresConstructorStatement)) { + function transformConstructor(constructor: ConstructorDeclaration | undefined, container: ClassDeclaration | ClassExpression) { + constructor = visitNode(constructor, visitor, isConstructorDeclaration); + if (!some(container.members, isClassElementThatRequiresConstructorStatement)) { return constructor; } - const extendsClauseElement = ts.getEffectiveBaseTypeNode(container); - const isDerivedClass = !!(extendsClauseElement && ts.skipOuterExpressions(extendsClauseElement.expression).kind !== ts.SyntaxKind.NullKeyword); - const parameters = ts.visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); + const extendsClauseElement = getEffectiveBaseTypeNode(container); + const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword); + const parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context); const body = transformConstructorBody(container, constructor, isDerivedClass); if (!body) { return constructor; } if (constructor) { - ts.Debug.assert(parameters); + Debug.assert(parameters); return factory.updateConstructorDeclaration(constructor, /*modifiers*/ undefined, parameters, body); } - return ts.startOnNewLine( - ts.setOriginalNode( - ts.setTextRange( + return startOnNewLine( + setOriginalNode( + setTextRange( factory.createConstructorDeclaration( /*modifiers*/ undefined, parameters ?? [], @@ -1504,18 +1540,18 @@ export function transformClassFields(context: ts.TransformationContext) { ); } - function transformConstructorBody(node: ts.ClassDeclaration | ts.ClassExpression, constructor: ts.ConstructorDeclaration | undefined, isDerivedClass: boolean) { - let properties = ts.getProperties(node, /*requireInitializer*/ false, /*isStatic*/ false); + function transformConstructorBody(node: ClassDeclaration | ClassExpression, constructor: ConstructorDeclaration | undefined, isDerivedClass: boolean) { + let properties = getProperties(node, /*requireInitializer*/ false, /*isStatic*/ false); if (!useDefineForClassFields) { - properties = ts.filter(properties, property => !!property.initializer || ts.isPrivateIdentifier(property.name) || ts.hasAccessorModifier(property)); + properties = filter(properties, property => !!property.initializer || isPrivateIdentifier(property.name) || hasAccessorModifier(property)); } const privateMethodsAndAccessors = getPrivateInstanceMethodsAndAccessors(node); - const needsConstructorBody = ts.some(properties) || ts.some(privateMethodsAndAccessors); + const needsConstructorBody = some(properties) || some(privateMethodsAndAccessors); // Only generate synthetic constructor when there are property initializers to move. if (!constructor && !needsConstructorBody) { - return ts.visitFunctionBody(/*node*/ undefined, visitor, context); + return visitFunctionBody(/*node*/ undefined, visitor, context); } resumeLexicalEnvironment(); @@ -1524,18 +1560,18 @@ export function transformClassFields(context: ts.TransformationContext) { let indexOfFirstStatementAfterSuperAndPrologue = 0; let prologueStatementCount = 0; let superStatementIndex = -1; - let statements: ts.Statement[] = []; + let statements: Statement[] = []; if (constructor?.body?.statements) { prologueStatementCount = factory.copyPrologue(constructor.body.statements, statements, /*ensureUseStrict*/ false, visitor); - superStatementIndex = ts.findSuperStatementIndex(constructor.body.statements, prologueStatementCount); + superStatementIndex = findSuperStatementIndex(constructor.body.statements, prologueStatementCount); // If there was a super call, visit existing statements up to and including it if (superStatementIndex >= 0) { indexOfFirstStatementAfterSuperAndPrologue = superStatementIndex + 1; statements = [ ...statements.slice(0, prologueStatementCount), - ...ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, prologueStatementCount, indexOfFirstStatementAfterSuperAndPrologue - prologueStatementCount), + ...visitNodes(constructor.body.statements, visitor, isStatement, prologueStatementCount, indexOfFirstStatementAfterSuperAndPrologue - prologueStatementCount), ...statements.slice(prologueStatementCount), ]; } @@ -1575,20 +1611,20 @@ export function transformClassFields(context: ts.TransformationContext) { let parameterPropertyDeclarationCount = 0; if (constructor?.body) { if (useDefineForClassFields) { - statements = statements.filter(statement => !ts.isParameterPropertyDeclaration(ts.getOriginalNode(statement), constructor)); + statements = statements.filter(statement => !isParameterPropertyDeclaration(getOriginalNode(statement), constructor)); } else { for (const statement of constructor.body.statements) { - if (ts.isParameterPropertyDeclaration(ts.getOriginalNode(statement), constructor)) { + if (isParameterPropertyDeclaration(getOriginalNode(statement), constructor)) { parameterPropertyDeclarationCount++; } } if (parameterPropertyDeclarationCount > 0) { - const parameterProperties = ts.visitNodes(constructor.body.statements, visitor, ts.isStatement, indexOfFirstStatementAfterSuperAndPrologue, parameterPropertyDeclarationCount); + const parameterProperties = visitNodes(constructor.body.statements, visitor, isStatement, indexOfFirstStatementAfterSuperAndPrologue, parameterPropertyDeclarationCount); // If there was a super() call found, add parameter properties immediately after it if (superStatementIndex >= 0) { - ts.addRange(statements, parameterProperties); + addRange(statements, parameterProperties); } else { // Add add parameter properties to the top of the constructor after the prologue @@ -1614,7 +1650,7 @@ export function transformClassFields(context: ts.TransformationContext) { // Add existing statements after the initial prologues and super call if (constructor) { - ts.addRange(statements, ts.visitNodes(constructor.body!.statements, visitBodyStatement, ts.isStatement, indexOfFirstStatementAfterSuperAndPrologue)); + addRange(statements, visitNodes(constructor.body!.statements, visitBodyStatement, isStatement, indexOfFirstStatementAfterSuperAndPrologue)); } statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); @@ -1627,9 +1663,9 @@ export function transformClassFields(context: ts.TransformationContext) { constructor.body.multiLine ?? statements.length > 0 : statements.length > 0; - return ts.setTextRange( + return setTextRange( factory.createBlock( - ts.setTextRange( + setTextRange( factory.createNodeArray(statements), /*location*/ constructor ? constructor.body!.statements : node.members ), @@ -1638,8 +1674,8 @@ export function transformClassFields(context: ts.TransformationContext) { /*location*/ constructor ? constructor.body : undefined ); - function visitBodyStatement(statement: ts.Node) { - if (useDefineForClassFields && ts.isParameterPropertyDeclaration(ts.getOriginalNode(statement), constructor!)) { + function visitBodyStatement(statement: Node) { + if (useDefineForClassFields && isParameterPropertyDeclaration(getOriginalNode(statement), constructor!)) { return undefined; } @@ -1653,9 +1689,9 @@ export function transformClassFields(context: ts.TransformationContext) { * @param properties An array of property declarations to transform. * @param receiver The receiver on which each property should be assigned. */ - function addPropertyOrClassStaticBlockStatements(statements: ts.Statement[], properties: readonly (ts.PropertyDeclaration | ts.ClassStaticBlockDeclaration)[], receiver: ts.LeftHandSideExpression) { + function addPropertyOrClassStaticBlockStatements(statements: Statement[], properties: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], receiver: LeftHandSideExpression) { for (const property of properties) { - if (ts.isStatic(property) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { + if (isStatic(property) && !shouldTransformPrivateElementsOrClassStaticBlocks && !useDefineForClassFields) { continue; } @@ -1668,8 +1704,8 @@ export function transformClassFields(context: ts.TransformationContext) { } } - function transformPropertyOrClassStaticBlock(property: ts.PropertyDeclaration | ts.ClassStaticBlockDeclaration, receiver: ts.LeftHandSideExpression) { - const expression = ts.isClassStaticBlockDeclaration(property) ? + function transformPropertyOrClassStaticBlock(property: PropertyDeclaration | ClassStaticBlockDeclaration, receiver: LeftHandSideExpression) { + const expression = isClassStaticBlockDeclaration(property) ? transformClassStaticBlockDeclaration(property) : transformProperty(property, receiver); if (!expression) { @@ -1677,16 +1713,16 @@ export function transformClassFields(context: ts.TransformationContext) { } const statement = factory.createExpressionStatement(expression); - ts.setOriginalNode(statement, property); - ts.addEmitFlags(statement, ts.getEmitFlags(property) & ts.EmitFlags.NoComments); - ts.setSourceMapRange(statement, ts.moveRangePastModifiers(property)); - ts.setCommentRange(statement, property); + setOriginalNode(statement, property); + addEmitFlags(statement, getEmitFlags(property) & EmitFlags.NoComments); + setSourceMapRange(statement, moveRangePastModifiers(property)); + setCommentRange(statement, property); // `setOriginalNode` *copies* the `emitNode` from `property`, so now both // `statement` and `expression` have a copy of the synthesized comments. // Drop the comments from expression to avoid printing them twice. - ts.setSyntheticLeadingComments(expression, undefined); - ts.setSyntheticTrailingComments(expression, undefined); + setSyntheticLeadingComments(expression, undefined); + setSyntheticTrailingComments(expression, undefined); return statement; } @@ -1697,18 +1733,18 @@ export function transformClassFields(context: ts.TransformationContext) { * @param propertiesOrClassStaticBlocks An array of property declarations to transform. * @param receiver The receiver on which each property should be assigned. */ - function generateInitializedPropertyExpressionsOrClassStaticBlock(propertiesOrClassStaticBlocks: readonly (ts.PropertyDeclaration | ts.ClassStaticBlockDeclaration)[], receiver: ts.LeftHandSideExpression) { - const expressions: ts.Expression[] = []; + function generateInitializedPropertyExpressionsOrClassStaticBlock(propertiesOrClassStaticBlocks: readonly (PropertyDeclaration | ClassStaticBlockDeclaration)[], receiver: LeftHandSideExpression) { + const expressions: Expression[] = []; for (const property of propertiesOrClassStaticBlocks) { - const expression = ts.isClassStaticBlockDeclaration(property) ? transformClassStaticBlockDeclaration(property) : transformProperty(property, receiver); + const expression = isClassStaticBlockDeclaration(property) ? transformClassStaticBlockDeclaration(property) : transformProperty(property, receiver); if (!expression) { continue; } - ts.startOnNewLine(expression); - ts.setOriginalNode(expression, property); - ts.addEmitFlags(expression, ts.getEmitFlags(property) & ts.EmitFlags.NoComments); - ts.setSourceMapRange(expression, ts.moveRangePastModifiers(property)); - ts.setCommentRange(expression, property); + startOnNewLine(expression); + setOriginalNode(expression, property); + addEmitFlags(expression, getEmitFlags(property) & EmitFlags.NoComments); + setSourceMapRange(expression, moveRangePastModifiers(property)); + setCommentRange(expression, property); expressions.push(expression); } @@ -1721,49 +1757,49 @@ export function transformClassFields(context: ts.TransformationContext) { * @param property The property declaration. * @param receiver The object receiving the property assignment. */ - function transformProperty(property: ts.PropertyDeclaration, receiver: ts.LeftHandSideExpression) { + function transformProperty(property: PropertyDeclaration, receiver: LeftHandSideExpression) { const savedCurrentStaticPropertyDeclarationOrStaticBlock = currentStaticPropertyDeclarationOrStaticBlock; const transformed = transformPropertyWorker(property, receiver); - if (transformed && ts.hasStaticModifier(property) && currentClassLexicalEnvironment?.facts) { + if (transformed && hasStaticModifier(property) && currentClassLexicalEnvironment?.facts) { // capture the lexical environment for the member - ts.setOriginalNode(transformed, property); - ts.addEmitFlags(transformed, ts.EmitFlags.AdviseOnEmitNode); - classLexicalEnvironmentMap.set(ts.getOriginalNodeId(transformed), currentClassLexicalEnvironment); + setOriginalNode(transformed, property); + addEmitFlags(transformed, EmitFlags.AdviseOnEmitNode); + classLexicalEnvironmentMap.set(getOriginalNodeId(transformed), currentClassLexicalEnvironment); } currentStaticPropertyDeclarationOrStaticBlock = savedCurrentStaticPropertyDeclarationOrStaticBlock; return transformed; } - function transformPropertyWorker(property: ts.PropertyDeclaration, receiver: ts.LeftHandSideExpression) { + function transformPropertyWorker(property: PropertyDeclaration, receiver: LeftHandSideExpression) { // We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name) const emitAssignment = !useDefineForClassFields; const propertyName = - ts.hasAccessorModifier(property) ? + hasAccessorModifier(property) ? factory.getGeneratedPrivateNameForNode(property.name) : - ts.isComputedPropertyName(property.name) && !ts.isSimpleInlineableExpression(property.name.expression) ? + isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression) ? factory.updateComputedPropertyName(property.name, factory.getGeneratedNameForNode(property.name)) : property.name; - if (ts.hasStaticModifier(property)) { + if (hasStaticModifier(property)) { currentStaticPropertyDeclarationOrStaticBlock = property; } - if (shouldTransformPrivateElementsOrClassStaticBlocks && ts.isPrivateIdentifier(propertyName)) { + if (shouldTransformPrivateElementsOrClassStaticBlocks && isPrivateIdentifier(propertyName)) { const privateIdentifierInfo = accessPrivateIdentifier(propertyName); if (privateIdentifierInfo) { if (privateIdentifierInfo.kind === PrivateIdentifierKind.Field) { if (!privateIdentifierInfo.isStatic) { return createPrivateInstanceFieldInitializer( receiver, - ts.visitNode(property.initializer, visitor, ts.isExpression), + visitNode(property.initializer, visitor, isExpression), privateIdentifierInfo.brandCheckIdentifier ); } else { return createPrivateStaticFieldInitializer( privateIdentifierInfo.variableName, - ts.visitNode(property.initializer, visitor, ts.isExpression) + visitNode(property.initializer, visitor, isExpression) ); } } @@ -1772,29 +1808,29 @@ export function transformClassFields(context: ts.TransformationContext) { } } else { - ts.Debug.fail("Undeclared private name for property declaration."); + Debug.fail("Undeclared private name for property declaration."); } } - if ((ts.isPrivateIdentifier(propertyName) || ts.hasStaticModifier(property)) && !property.initializer) { + if ((isPrivateIdentifier(propertyName) || hasStaticModifier(property)) && !property.initializer) { return undefined; } - const propertyOriginalNode = ts.getOriginalNode(property); - if (ts.hasSyntacticModifier(propertyOriginalNode, ts.ModifierFlags.Abstract)) { + const propertyOriginalNode = getOriginalNode(property); + if (hasSyntacticModifier(propertyOriginalNode, ModifierFlags.Abstract)) { return undefined; } - const initializer = property.initializer || emitAssignment ? ts.visitNode(property.initializer, visitor, ts.isExpression) ?? factory.createVoidZero() - : ts.isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) && ts.isIdentifier(propertyName) ? propertyName + const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) ?? factory.createVoidZero() + : isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) && isIdentifier(propertyName) ? propertyName : factory.createVoidZero(); - if (emitAssignment || ts.isPrivateIdentifier(propertyName)) { - const memberAccess = ts.createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ propertyName); + if (emitAssignment || isPrivateIdentifier(propertyName)) { + const memberAccess = createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ propertyName); return factory.createAssignment(memberAccess, initializer); } else { - const name = ts.isComputedPropertyName(propertyName) ? propertyName.expression - : ts.isIdentifier(propertyName) ? factory.createStringLiteral(ts.unescapeLeadingUnderscores(propertyName.escapedText)) + const name = isComputedPropertyName(propertyName) ? propertyName.expression + : isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText)) : propertyName; const descriptor = factory.createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true }); return factory.createObjectDefinePropertyCall(receiver, name, descriptor); @@ -1807,7 +1843,7 @@ export function transformClassFields(context: ts.TransformationContext) { // We need to enable substitutions for identifiers. This allows us to // substitute class names inside of a class declaration. - context.enableSubstitution(ts.SyntaxKind.Identifier); + context.enableSubstitution(SyntaxKind.Identifier); // Keep track of class aliases. classAliases = []; @@ -1819,22 +1855,22 @@ export function transformClassFields(context: ts.TransformationContext) { enabledSubstitutions |= ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference; // substitute `this` in a static field initializer - context.enableSubstitution(ts.SyntaxKind.ThisKeyword); + context.enableSubstitution(SyntaxKind.ThisKeyword); // these push a new lexical environment that is not the class lexical environment - context.enableEmitNotification(ts.SyntaxKind.FunctionDeclaration); - context.enableEmitNotification(ts.SyntaxKind.FunctionExpression); - context.enableEmitNotification(ts.SyntaxKind.Constructor); + context.enableEmitNotification(SyntaxKind.FunctionDeclaration); + context.enableEmitNotification(SyntaxKind.FunctionExpression); + context.enableEmitNotification(SyntaxKind.Constructor); // these push a new lexical environment that is not the class lexical environment, except // when they have a computed property name - context.enableEmitNotification(ts.SyntaxKind.GetAccessor); - context.enableEmitNotification(ts.SyntaxKind.SetAccessor); - context.enableEmitNotification(ts.SyntaxKind.MethodDeclaration); - context.enableEmitNotification(ts.SyntaxKind.PropertyDeclaration); + context.enableEmitNotification(SyntaxKind.GetAccessor); + context.enableEmitNotification(SyntaxKind.SetAccessor); + context.enableEmitNotification(SyntaxKind.MethodDeclaration); + context.enableEmitNotification(SyntaxKind.PropertyDeclaration); // class lexical environments are restored when entering a computed property name - context.enableEmitNotification(ts.SyntaxKind.ComputedPropertyName); + context.enableEmitNotification(SyntaxKind.ComputedPropertyName); } } @@ -1845,13 +1881,13 @@ export function transformClassFields(context: ts.TransformationContext) { * @param methods An array of method declarations. * @param receiver The receiver on which each method should be assigned. */ - function addMethodStatements(statements: ts.Statement[], methods: readonly (ts.MethodDeclaration | ts.AccessorDeclaration | ts.AutoAccessorPropertyDeclaration)[], receiver: ts.LeftHandSideExpression) { - if (!shouldTransformPrivateElementsOrClassStaticBlocks || !ts.some(methods)) { + function addMethodStatements(statements: Statement[], methods: readonly (MethodDeclaration | AccessorDeclaration | AutoAccessorPropertyDeclaration)[], receiver: LeftHandSideExpression) { + if (!shouldTransformPrivateElementsOrClassStaticBlocks || !some(methods)) { return; } const { weakSetName } = getPrivateIdentifierEnvironment(); - ts.Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); + Debug.assert(weakSetName, "weakSetName should be set in private identifier environment"); statements.push( factory.createExpressionStatement( createPrivateInstanceMethodInitializer(receiver, weakSetName) @@ -1859,8 +1895,8 @@ export function transformClassFields(context: ts.TransformationContext) { ); } - function visitInvalidSuperProperty(node: ts.SuperProperty) { - return ts.isPropertyAccessExpression(node) ? + function visitInvalidSuperProperty(node: SuperProperty) { + return isPropertyAccessExpression(node) ? factory.updatePropertyAccessExpression( node, factory.createVoidZero(), @@ -1868,11 +1904,11 @@ export function transformClassFields(context: ts.TransformationContext) { factory.updateElementAccessExpression( node, factory.createVoidZero(), - ts.visitNode(node.argumentExpression, visitor, ts.isExpression)); + visitNode(node.argumentExpression, visitor, isExpression)); } - function onEmitNode(hint: ts.EmitHint, node: ts.Node, emitCallback: (hint: ts.EmitHint, node: ts.Node) => void) { - const original = ts.getOriginalNode(node); + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { + const original = getOriginalNode(node); if (original.id) { const classLexicalEnvironment = classLexicalEnvironmentMap.get(original.id); if (classLexicalEnvironment) { @@ -1888,14 +1924,14 @@ export function transformClassFields(context: ts.TransformationContext) { } switch (node.kind) { - case ts.SyntaxKind.FunctionExpression: - if (ts.isArrowFunction(original) || ts.getEmitFlags(node) & ts.EmitFlags.AsyncFunctionBody) { + case SyntaxKind.FunctionExpression: + if (isArrowFunction(original) || getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { break; } // falls through - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.Constructor: { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.Constructor: { const savedClassLexicalEnvironment = currentClassLexicalEnvironment; const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment; currentClassLexicalEnvironment = undefined; @@ -1906,10 +1942,10 @@ export function transformClassFields(context: ts.TransformationContext) { return; } - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.PropertyDeclaration: { + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: { const savedClassLexicalEnvironment = currentClassLexicalEnvironment; const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment; currentComputedPropertyNameClassLexicalEnvironment = currentClassLexicalEnvironment; @@ -1919,7 +1955,7 @@ export function transformClassFields(context: ts.TransformationContext) { currentComputedPropertyNameClassLexicalEnvironment = savedCurrentComputedPropertyNameClassLexicalEnvironment; return; } - case ts.SyntaxKind.ComputedPropertyName: { + case SyntaxKind.ComputedPropertyName: { const savedClassLexicalEnvironment = currentClassLexicalEnvironment; const savedCurrentComputedPropertyNameClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment; currentClassLexicalEnvironment = currentComputedPropertyNameClassLexicalEnvironment; @@ -1939,33 +1975,33 @@ export function transformClassFields(context: ts.TransformationContext) { * @param hint The context for the emitter. * @param node The node to substitute. */ - function onSubstituteNode(hint: ts.EmitHint, node: ts.Node) { + function onSubstituteNode(hint: EmitHint, node: Node) { node = previousOnSubstituteNode(hint, node); - if (hint === ts.EmitHint.Expression) { - return substituteExpression(node as ts.Expression); + if (hint === EmitHint.Expression) { + return substituteExpression(node as Expression); } return node; } - function substituteExpression(node: ts.Expression) { + function substituteExpression(node: Expression) { switch (node.kind) { - case ts.SyntaxKind.Identifier: - return substituteExpressionIdentifier(node as ts.Identifier); - case ts.SyntaxKind.ThisKeyword: - return substituteThisExpression(node as ts.ThisExpression); + case SyntaxKind.Identifier: + return substituteExpressionIdentifier(node as Identifier); + case SyntaxKind.ThisKeyword: + return substituteThisExpression(node as ThisExpression); } return node; } - function substituteThisExpression(node: ts.ThisExpression) { + function substituteThisExpression(node: ThisExpression) { if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassStaticThisOrSuperReference && currentClassLexicalEnvironment) { const { facts, classConstructor } = currentClassLexicalEnvironment; if (facts & ClassFacts.ClassWasDecorated) { return factory.createParenthesizedExpression(factory.createVoidZero()); } if (classConstructor) { - return ts.setTextRange( - ts.setOriginalNode( + return setTextRange( + setOriginalNode( factory.cloneNode(classConstructor), node, ), @@ -1976,13 +2012,13 @@ export function transformClassFields(context: ts.TransformationContext) { return node; } - function substituteExpressionIdentifier(node: ts.Identifier): ts.Expression { + function substituteExpressionIdentifier(node: Identifier): Expression { return trySubstituteClassAlias(node) || node; } - function trySubstituteClassAlias(node: ts.Identifier): ts.Expression | undefined { + function trySubstituteClassAlias(node: Identifier): Expression | undefined { if (enabledSubstitutions & ClassPropertySubstitutionFlags.ClassAliases) { - if (resolver.getNodeCheckFlags(node) & ts.NodeCheckFlags.ConstructorReferenceInClass) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ConstructorReferenceInClass) { // Due to the emit for class decorators, any reference to the class from inside of the class body // must instead be rewritten to point to a temporary variable to avoid issues with the double-bind // behavior of class names in ES6. @@ -1993,8 +2029,8 @@ export function transformClassFields(context: ts.TransformationContext) { const classAlias = classAliases[declaration.id!]; // TODO: GH#18217 if (classAlias) { const clone = factory.cloneNode(classAlias); - ts.setSourceMapRange(clone, node); - ts.setCommentRange(clone, node); + setSourceMapRange(clone, node); + setCommentRange(clone, node); return clone; } } @@ -2009,15 +2045,15 @@ export function transformClassFields(context: ts.TransformationContext) { * value of the result or the expression itself if the value is either unused or safe to inline into multiple locations * @param shouldHoist Does the expression need to be reused? (ie, for an initializer or a decorator) */ - function getPropertyNameExpressionIfNeeded(name: ts.PropertyName, shouldHoist: boolean): ts.Expression | undefined { - if (ts.isComputedPropertyName(name)) { - const expression = ts.visitNode(name.expression, visitor, ts.isExpression); - const innerExpression = ts.skipPartiallyEmittedExpressions(expression); - const inlinable = ts.isSimpleInlineableExpression(innerExpression); - const alreadyTransformed = ts.isAssignmentExpression(innerExpression) && ts.isGeneratedIdentifier(innerExpression.left); + function getPropertyNameExpressionIfNeeded(name: PropertyName, shouldHoist: boolean): Expression | undefined { + if (isComputedPropertyName(name)) { + const expression = visitNode(name.expression, visitor, isExpression); + const innerExpression = skipPartiallyEmittedExpressions(expression); + const inlinable = isSimpleInlineableExpression(innerExpression); + const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left); if (!alreadyTransformed && !inlinable && shouldHoist) { const generatedName = factory.getGeneratedNameForNode(name); - if (resolver.getNodeCheckFlags(name) & ts.NodeCheckFlags.BlockScopedBindingInLoop) { + if (resolver.getNodeCheckFlags(name) & NodeCheckFlags.BlockScopedBindingInLoop) { addBlockScopedVariable(generatedName); } else { @@ -2025,7 +2061,7 @@ export function transformClassFields(context: ts.TransformationContext) { } return factory.createAssignment(generatedName, expression); } - return (inlinable || ts.isIdentifier(innerExpression)) ? undefined : expression; + return (inlinable || isIdentifier(innerExpression)) ? undefined : expression; } } @@ -2063,34 +2099,34 @@ export function transformClassFields(context: ts.TransformationContext) { } function addPrivateIdentifierClassElementToEnvironment( - node: ts.PropertyDeclaration | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration, - name: ts.PrivateIdentifier, + node: PropertyDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, isValid: boolean, previousInfo: PrivateIdentifierInfo | undefined ) { - if (ts.isAutoAccessorPropertyDeclaration(node)) { + if (isAutoAccessorPropertyDeclaration(node)) { addPrivateIdentifierAutoAccessorPropertyDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - else if (ts.isPropertyDeclaration(node)) { + else if (isPropertyDeclaration(node)) { addPrivateIdentifierPropertyDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - else if (ts.isMethodDeclaration(node)) { + else if (isMethodDeclaration(node)) { addPrivateIdentifierMethodDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - else if (ts.isGetAccessorDeclaration(node)) { + else if (isGetAccessorDeclaration(node)) { addPrivateIdentifierGetAccessorDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - else if (ts.isSetAccessorDeclaration(node)) { + else if (isSetAccessorDeclaration(node)) { addPrivateIdentifierSetAccessorDeclarationToEnvironment(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } } function addPrivateIdentifierPropertyDeclarationToEnvironment( - _node: ts.PropertyDeclaration, - name: ts.PrivateIdentifier, + _node: PropertyDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2098,7 +2134,7 @@ export function transformClassFields(context: ts.TransformationContext) { _previousInfo: PrivateIdentifierInfo | undefined ) { if (isStatic) { - ts.Debug.assert(lex.classConstructor, "classConstructor should be set in private identifier environment"); + Debug.assert(lex.classConstructor, "classConstructor should be set in private identifier environment"); const variableName = createHoistedVariableForPrivateName(name); setPrivateIdentifier(privateEnv, name, { @@ -2132,8 +2168,8 @@ export function transformClassFields(context: ts.TransformationContext) { } function addPrivateIdentifierMethodDeclarationToEnvironment( - _node: ts.MethodDeclaration, - name: ts.PrivateIdentifier, + _node: MethodDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2142,8 +2178,8 @@ export function transformClassFields(context: ts.TransformationContext) { ) { const methodName = createHoistedVariableForPrivateName(name); const brandCheckIdentifier = isStatic ? - ts.Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : - ts.Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); + Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : + Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); setPrivateIdentifier(privateEnv, name, { kind: PrivateIdentifierKind.Method, @@ -2155,8 +2191,8 @@ export function transformClassFields(context: ts.TransformationContext) { } function addPrivateIdentifierGetAccessorDeclarationToEnvironment( - _node: ts.GetAccessorDeclaration, - name: ts.PrivateIdentifier, + _node: GetAccessorDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2165,8 +2201,8 @@ export function transformClassFields(context: ts.TransformationContext) { ) { const getterName = createHoistedVariableForPrivateName(name, "_get"); const brandCheckIdentifier = isStatic ? - ts.Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : - ts.Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); + Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : + Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); if (previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic === isStatic && !previousInfo.getterName) { previousInfo.getterName = getterName; @@ -2184,8 +2220,8 @@ export function transformClassFields(context: ts.TransformationContext) { } function addPrivateIdentifierSetAccessorDeclarationToEnvironment( - _node: ts.SetAccessorDeclaration, - name: ts.PrivateIdentifier, + _node: SetAccessorDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2194,8 +2230,8 @@ export function transformClassFields(context: ts.TransformationContext) { ) { const setterName = createHoistedVariableForPrivateName(name, "_set"); const brandCheckIdentifier = isStatic ? - ts.Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : - ts.Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); + Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : + Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); if (previousInfo?.kind === PrivateIdentifierKind.Accessor && previousInfo.isStatic === isStatic && !previousInfo.setterName) { previousInfo.setterName = setterName; @@ -2213,8 +2249,8 @@ export function transformClassFields(context: ts.TransformationContext) { } function addPrivateIdentifierAutoAccessorPropertyDeclarationToEnvironment( - _node: ts.AutoAccessorPropertyDeclaration, - name: ts.PrivateIdentifier, + _node: AutoAccessorPropertyDeclaration, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2224,8 +2260,8 @@ export function transformClassFields(context: ts.TransformationContext) { const getterName = createHoistedVariableForPrivateName(name, "_get"); const setterName = createHoistedVariableForPrivateName(name, "_set"); const brandCheckIdentifier = isStatic ? - ts.Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : - ts.Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); + Debug.checkDefined(lex.classConstructor, "classConstructor should be set in private identifier environment") : + Debug.checkDefined(privateEnv.weakSetName, "weakSetName should be set in private identifier environment"); setPrivateIdentifier(privateEnv, name, { kind: PrivateIdentifierKind.Accessor, @@ -2237,12 +2273,12 @@ export function transformClassFields(context: ts.TransformationContext) { }); } - function addPrivateIdentifierToEnvironment( + function addPrivateIdentifierToEnvironment( node: T, - name: ts.PrivateIdentifier, + name: PrivateIdentifier, addDeclaration: ( node: T, - name: ts.PrivateIdentifier, + name: PrivateIdentifier, lex: ClassLexicalEnvironment, privateEnv: PrivateIdentifierEnvironment, isStatic: boolean, @@ -2253,20 +2289,20 @@ export function transformClassFields(context: ts.TransformationContext) { const lex = getClassLexicalEnvironment(); const privateEnv = getPrivateIdentifierEnvironment(); const previousInfo = getPrivateIdentifier(privateEnv, name); - const isStatic = ts.hasStaticModifier(node); + const isStatic = hasStaticModifier(node); const isValid = !isReservedPrivateName(name) && previousInfo === undefined; addDeclaration(node, name, lex, privateEnv, isStatic, isValid, previousInfo); } - function createHoistedVariableForClass(name: string | ts.PrivateIdentifier | undefined, node: ts.PrivateIdentifier | ts.ClassStaticBlockDeclaration, suffix?: string): ts.Identifier { + function createHoistedVariableForClass(name: string | PrivateIdentifier | undefined, node: PrivateIdentifier | ClassStaticBlockDeclaration, suffix?: string): Identifier { const { className } = getPrivateIdentifierEnvironment(); - const prefix: ts.GeneratedNamePart | string = className ? { prefix: "_", node: className, suffix: "_" } : "_"; + const prefix: GeneratedNamePart | string = className ? { prefix: "_", node: className, suffix: "_" } : "_"; const identifier = - typeof name === "object" ? factory.getGeneratedNameForNode(name, ts.GeneratedIdentifierFlags.Optimistic | ts.GeneratedIdentifierFlags.ReservedInNestedScopes, prefix, suffix) : - typeof name === "string" ? factory.createUniqueName(name, ts.GeneratedIdentifierFlags.Optimistic, prefix, suffix) : + typeof name === "object" ? factory.getGeneratedNameForNode(name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes, prefix, suffix) : + typeof name === "string" ? factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic, prefix, suffix) : factory.createTempVariable(/*recordTempVariable*/ undefined, /*reserveInNestedScopes*/ true, prefix, suffix); - if (resolver.getNodeCheckFlags(node) & ts.NodeCheckFlags.BlockScopedBindingInLoop) { + if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.BlockScopedBindingInLoop) { addBlockScopedVariable(identifier); } else { @@ -2276,8 +2312,8 @@ export function transformClassFields(context: ts.TransformationContext) { return identifier; } - function createHoistedVariableForPrivateName(name: ts.PrivateIdentifier, suffix?: string): ts.Identifier { - const text = ts.tryGetTextOfPropertyName(name) as string | undefined; + function createHoistedVariableForPrivateName(name: PrivateIdentifier, suffix?: string): Identifier { + const text = tryGetTextOfPropertyName(name) as string | undefined; return createHoistedVariableForClass(text?.substring(1) ?? name, name, suffix); } @@ -2286,8 +2322,8 @@ export function transformClassFields(context: ts.TransformationContext) { * * @seealso {@link addPrivateIdentifierToEnvironment} */ - function accessPrivateIdentifier(name: ts.PrivateIdentifier) { - if (ts.isGeneratedPrivateIdentifier(name)) { + function accessPrivateIdentifier(name: PrivateIdentifier) { + if (isGeneratedPrivateIdentifier(name)) { return accessGeneratedPrivateIdentifier(name); } else { @@ -2295,15 +2331,15 @@ export function transformClassFields(context: ts.TransformationContext) { } } - function accessPrivateIdentifierByText(text: ts.__String) { + function accessPrivateIdentifierByText(text: __String) { return accessPrivateIdentifierWorker(getPrivateIdentifierInfo, text); } - function accessGeneratedPrivateIdentifier(name: ts.GeneratedPrivateIdentifier) { - return accessPrivateIdentifierWorker(getGeneratedPrivateIdentifierInfo, ts.getNodeForGeneratedName(name)); + function accessGeneratedPrivateIdentifier(name: GeneratedPrivateIdentifier) { + return accessPrivateIdentifierWorker(getGeneratedPrivateIdentifierInfo, getNodeForGeneratedName(name)); } - function accessPrivateIdentifierWorker( + function accessPrivateIdentifierWorker( getPrivateIdentifierInfo: (privateEnv: PrivateIdentifierEnvironment, key: K) => PrivateIdentifierInfo | undefined, privateIdentifierKey: K ) { @@ -2328,18 +2364,18 @@ export function transformClassFields(context: ts.TransformationContext) { return undefined; } - function wrapPrivateIdentifierForDestructuringTarget(node: ts.PrivateIdentifierPropertyAccessExpression) { + function wrapPrivateIdentifierForDestructuringTarget(node: PrivateIdentifierPropertyAccessExpression) { const parameter = factory.getGeneratedNameForNode(node); const info = accessPrivateIdentifier(node.name); if (!info) { - return ts.visitEachChild(node, visitor, context); + return visitEachChild(node, visitor, context); } let receiver = node.expression; // We cannot copy `this` or `super` into the function because they will be bound // differently inside the function. - if (ts.isThisProperty(node) || ts.isSuperProperty(node) || !ts.isSimpleCopiableExpression(node.expression)) { + if (isThisProperty(node) || isSuperProperty(node) || !isSimpleCopiableExpression(node.expression)) { receiver = factory.createTempVariable(hoistVariableDeclaration, /*reservedInNestedScopes*/ true); - getPendingExpressions().push(factory.createBinaryExpression(receiver, ts.SyntaxKind.EqualsToken, ts.visitNode(node.expression, visitor, ts.isExpression))); + getPendingExpressions().push(factory.createBinaryExpression(receiver, SyntaxKind.EqualsToken, visitNode(node.expression, visitor, isExpression))); } return factory.createAssignmentTargetWrapper( parameter, @@ -2347,20 +2383,20 @@ export function transformClassFields(context: ts.TransformationContext) { info, receiver, parameter, - ts.SyntaxKind.EqualsToken + SyntaxKind.EqualsToken ) ); } - function visitArrayAssignmentTarget(node: ts.BindingOrAssignmentElement) { - const target = ts.getTargetOfBindingOrAssignmentElement(node); + function visitArrayAssignmentTarget(node: BindingOrAssignmentElement) { + const target = getTargetOfBindingOrAssignmentElement(node); if (target) { - let wrapped: ts.LeftHandSideExpression | undefined; - if (ts.isPrivateIdentifierPropertyAccessExpression(target)) { + let wrapped: LeftHandSideExpression | undefined; + if (isPrivateIdentifierPropertyAccessExpression(target)) { wrapped = wrapPrivateIdentifierForDestructuringTarget(target); } else if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(target) && + isSuperProperty(target) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; @@ -2369,8 +2405,8 @@ export function transformClassFields(context: ts.TransformationContext) { } else if (classConstructor && superClassReference) { const name = - ts.isElementAccessExpression(target) ? ts.visitNode(target.argumentExpression, visitor, ts.isExpression) : - ts.isIdentifier(target.name) ? factory.createStringLiteralFromNode(target.name) : + isElementAccessExpression(target) ? visitNode(target.argumentExpression, visitor, isExpression) : + isIdentifier(target.name) ? factory.createStringLiteralFromNode(target.name) : undefined; if (name) { const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); @@ -2387,15 +2423,15 @@ export function transformClassFields(context: ts.TransformationContext) { } } if (wrapped) { - if (ts.isAssignmentExpression(node)) { + if (isAssignmentExpression(node)) { return factory.updateBinaryExpression( node, wrapped, node.operatorToken, - ts.visitNode(node.right, visitor, ts.isExpression) + visitNode(node.right, visitor, isExpression) ); } - else if (ts.isSpreadElement(node)) { + else if (isSpreadElement(node)) { return factory.updateSpreadElement(node, wrapped); } else { @@ -2403,19 +2439,19 @@ export function transformClassFields(context: ts.TransformationContext) { } } } - return ts.visitNode(node, assignmentTargetVisitor); + return visitNode(node, assignmentTargetVisitor); } - function visitObjectAssignmentTarget(node: ts.ObjectLiteralElementLike) { - if (ts.isObjectBindingOrAssignmentElement(node) && !ts.isShorthandPropertyAssignment(node)) { - const target = ts.getTargetOfBindingOrAssignmentElement(node); - let wrapped: ts.LeftHandSideExpression | undefined; + function visitObjectAssignmentTarget(node: ObjectLiteralElementLike) { + if (isObjectBindingOrAssignmentElement(node) && !isShorthandPropertyAssignment(node)) { + const target = getTargetOfBindingOrAssignmentElement(node); + let wrapped: LeftHandSideExpression | undefined; if (target) { - if (ts.isPrivateIdentifierPropertyAccessExpression(target)) { + if (isPrivateIdentifierPropertyAccessExpression(target)) { wrapped = wrapPrivateIdentifierForDestructuringTarget(target); } else if (shouldTransformSuperInStaticInitializers && - ts.isSuperProperty(target) && + isSuperProperty(target) && currentStaticPropertyDeclarationOrStaticBlock && currentClassLexicalEnvironment) { const { classConstructor, superClassReference, facts } = currentClassLexicalEnvironment; @@ -2424,8 +2460,8 @@ export function transformClassFields(context: ts.TransformationContext) { } else if (classConstructor && superClassReference) { const name = - ts.isElementAccessExpression(target) ? ts.visitNode(target.argumentExpression, visitor, ts.isExpression) : - ts.isIdentifier(target.name) ? factory.createStringLiteralFromNode(target.name) : + isElementAccessExpression(target) ? visitNode(target.argumentExpression, visitor, isExpression) : + isIdentifier(target.name) ? factory.createStringLiteralFromNode(target.name) : undefined; if (name) { const temp = factory.createTempVariable(/*recordTempVariable*/ undefined); @@ -2442,29 +2478,29 @@ export function transformClassFields(context: ts.TransformationContext) { } } } - if (ts.isPropertyAssignment(node)) { - const initializer = ts.getInitializerOfBindingOrAssignmentElement(node); + if (isPropertyAssignment(node)) { + const initializer = getInitializerOfBindingOrAssignmentElement(node); return factory.updatePropertyAssignment( node, - ts.visitNode(node.name, visitor, ts.isPropertyName), + visitNode(node.name, visitor, isPropertyName), wrapped ? - initializer ? factory.createAssignment(wrapped, ts.visitNode(initializer, visitor)) : wrapped : - ts.visitNode(node.initializer, assignmentTargetVisitor, ts.isExpression) + initializer ? factory.createAssignment(wrapped, visitNode(initializer, visitor)) : wrapped : + visitNode(node.initializer, assignmentTargetVisitor, isExpression) ); } - if (ts.isSpreadAssignment(node)) { + if (isSpreadAssignment(node)) { return factory.updateSpreadAssignment( node, - wrapped || ts.visitNode(node.expression, assignmentTargetVisitor, ts.isExpression) + wrapped || visitNode(node.expression, assignmentTargetVisitor, isExpression) ); } - ts.Debug.assert(wrapped === undefined, "Should not have generated a wrapped target"); + Debug.assert(wrapped === undefined, "Should not have generated a wrapped target"); } - return ts.visitNode(node, visitor); + return visitNode(node, visitor); } - function visitAssignmentPattern(node: ts.AssignmentPattern) { - if (ts.isArrayLiteralExpression(node)) { + function visitAssignmentPattern(node: AssignmentPattern) { + if (isArrayLiteralExpression(node)) { // Transforms private names in destructuring assignment array bindings. // Transforms SuperProperty assignments in destructuring assignment array bindings in static initializers. // @@ -2475,7 +2511,7 @@ export function transformClassFields(context: ts.TransformationContext) { // [ { set value(x) { this.#myProp = x; } }.value ] = [ "hello" ]; return factory.updateArrayLiteralExpression( node, - ts.visitNodes(node.elements, visitArrayAssignmentTarget, ts.isExpression) + visitNodes(node.elements, visitArrayAssignmentTarget, isExpression) ); } else { @@ -2489,62 +2525,62 @@ export function transformClassFields(context: ts.TransformationContext) { // ({ stringProperty: { set value(x) { this.#myProp = x; } }.value }) = { stringProperty: "hello" }; return factory.updateObjectLiteralExpression( node, - ts.visitNodes(node.properties, visitObjectAssignmentTarget, ts.isObjectLiteralElementLike) + visitNodes(node.properties, visitObjectAssignmentTarget, isObjectLiteralElementLike) ); } } } -function createPrivateStaticFieldInitializer(variableName: ts.Identifier, initializer: ts.Expression | undefined) { - return ts.factory.createAssignment( +function createPrivateStaticFieldInitializer(variableName: Identifier, initializer: Expression | undefined) { + return factory.createAssignment( variableName, - ts.factory.createObjectLiteralExpression([ - ts.factory.createPropertyAssignment("value", initializer || ts.factory.createVoidZero()) + factory.createObjectLiteralExpression([ + factory.createPropertyAssignment("value", initializer || factory.createVoidZero()) ]) ); } -function createPrivateInstanceFieldInitializer(receiver: ts.LeftHandSideExpression, initializer: ts.Expression | undefined, weakMapName: ts.Identifier) { - return ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(weakMapName, "set"), +function createPrivateInstanceFieldInitializer(receiver: LeftHandSideExpression, initializer: Expression | undefined, weakMapName: Identifier) { + return factory.createCallExpression( + factory.createPropertyAccessExpression(weakMapName, "set"), /*typeArguments*/ undefined, - [receiver, initializer || ts.factory.createVoidZero()] + [receiver, initializer || factory.createVoidZero()] ); } -function createPrivateInstanceMethodInitializer(receiver: ts.LeftHandSideExpression, weakSetName: ts.Identifier) { - return ts.factory.createCallExpression( - ts.factory.createPropertyAccessExpression(weakSetName, "add"), +function createPrivateInstanceMethodInitializer(receiver: LeftHandSideExpression, weakSetName: Identifier) { + return factory.createCallExpression( + factory.createPropertyAccessExpression(weakSetName, "add"), /*typeArguments*/ undefined, [receiver] ); } -function isReservedPrivateName(node: ts.PrivateIdentifier) { - return !ts.isGeneratedPrivateIdentifier(node) && node.escapedText === "#constructor"; +function isReservedPrivateName(node: PrivateIdentifier) { + return !isGeneratedPrivateIdentifier(node) && node.escapedText === "#constructor"; } -function getPrivateIdentifier(privateEnv: PrivateIdentifierEnvironment, name: ts.PrivateIdentifier) { - return ts.isGeneratedPrivateIdentifier(name) ? - getGeneratedPrivateIdentifierInfo(privateEnv, ts.getNodeForGeneratedName(name)) : +function getPrivateIdentifier(privateEnv: PrivateIdentifierEnvironment, name: PrivateIdentifier) { + return isGeneratedPrivateIdentifier(name) ? + getGeneratedPrivateIdentifierInfo(privateEnv, getNodeForGeneratedName(name)) : getPrivateIdentifierInfo(privateEnv, name.escapedText); } -function setPrivateIdentifier(privateEnv: PrivateIdentifierEnvironment, name: ts.PrivateIdentifier, info: PrivateIdentifierInfo) { - if (ts.isGeneratedPrivateIdentifier(name)) { - privateEnv.generatedIdentifiers ??= new ts.Map(); - privateEnv.generatedIdentifiers.set(ts.getNodeForGeneratedName(name), info); +function setPrivateIdentifier(privateEnv: PrivateIdentifierEnvironment, name: PrivateIdentifier, info: PrivateIdentifierInfo) { + if (isGeneratedPrivateIdentifier(name)) { + privateEnv.generatedIdentifiers ??= new Map(); + privateEnv.generatedIdentifiers.set(getNodeForGeneratedName(name), info); } else { - privateEnv.identifiers ??= new ts.Map(); + privateEnv.identifiers ??= new Map(); privateEnv.identifiers.set(name.escapedText, info); } } -function getPrivateIdentifierInfo(privateEnv: PrivateIdentifierEnvironment, key: ts.__String) { +function getPrivateIdentifierInfo(privateEnv: PrivateIdentifierEnvironment, key: __String) { return privateEnv.identifiers?.get(key); } -function getGeneratedPrivateIdentifierInfo(privateEnv: PrivateIdentifierEnvironment, key: ts.Node) { +function getGeneratedPrivateIdentifierInfo(privateEnv: PrivateIdentifierEnvironment, key: Node) { return privateEnv.generatedIdentifiers?.get(key); } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index beb23c5dbcc24..babd5dcb098a0 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1,49 +1,89 @@ -import * as ts from "../_namespaces/ts"; +import { + AccessorDeclaration, addRelatedInfo, AllAccessorDeclarations, AnyImportSyntax, append, ArrayBindingElement, + arrayFrom, AssertClause, BindingElement, BindingName, BindingPattern, Bundle, CallSignatureDeclaration, + canHaveModifiers, canProduceDiagnostics, ClassDeclaration, CommentRange, compact, concatenate, ConditionalTypeNode, + ConstructorDeclaration, ConstructorTypeNode, ConstructSignatureDeclaration, contains, createDiagnosticForNode, + createEmptyExports, createGetSymbolAccessibilityDiagnosticForNode, + createGetSymbolAccessibilityDiagnosticForNodeName, createSymbolTable, createUnparsedSourceFile, Debug, Declaration, + DeclarationDiagnosticProducing, DeclarationName, declarationNameToString, Diagnostics, DiagnosticWithLocation, + EmitFlags, EmitHost, EmitResolver, emptyArray, EntityNameOrEntityNameExpression, EnumDeclaration, ESMap, + ExportAssignment, ExportDeclaration, ExpressionWithTypeArguments, factory, FileReference, filter, flatMap, flatten, + forEach, FunctionDeclaration, FunctionTypeNode, GeneratedIdentifierFlags, GetAccessorDeclaration, getCommentRange, + getDirectoryPath, getEffectiveBaseTypeNode, getEffectiveModifierFlags, + getExternalModuleImportEqualsDeclarationExpression, getExternalModuleNameFromDeclaration, + getFirstConstructorWithBody, getLeadingCommentRanges, getLeadingCommentRangesOfNode, getLineAndCharacterOfPosition, + getNameOfDeclaration, getOriginalNodeId, getOutputPathsFor, getParseTreeNode, getRelativePathToDirectoryOrUrl, + getResolutionModeOverrideForClause, getResolvedExternalModuleName, getSetAccessorValueParameter, + getSourceFileOfNode, GetSymbolAccessibilityDiagnostic, getTextOfNode, getThisParameter, getTrailingCommentRanges, + hasDynamicName, hasEffectiveModifier, hasExtension, hasJSDocNodes, HasModifiers, hasSyntacticModifier, + HeritageClause, Identifier, ImportDeclaration, ImportEqualsDeclaration, ImportTypeNode, IndexSignatureDeclaration, + InterfaceDeclaration, isAnyImportSyntax, isArray, isBindingPattern, isClassDeclaration, isDeclaration, isEntityName, + isEntityNameExpression, isExportAssignment, isExportDeclaration, isExternalModule, isExternalModuleAugmentation, + isExternalModuleIndicator, isExternalModuleReference, isExternalOrCommonJsModule, isFunctionDeclaration, + isFunctionLike, isGlobalScopeAugmentation, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, + isIndexSignatureDeclaration, isInterfaceDeclaration, isJsonSourceFile, isLateVisibilityPaintedStatement, + isLiteralImportTypeNode, isMappedTypeNode, isMethodDeclaration, isMethodSignature, isModifier, isModuleDeclaration, + isNightly, isOmittedExpression, isPrivateIdentifier, isPropertyAccessExpression, isPropertySignature, + isSemicolonClassElement, isSetAccessorDeclaration, isSourceFile, isSourceFileJS, isSourceFileNotJson, + isStringANonContextualKeyword, isStringLiteral, isStringLiteralLike, isTupleTypeNode, isTypeAliasDeclaration, + isTypeNode, isTypeParameterDeclaration, isTypeQueryNode, isUnparsedSource, last, LateBoundDeclaration, + LateVisibilityPaintedStatement, length, map, Map, mapDefined, MethodDeclaration, MethodSignature, Modifier, + ModifierFlags, ModuleBody, ModuleDeclaration, moduleSpecifiers, NamedDeclaration, NamespaceDeclaration, + needsScopeMarker, Node, NodeArray, NodeBuilderFlags, NodeFlags, NodeId, normalizeSlashes, OmittedExpression, + orderedRemoveItem, ParameterDeclaration, parseNodeFactory, pathContainsNodeModules, pathIsRelative, + PropertyDeclaration, PropertySignature, pushIfUnique, removeAllComments, Set, SetAccessorDeclaration, + setCommentRange, setEmitFlags, setOriginalNode, setParent, setTextRange, SignatureDeclaration, skipTrivia, some, + SourceFile, startsWith, Statement, stringContains, StringLiteral, Symbol, SymbolAccessibility, + SymbolAccessibilityResult, SymbolFlags, SymbolTracker, SyntaxKind, toFileNameLowerCase, toPath, + TransformationContext, transformNodes, tryCast, TypeAliasDeclaration, TypeNode, TypeParameterDeclaration, + TypeReferenceNode, unescapeLeadingUnderscores, UnparsedSource, VariableDeclaration, VariableStatement, visitArray, + visitEachChild, visitNode, visitNodes, VisitResult, +} from "../_namespaces/ts"; /** @internal */ -export function getDeclarationDiagnostics(host: ts.EmitHost, resolver: ts.EmitResolver, file: ts.SourceFile | undefined): ts.DiagnosticWithLocation[] | undefined { +export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined { const compilerOptions = host.getCompilerOptions(); - const result = ts.transformNodes(resolver, host, ts.factory, compilerOptions, file ? [file] : ts.filter(host.getSourceFiles(), ts.isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false); + const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false); return result.diagnostics; } -function hasInternalAnnotation(range: ts.CommentRange, currentSourceFile: ts.SourceFile) { +function hasInternalAnnotation(range: CommentRange, currentSourceFile: SourceFile) { const comment = currentSourceFile.text.substring(range.pos, range.end); - return ts.stringContains(comment, "@internal"); + return stringContains(comment, "@internal"); } /** @internal */ -export function isInternalDeclaration(node: ts.Node, currentSourceFile: ts.SourceFile) { - const parseTreeNode = ts.getParseTreeNode(node); - if (parseTreeNode && parseTreeNode.kind === ts.SyntaxKind.Parameter) { - const paramIdx = (parseTreeNode.parent as ts.SignatureDeclaration).parameters.indexOf(parseTreeNode as ts.ParameterDeclaration); - const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as ts.SignatureDeclaration).parameters[paramIdx - 1] : undefined; +export function isInternalDeclaration(node: Node, currentSourceFile: SourceFile) { + const parseTreeNode = getParseTreeNode(node); + if (parseTreeNode && parseTreeNode.kind === SyntaxKind.Parameter) { + const paramIdx = (parseTreeNode.parent as SignatureDeclaration).parameters.indexOf(parseTreeNode as ParameterDeclaration); + const previousSibling = paramIdx > 0 ? (parseTreeNode.parent as SignatureDeclaration).parameters[paramIdx - 1] : undefined; const text = currentSourceFile.text; const commentRanges = previousSibling - ? ts.concatenate( + ? concatenate( // to handle // ... parameters, /* @internal */ // public param: string - ts.getTrailingCommentRanges(text, ts.skipTrivia(text, previousSibling.end + 1, /* stopAfterLineBreak */ false, /* stopAtComments */ true)), - ts.getLeadingCommentRanges(text, node.pos) + getTrailingCommentRanges(text, skipTrivia(text, previousSibling.end + 1, /* stopAfterLineBreak */ false, /* stopAtComments */ true)), + getLeadingCommentRanges(text, node.pos) ) - : ts.getTrailingCommentRanges(text, ts.skipTrivia(text, node.pos, /* stopAfterLineBreak */ false, /* stopAtComments */ true)); - return commentRanges && commentRanges.length && hasInternalAnnotation(ts.last(commentRanges), currentSourceFile); + : getTrailingCommentRanges(text, skipTrivia(text, node.pos, /* stopAfterLineBreak */ false, /* stopAtComments */ true)); + return commentRanges && commentRanges.length && hasInternalAnnotation(last(commentRanges), currentSourceFile); } - const leadingCommentRanges = parseTreeNode && ts.getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile); - return !!ts.forEach(leadingCommentRanges, range => { + const leadingCommentRanges = parseTreeNode && getLeadingCommentRangesOfNode(parseTreeNode, currentSourceFile); + return !!forEach(leadingCommentRanges, range => { return hasInternalAnnotation(range, currentSourceFile); }); } const declarationEmitNodeBuilderFlags = - ts.NodeBuilderFlags.MultilineObjectLiterals | - ts.NodeBuilderFlags.WriteClassExpressionAsTypeLiteral | - ts.NodeBuilderFlags.UseTypeOfFunction | - ts.NodeBuilderFlags.UseStructuralFallback | - ts.NodeBuilderFlags.AllowEmptyTuple | - ts.NodeBuilderFlags.GenerateNamesForShadowedTypeParams | - ts.NodeBuilderFlags.NoTruncation; + NodeBuilderFlags.MultilineObjectLiterals | + NodeBuilderFlags.WriteClassExpressionAsTypeLiteral | + NodeBuilderFlags.UseTypeOfFunction | + NodeBuilderFlags.UseStructuralFallback | + NodeBuilderFlags.AllowEmptyTuple | + NodeBuilderFlags.GenerateNamesForShadowedTypeParams | + NodeBuilderFlags.NoTruncation; /** @internal */ /** @@ -52,24 +92,24 @@ const declarationEmitNodeBuilderFlags = * in many places this transformer assumes it will be operating on parse tree nodes directly. * This means that _no transforms should be allowed to occur before this one_. */ -export function transformDeclarations(context: ts.TransformationContext) { - const throwDiagnostic = () => ts.Debug.fail("Diagnostic emitted without context"); - let getSymbolAccessibilityDiagnostic: ts.GetSymbolAccessibilityDiagnostic = throwDiagnostic; +export function transformDeclarations(context: TransformationContext) { + const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context"); + let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic; let needsDeclare = true; let isBundledEmit = false; let resultHasExternalModuleIndicator = false; let needsScopeFixMarker = false; let resultHasScopeMarker = false; - let enclosingDeclaration: ts.Node; - let necessaryTypeReferences: ts.Set<[specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined]> | undefined; - let lateMarkedStatements: ts.LateVisibilityPaintedStatement[] | undefined; - let lateStatementReplacementMap: ts.ESMap>; + let enclosingDeclaration: Node; + let necessaryTypeReferences: Set<[specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]> | undefined; + let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; + let lateStatementReplacementMap: ESMap>; let suppressNewDiagnosticContexts: boolean; - let exportedModulesFromDeclarationEmit: ts.Symbol[] | undefined; + let exportedModulesFromDeclarationEmit: Symbol[] | undefined; const { factory } = context; const host = context.getEmitHost(); - const symbolTracker: ts.SymbolTracker = { + const symbolTracker: SymbolTracker = { trackSymbol, reportInaccessibleThisError, reportInaccessibleUniqueSymbolError, @@ -84,41 +124,41 @@ export function transformDeclarations(context: ts.TransformationContext) { reportNonSerializableProperty, reportImportTypeNodeResolutionModeOverride, }; - let errorNameNode: ts.DeclarationName | undefined; - let errorFallbackNode: ts.Declaration | undefined; + let errorNameNode: DeclarationName | undefined; + let errorFallbackNode: Declaration | undefined; - let currentSourceFile: ts.SourceFile; - let refs: ts.ESMap; - let libs: ts.ESMap; - let emittedImports: readonly ts.AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass + let currentSourceFile: SourceFile; + let refs: ESMap; + let libs: ESMap; + let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass const resolver = context.getEmitResolver(); const options = context.getCompilerOptions(); const { noResolve, stripInternal } = options; return transformRoot; - function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: readonly [specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined][] | undefined): void { + function recordTypeReferenceDirectivesIfNecessary(typeReferenceDirectives: readonly [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined): void { if (!typeReferenceDirectives) { return; } - necessaryTypeReferences = necessaryTypeReferences || new ts.Set(); + necessaryTypeReferences = necessaryTypeReferences || new Set(); for (const ref of typeReferenceDirectives) { necessaryTypeReferences.add(ref); } } - function trackReferencedAmbientModule(node: ts.ModuleDeclaration, symbol: ts.Symbol) { + function trackReferencedAmbientModule(node: ModuleDeclaration, symbol: Symbol) { // If it is visible via `// `, then we should just use that - const directives = resolver.getTypeReferenceDirectivesForSymbol(symbol, ts.SymbolFlags.All); - if (ts.length(directives)) { + const directives = resolver.getTypeReferenceDirectivesForSymbol(symbol, SymbolFlags.All); + if (length(directives)) { return recordTypeReferenceDirectivesIfNecessary(directives); } // Otherwise we should emit a path-based reference - const container = ts.getSourceFileOfNode(node); - refs.set(ts.getOriginalNodeId(container), container); + const container = getSourceFileOfNode(node); + refs.set(getOriginalNodeId(container), container); } - function handleSymbolAccessibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult) { - if (symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.Accessible) { + function handleSymbolAccessibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) { + if (symbolAccessibilityResult.accessibility === SymbolAccessibility.Accessible) { // Add aliases back onto the possible imports list if they're not there so we can try them again with updated visibility info if (symbolAccessibilityResult && symbolAccessibilityResult.aliasesToMakeVisible) { if (!lateMarkedStatements) { @@ -126,7 +166,7 @@ export function transformDeclarations(context: ts.TransformationContext) { } else { for (const ref of symbolAccessibilityResult.aliasesToMakeVisible) { - ts.pushIfUnique(lateMarkedStatements, ref); + pushIfUnique(lateMarkedStatements, ref); } } } @@ -138,14 +178,14 @@ export function transformDeclarations(context: ts.TransformationContext) { const errorInfo = getSymbolAccessibilityDiagnostic(symbolAccessibilityResult); if (errorInfo) { if (errorInfo.typeName) { - context.addDiagnostic(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, + context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, - ts.getTextOfNode(errorInfo.typeName), + getTextOfNode(errorInfo.typeName), symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); } else { - context.addDiagnostic(ts.createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, + context.addDiagnostic(createDiagnosticForNode(symbolAccessibilityResult.errorNode || errorInfo.errorNode, errorInfo.diagnosticMessage, symbolAccessibilityResult.errorSymbolName, symbolAccessibilityResult.errorModuleName)); @@ -156,14 +196,14 @@ export function transformDeclarations(context: ts.TransformationContext) { return false; } - function trackExternalModuleSymbolOfImportTypeNode(symbol: ts.Symbol) { + function trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol) { if (!isBundledEmit) { (exportedModulesFromDeclarationEmit || (exportedModulesFromDeclarationEmit = [])).push(symbol); } } - function trackSymbol(symbol: ts.Symbol, enclosingDeclaration?: ts.Node, meaning?: ts.SymbolFlags) { - if (symbol.flags & ts.SymbolFlags.TypeParameter) return false; + function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { + if (symbol.flags & SymbolFlags.TypeParameter) return false; const issuedDiagnostic = handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning)); return issuedDiagnostic; @@ -172,20 +212,20 @@ export function transformDeclarations(context: ts.TransformationContext) { function reportPrivateInBaseOfClassExpression(propertyName: string) { if (errorNameNode || errorFallbackNode) { context.addDiagnostic( - ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName)); + createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.Property_0_of_exported_class_expression_may_not_be_private_or_protected, propertyName)); } } function errorDeclarationNameWithFallback() { - return errorNameNode ? ts.declarationNameToString(errorNameNode) : - errorFallbackNode && ts.getNameOfDeclaration(errorFallbackNode) ? ts.declarationNameToString(ts.getNameOfDeclaration(errorFallbackNode)) : - errorFallbackNode && ts.isExportAssignment(errorFallbackNode) ? errorFallbackNode.isExportEquals ? "export=" : "default" : + return errorNameNode ? declarationNameToString(errorNameNode) : + errorFallbackNode && getNameOfDeclaration(errorFallbackNode) ? declarationNameToString(getNameOfDeclaration(errorFallbackNode)) : + errorFallbackNode && isExportAssignment(errorFallbackNode) ? errorFallbackNode.isExportEquals ? "export=" : "default" : "(Missing)"; // same fallback declarationNameToString uses when node is zero-width (ie, nameless) } function reportInaccessibleUniqueSymbolError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), "unique symbol")); } @@ -193,14 +233,14 @@ export function transformDeclarations(context: ts.TransformationContext) { function reportCyclicStructureError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary, + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_a_type_with_a_cyclic_structure_which_cannot_be_trivially_serialized_A_type_annotation_is_necessary, errorDeclarationNameWithFallback())); } } function reportInaccessibleThisError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), "this")); } @@ -208,7 +248,7 @@ export function transformDeclarations(context: ts.TransformationContext) { function reportLikelyUnsafeImportRequiredError(specifier: string) { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary, + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_0_cannot_be_named_without_a_reference_to_1_This_is_likely_not_portable_A_type_annotation_is_necessary, errorDeclarationNameWithFallback(), specifier)); } @@ -216,18 +256,18 @@ export function transformDeclarations(context: ts.TransformationContext) { function reportTruncationError() { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed)); + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_inferred_type_of_this_node_exceeds_the_maximum_length_the_compiler_will_serialize_An_explicit_type_annotation_is_needed)); } } - function reportNonlocalAugmentation(containingFile: ts.SourceFile, parentSymbol: ts.Symbol, symbol: ts.Symbol) { - const primaryDeclaration = parentSymbol.declarations?.find(d => ts.getSourceFileOfNode(d) === containingFile); - const augmentingDeclarations = ts.filter(symbol.declarations, d => ts.getSourceFileOfNode(d) !== containingFile); + function reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, symbol: Symbol) { + const primaryDeclaration = parentSymbol.declarations?.find(d => getSourceFileOfNode(d) === containingFile); + const augmentingDeclarations = filter(symbol.declarations, d => getSourceFileOfNode(d) !== containingFile); if (primaryDeclaration && augmentingDeclarations) { for (const augmentations of augmentingDeclarations) { - context.addDiagnostic(ts.addRelatedInfo( - ts.createDiagnosticForNode(augmentations, ts.Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized), - ts.createDiagnosticForNode(primaryDeclaration, ts.Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file) + context.addDiagnostic(addRelatedInfo( + createDiagnosticForNode(augmentations, Diagnostics.Declaration_augments_declaration_in_another_file_This_cannot_be_serialized), + createDiagnosticForNode(primaryDeclaration, Diagnostics.This_is_the_declaration_being_augmented_Consider_moving_the_augmenting_declaration_into_the_same_file) )); } } @@ -235,22 +275,22 @@ export function transformDeclarations(context: ts.TransformationContext) { function reportNonSerializableProperty(propertyName: string) { if (errorNameNode || errorFallbackNode) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, propertyName)); + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_node_cannot_be_serialized_because_its_property_0_cannot_be_serialized, propertyName)); } } function reportImportTypeNodeResolutionModeOverride() { - if (!ts.isNightly() && (errorNameNode || errorFallbackNode)) { - context.addDiagnostic(ts.createDiagnosticForNode((errorNameNode || errorFallbackNode)!, ts.Diagnostics.The_type_of_this_expression_cannot_be_named_without_a_resolution_mode_assertion_which_is_an_unstable_feature_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); + if (!isNightly() && (errorNameNode || errorFallbackNode)) { + context.addDiagnostic(createDiagnosticForNode((errorNameNode || errorFallbackNode)!, Diagnostics.The_type_of_this_expression_cannot_be_named_without_a_resolution_mode_assertion_which_is_an_unstable_feature_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); } } - function transformDeclarationsForJS(sourceFile: ts.SourceFile, bundled?: boolean) { + function transformDeclarationsForJS(sourceFile: SourceFile, bundled?: boolean) { const oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = (s) => (s.errorNode && ts.canProduceDiagnostics(s.errorNode) ? ts.createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({ + getSymbolAccessibilityDiagnostic = (s) => (s.errorNode && canProduceDiagnostics(s.errorNode) ? createGetSymbolAccessibilityDiagnosticForNode(s.errorNode)(s) : ({ diagnosticMessage: s.errorModuleName - ? ts.Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit - : ts.Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit, + ? Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_from_module_1_An_explicit_type_annotation_may_unblock_declaration_emit + : Diagnostics.Declaration_emit_for_this_file_requires_using_private_name_0_An_explicit_type_annotation_may_unblock_declaration_emit, errorNode: s.errorNode || sourceFile })); const result = resolver.getDeclarationStatementsForSourceFile(sourceFile, declarationEmitNodeBuilderFlags, symbolTracker, bundled); @@ -258,20 +298,20 @@ export function transformDeclarations(context: ts.TransformationContext) { return result; } - function transformRoot(node: ts.Bundle): ts.Bundle; - function transformRoot(node: ts.SourceFile): ts.SourceFile; - function transformRoot(node: ts.SourceFile | ts.Bundle): ts.SourceFile | ts.Bundle; - function transformRoot(node: ts.SourceFile | ts.Bundle) { - if (node.kind === ts.SyntaxKind.SourceFile && node.isDeclarationFile) { + function transformRoot(node: Bundle): Bundle; + function transformRoot(node: SourceFile): SourceFile; + function transformRoot(node: SourceFile | Bundle): SourceFile | Bundle; + function transformRoot(node: SourceFile | Bundle) { + if (node.kind === SyntaxKind.SourceFile && node.isDeclarationFile) { return node; } - if (node.kind === ts.SyntaxKind.Bundle) { + if (node.kind === SyntaxKind.Bundle) { isBundledEmit = true; - refs = new ts.Map(); - libs = new ts.Map(); + refs = new Map(); + libs = new Map(); let hasNoDefaultLib = false; - const bundle = factory.createBundle(ts.map(node.sourceFiles, + const bundle = factory.createBundle(map(node.sourceFiles, sourceFile => { if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217 hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib; @@ -279,33 +319,33 @@ export function transformDeclarations(context: ts.TransformationContext) { enclosingDeclaration = sourceFile; lateMarkedStatements = undefined; suppressNewDiagnosticContexts = false; - lateStatementReplacementMap = new ts.Map(); + lateStatementReplacementMap = new Map(); getSymbolAccessibilityDiagnostic = throwDiagnostic; needsScopeFixMarker = false; resultHasScopeMarker = false; collectReferences(sourceFile, refs); collectLibs(sourceFile, libs); - if (ts.isExternalOrCommonJsModule(sourceFile) || ts.isJsonSourceFile(sourceFile)) { + if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) { resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules) needsDeclare = false; - const statements = ts.isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : ts.visitNodes(sourceFile.statements, visitDeclarationStatements); + const statements = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements); const newFile = factory.updateSourceFile(sourceFile, [factory.createModuleDeclaration( - [factory.createModifier(ts.SyntaxKind.DeclareKeyword)], - factory.createStringLiteral(ts.getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), - factory.createModuleBlock(ts.setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)) + [factory.createModifier(SyntaxKind.DeclareKeyword)], + factory.createStringLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), + factory.createModuleBlock(setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)) )], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); return newFile; } needsDeclare = true; - const updated = ts.isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : ts.visitNodes(sourceFile.statements, visitDeclarationStatements); + const updated = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements); return factory.updateSourceFile(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []); } - ), ts.mapDefined(node.prepends, prepend => { - if (prepend.kind === ts.SyntaxKind.InputFiles) { - const sourceFile = ts.createUnparsedSourceFile(prepend, "dts", stripInternal); + ), mapDefined(node.prepends, prepend => { + if (prepend.kind === SyntaxKind.InputFiles) { + const sourceFile = createUnparsedSourceFile(prepend, "dts", stripInternal); hasNoDefaultLib = hasNoDefaultLib || !!sourceFile.hasNoDefaultLib; collectReferences(sourceFile, refs); - recordTypeReferenceDirectivesIfNecessary(ts.map(sourceFile.typeReferenceDirectives, ref => [ref.fileName, ref.resolutionMode])); + recordTypeReferenceDirectivesIfNecessary(map(sourceFile.typeReferenceDirectives, ref => [ref.fileName, ref.resolutionMode])); collectLibs(sourceFile, libs); return sourceFile; } @@ -315,8 +355,8 @@ export function transformDeclarations(context: ts.TransformationContext) { bundle.syntheticTypeReferences = getFileReferencesForUsedTypeReferences(); bundle.syntheticLibReferences = getLibReferences(); bundle.hasNoDefaultLib = hasNoDefaultLib; - const outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); - const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as ts.FileReference[], outputFilePath); + const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); + const referenceVisitor = mapReferencesIntoArray(bundle.syntheticFileReferences as FileReference[], outputFilePath); refs.forEach(referenceVisitor); return bundle; } @@ -332,26 +372,26 @@ export function transformDeclarations(context: ts.TransformationContext) { resultHasExternalModuleIndicator = false; suppressNewDiagnosticContexts = false; lateMarkedStatements = undefined; - lateStatementReplacementMap = new ts.Map(); + lateStatementReplacementMap = new Map(); necessaryTypeReferences = undefined; - refs = collectReferences(currentSourceFile, new ts.Map()); - libs = collectLibs(currentSourceFile, new ts.Map()); - const references: ts.FileReference[] = []; - const outputFilePath = ts.getDirectoryPath(ts.normalizeSlashes(ts.getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); + refs = collectReferences(currentSourceFile, new Map()); + libs = collectLibs(currentSourceFile, new Map()); + const references: FileReference[] = []; + const outputFilePath = getDirectoryPath(normalizeSlashes(getOutputPathsFor(node, host, /*forceDtsPaths*/ true).declarationFilePath!)); const referenceVisitor = mapReferencesIntoArray(references, outputFilePath); - let combinedStatements: ts.NodeArray; - if (ts.isSourceFileJS(currentSourceFile)) { + let combinedStatements: NodeArray; + if (isSourceFileJS(currentSourceFile)) { combinedStatements = factory.createNodeArray(transformDeclarationsForJS(node)); refs.forEach(referenceVisitor); - emittedImports = ts.filter(combinedStatements, ts.isAnyImportSyntax); + emittedImports = filter(combinedStatements, isAnyImportSyntax); } else { - const statements = ts.visitNodes(node.statements, visitDeclarationStatements); - combinedStatements = ts.setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); + const statements = visitNodes(node.statements, visitDeclarationStatements); + combinedStatements = setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); refs.forEach(referenceVisitor); - emittedImports = ts.filter(combinedStatements, ts.isAnyImportSyntax); - if (ts.isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { - combinedStatements = ts.setTextRange(factory.createNodeArray([...combinedStatements, ts.createEmptyExports(factory)]), combinedStatements); + emittedImports = filter(combinedStatements, isAnyImportSyntax); + if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { + combinedStatements = setTextRange(factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), combinedStatements); } } const updated = factory.updateSourceFile(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences()); @@ -359,24 +399,24 @@ export function transformDeclarations(context: ts.TransformationContext) { return updated; function getLibReferences() { - return ts.map(ts.arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 })); + return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 })); } function getFileReferencesForUsedTypeReferences() { - return necessaryTypeReferences ? ts.mapDefined(ts.arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; + return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; } - function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: ts.SourceFile["impliedNodeFormat"] | undefined]): ts.FileReference | undefined { + function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: SourceFile["impliedNodeFormat"] | undefined]): FileReference | undefined { // Elide type references for which we have imports if (emittedImports) { for (const importStatement of emittedImports) { - if (ts.isImportEqualsDeclaration(importStatement) && ts.isExternalModuleReference(importStatement.moduleReference)) { + if (isImportEqualsDeclaration(importStatement) && isExternalModuleReference(importStatement.moduleReference)) { const expr = importStatement.moduleReference.expression; - if (ts.isStringLiteralLike(expr) && expr.text === typeName) { + if (isStringLiteralLike(expr) && expr.text === typeName) { return undefined; } } - else if (ts.isImportDeclaration(importStatement) && ts.isStringLiteral(importStatement.moduleSpecifier) && importStatement.moduleSpecifier.text === typeName) { + else if (isImportDeclaration(importStatement) && isStringLiteral(importStatement.moduleSpecifier) && importStatement.moduleSpecifier.text === typeName) { return undefined; } } @@ -384,27 +424,27 @@ export function transformDeclarations(context: ts.TransformationContext) { return { fileName: typeName, pos: -1, end: -1, ...(mode ? { resolutionMode: mode } : undefined) }; } - function mapReferencesIntoArray(references: ts.FileReference[], outputFilePath: string): (file: ts.SourceFile) => void { + function mapReferencesIntoArray(references: FileReference[], outputFilePath: string): (file: SourceFile) => void { return file => { let declFileName: string; if (file.isDeclarationFile) { // Neither decl files or js should have their refs changed declFileName = file.fileName; } else { - if (isBundledEmit && ts.contains((node as ts.Bundle).sourceFiles, file)) return; // Omit references to files which are being merged - const paths = ts.getOutputPathsFor(file, host, /*forceDtsPaths*/ true); + if (isBundledEmit && contains((node as Bundle).sourceFiles, file)) return; // Omit references to files which are being merged + const paths = getOutputPathsFor(file, host, /*forceDtsPaths*/ true); declFileName = paths.declarationFilePath || paths.jsFilePath || file.fileName; } if (declFileName) { - const specifier = ts.moduleSpecifiers.getModuleSpecifier( + const specifier = moduleSpecifiers.getModuleSpecifier( options, currentSourceFile, - ts.toPath(outputFilePath, host.getCurrentDirectory(), host.getCanonicalFileName), - ts.toPath(declFileName, host.getCurrentDirectory(), host.getCanonicalFileName), + toPath(outputFilePath, host.getCurrentDirectory(), host.getCanonicalFileName), + toPath(declFileName, host.getCurrentDirectory(), host.getCanonicalFileName), host, ); - if (!ts.pathIsRelative(specifier)) { + if (!pathIsRelative(specifier)) { // If some compiler option/symlink/whatever allows access to the file containing the ambient module declaration // via a non-relative name, emit a type reference directive to that non-relative name, rather than // a relative path to the declaration file @@ -412,20 +452,20 @@ export function transformDeclarations(context: ts.TransformationContext) { return; } - let fileName = ts.getRelativePathToDirectoryOrUrl( + let fileName = getRelativePathToDirectoryOrUrl( outputFilePath, declFileName, host.getCurrentDirectory(), host.getCanonicalFileName, /*isAbsolutePathAnUrl*/ false ); - if (ts.startsWith(fileName, "./") && ts.hasExtension(fileName)) { + if (startsWith(fileName, "./") && hasExtension(fileName)) { fileName = fileName.substring(2); } // omit references to files from node_modules (npm may disambiguate module // references when installing this package, making the path is unreliable). - if (ts.startsWith(fileName, "node_modules/") || ts.pathContainsNodeModules(fileName)) { + if (startsWith(fileName, "node_modules/") || pathContainsNodeModules(fileName)) { return; } @@ -435,46 +475,46 @@ export function transformDeclarations(context: ts.TransformationContext) { } } - function collectReferences(sourceFile: ts.SourceFile | ts.UnparsedSource, ret: ts.ESMap) { - if (noResolve || (!ts.isUnparsedSource(sourceFile) && ts.isSourceFileJS(sourceFile))) return ret; - ts.forEach(sourceFile.referencedFiles, f => { + function collectReferences(sourceFile: SourceFile | UnparsedSource, ret: ESMap) { + if (noResolve || (!isUnparsedSource(sourceFile) && isSourceFileJS(sourceFile))) return ret; + forEach(sourceFile.referencedFiles, f => { const elem = host.getSourceFileFromReference(sourceFile, f); if (elem) { - ret.set(ts.getOriginalNodeId(elem), elem); + ret.set(getOriginalNodeId(elem), elem); } }); return ret; } - function collectLibs(sourceFile: ts.SourceFile | ts.UnparsedSource, ret: ts.ESMap) { - ts.forEach(sourceFile.libReferenceDirectives, ref => { + function collectLibs(sourceFile: SourceFile | UnparsedSource, ret: ESMap) { + forEach(sourceFile.libReferenceDirectives, ref => { const lib = host.getLibFileFromReference(ref); if (lib) { - ret.set(ts.toFileNameLowerCase(ref.fileName), true); + ret.set(toFileNameLowerCase(ref.fileName), true); } }); return ret; } - function filterBindingPatternInitializersAndRenamings(name: ts.BindingName) { - if (name.kind === ts.SyntaxKind.Identifier) { + function filterBindingPatternInitializersAndRenamings(name: BindingName) { + if (name.kind === SyntaxKind.Identifier) { return name; } else { - if (name.kind === ts.SyntaxKind.ArrayBindingPattern) { - return factory.updateArrayBindingPattern(name, ts.visitNodes(name.elements, visitBindingElement)); + if (name.kind === SyntaxKind.ArrayBindingPattern) { + return factory.updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement)); } else { - return factory.updateObjectBindingPattern(name, ts.visitNodes(name.elements, visitBindingElement)); + return factory.updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement)); } } - function visitBindingElement(elem: T): T; - function visitBindingElement(elem: ts.ArrayBindingElement): ts.ArrayBindingElement { - if (elem.kind === ts.SyntaxKind.OmittedExpression) { + function visitBindingElement(elem: T): T; + function visitBindingElement(elem: ArrayBindingElement): ArrayBindingElement { + if (elem.kind === SyntaxKind.OmittedExpression) { return elem; } - if (elem.propertyName && ts.isIdentifier(elem.propertyName) && ts.isIdentifier(elem.name) && !elem.symbol.isReferenced) { + if (elem.propertyName && isIdentifier(elem.propertyName) && isIdentifier(elem.name) && !elem.symbol.isReferenced) { // Unnecessary property renaming is forbidden in types, so remove renaming return factory.updateBindingElement( elem, @@ -494,18 +534,18 @@ export function transformDeclarations(context: ts.TransformationContext) { } } - function ensureParameter(p: ts.ParameterDeclaration, modifierMask?: ts.ModifierFlags, type?: ts.TypeNode): ts.ParameterDeclaration { + function ensureParameter(p: ParameterDeclaration, modifierMask?: ModifierFlags, type?: TypeNode): ParameterDeclaration { let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(p); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p); } const newParam = factory.updateParameterDeclaration( p, maskModifiers(p, modifierMask), p.dotDotDotToken, filterBindingPatternInitializersAndRenamings(p.name), - resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(ts.SyntaxKind.QuestionToken)) : undefined, + resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) : undefined, ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param ensureNoInitializer(p) ); @@ -515,33 +555,33 @@ export function transformDeclarations(context: ts.TransformationContext) { return newParam; } - function shouldPrintWithInitializer(node: ts.Node) { - return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(ts.getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe + function shouldPrintWithInitializer(node: Node) { + return canHaveLiteralInitializer(node) && resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safe } function ensureNoInitializer(node: CanHaveLiteralInitializer) { if (shouldPrintWithInitializer(node)) { - return resolver.createLiteralConstValue(ts.getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe + return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe } return undefined; } type HasInferredType = - | ts.FunctionDeclaration - | ts.MethodDeclaration - | ts.GetAccessorDeclaration - | ts.SetAccessorDeclaration - | ts.BindingElement - | ts.ConstructSignatureDeclaration - | ts.VariableDeclaration - | ts.MethodSignature - | ts.CallSignatureDeclaration - | ts.ParameterDeclaration - | ts.PropertyDeclaration - | ts.PropertySignature; - - function ensureType(node: HasInferredType, type: ts.TypeNode | undefined, ignorePrivate?: boolean): ts.TypeNode | undefined { - if (!ignorePrivate && ts.hasEffectiveModifier(node, ts.ModifierFlags.Private)) { + | FunctionDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | BindingElement + | ConstructSignatureDeclaration + | VariableDeclaration + | MethodSignature + | CallSignatureDeclaration + | ParameterDeclaration + | PropertyDeclaration + | PropertySignature; + + function ensureType(node: HasInferredType, type: TypeNode | undefined, ignorePrivate?: boolean): TypeNode | undefined { + if (!ignorePrivate && hasEffectiveModifier(node, ModifierFlags.Private)) { // Private nodes emit no types (except private parameter properties, whose parameter types are actually visible) return; } @@ -549,116 +589,116 @@ export function transformDeclarations(context: ts.TransformationContext) { // Literal const declarations will have an initializer ensured rather than a type return; } - const shouldUseResolverType = node.kind === ts.SyntaxKind.Parameter && + const shouldUseResolverType = node.kind === SyntaxKind.Parameter && (resolver.isRequiredInitializedParameter(node) || resolver.isOptionalUninitializedParameterProperty(node)); if (type && !shouldUseResolverType) { - return ts.visitNode(type, visitDeclarationSubtree); + return visitNode(type, visitDeclarationSubtree); } - if (!ts.getParseTreeNode(node)) { - return type ? ts.visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + if (!getParseTreeNode(node)) { + return type ? visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } - if (node.kind === ts.SyntaxKind.SetAccessor) { + if (node.kind === SyntaxKind.SetAccessor) { // Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now // (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that) - return factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } errorNameNode = node.name; let oldDiag: typeof getSymbolAccessibilityDiagnostic; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(node); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node); } - if (node.kind === ts.SyntaxKind.VariableDeclaration || node.kind === ts.SyntaxKind.BindingElement) { + if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) { return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); } - if (node.kind === ts.SyntaxKind.Parameter - || node.kind === ts.SyntaxKind.PropertyDeclaration - || node.kind === ts.SyntaxKind.PropertySignature) { - if (ts.isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType)); + if (node.kind === SyntaxKind.Parameter + || node.kind === SyntaxKind.PropertyDeclaration + || node.kind === SyntaxKind.PropertySignature) { + if (isPropertySignature(node) || !node.initializer) return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType)); return cleanup(resolver.createTypeOfDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker, shouldUseResolverType) || resolver.createTypeOfExpression(node.initializer, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); } return cleanup(resolver.createReturnTypeOfSignatureDeclaration(node, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker)); - function cleanup(returnValue: ts.TypeNode | undefined) { + function cleanup(returnValue: TypeNode | undefined) { errorNameNode = undefined; if (!suppressNewDiagnosticContexts) { getSymbolAccessibilityDiagnostic = oldDiag; } - return returnValue || factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); + return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword); } } - function isDeclarationAndNotVisible(node: ts.NamedDeclaration) { - node = ts.getParseTreeNode(node) as ts.NamedDeclaration; + function isDeclarationAndNotVisible(node: NamedDeclaration) { + node = getParseTreeNode(node) as NamedDeclaration; switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.EnumDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: return !resolver.isDeclarationVisible(node); // The following should be doing their own visibility checks based on filtering their members - case ts.SyntaxKind.VariableDeclaration: - return !getBindingNameVisible(node as ts.VariableDeclaration); - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.VariableDeclaration: + return !getBindingNameVisible(node as VariableDeclaration); + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: return false; - case ts.SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.ClassStaticBlockDeclaration: return true; } return false; } // If the ExpandoFunctionDeclaration have multiple overloads, then we only need to emit properties for the last one. - function shouldEmitFunctionProperties(input: ts.FunctionDeclaration) { + function shouldEmitFunctionProperties(input: FunctionDeclaration) { if (input.body) { return true; } - const overloadSignatures = input.symbol.declarations?.filter(decl => ts.isFunctionDeclaration(decl) && !decl.body); + const overloadSignatures = input.symbol.declarations?.filter(decl => isFunctionDeclaration(decl) && !decl.body); return !overloadSignatures || overloadSignatures.indexOf(input) === overloadSignatures.length - 1; } - function getBindingNameVisible(elem: ts.BindingElement | ts.VariableDeclaration | ts.OmittedExpression): boolean { - if (ts.isOmittedExpression(elem)) { + function getBindingNameVisible(elem: BindingElement | VariableDeclaration | OmittedExpression): boolean { + if (isOmittedExpression(elem)) { return false; } - if (ts.isBindingPattern(elem.name)) { + if (isBindingPattern(elem.name)) { // If any child binding pattern element has been marked visible (usually by collect linked aliases), then this is visible - return ts.some(elem.name.elements, getBindingNameVisible); + return some(elem.name.elements, getBindingNameVisible); } else { return resolver.isDeclarationVisible(elem); } } - function updateParamsList(node: ts.Node, params: ts.NodeArray, modifierMask?: ts.ModifierFlags) { - if (ts.hasEffectiveModifier(node, ts.ModifierFlags.Private)) { + function updateParamsList(node: Node, params: NodeArray, modifierMask?: ModifierFlags) { + if (hasEffectiveModifier(node, ModifierFlags.Private)) { return undefined!; // TODO: GH#18217 } - const newParams = ts.map(params, p => ensureParameter(p, modifierMask)); + const newParams = map(params, p => ensureParameter(p, modifierMask)); if (!newParams) { return undefined!; // TODO: GH#18217 } return factory.createNodeArray(newParams, params.hasTrailingComma); } - function updateAccessorParamsList(input: ts.AccessorDeclaration, isPrivate: boolean) { - let newParams: ts.ParameterDeclaration[] | undefined; + function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) { + let newParams: ParameterDeclaration[] | undefined; if (!isPrivate) { - const thisParameter = ts.getThisParameter(input); + const thisParameter = getThisParameter(input); if (thisParameter) { newParams = [ensureParameter(thisParameter)]; } } - if (ts.isSetAccessorDeclaration(input)) { - let newValueParameter: ts.ParameterDeclaration | undefined; + if (isSetAccessorDeclaration(input)) { + let newValueParameter: ParameterDeclaration | undefined; if (!isPrivate) { - const valueParameter = ts.getSetAccessorValueParameter(input); + const valueParameter = getSetAccessorValueParameter(input); if (valueParameter) { const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); newValueParameter = ensureParameter(valueParameter, /*modifierMask*/ undefined, accessorType); @@ -671,45 +711,45 @@ export function transformDeclarations(context: ts.TransformationContext) { "value" ); } - newParams = ts.append(newParams, newValueParameter); + newParams = append(newParams, newValueParameter); } - return factory.createNodeArray(newParams || ts.emptyArray); + return factory.createNodeArray(newParams || emptyArray); } - function ensureTypeParams(node: ts.Node, params: ts.NodeArray | undefined) { - return ts.hasEffectiveModifier(node, ts.ModifierFlags.Private) ? undefined : ts.visitNodes(params, visitDeclarationSubtree); + function ensureTypeParams(node: Node, params: NodeArray | undefined) { + return hasEffectiveModifier(node, ModifierFlags.Private) ? undefined : visitNodes(params, visitDeclarationSubtree); } - function isEnclosingDeclaration(node: ts.Node) { - return ts.isSourceFile(node) - || ts.isTypeAliasDeclaration(node) - || ts.isModuleDeclaration(node) - || ts.isClassDeclaration(node) - || ts.isInterfaceDeclaration(node) - || ts.isFunctionLike(node) - || ts.isIndexSignatureDeclaration(node) - || ts.isMappedTypeNode(node); + function isEnclosingDeclaration(node: Node) { + return isSourceFile(node) + || isTypeAliasDeclaration(node) + || isModuleDeclaration(node) + || isClassDeclaration(node) + || isInterfaceDeclaration(node) + || isFunctionLike(node) + || isIndexSignatureDeclaration(node) + || isMappedTypeNode(node); } - function checkEntityNameVisibility(entityName: ts.EntityNameOrEntityNameExpression, enclosingDeclaration: ts.Node) { + function checkEntityNameVisibility(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node) { const visibilityResult = resolver.isEntityNameVisible(entityName, enclosingDeclaration); handleSymbolAccessibilityError(visibilityResult); recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForEntityName(entityName)); } - function preserveJsDoc(updated: T, original: ts.Node): T { - if (ts.hasJSDocNodes(updated) && ts.hasJSDocNodes(original)) { + function preserveJsDoc(updated: T, original: Node): T { + if (hasJSDocNodes(updated) && hasJSDocNodes(original)) { updated.jsDoc = original.jsDoc; } - return ts.setCommentRange(updated, ts.getCommentRange(original)); + return setCommentRange(updated, getCommentRange(original)); } - function rewriteModuleSpecifier(parent: ts.ImportEqualsDeclaration | ts.ImportDeclaration | ts.ExportDeclaration | ts.ModuleDeclaration | ts.ImportTypeNode, input: T | undefined): T | ts.StringLiteral { + function rewriteModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral { if (!input) return undefined!; // TODO: GH#18217 - resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== ts.SyntaxKind.ModuleDeclaration && parent.kind !== ts.SyntaxKind.ImportType); - if (ts.isStringLiteralLike(input)) { + resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType); + if (isStringLiteralLike(input)) { if (isBundledEmit) { - const newName = ts.getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); + const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); if (newName) { return factory.createStringLiteral(newName); } @@ -724,11 +764,11 @@ export function transformDeclarations(context: ts.TransformationContext) { return input; } - function transformImportEqualsDeclaration(decl: ts.ImportEqualsDeclaration) { + function transformImportEqualsDeclaration(decl: ImportEqualsDeclaration) { if (!resolver.isDeclarationVisible(decl)) return; - if (decl.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference) { + if (decl.moduleReference.kind === SyntaxKind.ExternalModuleReference) { // Rewrite external module names if necessary - const specifier = ts.getExternalModuleImportEqualsDeclarationExpression(decl); + const specifier = getExternalModuleImportEqualsDeclarationExpression(decl); return factory.updateImportEqualsDeclaration( decl, decl.modifiers, @@ -739,14 +779,14 @@ export function transformDeclarations(context: ts.TransformationContext) { } else { const oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(decl); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(decl); checkEntityNameVisibility(decl.moduleReference, enclosingDeclaration); getSymbolAccessibilityDiagnostic = oldDiag; return decl; } } - function transformImportDeclaration(decl: ts.ImportDeclaration) { + function transformImportDeclaration(decl: ImportDeclaration) { if (!decl.importClause) { // import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc) return factory.updateImportDeclaration( @@ -768,7 +808,7 @@ export function transformDeclarations(context: ts.TransformationContext) { /*namedBindings*/ undefined, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)); } - if (decl.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { // Namespace import (optionally with visible default) const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined; return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration(decl, decl.modifiers, factory.updateImportClause( @@ -779,7 +819,7 @@ export function transformDeclarations(context: ts.TransformationContext) { ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)) : undefined; } // Named imports (optionally with visible default) - const bindingList = ts.mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined); + const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined); if ((bindingList && bindingList.length) || visibleDefaultBinding) { return factory.updateImportDeclaration( decl, @@ -807,18 +847,18 @@ export function transformDeclarations(context: ts.TransformationContext) { // Nothing visible } - function getResolutionModeOverrideForClauseInNightly(assertClause: ts.AssertClause | undefined) { - const mode = ts.getResolutionModeOverrideForClause(assertClause); + function getResolutionModeOverrideForClauseInNightly(assertClause: AssertClause | undefined) { + const mode = getResolutionModeOverrideForClause(assertClause); if (mode !== undefined) { - if (!ts.isNightly()) { - context.addDiagnostic(ts.createDiagnosticForNode(assertClause!, ts.Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); + if (!isNightly()) { + context.addDiagnostic(createDiagnosticForNode(assertClause!, Diagnostics.resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); } return assertClause; } return undefined; } - function transformAndReplaceLatePaintedStatements(statements: ts.NodeArray): ts.NodeArray { + function transformAndReplaceLatePaintedStatements(statements: NodeArray): NodeArray { // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during // error handling which must now be included in the output and themselves checked for errors. // For example: @@ -833,34 +873,34 @@ export function transformDeclarations(context: ts.TransformationContext) { // In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases. - while (ts.length(lateMarkedStatements)) { + while (length(lateMarkedStatements)) { const i = lateMarkedStatements!.shift()!; - if (!ts.isLateVisibilityPaintedStatement(i)) { - return ts.Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${ts.Debug.formatSyntaxKind((i as ts.Node).kind)}`); + if (!isLateVisibilityPaintedStatement(i)) { + return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${Debug.formatSyntaxKind((i as Node).kind)}`); } const priorNeedsDeclare = needsDeclare; - needsDeclare = i.parent && ts.isSourceFile(i.parent) && !(ts.isExternalModule(i.parent) && isBundledEmit); + needsDeclare = i.parent && isSourceFile(i.parent) && !(isExternalModule(i.parent) && isBundledEmit); const result = transformTopLevelDeclaration(i); needsDeclare = priorNeedsDeclare; - lateStatementReplacementMap.set(ts.getOriginalNodeId(i), result); + lateStatementReplacementMap.set(getOriginalNodeId(i), result); } // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list // (and remove them from the set to examine for outter declarations) - return ts.visitNodes(statements, visitLateVisibilityMarkedStatements); + return visitNodes(statements, visitLateVisibilityMarkedStatements); - function visitLateVisibilityMarkedStatements(statement: ts.Statement) { - if (ts.isLateVisibilityPaintedStatement(statement)) { - const key = ts.getOriginalNodeId(statement); + function visitLateVisibilityMarkedStatements(statement: Statement) { + if (isLateVisibilityPaintedStatement(statement)) { + const key = getOriginalNodeId(statement); if (lateStatementReplacementMap.has(key)) { const result = lateStatementReplacementMap.get(key); lateStatementReplacementMap.delete(key); if (result) { - if (ts.isArray(result) ? ts.some(result, ts.needsScopeMarker) : ts.needsScopeMarker(result)) { + if (isArray(result) ? some(result, needsScopeMarker) : needsScopeMarker(result)) { // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier needsScopeFixMarker = true; } - if (ts.isSourceFile(statement.parent) && (ts.isArray(result) ? ts.some(result, ts.isExternalModuleIndicator) : ts.isExternalModuleIndicator(result))) { + if (isSourceFile(statement.parent) && (isArray(result) ? some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result))) { resultHasExternalModuleIndicator = true; } } @@ -871,47 +911,47 @@ export function transformDeclarations(context: ts.TransformationContext) { } } - function visitDeclarationSubtree(input: ts.Node): ts.VisitResult { + function visitDeclarationSubtree(input: Node): VisitResult { if (shouldStripInternal(input)) return; - if (ts.isDeclaration(input)) { + if (isDeclaration(input)) { if (isDeclarationAndNotVisible(input)) return; - if (ts.hasDynamicName(input) && !resolver.isLateBound(ts.getParseTreeNode(input) as ts.Declaration)) { + if (hasDynamicName(input) && !resolver.isLateBound(getParseTreeNode(input) as Declaration)) { return; } } // Elide implementation signatures from overload sets - if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; + if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; // Elide semicolon class statements - if (ts.isSemicolonClassElement(input)) return; + if (isSemicolonClassElement(input)) return; let previousEnclosingDeclaration: typeof enclosingDeclaration; if (isEnclosingDeclaration(input)) { previousEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = input as ts.Declaration; + enclosingDeclaration = input as Declaration; } const oldDiag = getSymbolAccessibilityDiagnostic; // Setup diagnostic-related flags before first potential `cleanup` call, otherwise // We'd see a TDZ violation at runtime - const canProduceDiagnostic = ts.canProduceDiagnostics(input); + const canProduceDiagnostic = canProduceDiagnostics(input); const oldWithinObjectLiteralType = suppressNewDiagnosticContexts; - let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === ts.SyntaxKind.TypeLiteral || input.kind === ts.SyntaxKind.MappedType) && input.parent.kind !== ts.SyntaxKind.TypeAliasDeclaration); + let shouldEnterSuppressNewDiagnosticsContextContext = ((input.kind === SyntaxKind.TypeLiteral || input.kind === SyntaxKind.MappedType) && input.parent.kind !== SyntaxKind.TypeAliasDeclaration); // Emit methods which are private as properties with no type information - if (ts.isMethodDeclaration(input) || ts.isMethodSignature(input)) { - if (ts.hasEffectiveModifier(input, ts.ModifierFlags.Private)) { + if (isMethodDeclaration(input) || isMethodSignature(input)) { + if (hasEffectiveModifier(input, ModifierFlags.Private)) { if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload return cleanup(factory.createPropertyDeclaration(ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined)); } } if (canProduceDiagnostic && !suppressNewDiagnosticContexts) { - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(input); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input); } - if (ts.isTypeQueryNode(input)) { + if (isTypeQueryNode(input)) { checkEntityNameVisibility(input.exprName, enclosingDeclaration); } @@ -922,36 +962,36 @@ export function transformDeclarations(context: ts.TransformationContext) { if (isProcessedComponent(input)) { switch (input.kind) { - case ts.SyntaxKind.ExpressionWithTypeArguments: { - if ((ts.isEntityName(input.expression) || ts.isEntityNameExpression(input.expression))) { + case SyntaxKind.ExpressionWithTypeArguments: { + if ((isEntityName(input.expression) || isEntityNameExpression(input.expression))) { checkEntityNameVisibility(input.expression, enclosingDeclaration); } - const node = ts.visitEachChild(input, visitDeclarationSubtree, context); + const node = visitEachChild(input, visitDeclarationSubtree, context); return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments)); } - case ts.SyntaxKind.TypeReference: { + case SyntaxKind.TypeReference: { checkEntityNameVisibility(input.typeName, enclosingDeclaration); - const node = ts.visitEachChild(input, visitDeclarationSubtree, context); + const node = visitEachChild(input, visitDeclarationSubtree, context); return cleanup(factory.updateTypeReferenceNode(node, node.typeName, node.typeArguments)); } - case ts.SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructSignature: return cleanup(factory.updateConstructSignature( input, ensureTypeParams(input, input.typeParameters), updateParamsList(input, input.parameters), ensureType(input, input.type) )); - case ts.SyntaxKind.Constructor: { + case SyntaxKind.Constructor: { // A constructor declaration may not have a type annotation const ctor = factory.createConstructorDeclaration( /*modifiers*/ ensureModifiers(input), - updateParamsList(input, input.parameters, ts.ModifierFlags.None), + updateParamsList(input, input.parameters, ModifierFlags.None), /*body*/ undefined ); return cleanup(ctor); } - case ts.SyntaxKind.MethodDeclaration: { - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.MethodDeclaration: { + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } const sig = factory.createMethodDeclaration( @@ -966,8 +1006,8 @@ export function transformDeclarations(context: ts.TransformationContext) { ); return cleanup(sig); } - case ts.SyntaxKind.GetAccessor: { - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.GetAccessor: { + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input)); @@ -975,23 +1015,23 @@ export function transformDeclarations(context: ts.TransformationContext) { input, ensureModifiers(input), input.name, - updateAccessorParamsList(input, ts.hasEffectiveModifier(input, ts.ModifierFlags.Private)), + updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)), ensureType(input, accessorType), /*body*/ undefined)); } - case ts.SyntaxKind.SetAccessor: { - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.SetAccessor: { + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } return cleanup(factory.updateSetAccessorDeclaration( input, ensureModifiers(input), input.name, - updateAccessorParamsList(input, ts.hasEffectiveModifier(input, ts.ModifierFlags.Private)), + updateAccessorParamsList(input, hasEffectiveModifier(input, ModifierFlags.Private)), /*body*/ undefined)); } - case ts.SyntaxKind.PropertyDeclaration: - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.PropertyDeclaration: + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } return cleanup(factory.updatePropertyDeclaration( @@ -1002,8 +1042,8 @@ export function transformDeclarations(context: ts.TransformationContext) { ensureType(input, input.type), ensureNoInitializer(input) )); - case ts.SyntaxKind.PropertySignature: - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.PropertySignature: + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } return cleanup(factory.updatePropertySignature( @@ -1013,8 +1053,8 @@ export function transformDeclarations(context: ts.TransformationContext) { input.questionToken, ensureType(input, input.type) )); - case ts.SyntaxKind.MethodSignature: { - if (ts.isPrivateIdentifier(input.name)) { + case SyntaxKind.MethodSignature: { + if (isPrivateIdentifier(input.name)) { return cleanup(/*returnValue*/ undefined); } return cleanup(factory.updateMethodSignature( @@ -1027,7 +1067,7 @@ export function transformDeclarations(context: ts.TransformationContext) { ensureType(input, input.type) )); } - case ts.SyntaxKind.CallSignature: { + case SyntaxKind.CallSignature: { return cleanup(factory.updateCallSignature( input, ensureTypeParams(input, input.typeParameters), @@ -1035,69 +1075,69 @@ export function transformDeclarations(context: ts.TransformationContext) { ensureType(input, input.type) )); } - case ts.SyntaxKind.IndexSignature: { + case SyntaxKind.IndexSignature: { return cleanup(factory.updateIndexSignature( input, ensureModifiers(input), updateParamsList(input, input.parameters), - ts.visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) )); } - case ts.SyntaxKind.VariableDeclaration: { - if (ts.isBindingPattern(input.name)) { + case SyntaxKind.VariableDeclaration: { + if (isBindingPattern(input.name)) { return recreateBindingPattern(input.name); } shouldEnterSuppressNewDiagnosticsContextContext = true; suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input))); } - case ts.SyntaxKind.TypeParameter: { + case SyntaxKind.TypeParameter: { if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) { return cleanup(factory.updateTypeParameterDeclaration(input, input.modifiers, input.name, /*constraint*/ undefined, /*defaultType*/ undefined)); } - return cleanup(ts.visitEachChild(input, visitDeclarationSubtree, context)); + return cleanup(visitEachChild(input, visitDeclarationSubtree, context)); } - case ts.SyntaxKind.ConditionalType: { + case SyntaxKind.ConditionalType: { // We have to process conditional types in a special way because for visibility purposes we need to push a new enclosingDeclaration // just for the `infer` types in the true branch. It's an implicit declaration scope that only applies to _part_ of the type. - const checkType = ts.visitNode(input.checkType, visitDeclarationSubtree); - const extendsType = ts.visitNode(input.extendsType, visitDeclarationSubtree); + const checkType = visitNode(input.checkType, visitDeclarationSubtree); + const extendsType = visitNode(input.extendsType, visitDeclarationSubtree); const oldEnclosingDecl = enclosingDeclaration; enclosingDeclaration = input.trueType; - const trueType = ts.visitNode(input.trueType, visitDeclarationSubtree); + const trueType = visitNode(input.trueType, visitDeclarationSubtree); enclosingDeclaration = oldEnclosingDecl; - const falseType = ts.visitNode(input.falseType, visitDeclarationSubtree); + const falseType = visitNode(input.falseType, visitDeclarationSubtree); return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType)); } - case ts.SyntaxKind.FunctionType: { - return cleanup(factory.updateFunctionTypeNode(input, ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); + case SyntaxKind.FunctionType: { + return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); } - case ts.SyntaxKind.ConstructorType: { - return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), ts.visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), ts.visitNode(input.type, visitDeclarationSubtree))); + case SyntaxKind.ConstructorType: { + return cleanup(factory.updateConstructorTypeNode(input, ensureModifiers(input), visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree))); } - case ts.SyntaxKind.ImportType: { - if (!ts.isLiteralImportTypeNode(input)) return cleanup(input); + case SyntaxKind.ImportType: { + if (!isLiteralImportTypeNode(input)) return cleanup(input); return cleanup(factory.updateImportTypeNode( input, factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)), input.assertions, input.qualifier, - ts.visitNodes(input.typeArguments, visitDeclarationSubtree, ts.isTypeNode), + visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode), input.isTypeOf )); } - default: ts.Debug.assertNever(input, `Attempted to process unhandled node kind: ${ts.Debug.formatSyntaxKind((input as ts.Node).kind)}`); + default: Debug.assertNever(input, `Attempted to process unhandled node kind: ${Debug.formatSyntaxKind((input as Node).kind)}`); } } - if (ts.isTupleTypeNode(input) && (ts.getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === ts.getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) { - ts.setEmitFlags(input, ts.EmitFlags.SingleLine); + if (isTupleTypeNode(input) && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) { + setEmitFlags(input, EmitFlags.SingleLine); } - return cleanup(ts.visitEachChild(input, visitDeclarationSubtree, context)); + return cleanup(visitEachChild(input, visitDeclarationSubtree, context)); - function cleanup(returnValue: T | undefined): T | undefined { - if (returnValue && canProduceDiagnostic && ts.hasDynamicName(input as ts.Declaration)) { + function cleanup(returnValue: T | undefined): T | undefined { + if (returnValue && canProduceDiagnostic && hasDynamicName(input as Declaration)) { checkName(input); } if (isEnclosingDeclaration(input)) { @@ -1112,15 +1152,15 @@ export function transformDeclarations(context: ts.TransformationContext) { if (returnValue === input) { return returnValue; } - return returnValue && ts.setOriginalNode(preserveJsDoc(returnValue, input), input); + return returnValue && setOriginalNode(preserveJsDoc(returnValue, input), input); } } - function isPrivateMethodTypeParameter(node: ts.TypeParameterDeclaration) { - return node.parent.kind === ts.SyntaxKind.MethodDeclaration && ts.hasEffectiveModifier(node.parent, ts.ModifierFlags.Private); + function isPrivateMethodTypeParameter(node: TypeParameterDeclaration) { + return node.parent.kind === SyntaxKind.MethodDeclaration && hasEffectiveModifier(node.parent, ModifierFlags.Private); } - function visitDeclarationStatements(input: ts.Node): ts.VisitResult { + function visitDeclarationStatements(input: Node): VisitResult { if (!isPreservedDeclarationStatement(input)) { // return undefined for unmatched kinds to omit them from the tree return; @@ -1128,8 +1168,8 @@ export function transformDeclarations(context: ts.TransformationContext) { if (shouldStripInternal(input)) return; switch (input.kind) { - case ts.SyntaxKind.ExportDeclaration: { - if (ts.isSourceFile(input.parent)) { + case SyntaxKind.ExportDeclaration: { + if (isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; } resultHasScopeMarker = true; @@ -1141,31 +1181,31 @@ export function transformDeclarations(context: ts.TransformationContext) { input.isTypeOnly, input.exportClause, rewriteModuleSpecifier(input, input.moduleSpecifier), - ts.getResolutionModeOverrideForClause(input.assertClause) ? input.assertClause : undefined + getResolutionModeOverrideForClause(input.assertClause) ? input.assertClause : undefined ); } - case ts.SyntaxKind.ExportAssignment: { + case SyntaxKind.ExportAssignment: { // Always visible if the parent node isn't dropped for being not visible - if (ts.isSourceFile(input.parent)) { + if (isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; } resultHasScopeMarker = true; - if (input.expression.kind === ts.SyntaxKind.Identifier) { + if (input.expression.kind === SyntaxKind.Identifier) { return input; } else { - const newId = factory.createUniqueName("_default", ts.GeneratedIdentifierFlags.Optimistic); + const newId = factory.createUniqueName("_default", GeneratedIdentifierFlags.Optimistic); getSymbolAccessibilityDiagnostic = () => ({ - diagnosticMessage: ts.Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, + diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input }); errorFallbackNode = input; const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); errorFallbackNode = undefined; - const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(ts.SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], ts.NodeFlags.Const)); + const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); preserveJsDoc(statement, input); - ts.removeAllComments(input); + removeAllComments(input); return [statement, factory.updateExportAssignment(input, input.modifiers, newId)]; } } @@ -1173,76 +1213,76 @@ export function transformDeclarations(context: ts.TransformationContext) { const result = transformTopLevelDeclaration(input); // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass - lateStatementReplacementMap.set(ts.getOriginalNodeId(input), result); + lateStatementReplacementMap.set(getOriginalNodeId(input), result); return input; } - function stripExportModifiers(statement: ts.Statement): ts.Statement { - if (ts.isImportEqualsDeclaration(statement) || ts.hasEffectiveModifier(statement, ts.ModifierFlags.Default) || !ts.canHaveModifiers(statement)) { + function stripExportModifiers(statement: Statement): Statement { + if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) || !canHaveModifiers(statement)) { // `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace // Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too return statement; } - const modifiers = factory.createModifiersFromModifierFlags(ts.getEffectiveModifierFlags(statement) & (ts.ModifierFlags.All ^ ts.ModifierFlags.Export)); + const modifiers = factory.createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export)); return factory.updateModifiers(statement, modifiers); } - function transformTopLevelDeclaration(input: ts.LateVisibilityPaintedStatement) { + function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) { if (lateMarkedStatements) { - while (ts.orderedRemoveItem(lateMarkedStatements, input)); + while (orderedRemoveItem(lateMarkedStatements, input)); } if (shouldStripInternal(input)) return; switch (input.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: { + case SyntaxKind.ImportEqualsDeclaration: { return transformImportEqualsDeclaration(input); } - case ts.SyntaxKind.ImportDeclaration: { + case SyntaxKind.ImportDeclaration: { return transformImportDeclaration(input); } } - if (ts.isDeclaration(input) && isDeclarationAndNotVisible(input)) return; + if (isDeclaration(input) && isDeclarationAndNotVisible(input)) return; // Elide implementation signatures from overload sets - if (ts.isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; + if (isFunctionLike(input) && resolver.isImplementationOfOverload(input)) return; let previousEnclosingDeclaration: typeof enclosingDeclaration; if (isEnclosingDeclaration(input)) { previousEnclosingDeclaration = enclosingDeclaration; - enclosingDeclaration = input as ts.Declaration; + enclosingDeclaration = input as Declaration; } - const canProdiceDiagnostic = ts.canProduceDiagnostics(input); + const canProdiceDiagnostic = canProduceDiagnostics(input); const oldDiag = getSymbolAccessibilityDiagnostic; if (canProdiceDiagnostic) { - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(input as ts.DeclarationDiagnosticProducing); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing); } const previousNeedsDeclare = needsDeclare; switch (input.kind) { - case ts.SyntaxKind.TypeAliasDeclaration: { + case SyntaxKind.TypeAliasDeclaration: { needsDeclare = false; const clean = cleanup(factory.updateTypeAliasDeclaration( input, ensureModifiers(input), input.name, - ts.visitNodes(input.typeParameters, visitDeclarationSubtree, ts.isTypeParameterDeclaration), - ts.visitNode(input.type, visitDeclarationSubtree, ts.isTypeNode) + visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), + visitNode(input.type, visitDeclarationSubtree, isTypeNode) )); needsDeclare = previousNeedsDeclare; return clean; } - case ts.SyntaxKind.InterfaceDeclaration: { + case SyntaxKind.InterfaceDeclaration: { return cleanup(factory.updateInterfaceDeclaration( input, ensureModifiers(input), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), - ts.visitNodes(input.members, visitDeclarationSubtree) + visitNodes(input.members, visitDeclarationSubtree) )); } - case ts.SyntaxKind.FunctionDeclaration: { + case SyntaxKind.FunctionDeclaration: { // Generators lose their generator-ness, excepting their return type const clean = cleanup(factory.updateFunctionDeclaration( input, @@ -1257,45 +1297,45 @@ export function transformDeclarations(context: ts.TransformationContext) { if (clean && resolver.isExpandoFunctionDeclaration(input) && shouldEmitFunctionProperties(input)) { const props = resolver.getPropertiesOfContainerFunction(input); // Use parseNodeFactory so it is usable as an enclosing declaration - const fakespace = ts.parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), ts.NodeFlags.Namespace); - ts.setParent(fakespace, enclosingDeclaration as ts.SourceFile | ts.NamespaceDeclaration); - fakespace.locals = ts.createSymbolTable(props); + const fakespace = parseNodeFactory.createModuleDeclaration(/*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace); + setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration); + fakespace.locals = createSymbolTable(props); fakespace.symbol = props[0].parent!; - const exportMappings: [ts.Identifier, string][] = []; - let declarations: (ts.VariableStatement | ts.ExportDeclaration)[] = ts.mapDefined(props, p => { - if (!p.valueDeclaration || !ts.isPropertyAccessExpression(p.valueDeclaration)) { + const exportMappings: [Identifier, string][] = []; + let declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => { + if (!p.valueDeclaration || !isPropertyAccessExpression(p.valueDeclaration)) { return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them) } - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.valueDeclaration); const type = resolver.createTypeOfDeclaration(p.valueDeclaration, fakespace, declarationEmitNodeBuilderFlags, symbolTracker); getSymbolAccessibilityDiagnostic = oldDiag; - const nameStr = ts.unescapeLeadingUnderscores(p.escapedName); - const isNonContextualKeywordName = ts.isStringANonContextualKeyword(nameStr); + const nameStr = unescapeLeadingUnderscores(p.escapedName); + const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr); const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr); if (isNonContextualKeywordName) { exportMappings.push([name, nameStr]); } const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined); - return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(ts.SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl])); + return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl])); }); if (!exportMappings.length) { - declarations = ts.mapDefined(declarations, declaration => factory.updateModifiers(declaration, ts.ModifierFlags.None)); + declarations = mapDefined(declarations, declaration => factory.updateModifiers(declaration, ModifierFlags.None)); } else { declarations.push(factory.createExportDeclaration( /*modifiers*/ undefined, /*isTypeOnly*/ false, - factory.createNamedExports(ts.map(exportMappings, ([gen, exp]) => { + factory.createNamedExports(map(exportMappings, ([gen, exp]) => { return factory.createExportSpecifier(/*isTypeOnly*/ false, gen, exp); })) )); } - const namespaceDecl = factory.createModuleDeclaration(ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), ts.NodeFlags.Namespace); - if (!ts.hasEffectiveModifier(clean, ts.ModifierFlags.Default)) { + const namespaceDecl = factory.createModuleDeclaration(ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace); + if (!hasEffectiveModifier(clean, ModifierFlags.Default)) { return [clean, namespaceDecl]; } - const modifiers = factory.createModifiersFromModifierFlags((ts.getEffectiveModifierFlags(clean) & ~ts.ModifierFlags.ExportDefault) | ts.ModifierFlags.Ambient); + const modifiers = factory.createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient); const cleanDeclaration = factory.updateFunctionDeclaration( clean, modifiers, @@ -1320,7 +1360,7 @@ export function transformDeclarations(context: ts.TransformationContext) { namespaceDecl.name ); - if (ts.isSourceFile(input.parent)) { + if (isSourceFile(input.parent)) { resultHasExternalModuleIndicator = true; } resultHasScopeMarker = true; @@ -1331,29 +1371,29 @@ export function transformDeclarations(context: ts.TransformationContext) { return clean; } } - case ts.SyntaxKind.ModuleDeclaration: { + case SyntaxKind.ModuleDeclaration: { needsDeclare = false; const inner = input.body; - if (inner && inner.kind === ts.SyntaxKind.ModuleBlock) { + if (inner && inner.kind === SyntaxKind.ModuleBlock) { const oldNeedsScopeFix = needsScopeFixMarker; const oldHasScopeFix = resultHasScopeMarker; resultHasScopeMarker = false; needsScopeFixMarker = false; - const statements = ts.visitNodes(inner.statements, visitDeclarationStatements); + const statements = visitNodes(inner.statements, visitDeclarationStatements); let lateStatements = transformAndReplaceLatePaintedStatements(statements); - if (input.flags & ts.NodeFlags.Ambient) { + if (input.flags & NodeFlags.Ambient) { needsScopeFixMarker = false; // If it was `declare`'d everything is implicitly exported already, ignore late printed "privates" } // With the final list of statements, there are 3 possibilities: // 1. There's an export assignment or export declaration in the namespace - do nothing // 2. Everything is exported and there are no export assignments or export declarations - strip all export modifiers // 3. Some things are exported, some are not, and there's no marker - add an empty marker - if (!ts.isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) { + if (!isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) { if (needsScopeFixMarker) { - lateStatements = factory.createNodeArray([...lateStatements, ts.createEmptyExports(factory)]); + lateStatements = factory.createNodeArray([...lateStatements, createEmptyExports(factory)]); } else { - lateStatements = ts.visitNodes(lateStatements, stripExportModifiers); + lateStatements = visitNodes(lateStatements, stripExportModifiers); } } const body = factory.updateModuleBlock(inner, lateStatements); @@ -1364,7 +1404,7 @@ export function transformDeclarations(context: ts.TransformationContext) { return cleanup(factory.updateModuleDeclaration( input, mods, - ts.isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, + isExternalModuleAugmentation(input) ? rewriteModuleSpecifier(input, input.name) : input.name, body )); } @@ -1372,32 +1412,32 @@ export function transformDeclarations(context: ts.TransformationContext) { needsDeclare = previousNeedsDeclare; const mods = ensureModifiers(input); needsDeclare = false; - ts.visitNode(inner, visitDeclarationStatements); + visitNode(inner, visitDeclarationStatements); // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done) - const id = ts.getOriginalNodeId(inner!); // TODO: GH#18217 + const id = getOriginalNodeId(inner!); // TODO: GH#18217 const body = lateStatementReplacementMap.get(id); lateStatementReplacementMap.delete(id); return cleanup(factory.updateModuleDeclaration( input, mods, input.name, - body as ts.ModuleBody + body as ModuleBody )); } } - case ts.SyntaxKind.ClassDeclaration: { + case SyntaxKind.ClassDeclaration: { errorNameNode = input.name; errorFallbackNode = input; const modifiers = factory.createNodeArray(ensureModifiers(input)); const typeParameters = ensureTypeParams(input, input.typeParameters); - const ctor = ts.getFirstConstructorWithBody(input); - let parameterProperties: readonly ts.PropertyDeclaration[] | undefined; + const ctor = getFirstConstructorWithBody(input); + let parameterProperties: readonly PropertyDeclaration[] | undefined; if (ctor) { const oldDiag = getSymbolAccessibilityDiagnostic; - parameterProperties = ts.compact(ts.flatMap(ctor.parameters, (param) => { - if (!ts.hasSyntacticModifier(param, ts.ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(param); - if (param.name.kind === ts.SyntaxKind.Identifier) { + parameterProperties = compact(flatMap(ctor.parameters, (param) => { + if (!hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return; + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param); + if (param.name.kind === SyntaxKind.Identifier) { return preserveJsDoc(factory.createPropertyDeclaration( ensureModifiers(param), param.name, @@ -1410,17 +1450,17 @@ export function transformDeclarations(context: ts.TransformationContext) { return walkBindingPattern(param.name); } - function walkBindingPattern(pattern: ts.BindingPattern) { - let elems: ts.PropertyDeclaration[] | undefined; + function walkBindingPattern(pattern: BindingPattern) { + let elems: PropertyDeclaration[] | undefined; for (const elem of pattern.elements) { - if (ts.isOmittedExpression(elem)) continue; - if (ts.isBindingPattern(elem.name)) { - elems = ts.concatenate(elems, walkBindingPattern(elem.name)); + if (isOmittedExpression(elem)) continue; + if (isBindingPattern(elem.name)) { + elems = concatenate(elems, walkBindingPattern(elem.name)); } elems = elems || []; elems.push(factory.createPropertyDeclaration( ensureModifiers(param), - elem.name as ts.Identifier, + elem.name as Identifier, /*questionToken*/ undefined, ensureType(elem, /*type*/ undefined), /*initializer*/ undefined @@ -1432,7 +1472,7 @@ export function transformDeclarations(context: ts.TransformationContext) { getSymbolAccessibilityDiagnostic = oldDiag; } - const hasPrivateIdentifier = ts.some(input.members, member => !!member.name && ts.isPrivateIdentifier(member.name)); + const hasPrivateIdentifier = some(input.members, member => !!member.name && isPrivateIdentifier(member.name)); // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior // Prevents other classes with the same public members from being used in place of the current class const privateIdentifier = hasPrivateIdentifier ? [ @@ -1444,31 +1484,31 @@ export function transformDeclarations(context: ts.TransformationContext) { /*initializer*/ undefined ) ] : undefined; - const memberNodes = ts.concatenate(ts.concatenate(privateIdentifier, parameterProperties), ts.visitNodes(input.members, visitDeclarationSubtree)); + const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree)); const members = factory.createNodeArray(memberNodes); - const extendsClause = ts.getEffectiveBaseTypeNode(input); - if (extendsClause && !ts.isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== ts.SyntaxKind.NullKeyword) { + const extendsClause = getEffectiveBaseTypeNode(input); + if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) { // We must add a temporary declaration for the extends clause expression - const oldId = input.name ? ts.unescapeLeadingUnderscores(input.name.escapedText) : "default"; - const newId = factory.createUniqueName(`${oldId}_base`, ts.GeneratedIdentifierFlags.Optimistic); + const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default"; + const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic); getSymbolAccessibilityDiagnostic = () => ({ - diagnosticMessage: ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, + diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, typeName: input.name }); const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined); - const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(ts.SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], ts.NodeFlags.Const)); - const heritageClauses = factory.createNodeArray(ts.map(input.heritageClauses, clause => { - if (clause.token === ts.SyntaxKind.ExtendsKeyword) { + const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const)); + const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => { + if (clause.token === SyntaxKind.ExtendsKeyword) { const oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); - const newClause = factory.updateHeritageClause(clause, ts.map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, ts.visitNodes(t.typeArguments, visitDeclarationSubtree)))); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]); + const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree)))); getSymbolAccessibilityDiagnostic = oldDiag; return newClause; } - return factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, t => ts.isEntityNameExpression(t.expression) || t.expression.kind === ts.SyntaxKind.NullKeyword)), visitDeclarationSubtree)); + return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree)); })); return [statement, cleanup(factory.updateClassDeclaration( input, @@ -1491,11 +1531,11 @@ export function transformDeclarations(context: ts.TransformationContext) { )); } } - case ts.SyntaxKind.VariableStatement: { + case SyntaxKind.VariableStatement: { return cleanup(transformVariableStatement(input)); } - case ts.SyntaxKind.EnumDeclaration: { - return cleanup(factory.updateEnumDeclaration(input, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(ts.mapDefined(input.members, m => { + case SyntaxKind.EnumDeclaration: { + return cleanup(factory.updateEnumDeclaration(input, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(mapDefined(input.members, m => { if (shouldStripInternal(m)) return; // Rewrite enum values to their constants, if available const constValue = resolver.getConstantValue(m); @@ -1504,45 +1544,45 @@ export function transformDeclarations(context: ts.TransformationContext) { } } // Anything left unhandled is an error, so this should be unreachable - return ts.Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${ts.Debug.formatSyntaxKind((input as ts.Node).kind)}`); + return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${Debug.formatSyntaxKind((input as Node).kind)}`); - function cleanup(node: T | undefined): T | undefined { + function cleanup(node: T | undefined): T | undefined { if (isEnclosingDeclaration(input)) { enclosingDeclaration = previousEnclosingDeclaration; } if (canProdiceDiagnostic) { getSymbolAccessibilityDiagnostic = oldDiag; } - if (input.kind === ts.SyntaxKind.ModuleDeclaration) { + if (input.kind === SyntaxKind.ModuleDeclaration) { needsDeclare = previousNeedsDeclare; } - if (node as ts.Node === input) { + if (node as Node === input) { return node; } errorFallbackNode = undefined; errorNameNode = undefined; - return node && ts.setOriginalNode(preserveJsDoc(node, input), input); + return node && setOriginalNode(preserveJsDoc(node, input), input); } } - function transformVariableStatement(input: ts.VariableStatement) { - if (!ts.forEach(input.declarationList.declarations, getBindingNameVisible)) return; - const nodes = ts.visitNodes(input.declarationList.declarations, visitDeclarationSubtree); - if (!ts.length(nodes)) return; + function transformVariableStatement(input: VariableStatement) { + if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return; + const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree); + if (!length(nodes)) return; return factory.updateVariableStatement(input, factory.createNodeArray(ensureModifiers(input)), factory.updateVariableDeclarationList(input.declarationList, nodes)); } - function recreateBindingPattern(d: ts.BindingPattern): ts.VariableDeclaration[] { - return ts.flatten(ts.mapDefined(d.elements, e => recreateBindingElement(e))); + function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] { + return flatten(mapDefined(d.elements, e => recreateBindingElement(e))); } - function recreateBindingElement(e: ts.ArrayBindingElement) { - if (e.kind === ts.SyntaxKind.OmittedExpression) { + function recreateBindingElement(e: ArrayBindingElement) { + if (e.kind === SyntaxKind.OmittedExpression) { return; } if (e.name) { if (!getBindingNameVisible(e)) return; - if (ts.isBindingPattern(e.name)) { + if (isBindingPattern(e.name)) { return recreateBindingPattern(e.name); } else { @@ -1551,15 +1591,15 @@ export function transformDeclarations(context: ts.TransformationContext) { } } - function checkName(node: ts.DeclarationDiagnosticProducing) { + function checkName(node: DeclarationDiagnosticProducing) { let oldDiag: typeof getSymbolAccessibilityDiagnostic | undefined; if (!suppressNewDiagnosticContexts) { oldDiag = getSymbolAccessibilityDiagnostic; - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNodeName(node); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node); } - errorNameNode = (node as ts.NamedDeclaration).name; - ts.Debug.assert(resolver.isLateBound(ts.getParseTreeNode(node) as ts.Declaration)); // Should only be called with dynamic names - const decl = node as ts.NamedDeclaration as ts.LateBoundDeclaration; + errorNameNode = (node as NamedDeclaration).name; + Debug.assert(resolver.isLateBound(getParseTreeNode(node) as Declaration)); // Should only be called with dynamic names + const decl = node as NamedDeclaration as LateBoundDeclaration; const entityName = decl.name.expression; checkEntityNameVisibility(entityName, enclosingDeclaration); if (!suppressNewDiagnosticContexts) { @@ -1568,88 +1608,88 @@ export function transformDeclarations(context: ts.TransformationContext) { errorNameNode = undefined; } - function shouldStripInternal(node: ts.Node) { + function shouldStripInternal(node: Node) { return !!stripInternal && !!node && isInternalDeclaration(node, currentSourceFile); } - function isScopeMarker(node: ts.Node) { - return ts.isExportAssignment(node) || ts.isExportDeclaration(node); + function isScopeMarker(node: Node) { + return isExportAssignment(node) || isExportDeclaration(node); } - function hasScopeMarker(statements: readonly ts.Statement[]) { - return ts.some(statements, isScopeMarker); + function hasScopeMarker(statements: readonly Statement[]) { + return some(statements, isScopeMarker); } - function ensureModifiers(node: T): readonly ts.Modifier[] | undefined { - const currentFlags = ts.getEffectiveModifierFlags(node); + function ensureModifiers(node: T): readonly Modifier[] | undefined { + const currentFlags = getEffectiveModifierFlags(node); const newFlags = ensureModifierFlags(node); if (currentFlags === newFlags) { - return ts.visitArray(node.modifiers, n => ts.tryCast(n, ts.isModifier), ts.isModifier); + return visitArray(node.modifiers, n => tryCast(n, isModifier), isModifier); } return factory.createModifiersFromModifierFlags(newFlags); } - function ensureModifierFlags(node: ts.Node): ts.ModifierFlags { - let mask = ts.ModifierFlags.All ^ (ts.ModifierFlags.Public | ts.ModifierFlags.Async | ts.ModifierFlags.Override); // No async and override modifiers in declaration files - let additions = (needsDeclare && !isAlwaysType(node)) ? ts.ModifierFlags.Ambient : ts.ModifierFlags.None; - const parentIsFile = node.parent.kind === ts.SyntaxKind.SourceFile; - if (!parentIsFile || (isBundledEmit && parentIsFile && ts.isExternalModule(node.parent as ts.SourceFile))) { - mask ^= ts.ModifierFlags.Ambient; - additions = ts.ModifierFlags.None; + function ensureModifierFlags(node: Node): ModifierFlags { + let mask = ModifierFlags.All ^ (ModifierFlags.Public | ModifierFlags.Async | ModifierFlags.Override); // No async and override modifiers in declaration files + let additions = (needsDeclare && !isAlwaysType(node)) ? ModifierFlags.Ambient : ModifierFlags.None; + const parentIsFile = node.parent.kind === SyntaxKind.SourceFile; + if (!parentIsFile || (isBundledEmit && parentIsFile && isExternalModule(node.parent as SourceFile))) { + mask ^= ModifierFlags.Ambient; + additions = ModifierFlags.None; } return maskModifierFlags(node, mask, additions); } - function getTypeAnnotationFromAllAccessorDeclarations(node: ts.AccessorDeclaration, accessors: ts.AllAccessorDeclarations) { + function getTypeAnnotationFromAllAccessorDeclarations(node: AccessorDeclaration, accessors: AllAccessorDeclarations) { let accessorType = getTypeAnnotationFromAccessor(node); if (!accessorType && node !== accessors.firstAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.firstAccessor); // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(accessors.firstAccessor); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.firstAccessor); } if (!accessorType && accessors.secondAccessor && node !== accessors.secondAccessor) { accessorType = getTypeAnnotationFromAccessor(accessors.secondAccessor); // If we end up pulling the type from the second accessor, we also need to change the diagnostic context to get the expected error message - getSymbolAccessibilityDiagnostic = ts.createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); + getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(accessors.secondAccessor); } return accessorType; } - function transformHeritageClauses(nodes: ts.NodeArray | undefined) { - return factory.createNodeArray(ts.filter(ts.map(nodes, clause => factory.updateHeritageClause(clause, ts.visitNodes(factory.createNodeArray(ts.filter(clause.types, t => { - return ts.isEntityNameExpression(t.expression) || (clause.token === ts.SyntaxKind.ExtendsKeyword && t.expression.kind === ts.SyntaxKind.NullKeyword); + function transformHeritageClauses(nodes: NodeArray | undefined) { + return factory.createNodeArray(filter(map(nodes, clause => factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => { + return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword); })), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length)); } } -function isAlwaysType(node: ts.Node) { - if (node.kind === ts.SyntaxKind.InterfaceDeclaration) { +function isAlwaysType(node: Node) { + if (node.kind === SyntaxKind.InterfaceDeclaration) { return true; } return false; } // Elide "public" modifier, as it is the default -function maskModifiers(node: ts.Node, modifierMask?: ts.ModifierFlags, modifierAdditions?: ts.ModifierFlags): ts.Modifier[] | undefined { - return ts.factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); +function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] | undefined { + return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions)); } -function maskModifierFlags(node: ts.Node, modifierMask: ts.ModifierFlags = ts.ModifierFlags.All ^ ts.ModifierFlags.Public, modifierAdditions: ts.ModifierFlags = ts.ModifierFlags.None): ts.ModifierFlags { - let flags = (ts.getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions; - if (flags & ts.ModifierFlags.Default && !(flags & ts.ModifierFlags.Export)) { +function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags { + let flags = (getEffectiveModifierFlags(node) & modifierMask) | modifierAdditions; + if (flags & ModifierFlags.Default && !(flags & ModifierFlags.Export)) { // A non-exported default is a nonsequitor - we usually try to remove all export modifiers // from statements in ambient declarations; but a default export must retain its export modifier to be syntactically valid - flags ^= ts.ModifierFlags.Export; + flags ^= ModifierFlags.Export; } - if (flags & ts.ModifierFlags.Default && flags & ts.ModifierFlags.Ambient) { - flags ^= ts.ModifierFlags.Ambient; // `declare` is never required alongside `default` (and would be an error if printed) + if (flags & ModifierFlags.Default && flags & ModifierFlags.Ambient) { + flags ^= ModifierFlags.Ambient; // `declare` is never required alongside `default` (and would be an error if printed) } return flags; } -function getTypeAnnotationFromAccessor(accessor: ts.AccessorDeclaration): ts.TypeNode | undefined { +function getTypeAnnotationFromAccessor(accessor: AccessorDeclaration): TypeNode | undefined { if (accessor) { - return accessor.kind === ts.SyntaxKind.GetAccessor + return accessor.kind === SyntaxKind.GetAccessor ? accessor.type // Getter - return type : accessor.parameters.length > 0 ? accessor.parameters[0].type // Setter parameter type @@ -1657,90 +1697,90 @@ function getTypeAnnotationFromAccessor(accessor: ts.AccessorDeclaration): ts.Typ } } -type CanHaveLiteralInitializer = ts.VariableDeclaration | ts.PropertyDeclaration | ts.PropertySignature | ts.ParameterDeclaration; -function canHaveLiteralInitializer(node: ts.Node): boolean { +type CanHaveLiteralInitializer = VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration; +function canHaveLiteralInitializer(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - return !ts.hasEffectiveModifier(node, ts.ModifierFlags.Private); - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return !hasEffectiveModifier(node, ModifierFlags.Private); + case SyntaxKind.Parameter: + case SyntaxKind.VariableDeclaration: return true; } return false; } type ProcessedDeclarationStatement = - | ts.FunctionDeclaration - | ts.ModuleDeclaration - | ts.ImportEqualsDeclaration - | ts.InterfaceDeclaration - | ts.ClassDeclaration - | ts.TypeAliasDeclaration - | ts.EnumDeclaration - | ts.VariableStatement - | ts.ImportDeclaration - | ts.ExportDeclaration - | ts.ExportAssignment; - -function isPreservedDeclarationStatement(node: ts.Node): node is ProcessedDeclarationStatement { + | FunctionDeclaration + | ModuleDeclaration + | ImportEqualsDeclaration + | InterfaceDeclaration + | ClassDeclaration + | TypeAliasDeclaration + | EnumDeclaration + | VariableStatement + | ImportDeclaration + | ExportDeclaration + | ExportAssignment; + +function isPreservedDeclarationStatement(node: Node): node is ProcessedDeclarationStatement { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: return true; } return false; } type ProcessedComponent = - | ts.ConstructSignatureDeclaration - | ts.ConstructorDeclaration - | ts.MethodDeclaration - | ts.GetAccessorDeclaration - | ts.SetAccessorDeclaration - | ts.PropertyDeclaration - | ts.PropertySignature - | ts.MethodSignature - | ts.CallSignatureDeclaration - | ts.IndexSignatureDeclaration - | ts.VariableDeclaration - | ts.TypeParameterDeclaration - | ts.ExpressionWithTypeArguments - | ts.TypeReferenceNode - | ts.ConditionalTypeNode - | ts.FunctionTypeNode - | ts.ConstructorTypeNode - | ts.ImportTypeNode; - -function isProcessedComponent(node: ts.Node): node is ProcessedComponent { + | ConstructSignatureDeclaration + | ConstructorDeclaration + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | PropertyDeclaration + | PropertySignature + | MethodSignature + | CallSignatureDeclaration + | IndexSignatureDeclaration + | VariableDeclaration + | TypeParameterDeclaration + | ExpressionWithTypeArguments + | TypeReferenceNode + | ConditionalTypeNode + | FunctionTypeNode + | ConstructorTypeNode + | ImportTypeNode; + +function isProcessedComponent(node: Node): node is ProcessedComponent { switch (node.kind) { - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.TypeParameter: - case ts.SyntaxKind.ExpressionWithTypeArguments: - case ts.SyntaxKind.TypeReference: - case ts.SyntaxKind.ConditionalType: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ImportType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.Constructor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.TypeParameter: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.TypeReference: + case SyntaxKind.ConditionalType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.ImportType: return true; } return false; diff --git a/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index dba6a02b81346..bdd9903796ea4 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -1,496 +1,510 @@ -import * as ts from "../../_namespaces/ts"; +import { + BindingElement, CallSignatureDeclaration, ConstructorDeclaration, ConstructSignatureDeclaration, Debug, Declaration, + DeclarationName, DiagnosticMessage, Diagnostics, ExpressionWithTypeArguments, FunctionDeclaration, + GetAccessorDeclaration, getNameOfDeclaration, hasSyntacticModifier, ImportEqualsDeclaration, + IndexSignatureDeclaration, isBindingElement, isCallSignatureDeclaration, isClassDeclaration, + isConstructorDeclaration, isConstructSignatureDeclaration, isExpressionWithTypeArguments, isFunctionDeclaration, + isGetAccessor, isHeritageClause, isImportEqualsDeclaration, isIndexSignatureDeclaration, isJSDocTypeAlias, + isMethodDeclaration, isMethodSignature, isParameter, isParameterPropertyDeclaration, isPropertyAccessExpression, + isPropertyDeclaration, isPropertySignature, isSetAccessor, isStatic, isTypeAliasDeclaration, + isTypeParameterDeclaration, isVariableDeclaration, JSDocCallbackTag, JSDocEnumTag, JSDocTypedefTag, + MethodDeclaration, MethodSignature, ModifierFlags, NamedDeclaration, Node, ParameterDeclaration, + PropertyAccessExpression, PropertyDeclaration, PropertySignature, QualifiedName, SetAccessorDeclaration, + SymbolAccessibility, SymbolAccessibilityResult, SyntaxKind, TypeAliasDeclaration, TypeParameterDeclaration, + VariableDeclaration, +} from "../../_namespaces/ts"; /** @internal */ -export type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: ts.SymbolAccessibilityResult) => (SymbolAccessibilityDiagnostic | undefined); +export type GetSymbolAccessibilityDiagnostic = (symbolAccessibilityResult: SymbolAccessibilityResult) => (SymbolAccessibilityDiagnostic | undefined); /** @internal */ export interface SymbolAccessibilityDiagnostic { - errorNode: ts.Node; - diagnosticMessage: ts.DiagnosticMessage; - typeName?: ts.DeclarationName | ts.QualifiedName; + errorNode: Node; + diagnosticMessage: DiagnosticMessage; + typeName?: DeclarationName | QualifiedName; } /** @internal */ export type DeclarationDiagnosticProducing = - | ts.VariableDeclaration - | ts.PropertyDeclaration - | ts.PropertySignature - | ts.BindingElement - | ts.SetAccessorDeclaration - | ts.GetAccessorDeclaration - | ts.ConstructSignatureDeclaration - | ts.CallSignatureDeclaration - | ts.MethodDeclaration - | ts.MethodSignature - | ts.FunctionDeclaration - | ts.ParameterDeclaration - | ts.TypeParameterDeclaration - | ts.ExpressionWithTypeArguments - | ts.ImportEqualsDeclaration - | ts.TypeAliasDeclaration - | ts.ConstructorDeclaration - | ts.IndexSignatureDeclaration - | ts.PropertyAccessExpression - | ts.JSDocTypedefTag - | ts.JSDocCallbackTag - | ts.JSDocEnumTag; + | VariableDeclaration + | PropertyDeclaration + | PropertySignature + | BindingElement + | SetAccessorDeclaration + | GetAccessorDeclaration + | ConstructSignatureDeclaration + | CallSignatureDeclaration + | MethodDeclaration + | MethodSignature + | FunctionDeclaration + | ParameterDeclaration + | TypeParameterDeclaration + | ExpressionWithTypeArguments + | ImportEqualsDeclaration + | TypeAliasDeclaration + | ConstructorDeclaration + | IndexSignatureDeclaration + | PropertyAccessExpression + | JSDocTypedefTag + | JSDocCallbackTag + | JSDocEnumTag; /** @internal */ -export function canProduceDiagnostics(node: ts.Node): node is DeclarationDiagnosticProducing { - return ts.isVariableDeclaration(node) || - ts.isPropertyDeclaration(node) || - ts.isPropertySignature(node) || - ts.isBindingElement(node) || - ts.isSetAccessor(node) || - ts.isGetAccessor(node) || - ts.isConstructSignatureDeclaration(node) || - ts.isCallSignatureDeclaration(node) || - ts.isMethodDeclaration(node) || - ts.isMethodSignature(node) || - ts.isFunctionDeclaration(node) || - ts.isParameter(node) || - ts.isTypeParameterDeclaration(node) || - ts.isExpressionWithTypeArguments(node) || - ts.isImportEqualsDeclaration(node) || - ts.isTypeAliasDeclaration(node) || - ts.isConstructorDeclaration(node) || - ts.isIndexSignatureDeclaration(node) || - ts.isPropertyAccessExpression(node) || - ts.isJSDocTypeAlias(node); +export function canProduceDiagnostics(node: Node): node is DeclarationDiagnosticProducing { + return isVariableDeclaration(node) || + isPropertyDeclaration(node) || + isPropertySignature(node) || + isBindingElement(node) || + isSetAccessor(node) || + isGetAccessor(node) || + isConstructSignatureDeclaration(node) || + isCallSignatureDeclaration(node) || + isMethodDeclaration(node) || + isMethodSignature(node) || + isFunctionDeclaration(node) || + isParameter(node) || + isTypeParameterDeclaration(node) || + isExpressionWithTypeArguments(node) || + isImportEqualsDeclaration(node) || + isTypeAliasDeclaration(node) || + isConstructorDeclaration(node) || + isIndexSignatureDeclaration(node) || + isPropertyAccessExpression(node) || + isJSDocTypeAlias(node); } /** @internal */ export function createGetSymbolAccessibilityDiagnosticForNodeName(node: DeclarationDiagnosticProducing) { - if (ts.isSetAccessor(node) || ts.isGetAccessor(node)) { + if (isSetAccessor(node) || isGetAccessor(node)) { return getAccessorNameVisibilityError; } - else if (ts.isMethodSignature(node) || ts.isMethodDeclaration(node)) { + else if (isMethodSignature(node) || isMethodDeclaration(node)) { return getMethodNameVisibilityError; } else { return createGetSymbolAccessibilityDiagnosticForNode(node); } - function getAccessorNameVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult) { + function getAccessorNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult) { const diagnosticMessage = getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name } : undefined; } - function getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult: ts.SymbolAccessibilityResult) { - if (ts.isStatic(node)) { + function getAccessorNameVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { + if (isStatic(node)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === ts.SyntaxKind.ClassDeclaration) { + else if (node.parent.kind === SyntaxKind.ClassDeclaration) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; } } - function getMethodNameVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { + function getMethodNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name } : undefined; } - function getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult: ts.SymbolAccessibilityResult) { - if (ts.isStatic(node)) { + function getMethodNameVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { + if (isStatic(node)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_static_method_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === ts.SyntaxKind.ClassDeclaration) { + else if (node.parent.kind === SyntaxKind.ClassDeclaration) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_method_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_method_0_of_exported_class_has_or_is_using_private_name_1; } else { return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Method_0_of_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Method_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Method_0_of_exported_interface_has_or_is_using_private_name_1; } } } /** @internal */ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationDiagnosticProducing): GetSymbolAccessibilityDiagnostic { - if (ts.isVariableDeclaration(node) || ts.isPropertyDeclaration(node) || ts.isPropertySignature(node) || ts.isPropertyAccessExpression(node) || ts.isBindingElement(node) || ts.isConstructorDeclaration(node)) { + if (isVariableDeclaration(node) || isPropertyDeclaration(node) || isPropertySignature(node) || isPropertyAccessExpression(node) || isBindingElement(node) || isConstructorDeclaration(node)) { return getVariableDeclarationTypeVisibilityError; } - else if (ts.isSetAccessor(node) || ts.isGetAccessor(node)) { + else if (isSetAccessor(node) || isGetAccessor(node)) { return getAccessorDeclarationTypeVisibilityError; } - else if (ts.isConstructSignatureDeclaration(node) || ts.isCallSignatureDeclaration(node) || ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isFunctionDeclaration(node) || ts.isIndexSignatureDeclaration(node)) { + else if (isConstructSignatureDeclaration(node) || isCallSignatureDeclaration(node) || isMethodDeclaration(node) || isMethodSignature(node) || isFunctionDeclaration(node) || isIndexSignatureDeclaration(node)) { return getReturnTypeVisibilityError; } - else if (ts.isParameter(node)) { - if (ts.isParameterPropertyDeclaration(node, node.parent) && ts.hasSyntacticModifier(node.parent, ts.ModifierFlags.Private)) { + else if (isParameter(node)) { + if (isParameterPropertyDeclaration(node, node.parent) && hasSyntacticModifier(node.parent, ModifierFlags.Private)) { return getVariableDeclarationTypeVisibilityError; } return getParameterDeclarationTypeVisibilityError; } - else if (ts.isTypeParameterDeclaration(node)) { + else if (isTypeParameterDeclaration(node)) { return getTypeParameterConstraintVisibilityError; } - else if (ts.isExpressionWithTypeArguments(node)) { + else if (isExpressionWithTypeArguments(node)) { return getHeritageClauseVisibilityError; } - else if (ts.isImportEqualsDeclaration(node)) { + else if (isImportEqualsDeclaration(node)) { return getImportEntityNameVisibilityError; } - else if (ts.isTypeAliasDeclaration(node) || ts.isJSDocTypeAlias(node)) { + else if (isTypeAliasDeclaration(node) || isJSDocTypeAlias(node)) { return getTypeAliasDeclarationVisibilityError; } else { - return ts.Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${ts.Debug.formatSyntaxKind((node as ts.Node).kind)}`); + return Debug.assertNever(node, `Attempted to set a declaration diagnostic context for unhandled node kind: ${Debug.formatSyntaxKind((node as Node).kind)}`); } - function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: ts.SymbolAccessibilityResult) { - if (node.kind === ts.SyntaxKind.VariableDeclaration || node.kind === ts.SyntaxKind.BindingElement) { + function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { + if (node.kind === SyntaxKind.VariableDeclaration || node.kind === SyntaxKind.BindingElement) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Exported_variable_0_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Exported_variable_0_has_or_is_using_private_name_1; } // This check is to ensure we don't report error on constructor parameter property as that error would be reported during parameter emit // The only exception here is if the constructor was marked as private. we are not emitting the constructor parameters at all. - else if (node.kind === ts.SyntaxKind.PropertyDeclaration || node.kind === ts.SyntaxKind.PropertyAccessExpression || node.kind === ts.SyntaxKind.PropertySignature || - (node.kind === ts.SyntaxKind.Parameter && ts.hasSyntacticModifier(node.parent, ts.ModifierFlags.Private))) { + else if (node.kind === SyntaxKind.PropertyDeclaration || node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.PropertySignature || + (node.kind === SyntaxKind.Parameter && hasSyntacticModifier(node.parent, ModifierFlags.Private))) { // TODO(jfreeman): Deal with computed properties in error reporting. - if (ts.isStatic(node)) { + if (isStatic(node)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_static_property_0_of_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.Parameter) { + else if (node.parent.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.Parameter) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Public_property_0_of_exported_class_has_or_is_using_private_name_1; } else { // Interfaces cannot have types that cannot be named return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Property_0_of_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Property_0_of_exported_interface_has_or_is_using_private_name_1; } } } - function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name } : undefined; } - function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { - let diagnosticMessage: ts.DiagnosticMessage; - if (node.kind === ts.SyntaxKind.SetAccessor) { + function getAccessorDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + let diagnosticMessage: DiagnosticMessage; + if (node.kind === SyntaxKind.SetAccessor) { // Getters can infer the return type from the returned expression, but setters cannot, so the // "_from_external_module_1_but_cannot_be_named" case cannot occur. - if (ts.isStatic(node)) { + if (isStatic(node)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; + Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_type_of_public_static_setter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1; + Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_type_of_public_setter_0_from_exported_class_has_or_is_using_private_name_1; } } else { - if (ts.isStatic(node)) { + if (isStatic(node)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Return_type_of_public_static_getter_0_from_exported_class_has_or_is_using_private_name_1; } else { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Return_type_of_public_getter_0_from_exported_class_has_or_is_using_private_name_1; } } return { diagnosticMessage, - errorNode: (node as ts.NamedDeclaration).name!, - typeName: (node as ts.NamedDeclaration).name + errorNode: (node as NamedDeclaration).name!, + typeName: (node as NamedDeclaration).name }; } - function getReturnTypeVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { - let diagnosticMessage: ts.DiagnosticMessage; + function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + let diagnosticMessage: DiagnosticMessage; switch (node.kind) { - case ts.SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructSignature: // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case ts.SyntaxKind.CallSignature: + case SyntaxKind.CallSignature: // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_call_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case ts.SyntaxKind.IndexSignature: + case SyntaxKind.IndexSignature: // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_index_signature_from_exported_interface_has_or_is_using_private_name_0; break; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - if (ts.isStatic(node)) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + if (isStatic(node)) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_public_static_method_from_exported_class_has_or_is_using_private_name_0; } - else if (node.parent.kind === ts.SyntaxKind.ClassDeclaration) { + else if (node.parent.kind === SyntaxKind.ClassDeclaration) { diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_public_method_from_exported_class_has_or_is_using_private_name_0; } else { // Interfaces cannot have return types that cannot be named diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; + Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_method_from_exported_interface_has_or_is_using_private_name_0; } break; - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionDeclaration: diagnosticMessage = symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : - ts.Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_external_module_1_but_cannot_be_named : + Diagnostics.Return_type_of_exported_function_has_or_is_using_name_0_from_private_module_1 : + Diagnostics.Return_type_of_exported_function_has_or_is_using_private_name_0; break; default: - return ts.Debug.fail("This is unknown kind for signature: " + node.kind); + return Debug.fail("This is unknown kind for signature: " + node.kind); } return { diagnosticMessage, - errorNode: (node as ts.NamedDeclaration).name || node + errorNode: (node as NamedDeclaration).name || node }; } - function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { - const diagnosticMessage: ts.DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); + function getParameterDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { + const diagnosticMessage: DiagnosticMessage = getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name } : undefined; } - function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: ts.SymbolAccessibilityResult): ts.DiagnosticMessage { + function getParameterDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult): DiagnosticMessage { switch (node.parent.kind) { - case ts.SyntaxKind.Constructor: + case SyntaxKind.Constructor: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_constructor_from_exported_class_has_or_is_using_private_name_1; - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructorType: // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; - case ts.SyntaxKind.CallSignature: + case SyntaxKind.CallSignature: // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; - case ts.SyntaxKind.IndexSignature: + case SyntaxKind.IndexSignature: // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_index_signature_from_exported_interface_has_or_is_using_private_name_1; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - if (ts.isStatic(node.parent)) { + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + if (isStatic(node.parent)) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === ts.SyntaxKind.ClassDeclaration) { + else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { // Interfaces cannot have parameter types that cannot be named return symbolAccessibilityResult.errorModuleName ? - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionType: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionType: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.GetAccessor: + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Parameter_0_of_exported_function_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_exported_function_has_or_is_using_private_name_1; + case SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: return symbolAccessibilityResult.errorModuleName ? - symbolAccessibilityResult.accessibility === ts.SymbolAccessibility.CannotBeNamed ? - ts.Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : - ts.Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_private_module_2 : - ts.Diagnostics.Parameter_0_of_accessor_has_or_is_using_private_name_1; + symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? + Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_external_module_2_but_cannot_be_named : + Diagnostics.Parameter_0_of_accessor_has_or_is_using_name_1_from_private_module_2 : + Diagnostics.Parameter_0_of_accessor_has_or_is_using_private_name_1; default: - return ts.Debug.fail(`Unknown parent for parameter: ${ts.Debug.formatSyntaxKind(node.parent.kind)}`); + return Debug.fail(`Unknown parent for parameter: ${Debug.formatSyntaxKind(node.parent.kind)}`); } } function getTypeParameterConstraintVisibilityError(): SymbolAccessibilityDiagnostic { // Type parameter constraints are named by user so we should always be able to name it - let diagnosticMessage: ts.DiagnosticMessage; + let diagnosticMessage: DiagnosticMessage; switch (node.parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; + case SyntaxKind.ClassDeclaration: + diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_class_has_or_is_using_private_name_1; break; - case ts.SyntaxKind.InterfaceDeclaration: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; + case SyntaxKind.InterfaceDeclaration: + diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1; break; - case ts.SyntaxKind.MappedType: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; + case SyntaxKind.MappedType: + diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_mapped_object_type_is_using_private_name_1; break; - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ConstructSignature: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + diagnosticMessage = Diagnostics.Type_parameter_0_of_constructor_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case ts.SyntaxKind.CallSignature: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; + case SyntaxKind.CallSignature: + diagnosticMessage = Diagnostics.Type_parameter_0_of_call_signature_from_exported_interface_has_or_is_using_private_name_1; break; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - if (ts.isStatic(node.parent)) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + if (isStatic(node.parent)) { + diagnosticMessage = Diagnostics.Type_parameter_0_of_public_static_method_from_exported_class_has_or_is_using_private_name_1; } - else if (node.parent.parent.kind === ts.SyntaxKind.ClassDeclaration) { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; + else if (node.parent.parent.kind === SyntaxKind.ClassDeclaration) { + diagnosticMessage = Diagnostics.Type_parameter_0_of_public_method_from_exported_class_has_or_is_using_private_name_1; } else { - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics.Type_parameter_0_of_method_from_exported_interface_has_or_is_using_private_name_1; } break; - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.FunctionDeclaration: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; + case SyntaxKind.FunctionType: + case SyntaxKind.FunctionDeclaration: + diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_function_has_or_is_using_private_name_1; break; - case ts.SyntaxKind.TypeAliasDeclaration: - diagnosticMessage = ts.Diagnostics.Type_parameter_0_of_exported_type_alias_has_or_is_using_private_name_1; + case SyntaxKind.TypeAliasDeclaration: + diagnosticMessage = Diagnostics.Type_parameter_0_of_exported_type_alias_has_or_is_using_private_name_1; break; default: - return ts.Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); + return Debug.fail("This is unknown parent for type parameter: " + node.parent.kind); } return { diagnosticMessage, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name }; } function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic { - let diagnosticMessage: ts.DiagnosticMessage; + let diagnosticMessage: DiagnosticMessage; // Heritage clause is written by user so it can always be named - if (ts.isClassDeclaration(node.parent.parent)) { + if (isClassDeclaration(node.parent.parent)) { // Class or Interface implemented/extended is inaccessible - diagnosticMessage = ts.isHeritageClause(node.parent) && node.parent.token === ts.SyntaxKind.ImplementsKeyword ? - ts.Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : - node.parent.parent.name ? ts.Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1 : - ts.Diagnostics.extends_clause_of_exported_class_has_or_is_using_private_name_0; + diagnosticMessage = isHeritageClause(node.parent) && node.parent.token === SyntaxKind.ImplementsKeyword ? + Diagnostics.Implements_clause_of_exported_class_0_has_or_is_using_private_name_1 : + node.parent.parent.name ? Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1 : + Diagnostics.extends_clause_of_exported_class_has_or_is_using_private_name_0; } else { // interface is inaccessible - diagnosticMessage = ts.Diagnostics.extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; + diagnosticMessage = Diagnostics.extends_clause_of_exported_interface_0_has_or_is_using_private_name_1; } return { diagnosticMessage, errorNode: node, - typeName: ts.getNameOfDeclaration(node.parent.parent as ts.Declaration) + typeName: getNameOfDeclaration(node.parent.parent as Declaration) }; } function getImportEntityNameVisibilityError(): SymbolAccessibilityDiagnostic { return { - diagnosticMessage: ts.Diagnostics.Import_declaration_0_is_using_private_name_1, + diagnosticMessage: Diagnostics.Import_declaration_0_is_using_private_name_1, errorNode: node, - typeName: (node as ts.NamedDeclaration).name + typeName: (node as NamedDeclaration).name }; } - function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult: ts.SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getTypeAliasDeclarationVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { return { diagnosticMessage: symbolAccessibilityResult.errorModuleName - ? ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1_from_module_2 - : ts.Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, - errorNode: ts.isJSDocTypeAlias(node) ? ts.Debug.checkDefined(node.typeExpression) : (node as ts.TypeAliasDeclaration).type, - typeName: ts.isJSDocTypeAlias(node) ? ts.getNameOfDeclaration(node) : (node as ts.TypeAliasDeclaration).name, + ? Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1_from_module_2 + : Diagnostics.Exported_type_alias_0_has_or_is_using_private_name_1, + errorNode: isJSDocTypeAlias(node) ? Debug.checkDefined(node.typeExpression) : (node as TypeAliasDeclaration).type, + typeName: isJSDocTypeAlias(node) ? getNameOfDeclaration(node) : (node as TypeAliasDeclaration).name, }; } } diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index ef118aac232f8..3198bdead1099 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -1,17 +1,31 @@ -import * as ts from "../_namespaces/ts"; +import { + __String, addRange, append, ArrayBindingElement, ArrayBindingOrAssignmentPattern, BindingElement, BindingName, + BindingOrAssignmentElement, BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, Debug, + DestructuringAssignment, ElementAccessExpression, every, Expression, factory, forEach, + getElementsOfBindingOrAssignmentPattern, getInitializerOfBindingOrAssignmentElement, + getPropertyNameOfBindingOrAssignmentElement, getRestIndicatorOfBindingOrAssignmentElement, + getTargetOfBindingOrAssignmentElement, Identifier, idText, isArrayBindingElement, isArrayBindingOrAssignmentPattern, + isBindingElement, isBindingName, isBindingOrAssignmentPattern, isComputedPropertyName, isDeclarationBindingElement, + isDestructuringAssignment, isEmptyArrayLiteral, isEmptyObjectLiteral, isExpression, isIdentifier, + isLiteralExpression, isObjectBindingOrAssignmentPattern, isOmittedExpression, isPropertyNameLiteral, + isSimpleInlineableExpression, isStringOrNumericLiteralLike, isVariableDeclaration, last, LeftHandSideExpression, + map, Node, NodeFactory, nodeIsSynthesized, ObjectBindingOrAssignmentPattern, ParameterDeclaration, PropertyName, + setTextRange, some, TextRange, TransformationContext, TransformFlags, + tryGetPropertyNameOfBindingOrAssignmentElement, VariableDeclaration, visitNode, VisitResult, +} from "../_namespaces/ts"; interface FlattenContext { - context: ts.TransformationContext; + context: TransformationContext; level: FlattenLevel; downlevelIteration: boolean; hoistTempVariables: boolean; hasTransformedPriorElement?: boolean; // indicates whether we've transformed a prior declaration - emitExpression: (value: ts.Expression) => void; - emitBindingOrAssignment: (target: ts.BindingOrAssignmentElementTarget, value: ts.Expression, location: ts.TextRange, original: ts.Node | undefined) => void; - createArrayBindingOrAssignmentPattern: (elements: ts.BindingOrAssignmentElement[]) => ts.ArrayBindingOrAssignmentPattern; - createObjectBindingOrAssignmentPattern: (elements: ts.BindingOrAssignmentElement[]) => ts.ObjectBindingOrAssignmentPattern; - createArrayBindingOrAssignmentElement: (node: ts.Identifier) => ts.BindingOrAssignmentElement; - visitor?: (node: ts.Node) => ts.VisitResult; + emitExpression: (value: Expression) => void; + emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node | undefined) => void; + createArrayBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ArrayBindingOrAssignmentPattern; + createObjectBindingOrAssignmentPattern: (elements: BindingOrAssignmentElement[]) => ObjectBindingOrAssignmentPattern; + createArrayBindingOrAssignmentElement: (node: Identifier) => BindingOrAssignmentElement; + visitor?: (node: Node) => VisitResult; } /** @internal */ @@ -33,28 +47,28 @@ export const enum FlattenLevel { * @param createAssignmentCallback An optional callback used to create the assignment expression. */ export function flattenDestructuringAssignment( - node: ts.VariableDeclaration | ts.DestructuringAssignment, - visitor: ((node: ts.Node) => ts.VisitResult) | undefined, - context: ts.TransformationContext, + node: VariableDeclaration | DestructuringAssignment, + visitor: ((node: Node) => VisitResult) | undefined, + context: TransformationContext, level: FlattenLevel, needsValue?: boolean, - createAssignmentCallback?: (name: ts.Identifier, value: ts.Expression, location?: ts.TextRange) => ts.Expression): ts.Expression { - let location: ts.TextRange = node; - let value: ts.Expression | undefined; - if (ts.isDestructuringAssignment(node)) { + createAssignmentCallback?: (name: Identifier, value: Expression, location?: TextRange) => Expression): Expression { + let location: TextRange = node; + let value: Expression | undefined; + if (isDestructuringAssignment(node)) { value = node.right; - while (ts.isEmptyArrayLiteral(node.left) || ts.isEmptyObjectLiteral(node.left)) { - if (ts.isDestructuringAssignment(value)) { + while (isEmptyArrayLiteral(node.left) || isEmptyObjectLiteral(node.left)) { + if (isDestructuringAssignment(value)) { location = node = value; value = node.right; } else { - return ts.visitNode(value, visitor, ts.isExpression); + return visitNode(value, visitor, isExpression); } } } - let expressions: ts.Expression[] | undefined; + let expressions: Expression[] | undefined; const flattenContext: FlattenContext = { context, level, @@ -69,9 +83,9 @@ export function flattenDestructuringAssignment( }; if (value) { - value = ts.visitNode(value, visitor, ts.isExpression); + value = visitNode(value, visitor, isExpression); - if (ts.isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText) || + if (isIdentifier(value) && bindingOrAssignmentElementAssignsToName(node, value.escapedText) || bindingOrAssignmentElementContainsNonLiteralComputedName(node)) { // If the right-hand value of the assignment is also an assignment target then // we need to cache the right-hand value. @@ -86,7 +100,7 @@ export function flattenDestructuringAssignment( // expression. value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); } - else if (ts.nodeIsSynthesized(node)) { + else if (nodeIsSynthesized(node)) { // Generally, the source map location for a destructuring assignment is the root // expression. // @@ -97,10 +111,10 @@ export function flattenDestructuringAssignment( } } - flattenBindingOrAssignmentElement(flattenContext, node, value, location, /*skipInitializer*/ ts.isDestructuringAssignment(node)); + flattenBindingOrAssignmentElement(flattenContext, node, value, location, /*skipInitializer*/ isDestructuringAssignment(node)); if (value && needsValue) { - if (!ts.some(expressions)) { + if (!some(expressions)) { return value; } @@ -109,16 +123,16 @@ export function flattenDestructuringAssignment( return context.factory.inlineExpressions(expressions!) || context.factory.createOmittedExpression(); - function emitExpression(expression: ts.Expression) { - expressions = ts.append(expressions, expression); + function emitExpression(expression: Expression) { + expressions = append(expressions, expression); } - function emitBindingOrAssignment(target: ts.BindingOrAssignmentElementTarget, value: ts.Expression, location: ts.TextRange, original: ts.Node) { - ts.Debug.assertNode(target, createAssignmentCallback ? ts.isIdentifier : ts.isExpression); + function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) { + Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression); const expression = createAssignmentCallback - ? createAssignmentCallback(target as ts.Identifier, value, location) - : ts.setTextRange( - context.factory.createAssignment(ts.visitNode(target as ts.Expression, visitor, ts.isExpression), value), + ? createAssignmentCallback(target as Identifier, value, location) + : setTextRange( + context.factory.createAssignment(visitNode(target as Expression, visitor, isExpression), value), location ); expression.original = original; @@ -126,19 +140,19 @@ export function flattenDestructuringAssignment( } } -function bindingOrAssignmentElementAssignsToName(element: ts.BindingOrAssignmentElement, escapedName: ts.__String): boolean { - const target = ts.getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 - if (ts.isBindingOrAssignmentPattern(target)) { +function bindingOrAssignmentElementAssignsToName(element: BindingOrAssignmentElement, escapedName: __String): boolean { + const target = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 + if (isBindingOrAssignmentPattern(target)) { return bindingOrAssignmentPatternAssignsToName(target, escapedName); } - else if (ts.isIdentifier(target)) { + else if (isIdentifier(target)) { return target.escapedText === escapedName; } return false; } -function bindingOrAssignmentPatternAssignsToName(pattern: ts.BindingOrAssignmentPattern, escapedName: ts.__String): boolean { - const elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); +function bindingOrAssignmentPatternAssignsToName(pattern: BindingOrAssignmentPattern, escapedName: __String): boolean { + const elements = getElementsOfBindingOrAssignmentPattern(pattern); for (const element of elements) { if (bindingOrAssignmentElementAssignsToName(element, escapedName)) { return true; @@ -147,17 +161,17 @@ function bindingOrAssignmentPatternAssignsToName(pattern: ts.BindingOrAssignment return false; } -function bindingOrAssignmentElementContainsNonLiteralComputedName(element: ts.BindingOrAssignmentElement): boolean { - const propertyName = ts.tryGetPropertyNameOfBindingOrAssignmentElement(element); - if (propertyName && ts.isComputedPropertyName(propertyName) && !ts.isLiteralExpression(propertyName.expression)) { +function bindingOrAssignmentElementContainsNonLiteralComputedName(element: BindingOrAssignmentElement): boolean { + const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(element); + if (propertyName && isComputedPropertyName(propertyName) && !isLiteralExpression(propertyName.expression)) { return true; } - const target = ts.getTargetOfBindingOrAssignmentElement(element); - return !!target && ts.isBindingOrAssignmentPattern(target) && bindingOrAssignmentPatternContainsNonLiteralComputedName(target); + const target = getTargetOfBindingOrAssignmentElement(element); + return !!target && isBindingOrAssignmentPattern(target) && bindingOrAssignmentPatternContainsNonLiteralComputedName(target); } -function bindingOrAssignmentPatternContainsNonLiteralComputedName(pattern: ts.BindingOrAssignmentPattern): boolean { - return !!ts.forEach(ts.getElementsOfBindingOrAssignmentPattern(pattern), bindingOrAssignmentElementContainsNonLiteralComputedName); +function bindingOrAssignmentPatternContainsNonLiteralComputedName(pattern: BindingOrAssignmentPattern): boolean { + return !!forEach(getElementsOfBindingOrAssignmentPattern(pattern), bindingOrAssignmentElementContainsNonLiteralComputedName); } /** @internal */ @@ -173,16 +187,16 @@ function bindingOrAssignmentPatternContainsNonLiteralComputedName(pattern: ts.Bi * @param level Indicates the extent to which flattening should occur. */ export function flattenDestructuringBinding( - node: ts.VariableDeclaration | ts.ParameterDeclaration, - visitor: (node: ts.Node) => ts.VisitResult, - context: ts.TransformationContext, + node: VariableDeclaration | ParameterDeclaration, + visitor: (node: Node) => VisitResult, + context: TransformationContext, level: FlattenLevel, - rval?: ts.Expression, + rval?: Expression, hoistTempVariables = false, - skipInitializer?: boolean): ts.VariableDeclaration[] { - let pendingExpressions: ts.Expression[] | undefined; - const pendingDeclarations: { pendingExpressions?: ts.Expression[], name: ts.BindingName, value: ts.Expression, location?: ts.TextRange, original?: ts.Node; }[] = []; - const declarations: ts.VariableDeclaration[] = []; + skipInitializer?: boolean): VariableDeclaration[] { + let pendingExpressions: Expression[] | undefined; + const pendingDeclarations: { pendingExpressions?: Expression[], name: BindingName, value: Expression, location?: TextRange, original?: Node; }[] = []; + const declarations: VariableDeclaration[] = []; const flattenContext: FlattenContext = { context, level, @@ -196,13 +210,13 @@ export function flattenDestructuringBinding( visitor }; - if (ts.isVariableDeclaration(node)) { - let initializer = ts.getInitializerOfBindingOrAssignmentElement(node); - if (initializer && (ts.isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText) || + if (isVariableDeclaration(node)) { + let initializer = getInitializerOfBindingOrAssignmentElement(node); + if (initializer && (isIdentifier(initializer) && bindingOrAssignmentElementAssignsToName(node, initializer.escapedText) || bindingOrAssignmentElementContainsNonLiteralComputedName(node))) { // If the right-hand value of the assignment is also an assignment target then // we need to cache the right-hand value. - initializer = ensureIdentifier(flattenContext, ts.visitNode(initializer, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, initializer); + initializer = ensureIdentifier(flattenContext, visitNode(initializer, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, initializer); node = context.factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, initializer); } } @@ -217,12 +231,12 @@ export function flattenDestructuringBinding( } else { context.hoistVariableDeclaration(temp); - const pendingDeclaration = ts.last(pendingDeclarations); - pendingDeclaration.pendingExpressions = ts.append( + const pendingDeclaration = last(pendingDeclarations); + pendingDeclaration.pendingExpressions = append( pendingDeclaration.pendingExpressions, context.factory.createAssignment(temp, pendingDeclaration.value) ); - ts.addRange(pendingDeclaration.pendingExpressions, pendingExpressions); + addRange(pendingDeclaration.pendingExpressions, pendingExpressions); pendingDeclaration.value = temp; } } @@ -231,22 +245,22 @@ export function flattenDestructuringBinding( name, /*exclamationToken*/ undefined, /*type*/ undefined, - pendingExpressions ? context.factory.inlineExpressions(ts.append(pendingExpressions, value)) : value + pendingExpressions ? context.factory.inlineExpressions(append(pendingExpressions, value)) : value ); variable.original = original; - ts.setTextRange(variable, location); + setTextRange(variable, location); declarations.push(variable); } return declarations; - function emitExpression(value: ts.Expression) { - pendingExpressions = ts.append(pendingExpressions, value); + function emitExpression(value: Expression) { + pendingExpressions = append(pendingExpressions, value); } - function emitBindingOrAssignment(target: ts.BindingOrAssignmentElementTarget, value: ts.Expression, location: ts.TextRange | undefined, original: ts.Node | undefined) { - ts.Debug.assertNode(target, ts.isBindingName); + function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) { + Debug.assertNode(target, isBindingName); if (pendingExpressions) { - value = context.factory.inlineExpressions(ts.append(pendingExpressions, value)); + value = context.factory.inlineExpressions(append(pendingExpressions, value)); pendingExpressions = undefined; } pendingDeclarations.push({ pendingExpressions, name: target, value, location, original }); @@ -265,19 +279,19 @@ export function flattenDestructuringBinding( */ function flattenBindingOrAssignmentElement( flattenContext: FlattenContext, - element: ts.BindingOrAssignmentElement, - value: ts.Expression | undefined, - location: ts.TextRange, + element: BindingOrAssignmentElement, + value: Expression | undefined, + location: TextRange, skipInitializer?: boolean) { - const bindingTarget = ts.getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 + const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217 if (!skipInitializer) { - const initializer = ts.visitNode(ts.getInitializerOfBindingOrAssignmentElement(element), flattenContext.visitor, ts.isExpression); + const initializer = visitNode(getInitializerOfBindingOrAssignmentElement(element), flattenContext.visitor, isExpression); if (initializer) { // Combine value and initializer if (value) { value = createDefaultValueCheck(flattenContext, value, initializer, location); // If 'value' is not a simple expression, it could contain side-effecting code that should evaluate before an object or array binding pattern. - if (!ts.isSimpleInlineableExpression(initializer) && ts.isBindingOrAssignmentPattern(bindingTarget)) { + if (!isSimpleInlineableExpression(initializer) && isBindingOrAssignmentPattern(bindingTarget)) { value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); } } @@ -290,10 +304,10 @@ function flattenBindingOrAssignmentElement( value = flattenContext.context.factory.createVoidZero(); } } - if (ts.isObjectBindingOrAssignmentPattern(bindingTarget)) { + if (isObjectBindingOrAssignmentPattern(bindingTarget)) { flattenObjectBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location); } - else if (ts.isArrayBindingOrAssignmentPattern(bindingTarget)) { + else if (isArrayBindingOrAssignmentPattern(bindingTarget)) { flattenArrayBindingOrAssignmentPattern(flattenContext, element, bindingTarget, value!, location); } else { @@ -310,28 +324,28 @@ function flattenBindingOrAssignmentElement( * @param value The current RHS value to assign to the element. * @param location The location to use for source maps and comments. */ -function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: ts.BindingOrAssignmentElement, pattern: ts.ObjectBindingOrAssignmentPattern, value: ts.Expression, location: ts.TextRange) { - const elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); +function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ObjectBindingOrAssignmentPattern, value: Expression, location: TextRange) { + const elements = getElementsOfBindingOrAssignmentPattern(pattern); const numElements = elements.length; if (numElements !== 1) { // For anything other than a single-element destructuring we need to generate a temporary // to ensure value is evaluated exactly once. Additionally, if we have zero elements // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, // so in that case, we'll intentionally create that temporary. - const reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; + const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } - let bindingElements: ts.BindingOrAssignmentElement[] | undefined; - let computedTempVariables: ts.Expression[] | undefined; + let bindingElements: BindingOrAssignmentElement[] | undefined; + let computedTempVariables: Expression[] | undefined; for (let i = 0; i < numElements; i++) { const element = elements[i]; - if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { - const propertyName = ts.getPropertyNameOfBindingOrAssignmentElement(element)!; + if (!getRestIndicatorOfBindingOrAssignmentElement(element)) { + const propertyName = getPropertyNameOfBindingOrAssignmentElement(element)!; if (flattenContext.level >= FlattenLevel.ObjectRest - && !(element.transformFlags & (ts.TransformFlags.ContainsRestOrSpread | ts.TransformFlags.ContainsObjectRestOrSpread)) - && !(ts.getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (ts.TransformFlags.ContainsRestOrSpread | ts.TransformFlags.ContainsObjectRestOrSpread)) - && !ts.isComputedPropertyName(propertyName)) { - bindingElements = ts.append(bindingElements, ts.visitNode(element, flattenContext.visitor)); + && !(element.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) + && !(getTargetOfBindingOrAssignmentElement(element)!.transformFlags & (TransformFlags.ContainsRestOrSpread | TransformFlags.ContainsObjectRestOrSpread)) + && !isComputedPropertyName(propertyName)) { + bindingElements = append(bindingElements, visitNode(element, flattenContext.visitor)); } else { if (bindingElements) { @@ -339,8 +353,8 @@ function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, bindingElements = undefined; } const rhsValue = createDestructuringPropertyAccess(flattenContext, value, propertyName); - if (ts.isComputedPropertyName(propertyName)) { - computedTempVariables = ts.append(computedTempVariables, (rhsValue as ts.ElementAccessExpression).argumentExpression); + if (isComputedPropertyName(propertyName)) { + computedTempVariables = append(computedTempVariables, (rhsValue as ElementAccessExpression).argumentExpression); } flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } @@ -368,17 +382,17 @@ function flattenObjectBindingOrAssignmentPattern(flattenContext: FlattenContext, * @param value The current RHS value to assign to the element. * @param location The location to use for source maps and comments. */ -function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: ts.BindingOrAssignmentElement, pattern: ts.ArrayBindingOrAssignmentPattern, value: ts.Expression, location: ts.TextRange) { - const elements = ts.getElementsOfBindingOrAssignmentPattern(pattern); +function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ArrayBindingOrAssignmentPattern, value: Expression, location: TextRange) { + const elements = getElementsOfBindingOrAssignmentPattern(pattern); const numElements = elements.length; if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.downlevelIteration) { // Read the elements of the iterable into an array value = ensureIdentifier( flattenContext, - ts.setTextRange( + setTextRange( flattenContext.context.getEmitHelperFactory().createReadHelper( value, - numElements > 0 && ts.getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) + numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1]) ? undefined : numElements ), @@ -389,41 +403,41 @@ function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, ); } else if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0) - || ts.every(elements, ts.isOmittedExpression)) { + || every(elements, isOmittedExpression)) { // For anything other than a single-element destructuring we need to generate a temporary // to ensure value is evaluated exactly once. Additionally, if we have zero elements // we need to emit *something* to ensure that in case a 'var' keyword was already emitted, // so in that case, we'll intentionally create that temporary. // Or all the elements of the binding pattern are omitted expression such as "var [,] = [1,2]", // then we will create temporary variable. - const reuseIdentifierExpressions = !ts.isDeclarationBindingElement(parent) || numElements !== 0; + const reuseIdentifierExpressions = !isDeclarationBindingElement(parent) || numElements !== 0; value = ensureIdentifier(flattenContext, value, reuseIdentifierExpressions, location); } - let bindingElements: ts.BindingOrAssignmentElement[] | undefined; - let restContainingElements: [ts.Identifier, ts.BindingOrAssignmentElement][] | undefined; + let bindingElements: BindingOrAssignmentElement[] | undefined; + let restContainingElements: [Identifier, BindingOrAssignmentElement][] | undefined; for (let i = 0; i < numElements; i++) { const element = elements[i]; if (flattenContext.level >= FlattenLevel.ObjectRest) { // If an array pattern contains an ObjectRest, we must cache the result so that we // can perform the ObjectRest destructuring in a different declaration - if (element.transformFlags & ts.TransformFlags.ContainsObjectRestOrSpread || flattenContext.hasTransformedPriorElement && !isSimpleBindingOrAssignmentElement(element)) { + if (element.transformFlags & TransformFlags.ContainsObjectRestOrSpread || flattenContext.hasTransformedPriorElement && !isSimpleBindingOrAssignmentElement(element)) { flattenContext.hasTransformedPriorElement = true; const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); } - restContainingElements = ts.append(restContainingElements, [temp, element] as [ts.Identifier, ts.BindingOrAssignmentElement]); - bindingElements = ts.append(bindingElements, flattenContext.createArrayBindingOrAssignmentElement(temp)); + restContainingElements = append(restContainingElements, [temp, element] as [Identifier, BindingOrAssignmentElement]); + bindingElements = append(bindingElements, flattenContext.createArrayBindingOrAssignmentElement(temp)); } else { - bindingElements = ts.append(bindingElements, element); + bindingElements = append(bindingElements, element); } } - else if (ts.isOmittedExpression(element)) { + else if (isOmittedExpression(element)) { continue; } - else if (!ts.getRestIndicatorOfBindingOrAssignmentElement(element)) { + else if (!getRestIndicatorOfBindingOrAssignmentElement(element)) { const rhsValue = flattenContext.context.factory.createElementAccessExpression(value, i); flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element); } @@ -442,15 +456,15 @@ function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, } } -function isSimpleBindingOrAssignmentElement(element: ts.BindingOrAssignmentElement): boolean { - const target = ts.getTargetOfBindingOrAssignmentElement(element); - if (!target || ts.isOmittedExpression(target)) return true; - const propertyName = ts.tryGetPropertyNameOfBindingOrAssignmentElement(element); - if (propertyName && !ts.isPropertyNameLiteral(propertyName)) return false; - const initializer = ts.getInitializerOfBindingOrAssignmentElement(element); - if (initializer && !ts.isSimpleInlineableExpression(initializer)) return false; - if (ts.isBindingOrAssignmentPattern(target)) return ts.every(ts.getElementsOfBindingOrAssignmentPattern(target), isSimpleBindingOrAssignmentElement); - return ts.isIdentifier(target); +function isSimpleBindingOrAssignmentElement(element: BindingOrAssignmentElement): boolean { + const target = getTargetOfBindingOrAssignmentElement(element); + if (!target || isOmittedExpression(target)) return true; + const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(element); + if (propertyName && !isPropertyNameLiteral(propertyName)) return false; + const initializer = getInitializerOfBindingOrAssignmentElement(element); + if (initializer && !isSimpleInlineableExpression(initializer)) return false; + if (isBindingOrAssignmentPattern(target)) return every(getElementsOfBindingOrAssignmentPattern(target), isSimpleBindingOrAssignmentElement); + return isIdentifier(target); } /** @@ -461,7 +475,7 @@ function isSimpleBindingOrAssignmentElement(element: ts.BindingOrAssignmentEleme * @param defaultValue The default value to use if `value` is `undefined` at runtime. * @param location The location to use for source maps and comments. */ -function createDefaultValueCheck(flattenContext: FlattenContext, value: ts.Expression, defaultValue: ts.Expression, location: ts.TextRange): ts.Expression { +function createDefaultValueCheck(flattenContext: FlattenContext, value: Expression, defaultValue: Expression, location: TextRange): Expression { value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location); return flattenContext.context.factory.createConditionalExpression(flattenContext.context.factory.createTypeCheck(value, "undefined"), /*questionToken*/ undefined, defaultValue, /*colonToken*/ undefined, value); } @@ -476,17 +490,17 @@ function createDefaultValueCheck(flattenContext: FlattenContext, value: ts.Expre * @param value The RHS value that is the source of the property. * @param propertyName The destructuring property name. */ -function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: ts.Expression, propertyName: ts.PropertyName): ts.LeftHandSideExpression { - if (ts.isComputedPropertyName(propertyName)) { - const argumentExpression = ensureIdentifier(flattenContext, ts.visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); +function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: Expression, propertyName: PropertyName): LeftHandSideExpression { + if (isComputedPropertyName(propertyName)) { + const argumentExpression = ensureIdentifier(flattenContext, visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName); return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression); } - else if (ts.isStringOrNumericLiteralLike(propertyName)) { - const argumentExpression = ts.factory.cloneNode(propertyName); + else if (isStringOrNumericLiteralLike(propertyName)) { + const argumentExpression = factory.cloneNode(propertyName); return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression); } else { - const name = flattenContext.context.factory.createIdentifier(ts.idText(propertyName)); + const name = flattenContext.context.factory.createIdentifier(idText(propertyName)); return flattenContext.context.factory.createPropertyAccessExpression(value, name); } } @@ -502,15 +516,15 @@ function createDestructuringPropertyAccess(flattenContext: FlattenContext, value * false if it is necessary to always emit an identifier. * @param location The location to use for source maps and comments. */ -function ensureIdentifier(flattenContext: FlattenContext, value: ts.Expression, reuseIdentifierExpressions: boolean, location: ts.TextRange) { - if (ts.isIdentifier(value) && reuseIdentifierExpressions) { +function ensureIdentifier(flattenContext: FlattenContext, value: Expression, reuseIdentifierExpressions: boolean, location: TextRange) { + if (isIdentifier(value) && reuseIdentifierExpressions) { return value; } else { const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); - flattenContext.emitExpression(ts.setTextRange(flattenContext.context.factory.createAssignment(temp, value), location)); + flattenContext.emitExpression(setTextRange(flattenContext.context.factory.createAssignment(temp, value), location)); } else { flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); @@ -519,28 +533,28 @@ function ensureIdentifier(flattenContext: FlattenContext, value: ts.Expression, } } -function makeArrayBindingPattern(factory: ts.NodeFactory, elements: ts.BindingOrAssignmentElement[]) { - ts.Debug.assertEachNode(elements, ts.isArrayBindingElement); - return factory.createArrayBindingPattern(elements as ts.ArrayBindingElement[]); +function makeArrayBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + Debug.assertEachNode(elements, isArrayBindingElement); + return factory.createArrayBindingPattern(elements as ArrayBindingElement[]); } -function makeArrayAssignmentPattern(factory: ts.NodeFactory, elements: ts.BindingOrAssignmentElement[]) { - return factory.createArrayLiteralExpression(ts.map(elements, factory.converters.convertToArrayAssignmentElement)); +function makeArrayAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + return factory.createArrayLiteralExpression(map(elements, factory.converters.convertToArrayAssignmentElement)); } -function makeObjectBindingPattern(factory: ts.NodeFactory, elements: ts.BindingOrAssignmentElement[]) { - ts.Debug.assertEachNode(elements, ts.isBindingElement); - return factory.createObjectBindingPattern(elements as ts.BindingElement[]); +function makeObjectBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + Debug.assertEachNode(elements, isBindingElement); + return factory.createObjectBindingPattern(elements as BindingElement[]); } -function makeObjectAssignmentPattern(factory: ts.NodeFactory, elements: ts.BindingOrAssignmentElement[]) { - return factory.createObjectLiteralExpression(ts.map(elements, factory.converters.convertToObjectAssignmentElement)); +function makeObjectAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) { + return factory.createObjectLiteralExpression(map(elements, factory.converters.convertToObjectAssignmentElement)); } -function makeBindingElement(factory: ts.NodeFactory, name: ts.Identifier) { +function makeBindingElement(factory: NodeFactory, name: Identifier) { return factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name); } -function makeAssignmentElement(name: ts.Identifier) { +function makeAssignmentElement(name: Identifier) { return name; } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index e1151aa7d0524..ac22ce5ec5536 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -1,4 +1,40 @@ -import * as ts from "../_namespaces/ts"; +import { + __String, AccessorDeclaration, addEmitHelpers, addRange, addSyntheticLeadingComment, AllAccessorDeclarations, + append, arrayIsEqualTo, ArrayLiteralExpression, ArrowFunction, BinaryExpression, BindingElement, BindingPattern, + Block, BreakOrContinueStatement, CallExpression, CaseBlock, CaseClause, cast, CatchClause, chainBundle, + ClassDeclaration, ClassElement, ClassExpression, ClassLikeDeclaration, CommaListExpression, ComputedPropertyName, + concatenate, ConstructorDeclaration, createExpressionForPropertyName, createMemberAccessForPropertyName, + createRange, createTokenRange, Debug, Declaration, DoStatement, elementAt, EmitFlags, EmitHint, emptyArray, ESMap, + Expression, ExpressionStatement, ExpressionWithTypeArguments, filter, first, firstOrUndefined, flatMap, flatten, + flattenDestructuringAssignment, flattenDestructuringBinding, FlattenLevel, ForInStatement, ForOfStatement, + ForStatement, FunctionBody, FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, + GeneratedIdentifierFlags, getAllAccessorDeclarations, getClassExtendsHeritageElement, getCombinedNodeFlags, + getCommentRange, getEmitFlags, getEnclosingBlockScopeContainer, getFirstConstructorWithBody, getNameOfDeclaration, + getOriginalNode, getParseTreeNode, getSourceMapRange, getSuperCallFromStatement, getUseDefineForClassFields, + hasStaticModifier, hasSyntacticModifier, Identifier, idText, IfStatement, insertStatementAfterCustomPrologue, + insertStatementsAfterCustomPrologue, insertStatementsAfterStandardPrologue, isArrayLiteralExpression, + isArrowFunction, isAssignmentExpression, isBinaryExpression, isBindingPattern, isBlock, isCallExpression, + isCallToHelper, isCaseBlock, isCaseClause, isCatchClause, isClassElement, isClassLike, isComputedPropertyName, + isDefaultClause, isDestructuringAssignment, isExpression, isExpressionStatement, isForInitializer, isForStatement, + isFunctionExpression, isFunctionLike, isHoistedFunction, isHoistedVariableStatement, isIdentifier, + isIdentifierANonContextualKeyword, isIfStatement, isInternalName, isIterationStatement, isLabeledStatement, + isModifier, isObjectLiteralElementLike, isOmittedExpression, isPackedArrayLiteral, isPrivateIdentifier, + isPrologueDirective, isPropertyDeclaration, isPropertyName, isReturnStatement, isSpreadElement, isStatement, + isStatic, isSuperProperty, isSwitchStatement, isTryStatement, isVariableDeclarationList, isVariableStatement, + isWithStatement, IterationStatement, LabeledStatement, last, lastOrUndefined, LeftHandSideExpression, + LiteralExpression, map, Map, MetaProperty, MethodDeclaration, ModifierFlags, moveRangeEnd, moveRangePos, + moveSyntheticComments, NamedDeclaration, NewExpression, Node, NodeArray, NodeCheckFlags, NodeFlags, + nodeIsSynthesized, NumericLiteral, ObjectLiteralElementLike, ObjectLiteralExpression, ParameterDeclaration, + ParenthesizedExpression, PrimaryExpression, ProcessLevel, processTaggedTemplateExpression, PropertyAssignment, + rangeEndIsOnSameLineAsRangeStart, ReturnStatement, SemicolonClassElement, setCommentRange, setEmitFlags, + setOriginalNode, setParent, setSourceMapRange, setTextRange, setTextRangeEnd, setTextRangePos, + setTokenSourceMapRange, ShorthandPropertyAssignment, singleOrMany, singleOrUndefined, skipOuterExpressions, + skipTrivia, some, SourceFile, spanMap, SpreadElement, startOnNewLine, Statement, StringLiteral, SwitchStatement, + SyntaxKind, TaggedTemplateExpression, takeWhile, TemplateExpression, TextRange, TokenFlags, TransformationContext, + TransformFlags, tryCast, unescapeLeadingUnderscores, unwrapInnermostStatementOfLabel, VariableDeclaration, + VariableDeclarationList, VariableStatement, visitEachChild, visitNode, visitNodes, visitParameterList, VisitResult, + VoidExpression, WhileStatement, YieldExpression, +} from "../_namespaces/ts"; const enum ES2015SubstitutionFlags { /** Enables substitutions for captured `this` */ @@ -47,8 +83,8 @@ const enum ES2015SubstitutionFlags { */ interface LoopOutParameter { flags: LoopOutParameterFlags; - originalName: ts.Identifier; - outParamName: ts.Identifier; + originalName: Identifier; + outParamName: Identifier; } const enum LoopOutParameterFlags { @@ -72,15 +108,15 @@ interface ConvertedLoopState { * set of labels that occurred inside the converted loop * used to determine if labeled jump can be emitted as is or it should be dispatched to calling code */ - labels?: ts.ESMap; + labels?: ESMap; /* * collection of labeled jumps that transfer control outside the converted loop. * maps store association 'label -> labelMarker' where * - label - value of label as it appear in code * - label marker - return value that should be interpreted by calling code as 'jump to " - const lessThanToken = ts.getTokenAtPosition(sourceFile, pos); + const lessThanToken = getTokenAtPosition(sourceFile, pos); const firstJsxElementOrOpenElement = lessThanToken.parent; let binaryExpr = firstJsxElementOrOpenElement.parent; - if (!ts.isBinaryExpression(binaryExpr)) { + if (!isBinaryExpression(binaryExpr)) { // In case the start element is a JsxSelfClosingElement, it the end. // For JsxOpenElement, find one more parent binaryExpr = binaryExpr.parent; - if (!ts.isBinaryExpression(binaryExpr)) return undefined; + if (!isBinaryExpression(binaryExpr)) return undefined; } - if (!ts.nodeIsMissing(binaryExpr.operatorToken)) return undefined; + if (!nodeIsMissing(binaryExpr.operatorToken)) return undefined; return binaryExpr; } -function doChange(changeTracker: ts.textChanges.ChangeTracker, sf: ts.SourceFile, node: ts.Node) { +function doChange(changeTracker: textChanges.ChangeTracker, sf: SourceFile, node: Node) { const jsx = flattenInvalidBinaryExpr(node); - if (jsx) changeTracker.replaceNode(sf, node, ts.factory.createJsxFragment(ts.factory.createJsxOpeningFragment(), jsx, ts.factory.createJsxJsxClosingFragment())); + if (jsx) changeTracker.replaceNode(sf, node, factory.createJsxFragment(factory.createJsxOpeningFragment(), jsx, factory.createJsxJsxClosingFragment())); } // The invalid syntax is constructed as // InvalidJsxTree :: One of // JsxElement CommaToken InvalidJsxTree // JsxElement CommaToken JsxElement -function flattenInvalidBinaryExpr(node: ts.Node): ts.JsxChild[] | undefined { - const children: ts.JsxChild[] = []; +function flattenInvalidBinaryExpr(node: Node): JsxChild[] | undefined { + const children: JsxChild[] = []; let current = node; while (true) { - if (ts.isBinaryExpression(current) && ts.nodeIsMissing(current.operatorToken) && current.operatorToken.kind === ts.SyntaxKind.CommaToken) { - children.push(current.left as ts.JsxChild); - if (ts.isJsxChild(current.right)) { + if (isBinaryExpression(current) && nodeIsMissing(current.operatorToken) && current.operatorToken.kind === SyntaxKind.CommaToken) { + children.push(current.left as JsxChild); + if (isJsxChild(current.right)) { children.push(current.right); // Indicates the tree has go to the bottom return children; } - else if (ts.isBinaryExpression(current.right)) { + else if (isBinaryExpression(current.right)) { current = current.right; continue; } diff --git a/src/services/completions.ts b/src/services/completions.ts index 3edcc910d06e1..9a4cc6a4bd634 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1,4 +1,66 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, addToSeen, append, BinaryExpression, BreakOrContinueStatement, CancellationToken, cast, CharacterCodes, + ClassElement, CodeAction, codefix, compareNumberOfDirectorySeparators, compareStringsCaseSensitiveUI, + compareTextSpans, Comparison, CompilerOptions, compilerOptionsIndicateEsModules, CompletionEntry, + CompletionEntryData, CompletionEntryDataAutoImport, CompletionEntryDataResolved, CompletionEntryDataUnresolved, + CompletionEntryDetails, CompletionEntryLabelDetails, CompletionInfo, CompletionInfoFlags, + CompletionsTriggerCharacter, CompletionTriggerKind, concatenate, ConstructorDeclaration, ContextFlags, + createModuleSpecifierResolutionHost, createPackageJsonImportFilter, createPrinter, createSortedArray, + createTextRangeFromSpan, createTextSpanFromBounds, createTextSpanFromNode, createTextSpanFromRange, Debug, + Declaration, Diagnostics, diagnosticToString, displayPart, EmitHint, EmitTextWriter, escapeSnippetText, every, + ExportKind, Expression, factory, filter, find, findAncestor, findChildOfKind, findPrecedingToken, first, + firstDefined, flatMap, formatting, FunctionLikeDeclaration, getAllSuperTypeNodes, getAncestor, + getCombinedLocalAndExportSymbolFlags, getContainingClass, getContextualTypeFromParent, + getDeclarationModifierFlagsFromSymbol, getEffectiveBaseTypeNode, getEffectiveModifierFlags, + getEffectiveTypeAnnotationNode, getEmitModuleResolutionKind, getEmitScriptTarget, + getEscapedTextOfIdentifierOrLiteral, getExportInfoMap, getFormatCodeSettingsForWriting, getLanguageVariant, + getLeftmostAccessExpression, getLineAndCharacterOfPosition, getLineStartPositionForPosition, + getLocalSymbolForExportDefault, getNameForExportedSymbol, getNameOfDeclaration, getNameTable, getNewLineCharacter, + getNewLineKind, getPropertyNameForPropertyNameNode, getQuotePreference, getReplacementSpanForContextToken, + getRootDeclaration, getSourceFileOfModule, getSwitchedType, getSymbolId, getSynthesizedDeepClone, + getTokenAtPosition, getTouchingPropertyName, hasDocComment, hasEffectiveModifier, hasInitializer, hasType, + Identifier, ImportDeclaration, ImportEqualsDeclaration, ImportKind, ImportOrExportSpecifier, ImportSpecifier, + ImportTypeNode, IncompleteCompletionsCache, insertSorted, InternalSymbolName, isAbstractConstructorSymbol, + isArrowFunction, isAssertionExpression, isBigIntLiteral, isBinaryExpression, isBindingElement, isBindingPattern, + isBreakOrContinueStatement, isCallExpression, isCaseClause, isCheckJsEnabledForFile, isClassElement, isClassLike, + isClassMemberModifier, isClassOrTypeElement, isClassStaticBlockDeclaration, isComputedPropertyName, + isConstructorDeclaration, isContextualKeyword, isDeclarationName, isDeprecatedDeclaration, isEntityName, + isEqualityOperatorKind, isExportAssignment, isExportDeclaration, isExpression, isExternalModuleNameRelative, + isExternalModuleReference, isExternalModuleSymbol, isFunctionBlock, isFunctionLike, isFunctionLikeDeclaration, + isFunctionLikeKind, isFunctionTypeNode, isIdentifier, isIdentifierText, isImportableFile, isImportDeclaration, + isImportEqualsDeclaration, isImportKeyword, isImportSpecifier, isInComment, isInitializedProperty, isInJSFile, + isInRightSideOfInternalImportEqualsDeclaration, isInString, isIntersectionTypeNode, isJSDoc, isJSDocParameterTag, + isJSDocTag, isJSDocTemplateTag, isJsxAttribute, isJsxClosingElement, isJsxElement, isJsxExpression, isJsxFragment, + isJsxOpeningLikeElement, isJsxSpreadAttribute, isKeyword, isKnownSymbol, isLabeledStatement, + isLiteralImportTypeNode, isMemberName, isMethodDeclaration, isModifier, isModifierKind, isModuleDeclaration, + isNamedExports, isNamedImports, isNamedImportsOrExports, isNamespaceImport, isObjectBindingPattern, + isObjectLiteralExpression, isObjectTypeDeclaration, isParameter, isParameterPropertyModifier, isPartOfTypeNode, + isPossiblyTypeArgumentPosition, isPrivateIdentifier, isPrivateIdentifierClassElementDeclaration, + isPropertyAccessExpression, isPropertyDeclaration, isPropertyNameLiteral, isRegularExpressionLiteral, + isShorthandPropertyAssignment, isSingleOrDoubleQuote, isSourceFile, isSourceFileJS, isSpreadAssignment, isStatement, + isStatic, isString, isStringANonContextualKeyword, isStringLiteralLike, isStringLiteralOrTemplate, + isStringTextContainingNode, isSyntaxList, isTypeKeyword, isTypeKeywordTokenOrIdentifier, isTypeLiteralNode, + isTypeNode, isTypeOfExpression, isTypeOnlyImportOrExportDeclaration, isTypeReferenceType, + isValidTypeOnlyAliasUseSite, isVariableDeclaration, isVariableLike, JsDoc, JSDocParameterTag, JSDocPropertyTag, + JSDocReturnTag, JSDocTag, JSDocTagInfo, JSDocTemplateTag, JSDocTypedefTag, JSDocTypeExpression, JSDocTypeTag, + JsTyping, JsxAttribute, JsxAttributes, JsxClosingElement, JsxElement, JsxOpeningLikeElement, JsxSpreadAttribute, + LanguageServiceHost, LanguageVariant, last, lastOrUndefined, length, ListFormat, Map, mapDefined, maybeBind, + MemberOverrideStatus, memoize, memoizeOne, MethodDeclaration, ModifierFlags, modifiersToFlags, ModifierSyntaxKind, + modifierToFlag, ModuleDeclaration, ModuleReference, moduleResolutionRespectsExports, NamedImportBindings, Node, + NodeArray, NodeBuilderFlags, NodeFlags, nodeIsMissing, ObjectBindingPattern, ObjectLiteralExpression, ObjectType, + ObjectTypeDeclaration, or, positionBelongsToNode, positionIsASICandidate, positionsAreOnSameLine, PrinterOptions, + probablyUsesSemicolons, Program, programContainsModules, PropertyAccessExpression, PropertyDeclaration, + PropertyName, PseudoBigInt, pseudoBigIntToString, QualifiedName, quote, QuotePreference, rangeContainsPosition, + rangeContainsPositionExclusive, rangeIsOnSingleLine, ScriptElementKind, ScriptElementKindModifier, ScriptTarget, + SemanticMeaning, Set, setSnippetElement, shouldUseUriStyleNodeCoreModules, SignatureHelp, SignatureKind, + singleElementArray, skipAlias, SnippetKind, some, SortedArray, SourceFile, SpreadAssignment, stableSort, startsWith, + stringToToken, stripQuotes, Symbol, SymbolDisplay, SymbolDisplayPart, SymbolDisplayPartKind, SymbolExportInfo, + SymbolFlags, SymbolId, SyntaxKind, TextChange, textChanges, textPart, TextRange, TextSpan, timestamp, Token, + TokenSyntaxKind, tokenToString, tryCast, tryGetImportFromModuleSpecifier, Type, TypeChecker, TypeElement, TypeFlags, + typeHasCallOrConstructSignatures, TypeLiteralNode, TypeOnlyAliasDeclaration, unescapeLeadingUnderscores, + UnionReduction, UnionType, UserPreferences, VariableDeclaration, walkUpParenthesizedExpressions, +} from "./_namespaces/ts"; +import { StringCompletions } from "./_namespaces/ts.Completions"; // Exported only for tests /** @internal */ @@ -84,7 +146,7 @@ interface SymbolOriginInfo { interface SymbolOriginInfoExport extends SymbolOriginInfo { symbolName: string; - moduleSymbol: ts.Symbol; + moduleSymbol: Symbol; isDefaultExport: boolean; exportName: string; exportMapKey: string; @@ -92,18 +154,18 @@ interface SymbolOriginInfoExport extends SymbolOriginInfo { interface SymbolOriginInfoResolvedExport extends SymbolOriginInfo { symbolName: string; - moduleSymbol: ts.Symbol; + moduleSymbol: Symbol; exportName: string; moduleSpecifier: string; } interface SymbolOriginInfoTypeOnlyAlias extends SymbolOriginInfo { - declaration: ts.TypeOnlyAliasDeclaration; + declaration: TypeOnlyAliasDeclaration; } interface SymbolOriginInfoObjectLiteralMethod extends SymbolOriginInfo { insertText: string, - labelDetails: ts.CompletionEntryLabelDetails, + labelDetails: CompletionEntryLabelDetails, isSnippet?: true, } @@ -176,35 +238,35 @@ const enum KeywordCompletionFilters { const enum GlobalsSearch { Continue, Success, Fail } interface ModuleSpecifierResolutioContext { - tryResolve: (exportInfo: readonly ts.SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult; + tryResolve: (exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult; resolvedAny: () => boolean; skippedAny: () => boolean; resolvedBeyondLimit: () => boolean; } type ModuleSpecifierResolutionResult = "skipped" | "failed" | { - exportInfo?: ts.SymbolExportInfo; + exportInfo?: SymbolExportInfo; moduleSpecifier: string; }; function resolvingModuleSpecifiers( logPrefix: string, - host: ts.LanguageServiceHost, - resolver: ts.codefix.ImportSpecifierResolver, - program: ts.Program, + host: LanguageServiceHost, + resolver: codefix.ImportSpecifierResolver, + program: Program, position: number, - preferences: ts.UserPreferences, + preferences: UserPreferences, isForImportStatementCompletion: boolean, isValidTypeOnlyUseSite: boolean, cb: (context: ModuleSpecifierResolutioContext) => TReturn, ): TReturn { - const start = ts.timestamp(); + const start = timestamp(); // Under `--moduleResolution nodenext`, we have to resolve module specifiers up front, because // package.json exports can mean we *can't* resolve a module specifier (that doesn't include a // relative path into node_modules), and we want to filter those completions out entirely. // Import statement completions always need specifier resolution because the module specifier is // part of their `insertText`, not the `codeActions` creating edits away from the cursor. - const needsFullResolution = isForImportStatementCompletion || ts.moduleResolutionRespectsExports(ts.getEmitModuleResolutionKind(program.getCompilerOptions())); + const needsFullResolution = isForImportStatementCompletion || moduleResolutionRespectsExports(getEmitModuleResolutionKind(program.getCompilerOptions())); let skippedAny = false; let ambientCount = 0; let resolvedCount = 0; @@ -221,10 +283,10 @@ function resolvingModuleSpecifiers( const hitRateMessage = cacheAttemptCount ? ` (${(resolvedFromCacheCount / cacheAttemptCount * 100).toFixed(1)}% hit rate)` : ""; host.log?.(`${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`); host.log?.(`${logPrefix}: response is ${skippedAny ? "incomplete" : "complete"}`); - host.log?.(`${logPrefix}: ${ts.timestamp() - start}`); + host.log?.(`${logPrefix}: ${timestamp() - start}`); return result; - function tryResolve(exportInfo: readonly ts.SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean): ModuleSpecifierResolutionResult { + function tryResolve(exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean): ModuleSpecifierResolutionResult { if (isFromAmbientModule) { const result = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result) { @@ -254,19 +316,19 @@ function resolvingModuleSpecifiers( /** @internal */ export function getCompletionsAtPosition( - host: ts.LanguageServiceHost, - program: ts.Program, + host: LanguageServiceHost, + program: Program, log: Log, - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, - preferences: ts.UserPreferences, - triggerCharacter: ts.CompletionsTriggerCharacter | undefined, - completionKind: ts.CompletionTriggerKind | undefined, - cancellationToken: ts.CancellationToken, - formatContext?: ts.formatting.FormatContext, -): ts.CompletionInfo | undefined { + preferences: UserPreferences, + triggerCharacter: CompletionsTriggerCharacter | undefined, + completionKind: CompletionTriggerKind | undefined, + cancellationToken: CancellationToken, + formatContext?: formatting.FormatContext, +): CompletionInfo | undefined { const { previousToken } = getRelevantTokens(position, sourceFile); - if (triggerCharacter && !ts.isInString(sourceFile, position, previousToken) && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position)) { + if (triggerCharacter && !isInString(sourceFile, position, previousToken) && !isValidTrigger(sourceFile, triggerCharacter, previousToken, position)) { return undefined; } @@ -283,7 +345,7 @@ export function getCompletionsAtPosition( // we can continue it from the cached previous response. const compilerOptions = program.getCompilerOptions(); const incompleteCompletionsCache = preferences.allowIncompleteCompletions ? host.getIncompleteCompletionsCache?.() : undefined; - if (incompleteCompletionsCache && completionKind === ts.CompletionTriggerKind.TriggerForIncompleteCompletions && previousToken && ts.isIdentifier(previousToken)) { + if (incompleteCompletionsCache && completionKind === CompletionTriggerKind.TriggerForIncompleteCompletions && previousToken && isIdentifier(previousToken)) { const incompleteContinuation = continuePreviousIncompleteResponse(incompleteCompletionsCache, sourceFile, previousToken, program, host, preferences, cancellationToken); if (incompleteContinuation) { return incompleteContinuation; @@ -293,13 +355,13 @@ export function getCompletionsAtPosition( incompleteCompletionsCache?.clear(); } - const stringCompletions = ts.Completions.StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences); + const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, previousToken, compilerOptions, host, program, log, preferences); if (stringCompletions) { return stringCompletions; } - if (previousToken && ts.isBreakOrContinueStatement(previousToken.parent) - && (previousToken.kind === ts.SyntaxKind.BreakKeyword || previousToken.kind === ts.SyntaxKind.ContinueKeyword || previousToken.kind === ts.SyntaxKind.Identifier)) { + if (previousToken && isBreakOrContinueStatement(previousToken.parent) + && (previousToken.kind === SyntaxKind.BreakKeyword || previousToken.kind === SyntaxKind.ContinueKeyword || previousToken.kind === SyntaxKind.Identifier)) { return getLabelCompletionAtPosition(previousToken.parent); } @@ -317,16 +379,16 @@ export function getCompletionsAtPosition( return response; case CompletionDataKind.JsDocTagName: // If the current position is a jsDoc tag name, only tag names should be provided for completion - return jsdocCompletionInfo(ts.JsDoc.getJSDocTagNameCompletions()); + return jsdocCompletionInfo(JsDoc.getJSDocTagNameCompletions()); case CompletionDataKind.JsDocTag: // If the current position is a jsDoc tag, only tags should be provided for completion - return jsdocCompletionInfo(ts.JsDoc.getJSDocTagCompletions()); + return jsdocCompletionInfo(JsDoc.getJSDocTagCompletions()); case CompletionDataKind.JsDocParameterName: - return jsdocCompletionInfo(ts.JsDoc.getJSDocParameterNameCompletions(completionData.tag)); + return jsdocCompletionInfo(JsDoc.getJSDocParameterNameCompletions(completionData.tag)); case CompletionDataKind.Keywords: return specificKeywordCompletionInfo(completionData.keywordCompletions, completionData.isNewIdentifierLocation); default: - return ts.Debug.assertNever(completionData); + return Debug.assertNever(completionData); } } @@ -337,54 +399,54 @@ export function getCompletionsAtPosition( // by the language service consistent with what TS Server does and what editors typically do. This also makes // completions tests make more sense. We used to sort only alphabetically and only in the server layer, but // this made tests really weird, since most fourslash tests don't use the server. -function compareCompletionEntries(entryInArray: ts.CompletionEntry, entryToInsert: ts.CompletionEntry): ts.Comparison { - let result = ts.compareStringsCaseSensitiveUI(entryInArray.sortText, entryToInsert.sortText); - if (result === ts.Comparison.EqualTo) { - result = ts.compareStringsCaseSensitiveUI(entryInArray.name, entryToInsert.name); +function compareCompletionEntries(entryInArray: CompletionEntry, entryToInsert: CompletionEntry): Comparison { + let result = compareStringsCaseSensitiveUI(entryInArray.sortText, entryToInsert.sortText); + if (result === Comparison.EqualTo) { + result = compareStringsCaseSensitiveUI(entryInArray.name, entryToInsert.name); } - if (result === ts.Comparison.EqualTo && entryInArray.data?.moduleSpecifier && entryToInsert.data?.moduleSpecifier) { + if (result === Comparison.EqualTo && entryInArray.data?.moduleSpecifier && entryToInsert.data?.moduleSpecifier) { // Sort same-named auto-imports by module specifier - result = ts.compareNumberOfDirectorySeparators( - (entryInArray.data as ts.CompletionEntryDataResolved).moduleSpecifier, - (entryToInsert.data as ts.CompletionEntryDataResolved).moduleSpecifier, + result = compareNumberOfDirectorySeparators( + (entryInArray.data as CompletionEntryDataResolved).moduleSpecifier, + (entryToInsert.data as CompletionEntryDataResolved).moduleSpecifier, ); } - if (result === ts.Comparison.EqualTo) { + if (result === Comparison.EqualTo) { // Fall back to symbol order - if we return `EqualTo`, `insertSorted` will put later symbols first. - return ts.Comparison.LessThan; + return Comparison.LessThan; } return result; } -function completionEntryDataIsResolved(data: ts.CompletionEntryDataAutoImport | undefined): data is ts.CompletionEntryDataResolved { +function completionEntryDataIsResolved(data: CompletionEntryDataAutoImport | undefined): data is CompletionEntryDataResolved { return !!data?.moduleSpecifier; } function continuePreviousIncompleteResponse( - cache: ts.IncompleteCompletionsCache, - file: ts.SourceFile, - location: ts.Identifier, - program: ts.Program, - host: ts.LanguageServiceHost, - preferences: ts.UserPreferences, - cancellationToken: ts.CancellationToken, -): ts.CompletionInfo | undefined { + cache: IncompleteCompletionsCache, + file: SourceFile, + location: Identifier, + program: Program, + host: LanguageServiceHost, + preferences: UserPreferences, + cancellationToken: CancellationToken, +): CompletionInfo | undefined { const previousResponse = cache.get(); if (!previousResponse) return undefined; const lowerCaseTokenText = location.text.toLowerCase(); - const exportMap = ts.getExportInfoMap(file, host, program, preferences, cancellationToken); + const exportMap = getExportInfoMap(file, host, program, preferences, cancellationToken); const newEntries = resolvingModuleSpecifiers( "continuePreviousIncompleteResponse", host, - ts.codefix.createImportSpecifierResolver(file, program, host, preferences), + codefix.createImportSpecifierResolver(file, program, host, preferences), program, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, - ts.isValidTypeOnlyAliasUseSite(location), + isValidTypeOnlyAliasUseSite(location), context => { - const entries = ts.mapDefined(previousResponse.entries, entry => { + const entries = mapDefined(previousResponse.entries, entry => { if (!entry.hasAction || !entry.source || !entry.data || completionEntryDataIsResolved(entry.data)) { // Not an auto import or already resolved; keep as is return entry; @@ -394,10 +456,10 @@ function continuePreviousIncompleteResponse( return undefined; } - const { origin } = ts.Debug.checkDefined(getAutoImportSymbolFromCompletionEntryData(entry.name, entry.data, program, host)); + const { origin } = Debug.checkDefined(getAutoImportSymbolFromCompletionEntryData(entry.name, entry.data, program, host)); const info = exportMap.get(file.path, entry.data.exportMapKey); - const result = info && context.tryResolve(info, entry.name, !ts.isExternalModuleNameRelative(ts.stripQuotes(origin.moduleSymbol.name))); + const result = info && context.tryResolve(info, entry.name, !isExternalModuleNameRelative(stripQuotes(origin.moduleSymbol.name))); if (result === "skipped") return entry; if (!result || result === "failed") { host.log?.(`Unexpected failure resolving auto import for '${entry.name}' from '${entry.source}'`); @@ -413,7 +475,7 @@ function continuePreviousIncompleteResponse( // so why bother allocating a bunch of new objects? entry.data = originToCompletionEntryData(newOrigin); entry.source = getSourceFromOrigin(newOrigin); - entry.sourceDisplay = [ts.textPart(newOrigin.moduleSpecifier)]; + entry.sourceDisplay = [textPart(newOrigin.moduleSpecifier)]; return entry; }); @@ -426,24 +488,24 @@ function continuePreviousIncompleteResponse( ); previousResponse.entries = newEntries; - previousResponse.flags = (previousResponse.flags || 0) | ts.CompletionInfoFlags.IsContinuation; + previousResponse.flags = (previousResponse.flags || 0) | CompletionInfoFlags.IsContinuation; return previousResponse; } -function jsdocCompletionInfo(entries: ts.CompletionEntry[]): ts.CompletionInfo { +function jsdocCompletionInfo(entries: CompletionEntry[]): CompletionInfo { return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; } -function keywordToCompletionEntry(keyword: ts.TokenSyntaxKind) { +function keywordToCompletionEntry(keyword: TokenSyntaxKind) { return { - name: ts.tokenToString(keyword)!, - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, + name: tokenToString(keyword)!, + kind: ScriptElementKind.keyword, + kindModifiers: ScriptElementKindModifier.none, sortText: SortText.GlobalsOrKeywords, }; } -function specificKeywordCompletionInfo(entries: readonly ts.CompletionEntry[], isNewIdentifierLocation: boolean): ts.CompletionInfo { +function specificKeywordCompletionInfo(entries: readonly CompletionEntry[], isNewIdentifierLocation: boolean): CompletionInfo { return { isGlobalCompletion: false, isMemberCompletion: false, @@ -460,29 +522,29 @@ function keywordCompletionData(keywordFilters: KeywordCompletionFilters, filterO }; } -function keywordFiltersFromSyntaxKind(keywordCompletion: ts.TokenSyntaxKind): KeywordCompletionFilters { +function keywordFiltersFromSyntaxKind(keywordCompletion: TokenSyntaxKind): KeywordCompletionFilters { switch (keywordCompletion) { - case ts.SyntaxKind.TypeKeyword: return KeywordCompletionFilters.TypeKeyword; - default: ts.Debug.fail("Unknown mapping from SyntaxKind to KeywordCompletionFilters"); + case SyntaxKind.TypeKeyword: return KeywordCompletionFilters.TypeKeyword; + default: Debug.fail("Unknown mapping from SyntaxKind to KeywordCompletionFilters"); } } -function getOptionalReplacementSpan(location: ts.Node | undefined) { +function getOptionalReplacementSpan(location: Node | undefined) { // StringLiteralLike locations are handled separately in stringCompletions.ts - return location?.kind === ts.SyntaxKind.Identifier ? ts.createTextSpanFromNode(location) : undefined; + return location?.kind === SyntaxKind.Identifier ? createTextSpanFromNode(location) : undefined; } function completionInfoFromData( - sourceFile: ts.SourceFile, - host: ts.LanguageServiceHost, - program: ts.Program, - compilerOptions: ts.CompilerOptions, + sourceFile: SourceFile, + host: LanguageServiceHost, + program: Program, + compilerOptions: CompilerOptions, log: Log, completionData: CompletionData, - preferences: ts.UserPreferences, - formatContext: ts.formatting.FormatContext | undefined, + preferences: UserPreferences, + formatContext: formatting.FormatContext | undefined, position: number -): ts.CompletionInfo | undefined { +): CompletionInfo | undefined { const { symbols, contextToken, @@ -506,14 +568,14 @@ function completionInfoFromData( } = completionData; // Verify if the file is JSX language variant - if (ts.getLanguageVariant(sourceFile.scriptKind) === ts.LanguageVariant.JSX) { + if (getLanguageVariant(sourceFile.scriptKind) === LanguageVariant.JSX) { const completionInfo = getJsxClosingTagCompletion(location, sourceFile); if (completionInfo) { return completionInfo; } } - const entries = ts.createSortedArray(); + const entries = createSortedArray(); const isChecked = isCheckedFile(sourceFile, compilerOptions); if (isChecked && !isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { return undefined; @@ -527,7 +589,7 @@ function completionInfoFromData( sourceFile, host, program, - ts.getEmitScriptTarget(compilerOptions), + getEmitScriptTarget(compilerOptions), log, completionKind, preferences, @@ -546,10 +608,10 @@ function completionInfoFromData( ); if (keywordFilters !== KeywordCompletionFilters.None) { - for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && ts.isSourceFileJS(sourceFile))) { - if (isTypeOnlyLocation && ts.isTypeKeyword(ts.stringToToken(keywordEntry.name)!) || !uniqueNames.has(keywordEntry.name)) { + for (const keywordEntry of getKeywordCompletions(keywordFilters, !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile))) { + if (isTypeOnlyLocation && isTypeKeyword(stringToToken(keywordEntry.name)!) || !uniqueNames.has(keywordEntry.name)) { uniqueNames.add(keywordEntry.name); - ts.insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); } } } @@ -557,18 +619,18 @@ function completionInfoFromData( for (const keywordEntry of getContextualKeywords(contextToken, position)) { if (!uniqueNames.has(keywordEntry.name)) { uniqueNames.add(keywordEntry.name); - ts.insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, keywordEntry, compareCompletionEntries, /*allowDuplicates*/ true); } } for (const literal of literals) { const literalEntry = createCompletionEntryForLiteral(sourceFile, preferences, literal); uniqueNames.add(literalEntry.name); - ts.insertSorted(entries, literalEntry, compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, literalEntry, compareCompletionEntries, /*allowDuplicates*/ true); } if (!isChecked) { - getJSCompletionEntries(sourceFile, location.pos, uniqueNames, ts.getEmitScriptTarget(compilerOptions), entries); + getJSCompletionEntries(sourceFile, location.pos, uniqueNames, getEmitScriptTarget(compilerOptions), entries); } return { @@ -582,8 +644,8 @@ function completionInfoFromData( }; } -function isCheckedFile(sourceFile: ts.SourceFile, compilerOptions: ts.CompilerOptions): boolean { - return !ts.isSourceFileJS(sourceFile) || !!ts.isCheckJsEnabledForFile(sourceFile, compilerOptions); +function isCheckedFile(sourceFile: SourceFile, compilerOptions: CompilerOptions): boolean { + return !isSourceFileJS(sourceFile) || !!isCheckJsEnabledForFile(sourceFile, compilerOptions); } function isMemberCompletionKind(kind: CompletionKind): boolean { @@ -597,21 +659,21 @@ function isMemberCompletionKind(kind: CompletionKind): boolean { } } -function getJsxClosingTagCompletion(location: ts.Node | undefined, sourceFile: ts.SourceFile): ts.CompletionInfo | undefined { +function getJsxClosingTagCompletion(location: Node | undefined, sourceFile: SourceFile): CompletionInfo | undefined { // We wanna walk up the tree till we find a JSX closing element - const jsxClosingElement = ts.findAncestor(location, node => { + const jsxClosingElement = findAncestor(location, node => { switch (node.kind) { - case ts.SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxClosingElement: return true; - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.GreaterThanToken: - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.SlashToken: + case SyntaxKind.GreaterThanToken: + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: return false; default: return "quit"; } - }) as ts.JsxClosingElement | undefined; + }) as JsxClosingElement | undefined; if (jsxClosingElement) { // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, @@ -626,15 +688,15 @@ function getJsxClosingTagCompletion(location: ts.Node | undefined, sourceFile: t // var x = // var y = // the completion list at "1" and "2" will contain "MainComponent.Child" with a replacement span of closing tag name - const hasClosingAngleBracket = !!ts.findChildOfKind(jsxClosingElement, ts.SyntaxKind.GreaterThanToken, sourceFile); + const hasClosingAngleBracket = !!findChildOfKind(jsxClosingElement, SyntaxKind.GreaterThanToken, sourceFile); const tagName = jsxClosingElement.parent.openingElement.tagName; const closingTag = tagName.getText(sourceFile); const fullClosingTag = closingTag + (hasClosingAngleBracket ? "" : ">"); - const replacementSpan = ts.createTextSpanFromNode(jsxClosingElement.tagName); + const replacementSpan = createTextSpanFromNode(jsxClosingElement.tagName); - const entry: ts.CompletionEntry = { + const entry: CompletionEntry = { name: fullClosingTag, - kind: ts.ScriptElementKind.classElement, + kind: ScriptElementKind.classElement, kindModifiers: undefined, sortText: SortText.LocationPriority, }; @@ -644,22 +706,22 @@ function getJsxClosingTagCompletion(location: ts.Node | undefined, sourceFile: t } function getJSCompletionEntries( - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, uniqueNames: UniqueNameSet, - target: ts.ScriptTarget, - entries: ts.SortedArray): void { - ts.getNameTable(sourceFile).forEach((pos, name) => { + target: ScriptTarget, + entries: SortedArray): void { + getNameTable(sourceFile).forEach((pos, name) => { // Skip identifiers produced only from the current location if (pos === position) { return; } - const realName = ts.unescapeLeadingUnderscores(name); - if (!uniqueNames.has(realName) && ts.isIdentifierText(realName, target)) { + const realName = unescapeLeadingUnderscores(name); + if (!uniqueNames.has(realName) && isIdentifierText(realName, target)) { uniqueNames.add(realName); - ts.insertSorted(entries, { + insertSorted(entries, { name: realName, - kind: ts.ScriptElementKind.warning, + kind: ScriptElementKind.warning, kindModifiers: "", sortText: SortText.JavascriptIdentifiers, isFromUncheckedFile: true @@ -668,42 +730,42 @@ function getJSCompletionEntries( }); } -function completionNameForLiteral(sourceFile: ts.SourceFile, preferences: ts.UserPreferences, literal: string | number | ts.PseudoBigInt): string { - return typeof literal === "object" ? ts.pseudoBigIntToString(literal) + "n" : - ts.isString(literal) ? ts.quote(sourceFile, preferences, literal) : JSON.stringify(literal); +function completionNameForLiteral(sourceFile: SourceFile, preferences: UserPreferences, literal: string | number | PseudoBigInt): string { + return typeof literal === "object" ? pseudoBigIntToString(literal) + "n" : + isString(literal) ? quote(sourceFile, preferences, literal) : JSON.stringify(literal); } -function createCompletionEntryForLiteral(sourceFile: ts.SourceFile, preferences: ts.UserPreferences, literal: string | number | ts.PseudoBigInt): ts.CompletionEntry { - return { name: completionNameForLiteral(sourceFile, preferences, literal), kind: ts.ScriptElementKind.string, kindModifiers: ts.ScriptElementKindModifier.none, sortText: SortText.LocationPriority }; +function createCompletionEntryForLiteral(sourceFile: SourceFile, preferences: UserPreferences, literal: string | number | PseudoBigInt): CompletionEntry { + return { name: completionNameForLiteral(sourceFile, preferences, literal), kind: ScriptElementKind.string, kindModifiers: ScriptElementKindModifier.none, sortText: SortText.LocationPriority }; } function createCompletionEntry( - symbol: ts.Symbol, + symbol: Symbol, sortText: SortText, - replacementToken: ts.Node | undefined, - contextToken: ts.Node | undefined, - location: ts.Node, - sourceFile: ts.SourceFile, - host: ts.LanguageServiceHost, - program: ts.Program, + replacementToken: Node | undefined, + contextToken: Node | undefined, + location: Node, + sourceFile: SourceFile, + host: LanguageServiceHost, + program: Program, name: string, needsConvertPropertyAccess: boolean, origin: SymbolOriginInfo | undefined, - recommendedCompletion: ts.Symbol | undefined, - propertyAccessToConvert: ts.PropertyAccessExpression | undefined, + recommendedCompletion: Symbol | undefined, + propertyAccessToConvert: PropertyAccessExpression | undefined, isJsxInitializer: IsJsxInitializer | undefined, importStatementCompletion: ImportStatementCompletionInfo | undefined, useSemicolons: boolean, - options: ts.CompilerOptions, - preferences: ts.UserPreferences, + options: CompilerOptions, + preferences: UserPreferences, completionKind: CompletionKind, - formatContext: ts.formatting.FormatContext | undefined, + formatContext: formatting.FormatContext | undefined, isJsxIdentifierExpected: boolean | undefined, isRightOfOpenTag: boolean | undefined, -): ts.CompletionEntry | undefined { +): CompletionEntry | undefined { let insertText: string | undefined; - let replacementSpan = ts.getReplacementSpanForContextToken(replacementToken); - let data: ts.CompletionEntryData | undefined; + let replacementSpan = getReplacementSpanForContextToken(replacementToken); + let data: CompletionEntryData | undefined; let isSnippet: true | undefined; let source = getSourceFromOrigin(origin); let sourceDisplay; @@ -726,38 +788,38 @@ function createCompletionEntry( insertText = `?.${insertText}`; } - const dot = ts.findChildOfKind(propertyAccessToConvert, ts.SyntaxKind.DotToken, sourceFile) || - ts.findChildOfKind(propertyAccessToConvert, ts.SyntaxKind.QuestionDotToken, sourceFile); + const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile) || + findChildOfKind(propertyAccessToConvert, SyntaxKind.QuestionDotToken, sourceFile); if (!dot) { return undefined; } // If the text after the '.' starts with this name, write over it. Else, add new text. - const end = ts.startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end; - replacementSpan = ts.createTextSpanFromBounds(dot.getStart(sourceFile), end); + const end = startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end; + replacementSpan = createTextSpanFromBounds(dot.getStart(sourceFile), end); } if (isJsxInitializer) { if (insertText === undefined) insertText = name; insertText = `{${insertText}}`; if (typeof isJsxInitializer !== "boolean") { - replacementSpan = ts.createTextSpanFromNode(isJsxInitializer, sourceFile); + replacementSpan = createTextSpanFromNode(isJsxInitializer, sourceFile); } } if (origin && originIsPromise(origin) && propertyAccessToConvert) { if (insertText === undefined) insertText = name; - const precedingToken = ts.findPrecedingToken(propertyAccessToConvert.pos, sourceFile); + const precedingToken = findPrecedingToken(propertyAccessToConvert.pos, sourceFile); let awaitText = ""; - if (precedingToken && ts.positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) { + if (precedingToken && positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) { awaitText = ";"; } awaitText += `(await ${propertyAccessToConvert.expression.getText()})`; insertText = needsConvertPropertyAccess ? `${awaitText}${insertText}` : `${awaitText}${insertQuestionDot ? "?." : "."}${insertText}`; - replacementSpan = ts.createTextSpanFromBounds(propertyAccessToConvert.getStart(sourceFile), propertyAccessToConvert.end); + replacementSpan = createTextSpanFromBounds(propertyAccessToConvert.getStart(sourceFile), propertyAccessToConvert.end); } if (originIsResolvedExport(origin)) { - sourceDisplay = [ts.textPart(origin.moduleSpecifier)]; + sourceDisplay = [textPart(origin.moduleSpecifier)]; if (importStatementCompletion) { ({ insertText, replacementSpan } = getInsertTextAndReplacementSpanForImportCompletion(name, importStatementCompletion, origin, useSemicolons, sourceFile, options, preferences)); isSnippet = preferences.includeCompletionsWithSnippetText ? true : undefined; @@ -797,12 +859,12 @@ function createCompletionEntry( // If is boolean like or undefined, don't return a snippet we want just to return the completion. if (preferences.jsxAttributeCompletionStyle === "auto" - && !(type.flags & ts.TypeFlags.BooleanLike) - && !(type.flags & ts.TypeFlags.Union && ts.find((type as ts.UnionType).types, type => !!(type.flags & ts.TypeFlags.BooleanLike))) + && !(type.flags & TypeFlags.BooleanLike) + && !(type.flags & TypeFlags.Union && find((type as UnionType).types, type => !!(type.flags & TypeFlags.BooleanLike))) ) { - if (type.flags & ts.TypeFlags.StringLike || (type.flags & ts.TypeFlags.Union && ts.every((type as ts.UnionType).types, type => !!(type.flags & (ts.TypeFlags.StringLike | ts.TypeFlags.Undefined))))) { + if (type.flags & TypeFlags.StringLike || (type.flags & TypeFlags.Union && every((type as UnionType).types, type => !!(type.flags & (TypeFlags.StringLike | TypeFlags.Undefined))))) { // If is string like or undefined use quotes - insertText = `${ts.escapeSnippetText(name)}=${ts.quote(sourceFile, preferences, "$1")}`; + insertText = `${escapeSnippetText(name)}=${quote(sourceFile, preferences, "$1")}`; isSnippet = true; } else { @@ -812,7 +874,7 @@ function createCompletionEntry( } if (useBraces) { - insertText = `${ts.escapeSnippetText(name)}={$1}`; + insertText = `${escapeSnippetText(name)}={$1}`; isSnippet = true; } } @@ -836,8 +898,8 @@ function createCompletionEntry( // entries (like JavaScript identifier entries). return { name, - kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location), - kindModifiers: ts.SymbolDisplay.getSymbolModifiers(typeChecker, symbol), + kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location), + kindModifiers: SymbolDisplay.getSymbolModifiers(typeChecker, symbol), sortText, source, hasAction: hasAction ? true : undefined, @@ -853,16 +915,16 @@ function createCompletionEntry( }; } -function isClassLikeMemberCompletion(symbol: ts.Symbol, location: ts.Node, sourceFile: ts.SourceFile): boolean { +function isClassLikeMemberCompletion(symbol: Symbol, location: Node, sourceFile: SourceFile): boolean { // TODO: support JS files. - if (ts.isInJSFile(location)) { + if (isInJSFile(location)) { return false; } // Completion symbol must be for a class member. const memberFlags = - ts.SymbolFlags.ClassMember - & ts.SymbolFlags.EnumMemberExcludes; + SymbolFlags.ClassMember + & SymbolFlags.EnumMemberExcludes; /* In `class C { | @@ -885,41 +947,41 @@ function isClassLikeMemberCompletion(symbol: ts.Symbol, location: ts.Node, sourc */ return !!(symbol.flags & memberFlags) && ( - ts.isClassLike(location) || + isClassLike(location) || ( location.parent && location.parent.parent && - ts.isClassElement(location.parent) && + isClassElement(location.parent) && location === location.parent.name && location.parent.getLastToken(sourceFile) === location.parent.name && - ts.isClassLike(location.parent.parent) + isClassLike(location.parent.parent) ) || ( location.parent && - ts.isSyntaxList(location) && - ts.isClassLike(location.parent) + isSyntaxList(location) && + isClassLike(location.parent) ) ); } function getEntryForMemberCompletion( - host: ts.LanguageServiceHost, - program: ts.Program, - options: ts.CompilerOptions, - preferences: ts.UserPreferences, + host: LanguageServiceHost, + program: Program, + options: CompilerOptions, + preferences: UserPreferences, name: string, - symbol: ts.Symbol, - location: ts.Node, - contextToken: ts.Node | undefined, - formatContext: ts.formatting.FormatContext | undefined, -): { insertText: string, isSnippet?: true, importAdder?: ts.codefix.ImportAdder, replacementSpan?: ts.TextSpan } { - const classLikeDeclaration = ts.findAncestor(location, ts.isClassLike); + symbol: Symbol, + location: Node, + contextToken: Node | undefined, + formatContext: formatting.FormatContext | undefined, +): { insertText: string, isSnippet?: true, importAdder?: codefix.ImportAdder, replacementSpan?: TextSpan } { + const classLikeDeclaration = findAncestor(location, isClassLike); if (!classLikeDeclaration) { return { insertText: name }; } let isSnippet: true | undefined; - let replacementSpan: ts.TextSpan | undefined; + let replacementSpan: TextSpan | undefined; let insertText: string = name; const checker = program.getTypeChecker(); @@ -929,9 +991,9 @@ function getEntryForMemberCompletion( module: options.module, target: options.target, omitTrailingSemicolon: false, - newLine: ts.getNewLineKind(ts.getNewLineCharacter(options, ts.maybeBind(host, host.getNewLine))), + newLine: getNewLineKind(getNewLineCharacter(options, maybeBind(host, host.getNewLine))), }); - const importAdder = ts.codefix.createImportAdder(sourceFile, program, preferences, host); + const importAdder = codefix.createImportAdder(sourceFile, program, preferences, host); // Create empty body for possible method implementation. let body; @@ -940,21 +1002,21 @@ function getEntryForMemberCompletion( // We are adding a tabstop (i.e. `$0`) in the body of the suggested member, // if it has one, so that the cursor ends up in the body once the completion is inserted. // Note: this assumes we won't have more than one body in the completion nodes, which should be the case. - const emptyStmt = ts.factory.createEmptyStatement(); - body = ts.factory.createBlock([emptyStmt], /* multiline */ true); - ts.setSnippetElement(emptyStmt, { kind: ts.SnippetKind.TabStop, order: 0 }); + const emptyStmt = factory.createEmptyStatement(); + body = factory.createBlock([emptyStmt], /* multiline */ true); + setSnippetElement(emptyStmt, { kind: SnippetKind.TabStop, order: 0 }); } else { - body = ts.factory.createBlock([], /* multiline */ true); + body = factory.createBlock([], /* multiline */ true); } - let modifiers = ts.ModifierFlags.None; + let modifiers = ModifierFlags.None; // Whether the suggested member should be abstract. // e.g. in `abstract class C { abstract | }`, we should offer abstract method signatures at position `|`. const { modifiers: presentModifiers, span: modifiersSpan } = getPresentModifiers(contextToken); - const isAbstract = !!(presentModifiers & ts.ModifierFlags.Abstract); - const completionNodes: ts.Node[] = []; - ts.codefix.addNewNodeForMemberSymbol( + const isAbstract = !!(presentModifiers & ModifierFlags.Abstract); + const completionNodes: Node[] = []; + codefix.addNewNodeForMemberSymbol( symbol, classLikeDeclaration, sourceFile, @@ -969,13 +1031,13 @@ function getEntryForMemberCompletion( // - One node; // - More than one node if the member is overloaded (e.g. a method with overload signatures). node => { - let requiredModifiers = ts.ModifierFlags.None; + let requiredModifiers = ModifierFlags.None; if (isAbstract) { - requiredModifiers |= ts.ModifierFlags.Abstract; + requiredModifiers |= ModifierFlags.Abstract; } - if (ts.isClassElement(node) - && checker.getMemberOverrideModifierStatus(classLikeDeclaration, node) === ts.MemberOverrideStatus.NeedsOverride) { - requiredModifiers |= ts.ModifierFlags.Override; + if (isClassElement(node) + && checker.getMemberOverrideModifierStatus(classLikeDeclaration, node) === MemberOverrideStatus.NeedsOverride) { + requiredModifiers |= ModifierFlags.Override; } if (!completionNodes.length) { @@ -985,29 +1047,29 @@ function getEntryForMemberCompletion( // and we need to make sure the modifiers are uniform for all nodes/signatures. modifiers = node.modifierFlagsCache | requiredModifiers | presentModifiers; } - node = ts.factory.updateModifiers(node, modifiers); + node = factory.updateModifiers(node, modifiers); completionNodes.push(node); }, body, - ts.codefix.PreserveOptionalFlags.Property, + codefix.PreserveOptionalFlags.Property, isAbstract); if (completionNodes.length) { - const format = ts.ListFormat.MultiLine | ts.ListFormat.NoTrailingNewLine; + const format = ListFormat.MultiLine | ListFormat.NoTrailingNewLine; replacementSpan = modifiersSpan; // If we have access to formatting settings, we print the nodes using the emitter, // and then format the printed text. if (formatContext) { insertText = printer.printAndFormatSnippetList( format, - ts.factory.createNodeArray(completionNodes), + factory.createNodeArray(completionNodes), sourceFile, formatContext); } else { // Otherwise, just use emitter to print the new nodes. insertText = printer.printSnippetList( format, - ts.factory.createNodeArray(completionNodes), + factory.createNodeArray(completionNodes), sourceFile); } } @@ -1015,11 +1077,11 @@ function getEntryForMemberCompletion( return { insertText, isSnippet, importAdder, replacementSpan }; } -function getPresentModifiers(contextToken: ts.Node | undefined): { modifiers: ts.ModifierFlags, span?: ts.TextSpan } { +function getPresentModifiers(contextToken: Node | undefined): { modifiers: ModifierFlags, span?: TextSpan } { if (!contextToken) { - return { modifiers: ts.ModifierFlags.None }; + return { modifiers: ModifierFlags.None }; } - let modifiers = ts.ModifierFlags.None; + let modifiers = ModifierFlags.None; let span; let contextMod; /* @@ -1042,36 +1104,36 @@ function getPresentModifiers(contextToken: ts.Node | undefined): { modifiers: ts `location.parent.parent` is class declaration ``class C { ... }``. */ if (contextMod = isModifierLike(contextToken)) { - modifiers |= ts.modifierToFlag(contextMod); - span = ts.createTextSpanFromNode(contextToken); + modifiers |= modifierToFlag(contextMod); + span = createTextSpanFromNode(contextToken); } - if (ts.isPropertyDeclaration(contextToken.parent)) { - modifiers |= ts.modifiersToFlags(contextToken.parent.modifiers) & ts.ModifierFlags.Modifier; - span = ts.createTextSpanFromNode(contextToken.parent); + if (isPropertyDeclaration(contextToken.parent)) { + modifiers |= modifiersToFlags(contextToken.parent.modifiers) & ModifierFlags.Modifier; + span = createTextSpanFromNode(contextToken.parent); } return { modifiers, span }; } -function isModifierLike(node: ts.Node): ts.ModifierSyntaxKind | undefined { - if (ts.isModifier(node)) { +function isModifierLike(node: Node): ModifierSyntaxKind | undefined { + if (isModifier(node)) { return node.kind; } - if (ts.isIdentifier(node) && node.originalKeywordKind && ts.isModifierKind(node.originalKeywordKind)) { + if (isIdentifier(node) && node.originalKeywordKind && isModifierKind(node.originalKeywordKind)) { return node.originalKeywordKind; } return undefined; } function getEntryForObjectLiteralMethodCompletion( - symbol: ts.Symbol, + symbol: Symbol, name: string, - enclosingDeclaration: ts.ObjectLiteralExpression, - program: ts.Program, - host: ts.LanguageServiceHost, - options: ts.CompilerOptions, - preferences: ts.UserPreferences, - formatContext: ts.formatting.FormatContext | undefined, -): { insertText: string, isSnippet?: true, labelDetails: ts.CompletionEntryLabelDetails } | undefined { + enclosingDeclaration: ObjectLiteralExpression, + program: Program, + host: LanguageServiceHost, + options: CompilerOptions, + preferences: UserPreferences, + formatContext: formatting.FormatContext | undefined, +): { insertText: string, isSnippet?: true, labelDetails: CompletionEntryLabelDetails } | undefined { const isSnippet = preferences.includeCompletionsWithSnippetText || undefined; let insertText: string = name; @@ -1087,16 +1149,16 @@ function getEntryForObjectLiteralMethodCompletion( module: options.module, target: options.target, omitTrailingSemicolon: false, - newLine: ts.getNewLineKind(ts.getNewLineCharacter(options, ts.maybeBind(host, host.getNewLine))), + newLine: getNewLineKind(getNewLineCharacter(options, maybeBind(host, host.getNewLine))), }); if (formatContext) { - insertText = printer.printAndFormatSnippetList(ts.ListFormat.CommaDelimited | ts.ListFormat.AllowTrailingComma, ts.factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile, formatContext); + insertText = printer.printAndFormatSnippetList(ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile, formatContext); } else { - insertText = printer.printSnippetList(ts.ListFormat.CommaDelimited | ts.ListFormat.AllowTrailingComma, ts.factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile); + insertText = printer.printSnippetList(ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile); } - const signaturePrinter = ts.createPrinter({ + const signaturePrinter = createPrinter({ removeComments: true, module: options.module, target: options.target, @@ -1104,49 +1166,49 @@ function getEntryForObjectLiteralMethodCompletion( }); // The `labelDetails.detail` will be displayed right beside the method name, // so we drop the name (and modifiers) from the signature. - const methodSignature = ts.factory.createMethodSignature( + const methodSignature = factory.createMethodSignature( /*modifiers*/ undefined, /*name*/ "", method.questionToken, method.typeParameters, method.parameters, method.type); - const labelDetails = { detail: signaturePrinter.printNode(ts.EmitHint.Unspecified, methodSignature, sourceFile) }; + const labelDetails = { detail: signaturePrinter.printNode(EmitHint.Unspecified, methodSignature, sourceFile) }; return { isSnippet, insertText, labelDetails }; } function createObjectLiteralMethod( - symbol: ts.Symbol, - enclosingDeclaration: ts.ObjectLiteralExpression, - sourceFile: ts.SourceFile, - program: ts.Program, - host: ts.LanguageServiceHost, - preferences: ts.UserPreferences, -): ts.MethodDeclaration | undefined { + symbol: Symbol, + enclosingDeclaration: ObjectLiteralExpression, + sourceFile: SourceFile, + program: Program, + host: LanguageServiceHost, + preferences: UserPreferences, +): MethodDeclaration | undefined { const declarations = symbol.getDeclarations(); if (!(declarations && declarations.length)) { return undefined; } const checker = program.getTypeChecker(); const declaration = declarations[0]; - const name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration), /*includeTrivia*/ false) as ts.PropertyName; + const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName; const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration)); - const quotePreference = ts.getQuotePreference(sourceFile, preferences); - const builderFlags = ts.NodeBuilderFlags.OmitThisParameter | (quotePreference === ts.QuotePreference.Single ? ts.NodeBuilderFlags.UseSingleQuotesForStringLiteralType : ts.NodeBuilderFlags.None); + const quotePreference = getQuotePreference(sourceFile, preferences); + const builderFlags = NodeBuilderFlags.OmitThisParameter | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : NodeBuilderFlags.None); switch (declaration.kind) { - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.MethodDeclaration: { - let effectiveType = type.flags & ts.TypeFlags.Union && (type as ts.UnionType).types.length < 10 - ? checker.getUnionType((type as ts.UnionType).types, ts.UnionReduction.Subtype) + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.MethodDeclaration: { + let effectiveType = type.flags & TypeFlags.Union && (type as UnionType).types.length < 10 + ? checker.getUnionType((type as UnionType).types, UnionReduction.Subtype) : type; - if (effectiveType.flags & ts.TypeFlags.Union) { + if (effectiveType.flags & TypeFlags.Union) { // Only offer the completion if there's a single function type component. - const functionTypes = ts.filter((effectiveType as ts.UnionType).types, type => checker.getSignaturesOfType(type, ts.SignatureKind.Call).length > 0); + const functionTypes = filter((effectiveType as UnionType).types, type => checker.getSignaturesOfType(type, SignatureKind.Call).length > 0); if (functionTypes.length === 1) { effectiveType = functionTypes[0]; } @@ -1154,28 +1216,28 @@ function createObjectLiteralMethod( return undefined; } } - const signatures = checker.getSignaturesOfType(effectiveType, ts.SignatureKind.Call); + const signatures = checker.getSignaturesOfType(effectiveType, SignatureKind.Call); if (signatures.length !== 1) { // We don't support overloads in object literals. return undefined; } - const typeNode = checker.typeToTypeNode(effectiveType, enclosingDeclaration, builderFlags, ts.codefix.getNoopSymbolTrackerWithResolver({ program, host })); - if (!typeNode || !ts.isFunctionTypeNode(typeNode)) { + const typeNode = checker.typeToTypeNode(effectiveType, enclosingDeclaration, builderFlags, codefix.getNoopSymbolTrackerWithResolver({ program, host })); + if (!typeNode || !isFunctionTypeNode(typeNode)) { return undefined; } let body; if (preferences.includeCompletionsWithSnippetText) { - const emptyStmt = ts.factory.createEmptyStatement(); - body = ts.factory.createBlock([emptyStmt], /* multiline */ true); - ts.setSnippetElement(emptyStmt, { kind: ts.SnippetKind.TabStop, order: 0 }); + const emptyStmt = factory.createEmptyStatement(); + body = factory.createBlock([emptyStmt], /* multiline */ true); + setSnippetElement(emptyStmt, { kind: SnippetKind.TabStop, order: 0 }); } else { - body = ts.factory.createBlock([], /* multiline */ true); + body = factory.createBlock([], /* multiline */ true); } const parameters = typeNode.parameters.map(typedParam => - ts.factory.createParameterDeclaration( + factory.createParameterDeclaration( /*modifiers*/ undefined, typedParam.dotDotDotToken, typedParam.name, @@ -1183,7 +1245,7 @@ function createObjectLiteralMethod( /*type*/ undefined, typedParam.initializer, )); - return ts.factory.createMethodDeclaration( + return factory.createMethodDeclaration( /*modifiers*/ undefined, /*asteriskToken*/ undefined, name, @@ -1199,12 +1261,12 @@ function createObjectLiteralMethod( } function createSnippetPrinter( - printerOptions: ts.PrinterOptions, + printerOptions: PrinterOptions, ) { - let escapes: ts.TextChange[] | undefined; - const baseWriter = ts.textChanges.createWriter(ts.getNewLineCharacter(printerOptions)); - const printer = ts.createPrinter(printerOptions, baseWriter); - const writer: ts.EmitTextWriter = { + let escapes: TextChange[] | undefined; + const baseWriter = textChanges.createWriter(getNewLineCharacter(printerOptions)); + const printer = createPrinter(printerOptions, baseWriter); + const writer: EmitTextWriter = { ...baseWriter, write: s => escapingWrite(s, () => baseWriter.write(s)), nonEscapingWrite: baseWriter.write, @@ -1226,12 +1288,12 @@ function createSnippetPrinter( // generate a set of changes that can be applied to the unescaped text // to escape it post-formatting. function escapingWrite(s: string, write: () => void) { - const escaped = ts.escapeSnippetText(s); + const escaped = escapeSnippetText(s); if (escaped !== s) { const start = baseWriter.getTextPos(); write(); const end = baseWriter.getTextPos(); - escapes = ts.append(escapes ||= [], { newText: escaped, span: { start, length: end - start } }); + escapes = append(escapes ||= [], { newText: escaped, span: { start, length: end - start } }); } else { write(); @@ -1240,18 +1302,18 @@ function createSnippetPrinter( /* Snippet-escaping version of `printer.printList`. */ function printSnippetList( - format: ts.ListFormat, - list: ts.NodeArray, - sourceFile: ts.SourceFile | undefined, + format: ListFormat, + list: NodeArray, + sourceFile: SourceFile | undefined, ): string { const unescaped = printUnescapedSnippetList(format, list, sourceFile); - return escapes ? ts.textChanges.applyChanges(unescaped, escapes) : unescaped; + return escapes ? textChanges.applyChanges(unescaped, escapes) : unescaped; } function printUnescapedSnippetList( - format: ts.ListFormat, - list: ts.NodeArray, - sourceFile: ts.SourceFile | undefined, + format: ListFormat, + list: NodeArray, + sourceFile: SourceFile | undefined, ): string { escapes = undefined; writer.clear(); @@ -1260,10 +1322,10 @@ function createSnippetPrinter( } function printAndFormatSnippetList( - format: ts.ListFormat, - list: ts.NodeArray, - sourceFile: ts.SourceFile, - formatContext: ts.formatting.FormatContext, + format: ListFormat, + list: NodeArray, + sourceFile: SourceFile, + formatContext: formatting.FormatContext, ): string { const syntheticFile = { text: printUnescapedSnippetList( @@ -1271,14 +1333,14 @@ function createSnippetPrinter( list, sourceFile), getLineAndCharacterOfPosition(pos: number) { - return ts.getLineAndCharacterOfPosition(this, pos); + return getLineAndCharacterOfPosition(this, pos); }, }; - const formatOptions = ts.getFormatCodeSettingsForWriting(formatContext, sourceFile); - const changes = ts.flatMap(list, node => { - const nodeWithPos = ts.textChanges.assignPositionsToNode(node); - return ts.formatting.formatNodeGivenIndentation( + const formatOptions = getFormatCodeSettingsForWriting(formatContext, sourceFile); + const changes = flatMap(list, node => { + const nodeWithPos = textChanges.assignPositionsToNode(node); + return formatting.formatNodeGivenIndentation( nodeWithPos, syntheticFile, sourceFile.languageVariant, @@ -1288,17 +1350,17 @@ function createSnippetPrinter( }); const allChanges = escapes - ? ts.stableSort(ts.concatenate(changes, escapes), (a, b) => ts.compareTextSpans(a.span, b.span)) + ? stableSort(concatenate(changes, escapes), (a, b) => compareTextSpans(a.span, b.span)) : changes; - return ts.textChanges.applyChanges(syntheticFile.text, allChanges); + return textChanges.applyChanges(syntheticFile.text, allChanges); } } -function originToCompletionEntryData(origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport): ts.CompletionEntryData | undefined { - const ambientModuleName = origin.fileName ? undefined : ts.stripQuotes(origin.moduleSymbol.name); +function originToCompletionEntryData(origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport): CompletionEntryData | undefined { + const ambientModuleName = origin.fileName ? undefined : stripQuotes(origin.moduleSymbol.name); const isPackageJsonImport = origin.isFromPackageJson ? true : undefined; if (originIsResolvedExport(origin)) { - const resolvedData: ts.CompletionEntryDataResolved = { + const resolvedData: CompletionEntryDataResolved = { exportName: origin.exportName, moduleSpecifier: origin.moduleSpecifier, ambientModuleName, @@ -1307,18 +1369,18 @@ function originToCompletionEntryData(origin: SymbolOriginInfoExport | SymbolOrig }; return resolvedData; } - const unresolvedData: ts.CompletionEntryDataUnresolved = { + const unresolvedData: CompletionEntryDataUnresolved = { exportName: origin.exportName, exportMapKey: origin.exportMapKey, fileName: origin.fileName, - ambientModuleName: origin.fileName ? undefined : ts.stripQuotes(origin.moduleSymbol.name), + ambientModuleName: origin.fileName ? undefined : stripQuotes(origin.moduleSymbol.name), isPackageJsonImport: origin.isFromPackageJson ? true : undefined, }; return unresolvedData; } -function completionEntryDataToSymbolOriginInfo(data: ts.CompletionEntryData, completionName: string, moduleSymbol: ts.Symbol): SymbolOriginInfoExport | SymbolOriginInfoResolvedExport { - const isDefaultExport = data.exportName === ts.InternalSymbolName.Default; +function completionEntryDataToSymbolOriginInfo(data: CompletionEntryData, completionName: string, moduleSymbol: Symbol): SymbolOriginInfoExport | SymbolOriginInfoResolvedExport { + const isDefaultExport = data.exportName === InternalSymbolName.Default; const isFromPackageJson = !!data.isPackageJsonImport; if (completionEntryDataIsResolved(data)) { const resolvedOrigin: SymbolOriginInfoResolvedExport = { @@ -1346,43 +1408,43 @@ function completionEntryDataToSymbolOriginInfo(data: ts.CompletionEntryData, com return unresolvedOrigin; } -function getInsertTextAndReplacementSpanForImportCompletion(name: string, importStatementCompletion: ImportStatementCompletionInfo, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, sourceFile: ts.SourceFile, options: ts.CompilerOptions, preferences: ts.UserPreferences) { +function getInsertTextAndReplacementSpanForImportCompletion(name: string, importStatementCompletion: ImportStatementCompletionInfo, origin: SymbolOriginInfoResolvedExport, useSemicolons: boolean, sourceFile: SourceFile, options: CompilerOptions, preferences: UserPreferences) { const replacementSpan = importStatementCompletion.replacementSpan; - const quotedModuleSpecifier = ts.quote(sourceFile, preferences, origin.moduleSpecifier); + const quotedModuleSpecifier = quote(sourceFile, preferences, origin.moduleSpecifier); const exportKind = - origin.isDefaultExport ? ts.ExportKind.Default : - origin.exportName === ts.InternalSymbolName.ExportEquals ? ts.ExportKind.ExportEquals : - ts.ExportKind.Named; + origin.isDefaultExport ? ExportKind.Default : + origin.exportName === InternalSymbolName.ExportEquals ? ExportKind.ExportEquals : + ExportKind.Named; const tabStop = preferences.includeCompletionsWithSnippetText ? "$1" : ""; - const importKind = ts.codefix.getImportKind(sourceFile, exportKind, options, /*forceImportKeyword*/ true); + const importKind = codefix.getImportKind(sourceFile, exportKind, options, /*forceImportKeyword*/ true); const isImportSpecifierTypeOnly = importStatementCompletion.couldBeTypeOnlyImportSpecifier; - const topLevelTypeOnlyText = importStatementCompletion.isTopLevelTypeOnly ? ` ${ts.tokenToString(ts.SyntaxKind.TypeKeyword)} ` : " "; - const importSpecifierTypeOnlyText = isImportSpecifierTypeOnly ? `${ts.tokenToString(ts.SyntaxKind.TypeKeyword)} ` : ""; + const topLevelTypeOnlyText = importStatementCompletion.isTopLevelTypeOnly ? ` ${tokenToString(SyntaxKind.TypeKeyword)} ` : " "; + const importSpecifierTypeOnlyText = isImportSpecifierTypeOnly ? `${tokenToString(SyntaxKind.TypeKeyword)} ` : ""; const suffix = useSemicolons ? ";" : ""; switch (importKind) { - case ts.ImportKind.CommonJS: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${ts.escapeSnippetText(name)}${tabStop} = require(${quotedModuleSpecifier})${suffix}` }; - case ts.ImportKind.Default: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${ts.escapeSnippetText(name)}${tabStop} from ${quotedModuleSpecifier}${suffix}` }; - case ts.ImportKind.Namespace: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}* as ${ts.escapeSnippetText(name)} from ${quotedModuleSpecifier}${suffix}` }; - case ts.ImportKind.Named: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}{ ${importSpecifierTypeOnlyText}${ts.escapeSnippetText(name)}${tabStop} } from ${quotedModuleSpecifier}${suffix}` }; + case ImportKind.CommonJS: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${escapeSnippetText(name)}${tabStop} = require(${quotedModuleSpecifier})${suffix}` }; + case ImportKind.Default: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}${escapeSnippetText(name)}${tabStop} from ${quotedModuleSpecifier}${suffix}` }; + case ImportKind.Namespace: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}* as ${escapeSnippetText(name)} from ${quotedModuleSpecifier}${suffix}` }; + case ImportKind.Named: return { replacementSpan, insertText: `import${topLevelTypeOnlyText}{ ${importSpecifierTypeOnlyText}${escapeSnippetText(name)}${tabStop} } from ${quotedModuleSpecifier}${suffix}` }; } } -function quotePropertyName(sourceFile: ts.SourceFile, preferences: ts.UserPreferences, name: string,): string { +function quotePropertyName(sourceFile: SourceFile, preferences: UserPreferences, name: string,): string { if (/^\d+$/.test(name)) { return name; } - return ts.quote(sourceFile, preferences, name); + return quote(sourceFile, preferences, name); } -function isRecommendedCompletionMatch(localSymbol: ts.Symbol, recommendedCompletion: ts.Symbol | undefined, checker: ts.TypeChecker): boolean { +function isRecommendedCompletionMatch(localSymbol: Symbol, recommendedCompletion: Symbol | undefined, checker: TypeChecker): boolean { return localSymbol === recommendedCompletion || - !!(localSymbol.flags & ts.SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; + !!(localSymbol.flags & SymbolFlags.ExportValue) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion; } function getSourceFromOrigin(origin: SymbolOriginInfo | undefined): string | undefined { if (originIsExport(origin)) { - return ts.stripQuotes(origin.moduleSymbol.name); + return stripQuotes(origin.moduleSymbol.name); } if (originIsResolvedExport(origin)) { return origin.moduleSpecifier; @@ -1397,40 +1459,40 @@ function getSourceFromOrigin(origin: SymbolOriginInfo | undefined): string | und /** @internal */ export function getCompletionEntriesFromSymbols( - symbols: readonly ts.Symbol[], - entries: ts.SortedArray, - replacementToken: ts.Node | undefined, - contextToken: ts.Node | undefined, - location: ts.Node, - sourceFile: ts.SourceFile, - host: ts.LanguageServiceHost, - program: ts.Program, - target: ts.ScriptTarget, + symbols: readonly Symbol[], + entries: SortedArray, + replacementToken: Node | undefined, + contextToken: Node | undefined, + location: Node, + sourceFile: SourceFile, + host: LanguageServiceHost, + program: Program, + target: ScriptTarget, log: Log, kind: CompletionKind, - preferences: ts.UserPreferences, - compilerOptions: ts.CompilerOptions, - formatContext: ts.formatting.FormatContext | undefined, + preferences: UserPreferences, + compilerOptions: CompilerOptions, + formatContext: formatting.FormatContext | undefined, isTypeOnlyLocation?: boolean, - propertyAccessToConvert?: ts.PropertyAccessExpression, + propertyAccessToConvert?: PropertyAccessExpression, jsxIdentifierExpected?: boolean, isJsxInitializer?: IsJsxInitializer, importStatementCompletion?: ImportStatementCompletionInfo, - recommendedCompletion?: ts.Symbol, + recommendedCompletion?: Symbol, symbolToOriginInfoMap?: SymbolOriginInfoMap, symbolToSortTextMap?: SymbolSortTextMap, isJsxIdentifierExpected?: boolean, isRightOfOpenTag?: boolean, ): UniqueNameSet { - const start = ts.timestamp(); + const start = timestamp(); const variableDeclaration = getVariableDeclaration(location); - const useSemicolons = ts.probablyUsesSemicolons(sourceFile); + const useSemicolons = probablyUsesSemicolons(sourceFile); const typeChecker = program.getTypeChecker(); // Tracks unique names. // Value is set to false for global variables or completions from external module exports, because we can have multiple of those; // true otherwise. Based on the order we add things we will always see locals first, then globals, then module exports. // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name. - const uniques = new ts.Map(); + const uniques = new Map(); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const origin = symbolToOriginInfoMap?.[i]; @@ -1440,7 +1502,7 @@ export function getCompletionEntriesFromSymbols( } const { name, needsConvertPropertyAccess } = info; - const originalSortText = symbolToSortTextMap?.[ts.getSymbolId(symbol)] ?? SortText.LocationPriority; + const originalSortText = symbolToSortTextMap?.[getSymbolId(symbol)] ?? SortText.LocationPriority; const sortText = (isDeprecated(symbol, typeChecker) ? SortText.Deprecated(originalSortText) : originalSortText); const entry = createCompletionEntry( symbol, @@ -1471,12 +1533,12 @@ export function getCompletionEntriesFromSymbols( } /** True for locals; false for globals, module exports from other files, `this.` completions. */ - const shouldShadowLaterSymbols = (!origin || originIsTypeOnlyAlias(origin)) && !(symbol.parent === undefined && !ts.some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile())); + const shouldShadowLaterSymbols = (!origin || originIsTypeOnlyAlias(origin)) && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile())); uniques.set(name, shouldShadowLaterSymbols); - ts.insertSorted(entries, entry, compareCompletionEntries, /*allowDuplicates*/ true); + insertSorted(entries, entry, compareCompletionEntries, /*allowDuplicates*/ true); } - log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start)); + log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (timestamp() - start)); // Prevent consumers of this map from having to worry about // the boolean value. Externally, it should be seen as the @@ -1486,11 +1548,11 @@ export function getCompletionEntriesFromSymbols( add: name => uniques.set(name, true), }; - function shouldIncludeSymbol(symbol: ts.Symbol, symbolToSortTextMap: SymbolSortTextMap): boolean { + function shouldIncludeSymbol(symbol: Symbol, symbolToSortTextMap: SymbolSortTextMap): boolean { let allFlags = symbol.flags; - if (!ts.isSourceFile(location)) { + if (!isSourceFile(location)) { // export = /**/ here we want to get all meanings, so any symbol is ok - if (ts.isExportAssignment(location.parent)) { + if (isExportAssignment(location.parent)) { return true; } // Filter out variables from their own initializers @@ -1504,22 +1566,22 @@ export function getCompletionEntriesFromSymbols( // already has an explicit export and user only wants to user explicit // module imports then the global keywords will be filtered out so auto // import suggestions will win in the completion - const symbolOrigin = ts.skipAlias(symbol, typeChecker); + const symbolOrigin = skipAlias(symbol, typeChecker); // We only want to filter out the global keywords // Auto Imports are not available for scripts so this conditional is always false if (!!sourceFile.externalModuleIndicator && !compilerOptions.allowUmdGlobalAccess - && symbolToSortTextMap[ts.getSymbolId(symbol)] === SortText.GlobalsOrKeywords - && (symbolToSortTextMap[ts.getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions - || symbolToSortTextMap[ts.getSymbolId(symbolOrigin)] === SortText.LocationPriority)) { + && symbolToSortTextMap[getSymbolId(symbol)] === SortText.GlobalsOrKeywords + && (symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.AutoImportSuggestions + || symbolToSortTextMap[getSymbolId(symbolOrigin)] === SortText.LocationPriority)) { return false; } - allFlags |= ts.getCombinedLocalAndExportSymbolFlags(symbolOrigin); + allFlags |= getCombinedLocalAndExportSymbolFlags(symbolOrigin); // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace) - if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) { - return !!(allFlags & ts.SymbolFlags.Namespace); + if (isInRightSideOfInternalImportEqualsDeclaration(location)) { + return !!(allFlags & SymbolFlags.Namespace); } if (isTypeOnlyLocation) { @@ -1529,34 +1591,34 @@ export function getCompletionEntriesFromSymbols( } // expressions are value space (which includes the value namespaces) - return !!(allFlags & ts.SymbolFlags.Value); + return !!(allFlags & SymbolFlags.Value); } } -function getLabelCompletionAtPosition(node: ts.BreakOrContinueStatement): ts.CompletionInfo | undefined { +function getLabelCompletionAtPosition(node: BreakOrContinueStatement): CompletionInfo | undefined { const entries = getLabelStatementCompletions(node); if (entries.length) { return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; } } -function getLabelStatementCompletions(node: ts.Node): ts.CompletionEntry[] { - const entries: ts.CompletionEntry[] = []; - const uniques = new ts.Map(); +function getLabelStatementCompletions(node: Node): CompletionEntry[] { + const entries: CompletionEntry[] = []; + const uniques = new Map(); let current = node; while (current) { - if (ts.isFunctionLike(current)) { + if (isFunctionLike(current)) { break; } - if (ts.isLabeledStatement(current)) { + if (isLabeledStatement(current)) { const name = current.label.text; if (!uniques.has(name)) { uniques.set(name, true); entries.push({ name, - kindModifiers: ts.ScriptElementKindModifier.none, - kind: ts.ScriptElementKind.label, + kindModifiers: ScriptElementKindModifier.none, + kind: ScriptElementKind.label, sortText: SortText.LocationPriority }); } @@ -1568,23 +1630,23 @@ function getLabelStatementCompletions(node: ts.Node): ts.CompletionEntry[] { interface SymbolCompletion { type: "symbol"; - symbol: ts.Symbol; - location: ts.Node; + symbol: Symbol; + location: Node; origin: SymbolOriginInfo | SymbolOriginInfoExport | SymbolOriginInfoResolvedExport | undefined; - previousToken: ts.Node | undefined; - contextToken: ts.Node | undefined; + previousToken: Node | undefined; + contextToken: Node | undefined; readonly isJsxInitializer: IsJsxInitializer; readonly isTypeOnlyLocation: boolean; } function getSymbolCompletionFromEntryId( - program: ts.Program, + program: Program, log: Log, - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier, - host: ts.LanguageServiceHost, - preferences: ts.UserPreferences, -): SymbolCompletion | { type: "request", request: Request } | { type: "literal", literal: string | number | ts.PseudoBigInt } | { type: "none" } { + host: LanguageServiceHost, + preferences: UserPreferences, +): SymbolCompletion | { type: "request", request: Request } | { type: "literal", literal: string | number | PseudoBigInt } | { type: "none" } { if (entryId.data) { const autoImport = getAutoImportSymbolFromCompletionEntryData(entryId.name, entryId.data, program, host); if (autoImport) { @@ -1592,7 +1654,7 @@ function getSymbolCompletionFromEntryId( return { type: "symbol", symbol: autoImport.symbol, - location: ts.getTouchingPropertyName(sourceFile, position), + location: getTouchingPropertyName(sourceFile, position), previousToken, contextToken, isJsxInitializer: false, @@ -1613,19 +1675,19 @@ function getSymbolCompletionFromEntryId( const { symbols, literals, location, completionKind, symbolToOriginInfoMap, contextToken, previousToken, isJsxInitializer, isTypeOnlyLocation } = completionData; - const literal = ts.find(literals, l => completionNameForLiteral(sourceFile, preferences, l) === entryId.name); + const literal = find(literals, l => completionNameForLiteral(sourceFile, preferences, l) === entryId.name); if (literal !== undefined) return { type: "literal", literal }; // Find the symbol with the matching entry name. // We don't need to perform character checks here because we're only comparing the // name against 'entryName' (which is known to be good), not building a new // completion entry. - return ts.firstDefined(symbols, (symbol, index): SymbolCompletion | undefined => { + return firstDefined(symbols, (symbol, index): SymbolCompletion | undefined => { const origin = symbolToOriginInfoMap[index]; - const info = getCompletionEntryDisplayNameForSymbol(symbol, ts.getEmitScriptTarget(compilerOptions), origin, completionKind, completionData.isJsxIdentifierExpected); + const info = getCompletionEntryDisplayNameForSymbol(symbol, getEmitScriptTarget(compilerOptions), origin, completionKind, completionData.isJsxIdentifierExpected); return info && info.name === entryId.name && ( - entryId.source === CompletionSource.ClassMemberSnippet && symbol.flags & ts.SymbolFlags.ClassMember - || entryId.source === CompletionSource.ObjectLiteralMethodSnippet && symbol.flags & (ts.SymbolFlags.Property | ts.SymbolFlags.Method) + entryId.source === CompletionSource.ClassMemberSnippet && symbol.flags & SymbolFlags.ClassMember + || entryId.source === CompletionSource.ObjectLiteralMethodSnippet && symbol.flags & (SymbolFlags.Property | SymbolFlags.Method) || getSourceFromOrigin(origin) === entryId.source) ? { type: "symbol" as const, symbol, location, origin, contextToken, previousToken, isJsxInitializer, isTypeOnlyLocation } : undefined; @@ -1636,28 +1698,28 @@ function getSymbolCompletionFromEntryId( export interface CompletionEntryIdentifier { name: string; source?: string; - data?: ts.CompletionEntryData; + data?: CompletionEntryData; } /** @internal */ export function getCompletionEntryDetails( - program: ts.Program, + program: Program, log: Log, - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier, - host: ts.LanguageServiceHost, - formatContext: ts.formatting.FormatContext, - preferences: ts.UserPreferences, - cancellationToken: ts.CancellationToken, -): ts.CompletionEntryDetails | undefined { + host: LanguageServiceHost, + formatContext: formatting.FormatContext, + preferences: UserPreferences, + cancellationToken: CancellationToken, +): CompletionEntryDetails | undefined { const typeChecker = program.getTypeChecker(); const compilerOptions = program.getCompilerOptions(); const { name, source, data } = entryId; - const contextToken = ts.findPrecedingToken(position, sourceFile); - if (ts.isInString(sourceFile, position, contextToken)) { - return ts.Completions.StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken, preferences); + const contextToken = findPrecedingToken(position, sourceFile); + if (isInString(sourceFile, position, contextToken)) { + return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, compilerOptions, host, cancellationToken, preferences); } // Compute all the completion symbols again. @@ -1667,15 +1729,15 @@ export function getCompletionEntryDetails( const { request } = symbolCompletion; switch (request.kind) { case CompletionDataKind.JsDocTagName: - return ts.JsDoc.getJSDocTagNameCompletionDetails(name); + return JsDoc.getJSDocTagNameCompletionDetails(name); case CompletionDataKind.JsDocTag: - return ts.JsDoc.getJSDocTagCompletionDetails(name); + return JsDoc.getJSDocTagCompletionDetails(name); case CompletionDataKind.JsDocParameterName: - return ts.JsDoc.getJSDocParameterNameCompletionDetails(name); + return JsDoc.getJSDocParameterNameCompletionDetails(name); case CompletionDataKind.Keywords: - return ts.some(request.keywordCompletions, c => c.name === name) ? createSimpleDetails(name, ts.ScriptElementKind.keyword, ts.SymbolDisplayPartKind.keyword) : undefined; + return some(request.keywordCompletions, c => c.name === name) ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined; default: - return ts.Debug.assertNever(request); + return Debug.assertNever(request); } } case "symbol": { @@ -1685,60 +1747,60 @@ export function getCompletionEntryDetails( } case "literal": { const { literal } = symbolCompletion; - return createSimpleDetails(completionNameForLiteral(sourceFile, preferences, literal), ts.ScriptElementKind.string, typeof literal === "string" ? ts.SymbolDisplayPartKind.stringLiteral : ts.SymbolDisplayPartKind.numericLiteral); + return createSimpleDetails(completionNameForLiteral(sourceFile, preferences, literal), ScriptElementKind.string, typeof literal === "string" ? SymbolDisplayPartKind.stringLiteral : SymbolDisplayPartKind.numericLiteral); } case "none": // Didn't find a symbol with this name. See if we can find a keyword instead. - return allKeywordsCompletions().some(c => c.name === name) ? createSimpleDetails(name, ts.ScriptElementKind.keyword, ts.SymbolDisplayPartKind.keyword) : undefined; + return allKeywordsCompletions().some(c => c.name === name) ? createSimpleDetails(name, ScriptElementKind.keyword, SymbolDisplayPartKind.keyword) : undefined; default: - ts.Debug.assertNever(symbolCompletion); + Debug.assertNever(symbolCompletion); } } -function createSimpleDetails(name: string, kind: ts.ScriptElementKind, kind2: ts.SymbolDisplayPartKind): ts.CompletionEntryDetails { - return createCompletionDetails(name, ts.ScriptElementKindModifier.none, kind, [ts.displayPart(name, kind2)]); +function createSimpleDetails(name: string, kind: ScriptElementKind, kind2: SymbolDisplayPartKind): CompletionEntryDetails { + return createCompletionDetails(name, ScriptElementKindModifier.none, kind, [displayPart(name, kind2)]); } /** @internal */ -export function createCompletionDetailsForSymbol(symbol: ts.Symbol, checker: ts.TypeChecker, sourceFile: ts.SourceFile, location: ts.Node, cancellationToken: ts.CancellationToken, codeActions?: ts.CodeAction[], sourceDisplay?: ts.SymbolDisplayPart[]): ts.CompletionEntryDetails { +export function createCompletionDetailsForSymbol(symbol: Symbol, checker: TypeChecker, sourceFile: SourceFile, location: Node, cancellationToken: CancellationToken, codeActions?: CodeAction[], sourceDisplay?: SymbolDisplayPart[]): CompletionEntryDetails { const { displayParts, documentation, symbolKind, tags } = checker.runWithCancellationToken(cancellationToken, checker => - ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, ts.SemanticMeaning.All) + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, SemanticMeaning.All) ); - return createCompletionDetails(symbol.name, ts.SymbolDisplay.getSymbolModifiers(checker, symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); + return createCompletionDetails(symbol.name, SymbolDisplay.getSymbolModifiers(checker, symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay); } /** @internal */ -export function createCompletionDetails(name: string, kindModifiers: string, kind: ts.ScriptElementKind, displayParts: ts.SymbolDisplayPart[], documentation?: ts.SymbolDisplayPart[], tags?: ts.JSDocTagInfo[], codeActions?: ts.CodeAction[], source?: ts.SymbolDisplayPart[]): ts.CompletionEntryDetails { +export function createCompletionDetails(name: string, kindModifiers: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], documentation?: SymbolDisplayPart[], tags?: JSDocTagInfo[], codeActions?: CodeAction[], source?: SymbolDisplayPart[]): CompletionEntryDetails { return { name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source, sourceDisplay: source }; } interface CodeActionsAndSourceDisplay { - readonly codeActions: ts.CodeAction[] | undefined; - readonly sourceDisplay: ts.SymbolDisplayPart[] | undefined; + readonly codeActions: CodeAction[] | undefined; + readonly sourceDisplay: SymbolDisplayPart[] | undefined; } function getCompletionEntryCodeActionsAndSourceDisplay( name: string, - location: ts.Node, - contextToken: ts.Node | undefined, + location: Node, + contextToken: Node | undefined, origin: SymbolOriginInfo | SymbolOriginInfoExport | SymbolOriginInfoResolvedExport | undefined, - symbol: ts.Symbol, - program: ts.Program, - host: ts.LanguageServiceHost, - compilerOptions: ts.CompilerOptions, - sourceFile: ts.SourceFile, + symbol: Symbol, + program: Program, + host: LanguageServiceHost, + compilerOptions: CompilerOptions, + sourceFile: SourceFile, position: number, - previousToken: ts.Node | undefined, - formatContext: ts.formatting.FormatContext, - preferences: ts.UserPreferences, - data: ts.CompletionEntryData | undefined, + previousToken: Node | undefined, + formatContext: formatting.FormatContext, + preferences: UserPreferences, + data: CompletionEntryData | undefined, source: string | undefined, - cancellationToken: ts.CancellationToken, + cancellationToken: CancellationToken, ): CodeActionsAndSourceDisplay { if (data?.moduleSpecifier) { if (previousToken && getImportStatementCompletionInfo(contextToken || previousToken).replacementSpan) { // Import statement completion: 'import c|' - return { codeActions: undefined, sourceDisplay: [ts.textPart(data.moduleSpecifier)] }; + return { codeActions: undefined, sourceDisplay: [textPart(data.moduleSpecifier)] }; } } @@ -1754,21 +1816,21 @@ function getCompletionEntryCodeActionsAndSourceDisplay( contextToken, formatContext); if (importAdder) { - const changes = ts.textChanges.ChangeTracker.with( + const changes = textChanges.ChangeTracker.with( { host, formatContext, preferences }, importAdder.writeFixes); return { sourceDisplay: undefined, codeActions: [{ changes, - description: ts.diagnosticToString([ts.Diagnostics.Includes_imports_of_types_referenced_by_0, name]), + description: diagnosticToString([Diagnostics.Includes_imports_of_types_referenced_by_0, name]), }], }; } } if (originIsTypeOnlyAlias(origin)) { - const codeAction = ts.codefix.getPromoteTypeOnlyCompletionAction( + const codeAction = codefix.getPromoteTypeOnlyCompletionAction( sourceFile, origin.declaration.name, program, @@ -1776,7 +1838,7 @@ function getCompletionEntryCodeActionsAndSourceDisplay( formatContext, preferences); - ts.Debug.assertIsDefined(codeAction, "Expected to have a code action for promoting type-only alias"); + Debug.assertIsDefined(codeAction, "Expected to have a code action for promoting type-only alias"); return { codeActions: [codeAction], sourceDisplay: undefined }; } @@ -1786,56 +1848,56 @@ function getCompletionEntryCodeActionsAndSourceDisplay( const checker = origin.isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker(); const { moduleSymbol } = origin; - const targetSymbol = checker.getMergedSymbol(ts.skipAlias(symbol.exportSymbol || symbol, checker)); - const isJsxOpeningTagName = contextToken?.kind === ts.SyntaxKind.LessThanToken && ts.isJsxOpeningLikeElement(contextToken.parent); - const { moduleSpecifier, codeAction } = ts.codefix.getImportCompletionAction( + const targetSymbol = checker.getMergedSymbol(skipAlias(symbol.exportSymbol || symbol, checker)); + const isJsxOpeningTagName = contextToken?.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(contextToken.parent); + const { moduleSpecifier, codeAction } = codefix.getImportCompletionAction( targetSymbol, moduleSymbol, sourceFile, - ts.getNameForExportedSymbol(symbol, ts.getEmitScriptTarget(compilerOptions), isJsxOpeningTagName), + getNameForExportedSymbol(symbol, getEmitScriptTarget(compilerOptions), isJsxOpeningTagName), isJsxOpeningTagName, host, program, formatContext, - previousToken && ts.isIdentifier(previousToken) ? previousToken.getStart(sourceFile) : position, + previousToken && isIdentifier(previousToken) ? previousToken.getStart(sourceFile) : position, preferences, cancellationToken); - ts.Debug.assert(!data?.moduleSpecifier || moduleSpecifier === data.moduleSpecifier); - return { sourceDisplay: [ts.textPart(moduleSpecifier)], codeActions: [codeAction] }; + Debug.assert(!data?.moduleSpecifier || moduleSpecifier === data.moduleSpecifier); + return { sourceDisplay: [textPart(moduleSpecifier)], codeActions: [codeAction] }; } /** @internal */ export function getCompletionEntrySymbol( - program: ts.Program, + program: Program, log: Log, - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier, - host: ts.LanguageServiceHost, - preferences: ts.UserPreferences, -): ts.Symbol | undefined { + host: LanguageServiceHost, + preferences: UserPreferences, +): Symbol | undefined { const completion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences); return completion.type === "symbol" ? completion.symbol : undefined; } const enum CompletionDataKind { Data, JsDocTagName, JsDocTag, JsDocParameterName, Keywords } /** true: after the `=` sign but no identifier has been typed yet. Else is the Identifier after the initializer. */ -type IsJsxInitializer = boolean | ts.Identifier; +type IsJsxInitializer = boolean | Identifier; interface CompletionData { readonly kind: CompletionDataKind.Data; - readonly symbols: readonly ts.Symbol[]; + readonly symbols: readonly Symbol[]; readonly completionKind: CompletionKind; readonly isInSnippetScope: boolean; /** Note that the presence of this alone doesn't mean that we need a conversion. Only do that if the completion is not an ordinary identifier. */ - readonly propertyAccessToConvert: ts.PropertyAccessExpression | undefined; + readonly propertyAccessToConvert: PropertyAccessExpression | undefined; readonly isNewIdentifierLocation: boolean; - readonly location: ts.Node; + readonly location: Node; readonly keywordFilters: KeywordCompletionFilters; - readonly literals: readonly (string | number | ts.PseudoBigInt)[]; + readonly literals: readonly (string | number | PseudoBigInt)[]; readonly symbolToOriginInfoMap: SymbolOriginInfoMap; - readonly recommendedCompletion: ts.Symbol | undefined; - readonly previousToken: ts.Node | undefined; - readonly contextToken: ts.Node | undefined; + readonly recommendedCompletion: Symbol | undefined; + readonly previousToken: Node | undefined; + readonly contextToken: Node | undefined; readonly isJsxInitializer: IsJsxInitializer; readonly insideJsDocTagTypeExpression: boolean; readonly symbolToSortTextMap: SymbolSortTextMap; @@ -1845,12 +1907,12 @@ interface CompletionData { readonly isRightOfOpenTag: boolean; readonly importStatementCompletion?: ImportStatementCompletionInfo; readonly hasUnresolvedAutoImports?: boolean; - readonly flags: ts.CompletionInfoFlags; + readonly flags: CompletionInfoFlags; } type Request = | { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } - | { readonly kind: CompletionDataKind.JsDocParameterName, tag: ts.JSDocParameterTag } - | { readonly kind: CompletionDataKind.Keywords, keywordCompletions: readonly ts.CompletionEntry[], isNewIdentifierLocation: boolean }; + | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag } + | { readonly kind: CompletionDataKind.Keywords, keywordCompletions: readonly CompletionEntry[], isNewIdentifierLocation: boolean }; /** @internal */ export const enum CompletionKind { @@ -1862,91 +1924,91 @@ export const enum CompletionKind { None, } -function getRecommendedCompletion(previousToken: ts.Node, contextualType: ts.Type, checker: ts.TypeChecker): ts.Symbol | undefined { +function getRecommendedCompletion(previousToken: Node, contextualType: Type, checker: TypeChecker): Symbol | undefined { // For a union, return the first one with a recommended completion. - return ts.firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => { + return firstDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), type => { const symbol = type && type.symbol; // Don't include make a recommended completion for an abstract class - return symbol && (symbol.flags & (ts.SymbolFlags.EnumMember | ts.SymbolFlags.Enum | ts.SymbolFlags.Class) && !ts.isAbstractConstructorSymbol(symbol)) + return symbol && (symbol.flags & (SymbolFlags.EnumMember | SymbolFlags.Enum | SymbolFlags.Class) && !isAbstractConstructorSymbol(symbol)) ? getFirstSymbolInChain(symbol, previousToken, checker) : undefined; }); } -function getContextualType(previousToken: ts.Node, position: number, sourceFile: ts.SourceFile, checker: ts.TypeChecker): ts.Type | undefined { +function getContextualType(previousToken: Node, position: number, sourceFile: SourceFile, checker: TypeChecker): Type | undefined { const { parent } = previousToken; switch (previousToken.kind) { - case ts.SyntaxKind.Identifier: - return ts.getContextualTypeFromParent(previousToken as ts.Identifier, checker); - case ts.SyntaxKind.EqualsToken: + case SyntaxKind.Identifier: + return getContextualTypeFromParent(previousToken as Identifier, checker); + case SyntaxKind.EqualsToken: switch (parent.kind) { - case ts.SyntaxKind.VariableDeclaration: - return checker.getContextualType((parent as ts.VariableDeclaration).initializer!); // TODO: GH#18217 - case ts.SyntaxKind.BinaryExpression: - return checker.getTypeAtLocation((parent as ts.BinaryExpression).left); - case ts.SyntaxKind.JsxAttribute: - return checker.getContextualTypeForJsxAttribute(parent as ts.JsxAttribute); + case SyntaxKind.VariableDeclaration: + return checker.getContextualType((parent as VariableDeclaration).initializer!); // TODO: GH#18217 + case SyntaxKind.BinaryExpression: + return checker.getTypeAtLocation((parent as BinaryExpression).left); + case SyntaxKind.JsxAttribute: + return checker.getContextualTypeForJsxAttribute(parent as JsxAttribute); default: return undefined; } - case ts.SyntaxKind.NewKeyword: - return checker.getContextualType(parent as ts.Expression); - case ts.SyntaxKind.CaseKeyword: - const caseClause = ts.tryCast(parent, ts.isCaseClause); - return caseClause ? ts.getSwitchedType(caseClause, checker) : undefined; - case ts.SyntaxKind.OpenBraceToken: - return ts.isJsxExpression(parent) && !ts.isJsxElement(parent.parent) && !ts.isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; + case SyntaxKind.NewKeyword: + return checker.getContextualType(parent as Expression); + case SyntaxKind.CaseKeyword: + const caseClause = tryCast(parent, isCaseClause); + return caseClause ? getSwitchedType(caseClause, checker) : undefined; + case SyntaxKind.OpenBraceToken: + return isJsxExpression(parent) && !isJsxElement(parent.parent) && !isJsxFragment(parent.parent) ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined; default: - const argInfo = ts.SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile); + const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile); return argInfo ? // At `,`, treat this as the next argument after the comma. - checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === ts.SyntaxKind.CommaToken ? 1 : 0)) : - ts.isEqualityOperatorKind(previousToken.kind) && ts.isBinaryExpression(parent) && ts.isEqualityOperatorKind(parent.operatorToken.kind) ? + checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) : + isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) ? // completion at `x ===/**/` should be for the right side checker.getTypeAtLocation(parent.left) : - checker.getContextualType(previousToken as ts.Expression); + checker.getContextualType(previousToken as Expression); } } -function getFirstSymbolInChain(symbol: ts.Symbol, enclosingDeclaration: ts.Node, checker: ts.TypeChecker): ts.Symbol | undefined { - const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ ts.SymbolFlags.All, /*useOnlyExternalAliasing*/ false); - if (chain) return ts.first(chain); +function getFirstSymbolInChain(symbol: Symbol, enclosingDeclaration: Node, checker: TypeChecker): Symbol | undefined { + const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ SymbolFlags.All, /*useOnlyExternalAliasing*/ false); + if (chain) return first(chain); return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker)); } -function isModuleSymbol(symbol: ts.Symbol): boolean { - return !!symbol.declarations?.some(d => d.kind === ts.SyntaxKind.SourceFile); +function isModuleSymbol(symbol: Symbol): boolean { + return !!symbol.declarations?.some(d => d.kind === SyntaxKind.SourceFile); } function getCompletionData( - program: ts.Program, + program: Program, log: (message: string) => void, - sourceFile: ts.SourceFile, - compilerOptions: ts.CompilerOptions, + sourceFile: SourceFile, + compilerOptions: CompilerOptions, position: number, - preferences: ts.UserPreferences, + preferences: UserPreferences, detailsEntryId: CompletionEntryIdentifier | undefined, - host: ts.LanguageServiceHost, - formatContext: ts.formatting.FormatContext | undefined, - cancellationToken?: ts.CancellationToken, + host: LanguageServiceHost, + formatContext: formatting.FormatContext | undefined, + cancellationToken?: CancellationToken, ): CompletionData | Request | undefined { const typeChecker = program.getTypeChecker(); const inCheckedFile = isCheckedFile(sourceFile, compilerOptions); - let start = ts.timestamp(); - let currentToken = ts.getTokenAtPosition(sourceFile, position); // TODO: GH#15853 + let start = timestamp(); + let currentToken = getTokenAtPosition(sourceFile, position); // TODO: GH#15853 // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.) - log("getCompletionData: Get current token: " + (ts.timestamp() - start)); + log("getCompletionData: Get current token: " + (timestamp() - start)); - start = ts.timestamp(); - const insideComment = ts.isInComment(sourceFile, position, currentToken); - log("getCompletionData: Is inside comment: " + (ts.timestamp() - start)); + start = timestamp(); + const insideComment = isInComment(sourceFile, position, currentToken); + log("getCompletionData: Is inside comment: " + (timestamp() - start)); let insideJsDocTagTypeExpression = false; let isInSnippetScope = false; if (insideComment) { - if (ts.hasDocComment(sourceFile, position)) { - if (sourceFile.text.charCodeAt(position - 1) === ts.CharacterCodes.at) { + if (hasDocComment(sourceFile, position)) { + if (sourceFile.text.charCodeAt(position - 1) === CharacterCodes.at) { // The current position is next to the '@' sign, when no tag name being provided yet. // Provide a full list of tag names return { kind: CompletionDataKind.JsDocTagName }; @@ -1968,7 +2030,7 @@ function getCompletionData( // /** // * |c| // */ - const lineStart = ts.getLineStartPositionForPosition(position, sourceFile); + const lineStart = getLineStartPositionForPosition(position, sourceFile); if (!/[^\*|\s(/)]/.test(sourceFile.text.substring(lineStart, position))) { return { kind: CompletionDataKind.JsDocTag }; } @@ -1985,16 +2047,16 @@ function getCompletionData( } const typeExpression = tryGetTypeExpressionFromTag(tag); if (typeExpression) { - currentToken = ts.getTokenAtPosition(sourceFile, position); + currentToken = getTokenAtPosition(sourceFile, position); if (!currentToken || - (!ts.isDeclarationName(currentToken) && - (currentToken.parent.kind !== ts.SyntaxKind.JSDocPropertyTag || - (currentToken.parent as ts.JSDocPropertyTag).name !== currentToken))) { + (!isDeclarationName(currentToken) && + (currentToken.parent.kind !== SyntaxKind.JSDocPropertyTag || + (currentToken.parent as JSDocPropertyTag).name !== currentToken))) { // Use as type location if inside tag's type expression insideJsDocTagTypeExpression = isCurrentlyEditingNode(typeExpression); } } - if (!insideJsDocTagTypeExpression && ts.isJSDocParameterTag(tag) && (ts.nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { + if (!insideJsDocTagTypeExpression && isJSDocParameterTag(tag) && (nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) { return { kind: CompletionDataKind.JsDocParameterName, tag }; } } @@ -2007,20 +2069,20 @@ function getCompletionData( } } - start = ts.timestamp(); + start = timestamp(); // The decision to provide completion depends on the contextToken, which is determined through the previousToken. // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file - const isJsOnlyLocation = !insideJsDocTagTypeExpression && ts.isSourceFileJS(sourceFile); + const isJsOnlyLocation = !insideJsDocTagTypeExpression && isSourceFileJS(sourceFile); const tokens = getRelevantTokens(position, sourceFile); const previousToken = tokens.previousToken!; let contextToken = tokens.contextToken!; - log("getCompletionData: Get previous token: " + (ts.timestamp() - start)); + log("getCompletionData: Get previous token: " + (timestamp() - start)); // Find the node where completion is requested on. // Also determine whether we are trying to complete with members of that node // or attributes of a JSX tag. let node = currentToken; - let propertyAccessToConvert: ts.PropertyAccessExpression | undefined; + let propertyAccessToConvert: PropertyAccessExpression | undefined; let isRightOfDot = false; let isRightOfQuestionDot = false; let isRightOfOpenTag = false; @@ -2028,10 +2090,10 @@ function getCompletionData( let isJsxInitializer: IsJsxInitializer = false; let isJsxIdentifierExpected = false; let importStatementCompletion: ImportStatementCompletionInfo | undefined; - let location = ts.getTouchingPropertyName(sourceFile, position); + let location = getTouchingPropertyName(sourceFile, position); let keywordFilters = KeywordCompletionFilters.None; let isNewIdentifierLocation = false; - let flags = ts.CompletionInfoFlags.None; + let flags = CompletionInfoFlags.None; if (contextToken) { const importStatementCompletionInfo = getImportStatementCompletionInfo(contextToken); @@ -2050,7 +2112,7 @@ function getCompletionData( // added in TypeScript 4.3 to be sent back from the client during `getCompletionEntryDetails`. Since this feature // is not backward compatible with older clients, the language service defaults to disabling it, allowing newer clients // to opt in with the `includeCompletionsForImportStatements` user preference. - flags |= ts.CompletionInfoFlags.IsImportStatementCompletion; + flags |= CompletionInfoFlags.IsImportStatementCompletion; importStatementCompletion = importStatementCompletionInfo; isNewIdentifierLocation = importStatementCompletionInfo.isNewIdentifierLocation; } @@ -2063,19 +2125,19 @@ function getCompletionData( } let parent = contextToken.parent; - if (contextToken.kind === ts.SyntaxKind.DotToken || contextToken.kind === ts.SyntaxKind.QuestionDotToken) { - isRightOfDot = contextToken.kind === ts.SyntaxKind.DotToken; - isRightOfQuestionDot = contextToken.kind === ts.SyntaxKind.QuestionDotToken; + if (contextToken.kind === SyntaxKind.DotToken || contextToken.kind === SyntaxKind.QuestionDotToken) { + isRightOfDot = contextToken.kind === SyntaxKind.DotToken; + isRightOfQuestionDot = contextToken.kind === SyntaxKind.QuestionDotToken; switch (parent.kind) { - case ts.SyntaxKind.PropertyAccessExpression: - propertyAccessToConvert = parent as ts.PropertyAccessExpression; + case SyntaxKind.PropertyAccessExpression: + propertyAccessToConvert = parent as PropertyAccessExpression; node = propertyAccessToConvert.expression; - const leftmostAccessExpression = ts.getLeftmostAccessExpression(propertyAccessToConvert); - if (ts.nodeIsMissing(leftmostAccessExpression) || - ((ts.isCallExpression(node) || ts.isFunctionLike(node)) && + const leftmostAccessExpression = getLeftmostAccessExpression(propertyAccessToConvert); + if (nodeIsMissing(leftmostAccessExpression) || + ((isCallExpression(node) || isFunctionLike(node)) && node.end === contextToken.pos && node.getChildCount(sourceFile) && - ts.last(node.getChildren(sourceFile)).kind !== ts.SyntaxKind.CloseParenToken)) { + last(node.getChildren(sourceFile)).kind !== SyntaxKind.CloseParenToken)) { // This is likely dot from incorrectly parsed expression and user is starting to write spread // eg: Math.min(./**/) // const x = function (./**/) {} @@ -2083,18 +2145,18 @@ function getCompletionData( return undefined; } break; - case ts.SyntaxKind.QualifiedName: - node = (parent as ts.QualifiedName).left; + case SyntaxKind.QualifiedName: + node = (parent as QualifiedName).left; break; - case ts.SyntaxKind.ModuleDeclaration: - node = (parent as ts.ModuleDeclaration).name; + case SyntaxKind.ModuleDeclaration: + node = (parent as ModuleDeclaration).name; break; - case ts.SyntaxKind.ImportType: + case SyntaxKind.ImportType: node = parent; break; - case ts.SyntaxKind.MetaProperty: + case SyntaxKind.MetaProperty: node = parent.getFirstToken(sourceFile)!; - ts.Debug.assert(node.kind === ts.SyntaxKind.ImportKeyword || node.kind === ts.SyntaxKind.NewKeyword); + Debug.assert(node.kind === SyntaxKind.ImportKeyword || node.kind === SyntaxKind.NewKeyword); break; default: // There is nothing that precedes the dot, so this likely just a stray character @@ -2106,7 +2168,7 @@ function getCompletionData( // // If the tagname is a property access expression, we will then walk up to the top most of property access expression. // Then, try to get a JSX container and its associated attributes type. - if (parent && parent.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) { contextToken = parent; parent = parent.parent; } @@ -2114,14 +2176,14 @@ function getCompletionData( // Fix location if (currentToken.parent === location) { switch (currentToken.kind) { - case ts.SyntaxKind.GreaterThanToken: - if (currentToken.parent.kind === ts.SyntaxKind.JsxElement || currentToken.parent.kind === ts.SyntaxKind.JsxOpeningElement) { + case SyntaxKind.GreaterThanToken: + if (currentToken.parent.kind === SyntaxKind.JsxElement || currentToken.parent.kind === SyntaxKind.JsxOpeningElement) { location = currentToken; } break; - case ts.SyntaxKind.SlashToken: - if (currentToken.parent.kind === ts.SyntaxKind.JsxSelfClosingElement) { + case SyntaxKind.SlashToken: + if (currentToken.parent.kind === SyntaxKind.JsxSelfClosingElement) { location = currentToken; } break; @@ -2129,56 +2191,56 @@ function getCompletionData( } switch (parent.kind) { - case ts.SyntaxKind.JsxClosingElement: - if (contextToken.kind === ts.SyntaxKind.SlashToken) { + case SyntaxKind.JsxClosingElement: + if (contextToken.kind === SyntaxKind.SlashToken) { isStartingCloseTag = true; location = contextToken; } break; - case ts.SyntaxKind.BinaryExpression: - if (!binaryExpressionMayBeOpenTag(parent as ts.BinaryExpression)) { + case SyntaxKind.BinaryExpression: + if (!binaryExpressionMayBeOpenTag(parent as BinaryExpression)) { break; } // falls through - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxElement: - case ts.SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxElement: + case SyntaxKind.JsxOpeningElement: isJsxIdentifierExpected = true; - if (contextToken.kind === ts.SyntaxKind.LessThanToken) { + if (contextToken.kind === SyntaxKind.LessThanToken) { isRightOfOpenTag = true; location = contextToken; } break; - case ts.SyntaxKind.JsxExpression: - case ts.SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxExpression: + case SyntaxKind.JsxSpreadAttribute: // For `
`, `parent` will be `{true}` and `previousToken` will be `}` - if (previousToken.kind === ts.SyntaxKind.CloseBraceToken && currentToken.kind === ts.SyntaxKind.GreaterThanToken) { + if (previousToken.kind === SyntaxKind.CloseBraceToken && currentToken.kind === SyntaxKind.GreaterThanToken) { isJsxIdentifierExpected = true; } break; - case ts.SyntaxKind.JsxAttribute: + case SyntaxKind.JsxAttribute: // For `
`, `parent` will be JsxAttribute and `previousToken` will be its initializer - if ((parent as ts.JsxAttribute).initializer === previousToken && + if ((parent as JsxAttribute).initializer === previousToken && previousToken.end < position) { isJsxIdentifierExpected = true; break; } switch (previousToken.kind) { - case ts.SyntaxKind.EqualsToken: + case SyntaxKind.EqualsToken: isJsxInitializer = true; break; - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: isJsxIdentifierExpected = true; // For `
` we don't want to treat this as a jsx inializer, instead it's the attribute name. if (parent !== previousToken.parent && - !(parent as ts.JsxAttribute).initializer && - ts.findChildOfKind(parent, ts.SyntaxKind.EqualsToken, sourceFile)) { - isJsxInitializer = previousToken as ts.Identifier; + !(parent as JsxAttribute).initializer && + findChildOfKind(parent, SyntaxKind.EqualsToken, sourceFile)) { + isJsxInitializer = previousToken as Identifier; } } break; @@ -2186,19 +2248,19 @@ function getCompletionData( } } - const semanticStart = ts.timestamp(); + const semanticStart = timestamp(); let completionKind = CompletionKind.None; let isNonContextualObjectLiteral = false; let hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return - let symbols: ts.Symbol[] = []; - let importSpecifierResolver: ts.codefix.ImportSpecifierResolver | undefined; + let symbols: Symbol[] = []; + let importSpecifierResolver: codefix.ImportSpecifierResolver | undefined; const symbolToOriginInfoMap: SymbolOriginInfoMap = []; const symbolToSortTextMap: SymbolSortTextMap = []; - const seenPropertySymbols = new ts.Map(); + const seenPropertySymbols = new Map(); const isTypeOnlyLocation = isTypeOnlyCompletion(); - const getModuleSpecifierResolutionHost = ts.memoizeOne((isFromPackageJson: boolean) => { - return ts.createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, host); + const getModuleSpecifierResolutionHost = memoizeOne((isFromPackageJson: boolean) => { + return createModuleSpecifierResolutionHost(isFromPackageJson ? host.getPackageJsonAutoImportProvider!()! : program, host); }); if (isRightOfDot || isRightOfQuestionDot) { @@ -2206,13 +2268,13 @@ function getCompletionData( } else if (isRightOfOpenTag) { symbols = typeChecker.getJsxIntrinsicTagNamesAt(location); - ts.Debug.assertEachIsDefined(symbols, "getJsxIntrinsicTagNames() should all be defined"); + Debug.assertEachIsDefined(symbols, "getJsxIntrinsicTagNames() should all be defined"); tryGetGlobalSymbols(); completionKind = CompletionKind.Global; keywordFilters = KeywordCompletionFilters.None; } else if (isStartingCloseTag) { - const tagName = (contextToken.parent.parent as ts.JsxElement).openingElement.tagName; + const tagName = (contextToken.parent.parent as JsxElement).openingElement.tagName; const tagSymbol = typeChecker.getSymbolAtLocation(tagName); if (tagSymbol) { symbols = [tagSymbol]; @@ -2231,12 +2293,12 @@ function getCompletionData( } } - log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); + log("getCompletionData: Semantic work: " + (timestamp() - semanticStart)); const contextualType = previousToken && getContextualType(previousToken, position, sourceFile, typeChecker); - const literals = ts.mapDefined( + const literals = mapDefined( contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), - t => t.isLiteral() && !(t.flags & ts.TypeFlags.EnumLiteral) ? t.value : undefined); + t => t.isLiteral() && !(t.flags & TypeFlags.EnumLiteral) ? t.value : undefined); const recommendedCompletion = previousToken && contextualType && getRecommendedCompletion(previousToken, contextualType, typeChecker); return { @@ -2264,27 +2326,27 @@ function getCompletionData( flags, }; - type JSDocTagWithTypeExpression = ts.JSDocParameterTag | ts.JSDocPropertyTag | ts.JSDocReturnTag | ts.JSDocTypeTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag; + type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag | JSDocTemplateTag; - function isTagWithTypeExpression(tag: ts.JSDocTag): tag is JSDocTagWithTypeExpression { + function isTagWithTypeExpression(tag: JSDocTag): tag is JSDocTagWithTypeExpression { switch (tag.kind) { - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocPropertyTag: - case ts.SyntaxKind.JSDocReturnTag: - case ts.SyntaxKind.JSDocTypeTag: - case ts.SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocReturnTag: + case SyntaxKind.JSDocTypeTag: + case SyntaxKind.JSDocTypedefTag: return true; - case ts.SyntaxKind.JSDocTemplateTag: - return !!(tag as ts.JSDocTemplateTag).constraint; + case SyntaxKind.JSDocTemplateTag: + return !!(tag as JSDocTemplateTag).constraint; default: return false; } } - function tryGetTypeExpressionFromTag(tag: ts.JSDocTag): ts.JSDocTypeExpression | undefined { + function tryGetTypeExpressionFromTag(tag: JSDocTag): JSDocTypeExpression | undefined { if (isTagWithTypeExpression(tag)) { - const typeExpression = ts.isJSDocTemplateTag(tag) ? tag.constraint : tag.typeExpression; - return typeExpression && typeExpression.kind === ts.SyntaxKind.JSDocTypeExpression ? typeExpression : undefined; + const typeExpression = isJSDocTemplateTag(tag) ? tag.constraint : tag.typeExpression; + return typeExpression && typeExpression.kind === SyntaxKind.JSDocTypeExpression ? typeExpression : undefined; } return undefined; } @@ -2294,28 +2356,28 @@ function getCompletionData( completionKind = CompletionKind.PropertyAccess; // Since this is qualified name check it's a type node location - const isImportType = ts.isLiteralImportTypeNode(node); + const isImportType = isLiteralImportTypeNode(node); const isTypeLocation = insideJsDocTagTypeExpression - || (isImportType && !(node as ts.ImportTypeNode).isTypeOf) - || ts.isPartOfTypeNode(node.parent) - || ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker); - const isRhsOfImportDeclaration = ts.isInRightSideOfInternalImportEqualsDeclaration(node); - if (ts.isEntityName(node) || isImportType || ts.isPropertyAccessExpression(node)) { - const isNamespaceName = ts.isModuleDeclaration(node.parent); + || (isImportType && !(node as ImportTypeNode).isTypeOf) + || isPartOfTypeNode(node.parent) + || isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker); + const isRhsOfImportDeclaration = isInRightSideOfInternalImportEqualsDeclaration(node); + if (isEntityName(node) || isImportType || isPropertyAccessExpression(node)) { + const isNamespaceName = isModuleDeclaration(node.parent); if (isNamespaceName) isNewIdentifierLocation = true; let symbol = typeChecker.getSymbolAtLocation(node); if (symbol) { - symbol = ts.skipAlias(symbol, typeChecker); - if (symbol.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Enum)) { + symbol = skipAlias(symbol, typeChecker); + if (symbol.flags & (SymbolFlags.Module | SymbolFlags.Enum)) { // Extract module or enum members const exportedSymbols = typeChecker.getExportsOfModule(symbol); - ts.Debug.assertEachIsDefined(exportedSymbols, "getExportsOfModule() should all be defined"); - const isValidValueAccess = (symbol: ts.Symbol) => typeChecker.isValidPropertyAccess(isImportType ? node as ts.ImportTypeNode : (node.parent as ts.PropertyAccessExpression), symbol.name); - const isValidTypeAccess = (symbol: ts.Symbol) => symbolCanBeReferencedAtTypeLocation(symbol, typeChecker); - const isValidAccess: (symbol: ts.Symbol) => boolean = + Debug.assertEachIsDefined(exportedSymbols, "getExportsOfModule() should all be defined"); + const isValidValueAccess = (symbol: Symbol) => typeChecker.isValidPropertyAccess(isImportType ? node as ImportTypeNode : (node.parent as PropertyAccessExpression), symbol.name); + const isValidTypeAccess = (symbol: Symbol) => symbolCanBeReferencedAtTypeLocation(symbol, typeChecker); + const isValidAccess: (symbol: Symbol) => boolean = isNamespaceName // At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion. - ? symbol => !!(symbol.flags & ts.SymbolFlags.Namespace) && !symbol.declarations?.every(d => d.parent === node.parent) + ? symbol => !!(symbol.flags & SymbolFlags.Namespace) && !symbol.declarations?.every(d => d.parent === node.parent) : isRhsOfImportDeclaration ? // Any kind is allowed when dotting off namespace in internal import equals declaration symbol => isValidTypeAccess(symbol) || isValidValueAccess(symbol) : @@ -2329,7 +2391,7 @@ function getCompletionData( // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods). if (!isTypeLocation && symbol.declarations && - symbol.declarations.some(d => d.kind !== ts.SyntaxKind.SourceFile && d.kind !== ts.SyntaxKind.ModuleDeclaration && d.kind !== ts.SyntaxKind.EnumDeclaration)) { + symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration && d.kind !== SyntaxKind.EnumDeclaration)) { let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node).getNonOptionalType(); let insertQuestionDot = false; if (type.isNullableType()) { @@ -2345,7 +2407,7 @@ function getCompletionData( } } } - addTypeProperties(type, !!(node.flags & ts.NodeFlags.AwaitContext), insertQuestionDot); + addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot); } return; @@ -2374,17 +2436,17 @@ function getCompletionData( } } } - addTypeProperties(type, !!(node.flags & ts.NodeFlags.AwaitContext), insertQuestionDot); + addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot); } } - function addTypeProperties(type: ts.Type, insertAwait: boolean, insertQuestionDot: boolean): void { + function addTypeProperties(type: Type, insertAwait: boolean, insertQuestionDot: boolean): void { isNewIdentifierLocation = !!type.getStringIndexType(); - if (isRightOfQuestionDot && ts.some(type.getCallSignatures())) { + if (isRightOfQuestionDot && some(type.getCallSignatures())) { isNewIdentifierLocation = true; } - const propertyAccess = node.kind === ts.SyntaxKind.ImportType ? node as ts.ImportTypeNode : node.parent as ts.PropertyAccessExpression | ts.QualifiedName; + const propertyAccess = node.kind === SyntaxKind.ImportType ? node as ImportTypeNode : node.parent as PropertyAccessExpression | QualifiedName; if (inCheckedFile) { for (const symbol of type.getApparentProperties()) { if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) { @@ -2398,7 +2460,7 @@ function getCompletionData( // each individual type has. This is because we're going to add all identifiers // anyways. So we might as well elevate the members that were at least part // of the individual types to a higher status since we know what they are. - symbols.push(...ts.filter(getPropertiesForCompletion(type, typeChecker), s => typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, s))); + symbols.push(...filter(getPropertiesForCompletion(type, typeChecker), s => typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, s))); } if (insertAwait && preferences.includeCompletionsWithInsertText) { @@ -2413,36 +2475,36 @@ function getCompletionData( } } - function addPropertySymbol(symbol: ts.Symbol, insertAwait: boolean, insertQuestionDot: boolean) { + function addPropertySymbol(symbol: Symbol, insertAwait: boolean, insertQuestionDot: boolean) { // For a computed property with an accessible name like `Symbol.iterator`, // we'll add a completion for the *name* `Symbol` instead of for the property. // If this is e.g. [Symbol.iterator], add a completion for `Symbol`. - const computedPropertyName = ts.firstDefined(symbol.declarations, decl => ts.tryCast(ts.getNameOfDeclaration(decl), ts.isComputedPropertyName)); + const computedPropertyName = firstDefined(symbol.declarations, decl => tryCast(getNameOfDeclaration(decl), isComputedPropertyName)); if (computedPropertyName) { const leftMostName = getLeftMostName(computedPropertyName.expression); // The completion is for `Symbol`, not `iterator`. const nameSymbol = leftMostName && typeChecker.getSymbolAtLocation(leftMostName); // If this is nested like for `namespace N { export const sym = Symbol(); }`, we'll add the completion for `N`. const firstAccessibleSymbol = nameSymbol && getFirstSymbolInChain(nameSymbol, contextToken, typeChecker); - if (firstAccessibleSymbol && ts.addToSeen(seenPropertySymbols, ts.getSymbolId(firstAccessibleSymbol))) { + if (firstAccessibleSymbol && addToSeen(seenPropertySymbols, getSymbolId(firstAccessibleSymbol))) { const index = symbols.length; symbols.push(firstAccessibleSymbol); const moduleSymbol = firstAccessibleSymbol.parent; if (!moduleSymbol || - !ts.isExternalModuleSymbol(moduleSymbol) || + !isExternalModuleSymbol(moduleSymbol) || typeChecker.tryGetMemberInModuleExportsAndProperties(firstAccessibleSymbol.name, moduleSymbol) !== firstAccessibleSymbol ) { symbolToOriginInfoMap[index] = { kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.SymbolMemberNoExport) }; } else { - const fileName = ts.isExternalModuleNameRelative(ts.stripQuotes(moduleSymbol.name)) ? ts.getSourceFileOfModule(moduleSymbol)?.fileName : undefined; - const { moduleSpecifier } = (importSpecifierResolver ||= ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)).getModuleSpecifierForBestExportInfo([{ - exportKind: ts.ExportKind.Named, + const fileName = isExternalModuleNameRelative(stripQuotes(moduleSymbol.name)) ? getSourceFileOfModule(moduleSymbol)?.fileName : undefined; + const { moduleSpecifier } = (importSpecifierResolver ||= codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)).getModuleSpecifierForBestExportInfo([{ + exportKind: ExportKind.Named, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol, symbol: firstAccessibleSymbol, - targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location)) || {}; + targetFlags: skipAlias(firstAccessibleSymbol, typeChecker).flags, + }], firstAccessibleSymbol.name, position, isValidTypeOnlyAliasUseSite(location)) || {}; if (moduleSpecifier) { const origin: SymbolOriginInfoResolvedExport = { @@ -2470,15 +2532,15 @@ function getCompletionData( symbols.push(symbol); } - function addSymbolSortInfo(symbol: ts.Symbol) { + function addSymbolSortInfo(symbol: Symbol) { if (isStaticProperty(symbol)) { - symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.LocalDeclarationPriority; + symbolToSortTextMap[getSymbolId(symbol)] = SortText.LocalDeclarationPriority; } } - function addSymbolOriginInfo(symbol: ts.Symbol) { + function addSymbolOriginInfo(symbol: Symbol) { if (preferences.includeCompletionsWithInsertText) { - if (insertAwait && ts.addToSeen(seenPropertySymbols, ts.getSymbolId(symbol))) { + if (insertAwait && addToSeen(seenPropertySymbols, getSymbolId(symbol))) { symbolToOriginInfoMap[symbols.length] = { kind: getNullableSymbolOriginInfoKind(SymbolOriginInfoKind.Promise) }; } else if (insertQuestionDot) { @@ -2493,8 +2555,8 @@ function getCompletionData( } /** Given 'a.b.c', returns 'a'. */ - function getLeftMostName(e: ts.Expression): ts.Identifier | undefined { - return ts.isIdentifier(e) ? e : ts.isPropertyAccessExpression(e) ? getLeftMostName(e.expression) : undefined; + function getLeftMostName(e: Expression): Identifier | undefined { + return isIdentifier(e) ? e : isPropertyAccessExpression(e) ? getLeftMostName(e.expression) : undefined; } function tryGetGlobalSymbols(): boolean { @@ -2526,8 +2588,8 @@ function getCompletionData( // Cursor is inside a JSX self-closing element or opening element const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes); if (!attrsType) return GlobalsSearch.Continue; - const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ts.ContextFlags.Completions); - symbols = ts.concatenate(symbols, filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), jsxContainer.attributes.properties)); + const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions); + symbols = concatenate(symbols, filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), jsxContainer.attributes.properties)); setSortTextToOptionalMember(); completionKind = CompletionKind.MemberLike; isNewIdentifierLocation = false; @@ -2549,7 +2611,7 @@ function getCompletionData( isNewIdentifierLocation = isNewIdentifierDefinitionLocation(); if (previousToken !== contextToken) { - ts.Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); + Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'."); } // We need to find the node that will give us an appropriate scope to begin // aggregating completion candidates. This is achieved in 'getScopeNode' @@ -2583,19 +2645,19 @@ function getCompletionData( const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - const symbolMeanings = (isTypeOnlyLocation ? ts.SymbolFlags.None : ts.SymbolFlags.Value) | ts.SymbolFlags.Type | ts.SymbolFlags.Namespace | ts.SymbolFlags.Alias; - const typeOnlyAliasNeedsPromotion = previousToken && !ts.isValidTypeOnlyAliasUseSite(previousToken); + const symbolMeanings = (isTypeOnlyLocation ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias; + const typeOnlyAliasNeedsPromotion = previousToken && !isValidTypeOnlyAliasUseSite(previousToken); - symbols = ts.concatenate(symbols, typeChecker.getSymbolsInScope(scopeNode, symbolMeanings)); - ts.Debug.assertEachIsDefined(symbols, "getSymbolsInScope() should all be defined"); + symbols = concatenate(symbols, typeChecker.getSymbolsInScope(scopeNode, symbolMeanings)); + Debug.assertEachIsDefined(symbols, "getSymbolsInScope() should all be defined"); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; if (!typeChecker.isArgumentsSymbol(symbol) && - !ts.some(symbol.declarations, d => d.getSourceFile() === sourceFile)) { - symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.GlobalsOrKeywords; + !some(symbol.declarations, d => d.getSourceFile() === sourceFile)) { + symbolToSortTextMap[getSymbolId(symbol)] = SortText.GlobalsOrKeywords; } - if (typeOnlyAliasNeedsPromotion && !(symbol.flags & ts.SymbolFlags.Value)) { - const typeOnlyAliasDeclaration = symbol.declarations && ts.find(symbol.declarations, ts.isTypeOnlyImportOrExportDeclaration); + if (typeOnlyAliasNeedsPromotion && !(symbol.flags & SymbolFlags.Value)) { + const typeOnlyAliasDeclaration = symbol.declarations && find(symbol.declarations, isTypeOnlyImportOrExportDeclaration); if (typeOnlyAliasDeclaration) { const origin: SymbolOriginInfoTypeOnlyAlias = { kind: SymbolOriginInfoKind.TypeOnlyAlias, declaration: typeOnlyAliasDeclaration }; symbolToOriginInfoMap[i] = origin; @@ -2604,19 +2666,19 @@ function getCompletionData( } // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` - if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== ts.SyntaxKind.SourceFile) { - const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, ts.isClassLike(scopeNode.parent) ? scopeNode : undefined); + if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== SyntaxKind.SourceFile) { + const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, isClassLike(scopeNode.parent) ? scopeNode : undefined); if (thisType && !isProbablyGlobalType(thisType, sourceFile, typeChecker)) { for (const symbol of getPropertiesForCompletion(thisType, typeChecker)) { symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.ThisType }; symbols.push(symbol); - symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.SuggestedClassMembers; + symbolToSortTextMap[getSymbolId(symbol)] = SortText.SuggestedClassMembers; } } } collectAutoImports(); if (isTypeOnlyLocation) { - keywordFilters = contextToken && ts.isAssertionExpression(contextToken.parent) + keywordFilters = contextToken && isAssertionExpression(contextToken.parent) ? KeywordCompletionFilters.TypeAssertionKeywords : KeywordCompletionFilters.TypeKeywords; } @@ -2632,65 +2694,65 @@ function getCompletionData( // If already using ES modules, OK to continue using them. if (sourceFile.externalModuleIndicator || sourceFile.commonJsModuleIndicator) return true; // If module transpilation is enabled or we're targeting es6 or above, or not emitting, OK. - if (ts.compilerOptionsIndicateEsModules(program.getCompilerOptions())) return true; + if (compilerOptionsIndicateEsModules(program.getCompilerOptions())) return true; // If some file is using ES6 modules, assume that it's OK to add more. - return ts.programContainsModules(program); + return programContainsModules(program); } - function isSnippetScope(scopeNode: ts.Node): boolean { + function isSnippetScope(scopeNode: Node): boolean { switch (scopeNode.kind) { - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.JsxExpression: - case ts.SyntaxKind.Block: + case SyntaxKind.SourceFile: + case SyntaxKind.TemplateExpression: + case SyntaxKind.JsxExpression: + case SyntaxKind.Block: return true; default: - return ts.isStatement(scopeNode); + return isStatement(scopeNode); } } function isTypeOnlyCompletion(): boolean { return insideJsDocTagTypeExpression - || !!importStatementCompletion && ts.isTypeOnlyImportOrExportDeclaration(location.parent) + || !!importStatementCompletion && isTypeOnlyImportOrExportDeclaration(location.parent) || !isContextTokenValueLocation(contextToken) && - (ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker) - || ts.isPartOfTypeNode(location) + (isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker) + || isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); } - function isContextTokenValueLocation(contextToken: ts.Node) { + function isContextTokenValueLocation(contextToken: Node) { return contextToken && - ((contextToken.kind === ts.SyntaxKind.TypeOfKeyword && - (contextToken.parent.kind === ts.SyntaxKind.TypeQuery || ts.isTypeOfExpression(contextToken.parent))) || - (contextToken.kind === ts.SyntaxKind.AssertsKeyword && contextToken.parent.kind === ts.SyntaxKind.TypePredicate)); + ((contextToken.kind === SyntaxKind.TypeOfKeyword && + (contextToken.parent.kind === SyntaxKind.TypeQuery || isTypeOfExpression(contextToken.parent))) || + (contextToken.kind === SyntaxKind.AssertsKeyword && contextToken.parent.kind === SyntaxKind.TypePredicate)); } - function isContextTokenTypeLocation(contextToken: ts.Node): boolean { + function isContextTokenTypeLocation(contextToken: Node): boolean { if (contextToken) { const parentKind = contextToken.parent.kind; switch (contextToken.kind) { - case ts.SyntaxKind.ColonToken: - return parentKind === ts.SyntaxKind.PropertyDeclaration || - parentKind === ts.SyntaxKind.PropertySignature || - parentKind === ts.SyntaxKind.Parameter || - parentKind === ts.SyntaxKind.VariableDeclaration || - ts.isFunctionLikeKind(parentKind); + case SyntaxKind.ColonToken: + return parentKind === SyntaxKind.PropertyDeclaration || + parentKind === SyntaxKind.PropertySignature || + parentKind === SyntaxKind.Parameter || + parentKind === SyntaxKind.VariableDeclaration || + isFunctionLikeKind(parentKind); - case ts.SyntaxKind.EqualsToken: - return parentKind === ts.SyntaxKind.TypeAliasDeclaration; + case SyntaxKind.EqualsToken: + return parentKind === SyntaxKind.TypeAliasDeclaration; - case ts.SyntaxKind.AsKeyword: - return parentKind === ts.SyntaxKind.AsExpression; + case SyntaxKind.AsKeyword: + return parentKind === SyntaxKind.AsExpression; - case ts.SyntaxKind.LessThanToken: - return parentKind === ts.SyntaxKind.TypeReference || - parentKind === ts.SyntaxKind.TypeAssertionExpression; + case SyntaxKind.LessThanToken: + return parentKind === SyntaxKind.TypeReference || + parentKind === SyntaxKind.TypeAssertionExpression; - case ts.SyntaxKind.ExtendsKeyword: - return parentKind === ts.SyntaxKind.TypeParameter; + case SyntaxKind.ExtendsKeyword: + return parentKind === SyntaxKind.TypeParameter; - case ts.SyntaxKind.SatisfiesKeyword: - return parentKind === ts.SyntaxKind.SatisfiesExpression; + case SyntaxKind.SatisfiesKeyword: + return parentKind === SyntaxKind.SatisfiesExpression; } } return false; @@ -2699,53 +2761,53 @@ function getCompletionData( /** Mutates `symbols`, `symbolToOriginInfoMap`, and `symbolToSortTextMap` */ function collectAutoImports() { if (!shouldOfferImportCompletions()) return; - ts.Debug.assert(!detailsEntryId?.data, "Should not run 'collectAutoImports' when faster path is available via `data`"); + Debug.assert(!detailsEntryId?.data, "Should not run 'collectAutoImports' when faster path is available via `data`"); if (detailsEntryId && !detailsEntryId.source) { // Asking for completion details for an item that is not an auto-import return; } - flags |= ts.CompletionInfoFlags.MayIncludeAutoImports; + flags |= CompletionInfoFlags.MayIncludeAutoImports; // import { type | -> token text should be blank const isAfterTypeOnlyImportSpecifierModifier = previousToken === contextToken && importStatementCompletion; const lowerCaseTokenText = isAfterTypeOnlyImportSpecifierModifier ? "" : - previousToken && ts.isIdentifier(previousToken) ? previousToken.text.toLowerCase() : + previousToken && isIdentifier(previousToken) ? previousToken.text.toLowerCase() : ""; const moduleSpecifierCache = host.getModuleSpecifierCache?.(); - const exportInfo = ts.getExportInfoMap(sourceFile, host, program, preferences, cancellationToken); + const exportInfo = getExportInfoMap(sourceFile, host, program, preferences, cancellationToken); const packageJsonAutoImportProvider = host.getPackageJsonAutoImportProvider?.(); - const packageJsonFilter = detailsEntryId ? undefined : ts.createPackageJsonImportFilter(sourceFile, preferences, host); + const packageJsonFilter = detailsEntryId ? undefined : createPackageJsonImportFilter(sourceFile, preferences, host); resolvingModuleSpecifiers( "collectAutoImports", host, - importSpecifierResolver ||= ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences), + importSpecifierResolver ||= codefix.createImportSpecifierResolver(sourceFile, program, host, preferences), program, position, preferences, !!importStatementCompletion, - ts.isValidTypeOnlyAliasUseSite(location), + isValidTypeOnlyAliasUseSite(location), context => { exportInfo.search( sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, (symbolName, targetFlags) => { - if (!ts.isIdentifierText(symbolName, ts.getEmitScriptTarget(host.getCompilationSettings()))) return false; - if (!detailsEntryId && ts.isStringANonContextualKeyword(symbolName)) return false; - if (!isTypeOnlyLocation && !importStatementCompletion && !(targetFlags & ts.SymbolFlags.Value)) return false; - if (isTypeOnlyLocation && !(targetFlags & (ts.SymbolFlags.Module | ts.SymbolFlags.Type))) return false; + if (!isIdentifierText(symbolName, getEmitScriptTarget(host.getCompilationSettings()))) return false; + if (!detailsEntryId && isStringANonContextualKeyword(symbolName)) return false; + if (!isTypeOnlyLocation && !importStatementCompletion && !(targetFlags & SymbolFlags.Value)) return false; + if (isTypeOnlyLocation && !(targetFlags & (SymbolFlags.Module | SymbolFlags.Type))) return false; // Do not try to auto-import something with a lowercase first letter for a JSX tag const firstChar = symbolName.charCodeAt(0); - if (isRightOfOpenTag && (firstChar < ts.CharacterCodes.A || firstChar > ts.CharacterCodes.Z)) return false; + if (isRightOfOpenTag && (firstChar < CharacterCodes.A || firstChar > CharacterCodes.Z)) return false; if (detailsEntryId) return true; return charactersFuzzyMatchInString(symbolName, lowerCaseTokenText); }, (info, symbolName, isFromAmbientModule, exportMapKey) => { - if (detailsEntryId && !ts.some(info, i => detailsEntryId.source === ts.stripQuotes(i.moduleSymbol.name))) { + if (detailsEntryId && !some(info, i => detailsEntryId.source === stripQuotes(i.moduleSymbol.name))) { return; } @@ -2754,7 +2816,7 @@ function getCompletionData( // module resolution modes, getting past this point guarantees that we'll be // able to generate a suitable module specifier, so we can safely show a completion, // even if we defer computing the module specifier. - const firstImportableExportInfo = ts.find(info, isImportableExportInfo); + const firstImportableExportInfo = find(info, isImportableExportInfo); if (!firstImportableExportInfo) { return; } @@ -2777,15 +2839,15 @@ function getCompletionData( ({ exportInfo = firstImportableExportInfo, moduleSpecifier } = result); } - const isDefaultExport = exportInfo.exportKind === ts.ExportKind.Default; - const symbol = isDefaultExport && ts.getLocalSymbolForExportDefault(exportInfo.symbol) || exportInfo.symbol; + const isDefaultExport = exportInfo.exportKind === ExportKind.Default; + const symbol = isDefaultExport && getLocalSymbolForExportDefault(exportInfo.symbol) || exportInfo.symbol; pushAutoImportSymbol(symbol, { kind: moduleSpecifier ? SymbolOriginInfoKind.ResolvedExport : SymbolOriginInfoKind.Export, moduleSpecifier, symbolName, exportMapKey, - exportName: exportInfo.exportKind === ts.ExportKind.ExportEquals ? ts.InternalSymbolName.ExportEquals : exportInfo.symbol.name, + exportName: exportInfo.exportKind === ExportKind.ExportEquals ? InternalSymbolName.ExportEquals : exportInfo.symbol.name, fileName: exportInfo.moduleFileName, isDefaultExport, moduleSymbol: exportInfo.moduleSymbol, @@ -2795,23 +2857,23 @@ function getCompletionData( ); hasUnresolvedAutoImports = context.skippedAny(); - flags |= context.resolvedAny() ? ts.CompletionInfoFlags.ResolvedModuleSpecifiers : 0; - flags |= context.resolvedBeyondLimit() ? ts.CompletionInfoFlags.ResolvedModuleSpecifiersBeyondLimit : 0; + flags |= context.resolvedAny() ? CompletionInfoFlags.ResolvedModuleSpecifiers : 0; + flags |= context.resolvedBeyondLimit() ? CompletionInfoFlags.ResolvedModuleSpecifiersBeyondLimit : 0; } ); - function isImportableExportInfo(info: ts.SymbolExportInfo) { - const moduleFile = ts.tryCast(info.moduleSymbol.valueDeclaration, ts.isSourceFile); + function isImportableExportInfo(info: SymbolExportInfo) { + const moduleFile = tryCast(info.moduleSymbol.valueDeclaration, isSourceFile); if (!moduleFile) { - const moduleName = ts.stripQuotes(info.moduleSymbol.name); - if (ts.JsTyping.nodeCoreModules.has(moduleName) && ts.startsWith(moduleName, "node:") !== ts.shouldUseUriStyleNodeCoreModules(sourceFile, program)) { + const moduleName = stripQuotes(info.moduleSymbol.name); + if (JsTyping.nodeCoreModules.has(moduleName) && startsWith(moduleName, "node:") !== shouldUseUriStyleNodeCoreModules(sourceFile, program)) { return false; } return packageJsonFilter ? packageJsonFilter.allowsImportingAmbientModule(info.moduleSymbol, getModuleSpecifierResolutionHost(info.isFromPackageJson)) : true; } - return ts.isImportableFile( + return isImportableFile( info.isFromPackageJson ? packageJsonAutoImportProvider! : program, sourceFile, moduleFile, @@ -2822,8 +2884,8 @@ function getCompletionData( } } - function pushAutoImportSymbol(symbol: ts.Symbol, origin: SymbolOriginInfoResolvedExport | SymbolOriginInfoExport) { - const symbolId = ts.getSymbolId(symbol); + function pushAutoImportSymbol(symbol: Symbol, origin: SymbolOriginInfoResolvedExport | SymbolOriginInfoExport) { + const symbolId = getSymbolId(symbol); if (symbolToSortTextMap[symbolId] === SortText.GlobalsOrKeywords) { // If an auto-importable symbol is available as a global, don't add the auto import return; @@ -2834,9 +2896,9 @@ function getCompletionData( } /* Mutates `symbols` and `symbolToOriginInfoMap`. */ - function collectObjectLiteralMethodSymbols(members: ts.Symbol[], enclosingDeclaration: ts.ObjectLiteralExpression): void { + function collectObjectLiteralMethodSymbols(members: Symbol[], enclosingDeclaration: ObjectLiteralExpression): void { // TODO: support JS files. - if (ts.isInJSFile(location)) { + if (isInJSFile(location)) { return; } members.forEach(member => { @@ -2845,7 +2907,7 @@ function getCompletionData( } const displayName = getCompletionEntryDisplayNameForSymbol( member, - ts.getEmitScriptTarget(compilerOptions), + getEmitScriptTarget(compilerOptions), /*origin*/ undefined, CompletionKind.ObjectPropertyDeclaration, /*jsxIdentifierExpected*/ false); @@ -2866,13 +2928,13 @@ function getCompletionData( return; } const origin: SymbolOriginInfoObjectLiteralMethod = { kind: SymbolOriginInfoKind.ObjectLiteralMethod, ...entryProps }; - flags |= ts.CompletionInfoFlags.MayIncludeMethodSnippets; + flags |= CompletionInfoFlags.MayIncludeMethodSnippets; symbolToOriginInfoMap[symbols.length] = origin; symbols.push(member); }); } - function isObjectLiteralMethodSymbol(symbol: ts.Symbol): boolean { + function isObjectLiteralMethodSymbol(symbol: Symbol): boolean { /* For an object type `type Foo = { @@ -2882,7 +2944,7 @@ function getCompletionData( `bar` will have symbol flag `Method`, `foo` will have symbol flag `Property`. */ - if (!(symbol.flags & (ts.SymbolFlags.Property | ts.SymbolFlags.Method))) { + if (!(symbol.flags & (SymbolFlags.Property | SymbolFlags.Method))) { return false; } return true; @@ -2892,50 +2954,50 @@ function getCompletionData( * Finds the first node that "embraces" the position, so that one may * accurately aggregate locals from the closest containing scope. */ - function getScopeNode(initialToken: ts.Node | undefined, position: number, sourceFile: ts.SourceFile) { - let scope: ts.Node | undefined = initialToken; - while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) { + function getScopeNode(initialToken: Node | undefined, position: number, sourceFile: SourceFile) { + let scope: Node | undefined = initialToken; + while (scope && !positionBelongsToNode(scope, position, sourceFile)) { scope = scope.parent; } return scope; } - function isCompletionListBlocker(contextToken: ts.Node): boolean { - const start = ts.timestamp(); + function isCompletionListBlocker(contextToken: Node): boolean { + const start = timestamp(); const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) || isSolelyIdentifierDefinitionLocation(contextToken) || isDotOfNumericLiteral(contextToken) || isInJsxText(contextToken) || - ts.isBigIntLiteral(contextToken); - log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start)); + isBigIntLiteral(contextToken); + log("getCompletionsAtPosition: isCompletionListBlocker: " + (timestamp() - start)); return result; } - function isInJsxText(contextToken: ts.Node): boolean { - if (contextToken.kind === ts.SyntaxKind.JsxText) { + function isInJsxText(contextToken: Node): boolean { + if (contextToken.kind === SyntaxKind.JsxText) { return true; } - if (contextToken.kind === ts.SyntaxKind.GreaterThanToken && contextToken.parent) { + if (contextToken.kind === SyntaxKind.GreaterThanToken && contextToken.parent) { // /**/ /> // /**/ > // - contextToken: GreaterThanToken (before cursor) // - location: JsxSelfClosingElement or JsxOpeningElement // - contextToken.parent === location - if (location === contextToken.parent && (location.kind === ts.SyntaxKind.JsxOpeningElement || location.kind === ts.SyntaxKind.JsxSelfClosingElement)) { + if (location === contextToken.parent && (location.kind === SyntaxKind.JsxOpeningElement || location.kind === SyntaxKind.JsxSelfClosingElement)) { return false; } - if (contextToken.parent.kind === ts.SyntaxKind.JsxOpeningElement) { + if (contextToken.parent.kind === SyntaxKind.JsxOpeningElement) { //
/**/ // - contextToken: GreaterThanToken (before cursor) // - location: JSXElement // - different parents (JSXOpeningElement, JSXElement) - return location.parent.kind !== ts.SyntaxKind.JsxOpeningElement; + return location.parent.kind !== SyntaxKind.JsxOpeningElement; } - if (contextToken.parent.kind === ts.SyntaxKind.JsxClosingElement || contextToken.parent.kind === ts.SyntaxKind.JsxSelfClosingElement) { - return !!contextToken.parent.parent && contextToken.parent.parent.kind === ts.SyntaxKind.JsxElement; + if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) { + return !!contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement; } } return false; @@ -2947,55 +3009,55 @@ function getCompletionData( const tokenKind = keywordForNode(contextToken); // Previous token may have been a keyword that was converted to an identifier. switch (tokenKind) { - case ts.SyntaxKind.CommaToken: - return containingNodeKind === ts.SyntaxKind.CallExpression // func( a, | - || containingNodeKind === ts.SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ - || containingNodeKind === ts.SyntaxKind.NewExpression // new C(a, | - || containingNodeKind === ts.SyntaxKind.ArrayLiteralExpression // [a, | - || containingNodeKind === ts.SyntaxKind.BinaryExpression // const x = (a, | - || containingNodeKind === ts.SyntaxKind.FunctionType // var x: (s: string, list| - || containingNodeKind === ts.SyntaxKind.ObjectLiteralExpression; // const obj = { x, | - - case ts.SyntaxKind.OpenParenToken: - return containingNodeKind === ts.SyntaxKind.CallExpression // func( | - || containingNodeKind === ts.SyntaxKind.Constructor // constructor( | - || containingNodeKind === ts.SyntaxKind.NewExpression // new C(a| - || containingNodeKind === ts.SyntaxKind.ParenthesizedExpression // const x = (a| - || containingNodeKind === ts.SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ - - case ts.SyntaxKind.OpenBracketToken: - return containingNodeKind === ts.SyntaxKind.ArrayLiteralExpression // [ | - || containingNodeKind === ts.SyntaxKind.IndexSignature // [ | : string ] - || containingNodeKind === ts.SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ - - case ts.SyntaxKind.ModuleKeyword: // module | - case ts.SyntaxKind.NamespaceKeyword: // namespace | - case ts.SyntaxKind.ImportKeyword: // import | + case SyntaxKind.CommaToken: + return containingNodeKind === SyntaxKind.CallExpression // func( a, | + || containingNodeKind === SyntaxKind.Constructor // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */ + || containingNodeKind === SyntaxKind.NewExpression // new C(a, | + || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, | + || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, | + || containingNodeKind === SyntaxKind.FunctionType // var x: (s: string, list| + || containingNodeKind === SyntaxKind.ObjectLiteralExpression; // const obj = { x, | + + case SyntaxKind.OpenParenToken: + return containingNodeKind === SyntaxKind.CallExpression // func( | + || containingNodeKind === SyntaxKind.Constructor // constructor( | + || containingNodeKind === SyntaxKind.NewExpression // new C(a| + || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a| + || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */ + + case SyntaxKind.OpenBracketToken: + return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ | + || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ] + || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */ + + case SyntaxKind.ModuleKeyword: // module | + case SyntaxKind.NamespaceKeyword: // namespace | + case SyntaxKind.ImportKeyword: // import | return true; - case ts.SyntaxKind.DotToken: - return containingNodeKind === ts.SyntaxKind.ModuleDeclaration; // module A.| + case SyntaxKind.DotToken: + return containingNodeKind === SyntaxKind.ModuleDeclaration; // module A.| - case ts.SyntaxKind.OpenBraceToken: - return containingNodeKind === ts.SyntaxKind.ClassDeclaration // class A { | - || containingNodeKind === ts.SyntaxKind.ObjectLiteralExpression; // const obj = { | + case SyntaxKind.OpenBraceToken: + return containingNodeKind === SyntaxKind.ClassDeclaration // class A { | + || containingNodeKind === SyntaxKind.ObjectLiteralExpression; // const obj = { | - case ts.SyntaxKind.EqualsToken: - return containingNodeKind === ts.SyntaxKind.VariableDeclaration // const x = a| - || containingNodeKind === ts.SyntaxKind.BinaryExpression; // x = a| + case SyntaxKind.EqualsToken: + return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a| + || containingNodeKind === SyntaxKind.BinaryExpression; // x = a| - case ts.SyntaxKind.TemplateHead: - return containingNodeKind === ts.SyntaxKind.TemplateExpression; // `aa ${| + case SyntaxKind.TemplateHead: + return containingNodeKind === SyntaxKind.TemplateExpression; // `aa ${| - case ts.SyntaxKind.TemplateMiddle: - return containingNodeKind === ts.SyntaxKind.TemplateSpan; // `aa ${10} dd ${| + case SyntaxKind.TemplateMiddle: + return containingNodeKind === SyntaxKind.TemplateSpan; // `aa ${10} dd ${| - case ts.SyntaxKind.AsyncKeyword: - return containingNodeKind === ts.SyntaxKind.MethodDeclaration // const obj = { async c|() - || containingNodeKind === ts.SyntaxKind.ShorthandPropertyAssignment; // const obj = { async c| + case SyntaxKind.AsyncKeyword: + return containingNodeKind === SyntaxKind.MethodDeclaration // const obj = { async c|() + || containingNodeKind === SyntaxKind.ShorthandPropertyAssignment; // const obj = { async c| - case ts.SyntaxKind.AsteriskToken: - return containingNodeKind === ts.SyntaxKind.MethodDeclaration; // const obj = { * c| + case SyntaxKind.AsteriskToken: + return containingNodeKind === SyntaxKind.MethodDeclaration; // const obj = { * c| } if (isClassMemberCompletionKeyword(tokenKind)) { @@ -3006,21 +3068,21 @@ function getCompletionData( return false; } - function isInStringOrRegularExpressionOrTemplateLiteral(contextToken: ts.Node): boolean { + function isInStringOrRegularExpressionOrTemplateLiteral(contextToken: Node): boolean { // To be "in" one of these literals, the position has to be: // 1. entirely within the token text. // 2. at the end position of an unterminated token. // 3. at the end of a regular expression (due to trailing flags like '/foo/g'). - return (ts.isRegularExpressionLiteral(contextToken) || ts.isStringTextContainingNode(contextToken)) && ( - ts.rangeContainsPositionExclusive(ts.createTextRangeFromSpan(ts.createTextSpanFromNode(contextToken)), position) || - position === contextToken.end && (!!contextToken.isUnterminated || ts.isRegularExpressionLiteral(contextToken))); + return (isRegularExpressionLiteral(contextToken) || isStringTextContainingNode(contextToken)) && ( + rangeContainsPositionExclusive(createTextRangeFromSpan(createTextSpanFromNode(contextToken)), position) || + position === contextToken.end && (!!contextToken.isUnterminated || isRegularExpressionLiteral(contextToken))); } function tryGetObjectTypeLiteralInTypeArgumentCompletionSymbols(): GlobalsSearch | undefined { const typeLiteralNode = tryGetTypeLiteralNode(contextToken); if (!typeLiteralNode) return GlobalsSearch.Continue; - const intersectionTypeNode = ts.isIntersectionTypeNode(typeLiteralNode.parent) ? typeLiteralNode.parent : undefined; + const intersectionTypeNode = isIntersectionTypeNode(typeLiteralNode.parent) ? typeLiteralNode.parent : undefined; const containerTypeNode = intersectionTypeNode || typeLiteralNode; const containerExpectedType = getConstraintOfTypeArgumentProperty(containerTypeNode, typeChecker); @@ -3031,10 +3093,10 @@ function getCompletionData( const members = getPropertiesForCompletion(containerExpectedType, typeChecker); const existingMembers = getPropertiesForCompletion(containerActualType, typeChecker); - const existingMemberEscapedNames: ts.Set = new ts.Set(); + const existingMemberEscapedNames: Set<__String> = new Set(); existingMembers.forEach(s => existingMemberEscapedNames.add(s.escapedName)); - symbols = ts.concatenate(symbols, ts.filter(members, s => !existingMemberEscapedNames.has(s.escapedName))); + symbols = concatenate(symbols, filter(members, s => !existingMemberEscapedNames.has(s.escapedName))); completionKind = CompletionKind.ObjectPropertyDeclaration; isNewIdentifierLocation = true; @@ -3056,21 +3118,21 @@ function getCompletionData( // We're looking up possible property names from contextual/inferred/declared type. completionKind = CompletionKind.ObjectPropertyDeclaration; - let typeMembers: ts.Symbol[] | undefined; - let existingMembers: readonly ts.Declaration[] | undefined; + let typeMembers: Symbol[] | undefined; + let existingMembers: readonly Declaration[] | undefined; - if (objectLikeContainer.kind === ts.SyntaxKind.ObjectLiteralExpression) { + if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) { const instantiatedType = tryGetObjectLiteralContextualType(objectLikeContainer, typeChecker); // Check completions for Object property value shorthand if (instantiatedType === undefined) { - if (objectLikeContainer.flags & ts.NodeFlags.InWithStatement) { + if (objectLikeContainer.flags & NodeFlags.InWithStatement) { return GlobalsSearch.Fail; } isNonContextualObjectLiteral = true; return GlobalsSearch.Continue; } - const completionsType = typeChecker.getContextualType(objectLikeContainer, ts.ContextFlags.Completions); + const completionsType = typeChecker.getContextualType(objectLikeContainer, ContextFlags.Completions); const hasStringIndexType = (completionsType || instantiatedType).getStringIndexType(); const hasNumberIndextype = (completionsType || instantiatedType).getNumberIndexType(); isNewIdentifierLocation = !!hasStringIndexType || !!hasNumberIndextype; @@ -3086,25 +3148,25 @@ function getCompletionData( } } else { - ts.Debug.assert(objectLikeContainer.kind === ts.SyntaxKind.ObjectBindingPattern); + Debug.assert(objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern); // We are *only* completing on properties from the type being destructured. isNewIdentifierLocation = false; - const rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent); - if (!ts.isVariableLike(rootDeclaration)) return ts.Debug.fail("Root declaration is not variable-like."); + const rootDeclaration = getRootDeclaration(objectLikeContainer.parent); + if (!isVariableLike(rootDeclaration)) return Debug.fail("Root declaration is not variable-like."); // We don't want to complete using the type acquired by the shape // of the binding pattern; we are only interested in types acquired // through type declaration or inference. // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed - // type of parameter will flow in from the contextual type of the function - let canGetType = ts.hasInitializer(rootDeclaration) || !!ts.getEffectiveTypeAnnotationNode(rootDeclaration) || rootDeclaration.parent.parent.kind === ts.SyntaxKind.ForOfStatement; - if (!canGetType && rootDeclaration.kind === ts.SyntaxKind.Parameter) { - if (ts.isExpression(rootDeclaration.parent)) { - canGetType = !!typeChecker.getContextualType(rootDeclaration.parent as ts.Expression); + let canGetType = hasInitializer(rootDeclaration) || !!getEffectiveTypeAnnotationNode(rootDeclaration) || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement; + if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) { + if (isExpression(rootDeclaration.parent)) { + canGetType = !!typeChecker.getContextualType(rootDeclaration.parent as Expression); } - else if (rootDeclaration.parent.kind === ts.SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === ts.SyntaxKind.SetAccessor) { - canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent as ts.Expression); + else if (rootDeclaration.parent.kind === SyntaxKind.MethodDeclaration || rootDeclaration.parent.kind === SyntaxKind.SetAccessor) { + canGetType = isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent as Expression); } } if (canGetType) { @@ -3119,10 +3181,10 @@ function getCompletionData( if (typeMembers && typeMembers.length > 0) { // Add filtered items to the completion list - const filteredMembers = filterObjectMembersList(typeMembers, ts.Debug.checkDefined(existingMembers)); - symbols = ts.concatenate(symbols, filteredMembers); + const filteredMembers = filterObjectMembersList(typeMembers, Debug.checkDefined(existingMembers)); + symbols = concatenate(symbols, filteredMembers); setSortTextToOptionalMember(); - if (objectLikeContainer.kind === ts.SyntaxKind.ObjectLiteralExpression + if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression && preferences.includeCompletionsWithObjectLiteralMethodSnippets && preferences.includeCompletionsWithInsertText) { transformObjectLiteralMembersSortText(symbolsStartIndex); @@ -3151,21 +3213,21 @@ function getCompletionData( // `import { |` or `import { a as 0, | }` or `import { type | }` const namedImportsOrExports = - contextToken.kind === ts.SyntaxKind.OpenBraceToken || contextToken.kind === ts.SyntaxKind.CommaToken ? ts.tryCast(contextToken.parent, ts.isNamedImportsOrExports) : - ts.isTypeKeywordTokenOrIdentifier(contextToken) ? ts.tryCast(contextToken.parent.parent, ts.isNamedImportsOrExports) : undefined; + contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken ? tryCast(contextToken.parent, isNamedImportsOrExports) : + isTypeKeywordTokenOrIdentifier(contextToken) ? tryCast(contextToken.parent.parent, isNamedImportsOrExports) : undefined; if (!namedImportsOrExports) return GlobalsSearch.Continue; // We can at least offer `type` at `import { |` - if (!ts.isTypeKeywordTokenOrIdentifier(contextToken)) { + if (!isTypeKeywordTokenOrIdentifier(contextToken)) { keywordFilters = KeywordCompletionFilters.TypeKeyword; } // try to show exported member for imported/re-exported module - const { moduleSpecifier } = namedImportsOrExports.kind === ts.SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; + const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent; if (!moduleSpecifier) { isNewIdentifierLocation = true; - return namedImportsOrExports.kind === ts.SyntaxKind.NamedImports ? GlobalsSearch.Fail : GlobalsSearch.Continue; + return namedImportsOrExports.kind === SyntaxKind.NamedImports ? GlobalsSearch.Fail : GlobalsSearch.Continue; } const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217 if (!moduleSpecifierSymbol) { @@ -3176,9 +3238,9 @@ function getCompletionData( completionKind = CompletionKind.MemberLike; isNewIdentifierLocation = false; const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol); - const existing = new ts.Set((namedImportsOrExports.elements as ts.NodeArray).filter(n => !isCurrentlyEditingNode(n)).map(n => (n.propertyName || n.name).escapedText)); - const uniques = exports.filter(e => e.escapedName !== ts.InternalSymbolName.Default && !existing.has(e.escapedName)); - symbols = ts.concatenate(symbols, uniques); + const existing = new Set((namedImportsOrExports.elements as NodeArray).filter(n => !isCurrentlyEditingNode(n)).map(n => (n.propertyName || n.name).escapedText)); + const uniques = exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.has(e.escapedName)); + symbols = concatenate(symbols, uniques); if (!uniques.length) { // If there's nothing else to import, don't offer `type` either keywordFilters = KeywordCompletionFilters.None; @@ -3196,21 +3258,21 @@ function getCompletionData( * preventing this function from running. */ function tryGetLocalNamedExportCompletionSymbols(): GlobalsSearch { - const namedExports = contextToken && (contextToken.kind === ts.SyntaxKind.OpenBraceToken || contextToken.kind === ts.SyntaxKind.CommaToken) - ? ts.tryCast(contextToken.parent, ts.isNamedExports) + const namedExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken) + ? tryCast(contextToken.parent, isNamedExports) : undefined; if (!namedExports) { return GlobalsSearch.Continue; } - const localsContainer = ts.findAncestor(namedExports, ts.or(ts.isSourceFile, ts.isModuleDeclaration))!; + const localsContainer = findAncestor(namedExports, or(isSourceFile, isModuleDeclaration))!; completionKind = CompletionKind.None; isNewIdentifierLocation = false; localsContainer.locals?.forEach((symbol, name) => { symbols.push(symbol); if (localsContainer.symbol?.exports?.has(name)) { - symbolToSortTextMap[ts.getSymbolId(symbol)] = SortText.OptionalMember; + symbolToSortTextMap[getSymbolId(symbol)] = SortText.OptionalMember; } }); return GlobalsSearch.Success; @@ -3228,151 +3290,151 @@ function getCompletionData( completionKind = CompletionKind.MemberLike; // Declaring new property/method/accessor isNewIdentifierLocation = true; - keywordFilters = contextToken.kind === ts.SyntaxKind.AsteriskToken ? KeywordCompletionFilters.None : - ts.isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords : KeywordCompletionFilters.InterfaceElementKeywords; + keywordFilters = contextToken.kind === SyntaxKind.AsteriskToken ? KeywordCompletionFilters.None : + isClassLike(decl) ? KeywordCompletionFilters.ClassElementKeywords : KeywordCompletionFilters.InterfaceElementKeywords; // If you're in an interface you don't want to repeat things from super-interface. So just stop here. - if (!ts.isClassLike(decl)) return GlobalsSearch.Success; + if (!isClassLike(decl)) return GlobalsSearch.Success; - const classElement = contextToken.kind === ts.SyntaxKind.SemicolonToken ? contextToken.parent.parent : contextToken.parent; - let classElementModifierFlags = ts.isClassElement(classElement) ? ts.getEffectiveModifierFlags(classElement) : ts.ModifierFlags.None; + const classElement = contextToken.kind === SyntaxKind.SemicolonToken ? contextToken.parent.parent : contextToken.parent; + let classElementModifierFlags = isClassElement(classElement) ? getEffectiveModifierFlags(classElement) : ModifierFlags.None; // If this is context token is not something we are editing now, consider if this would lead to be modifier - if (contextToken.kind === ts.SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) { + if (contextToken.kind === SyntaxKind.Identifier && !isCurrentlyEditingNode(contextToken)) { switch (contextToken.getText()) { case "private": - classElementModifierFlags = classElementModifierFlags | ts.ModifierFlags.Private; + classElementModifierFlags = classElementModifierFlags | ModifierFlags.Private; break; case "static": - classElementModifierFlags = classElementModifierFlags | ts.ModifierFlags.Static; + classElementModifierFlags = classElementModifierFlags | ModifierFlags.Static; break; case "override": - classElementModifierFlags = classElementModifierFlags | ts.ModifierFlags.Override; + classElementModifierFlags = classElementModifierFlags | ModifierFlags.Override; break; } } - if (ts.isClassStaticBlockDeclaration(classElement)) { - classElementModifierFlags |= ts.ModifierFlags.Static; + if (isClassStaticBlockDeclaration(classElement)) { + classElementModifierFlags |= ModifierFlags.Static; } // No member list for private methods - if (!(classElementModifierFlags & ts.ModifierFlags.Private)) { + if (!(classElementModifierFlags & ModifierFlags.Private)) { // List of property symbols of base type that are not private and already implemented - const baseTypeNodes = ts.isClassLike(decl) && classElementModifierFlags & ts.ModifierFlags.Override ? ts.singleElementArray(ts.getEffectiveBaseTypeNode(decl)) : ts.getAllSuperTypeNodes(decl); - const baseSymbols = ts.flatMap(baseTypeNodes, baseTypeNode => { + const baseTypeNodes = isClassLike(decl) && classElementModifierFlags & ModifierFlags.Override ? singleElementArray(getEffectiveBaseTypeNode(decl)) : getAllSuperTypeNodes(decl); + const baseSymbols = flatMap(baseTypeNodes, baseTypeNode => { const type = typeChecker.getTypeAtLocation(baseTypeNode); - return classElementModifierFlags & ts.ModifierFlags.Static ? + return classElementModifierFlags & ModifierFlags.Static ? type?.symbol && typeChecker.getPropertiesOfType(typeChecker.getTypeOfSymbolAtLocation(type.symbol, decl)) : type && typeChecker.getPropertiesOfType(type); }); - symbols = ts.concatenate(symbols, filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags)); + symbols = concatenate(symbols, filterClassMembersList(baseSymbols, decl.members, classElementModifierFlags)); } return GlobalsSearch.Success; } - function isConstructorParameterCompletion(node: ts.Node): boolean { - return !!node.parent && ts.isParameter(node.parent) && ts.isConstructorDeclaration(node.parent.parent) - && (ts.isParameterPropertyModifier(node.kind) || ts.isDeclarationName(node)); + function isConstructorParameterCompletion(node: Node): boolean { + return !!node.parent && isParameter(node.parent) && isConstructorDeclaration(node.parent.parent) + && (isParameterPropertyModifier(node.kind) || isDeclarationName(node)); } /** * Returns the immediate owning class declaration of a context token, * on the condition that one exists and that the context implies completion should be given. */ - function tryGetConstructorLikeCompletionContainer(contextToken: ts.Node): ts.ConstructorDeclaration | undefined { + function tryGetConstructorLikeCompletionContainer(contextToken: Node): ConstructorDeclaration | undefined { if (contextToken) { const parent = contextToken.parent; switch (contextToken.kind) { - case ts.SyntaxKind.OpenParenToken: - case ts.SyntaxKind.CommaToken: - return ts.isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined; + case SyntaxKind.OpenParenToken: + case SyntaxKind.CommaToken: + return isConstructorDeclaration(contextToken.parent) ? contextToken.parent : undefined; default: if (isConstructorParameterCompletion(contextToken)) { - return parent.parent as ts.ConstructorDeclaration; + return parent.parent as ConstructorDeclaration; } } } return undefined; } - function tryGetFunctionLikeBodyCompletionContainer(contextToken: ts.Node): ts.FunctionLikeDeclaration | undefined { + function tryGetFunctionLikeBodyCompletionContainer(contextToken: Node): FunctionLikeDeclaration | undefined { if (contextToken) { - let prev: ts.Node; - const container = ts.findAncestor(contextToken.parent, (node: ts.Node) => { - if (ts.isClassLike(node)) { + let prev: Node; + const container = findAncestor(contextToken.parent, (node: Node) => { + if (isClassLike(node)) { return "quit"; } - if (ts.isFunctionLikeDeclaration(node) && prev === node.body) { + if (isFunctionLikeDeclaration(node) && prev === node.body) { return true; } prev = node; return false; }); - return container && container as ts.FunctionLikeDeclaration; + return container && container as FunctionLikeDeclaration; } } - function tryGetContainingJsxElement(contextToken: ts.Node): ts.JsxOpeningLikeElement | undefined { + function tryGetContainingJsxElement(contextToken: Node): JsxOpeningLikeElement | undefined { if (contextToken) { const parent = contextToken.parent; switch (contextToken.kind) { - case ts.SyntaxKind.GreaterThanToken: // End of a type argument list - case ts.SyntaxKind.LessThanSlashToken: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.JsxAttributes: - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.JsxSpreadAttribute: - if (parent && (parent.kind === ts.SyntaxKind.JsxSelfClosingElement || parent.kind === ts.SyntaxKind.JsxOpeningElement)) { - if (contextToken.kind === ts.SyntaxKind.GreaterThanToken) { - const precedingToken = ts.findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined); - if (!(parent as ts.JsxOpeningLikeElement).typeArguments || (precedingToken && precedingToken.kind === ts.SyntaxKind.SlashToken)) break; + case SyntaxKind.GreaterThanToken: // End of a type argument list + case SyntaxKind.LessThanSlashToken: + case SyntaxKind.SlashToken: + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.JsxAttributes: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxSpreadAttribute: + if (parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) { + if (contextToken.kind === SyntaxKind.GreaterThanToken) { + const precedingToken = findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined); + if (!(parent as JsxOpeningLikeElement).typeArguments || (precedingToken && precedingToken.kind === SyntaxKind.SlashToken)) break; } - return parent as ts.JsxOpeningLikeElement; + return parent as JsxOpeningLikeElement; } - else if (parent.kind === ts.SyntaxKind.JsxAttribute) { + else if (parent.kind === SyntaxKind.JsxAttribute) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement // attributes: JsxAttributes // properties: NodeArray - return parent.parent.parent as ts.JsxOpeningLikeElement; + return parent.parent.parent as JsxOpeningLikeElement; } break; // The context token is the closing } or " of an attribute, which means // its parent is a JsxExpression, whose parent is a JsxAttribute, // whose parent is a JsxOpeningLikeElement - case ts.SyntaxKind.StringLiteral: - if (parent && ((parent.kind === ts.SyntaxKind.JsxAttribute) || (parent.kind === ts.SyntaxKind.JsxSpreadAttribute))) { + case SyntaxKind.StringLiteral: + if (parent && ((parent.kind === SyntaxKind.JsxAttribute) || (parent.kind === SyntaxKind.JsxSpreadAttribute))) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement // attributes: JsxAttributes // properties: NodeArray - return parent.parent.parent as ts.JsxOpeningLikeElement; + return parent.parent.parent as JsxOpeningLikeElement; } break; - case ts.SyntaxKind.CloseBraceToken: + case SyntaxKind.CloseBraceToken: if (parent && - parent.kind === ts.SyntaxKind.JsxExpression && - parent.parent && parent.parent.kind === ts.SyntaxKind.JsxAttribute) { + parent.kind === SyntaxKind.JsxExpression && + parent.parent && parent.parent.kind === SyntaxKind.JsxAttribute) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement // attributes: JsxAttributes // properties: NodeArray // each JsxAttribute can have initializer as JsxExpression - return parent.parent.parent.parent as ts.JsxOpeningLikeElement; + return parent.parent.parent.parent as JsxOpeningLikeElement; } - if (parent && parent.kind === ts.SyntaxKind.JsxSpreadAttribute) { + if (parent && parent.kind === SyntaxKind.JsxSpreadAttribute) { // Currently we parse JsxOpeningLikeElement as: // JsxOpeningLikeElement // attributes: JsxAttributes // properties: NodeArray - return parent.parent.parent as ts.JsxOpeningLikeElement; + return parent.parent.parent as JsxOpeningLikeElement; } break; @@ -3384,96 +3446,96 @@ function getCompletionData( /** * @returns true if we are certain that the currently edited location must define a new location; false otherwise. */ - function isSolelyIdentifierDefinitionLocation(contextToken: ts.Node): boolean { + function isSolelyIdentifierDefinitionLocation(contextToken: Node): boolean { const parent = contextToken.parent; const containingNodeKind = parent.kind; switch (contextToken.kind) { - case ts.SyntaxKind.CommaToken: - return containingNodeKind === ts.SyntaxKind.VariableDeclaration || + case SyntaxKind.CommaToken: + return containingNodeKind === SyntaxKind.VariableDeclaration || isVariableDeclarationListButNotTypeArgument(contextToken) || - containingNodeKind === ts.SyntaxKind.VariableStatement || - containingNodeKind === ts.SyntaxKind.EnumDeclaration || // enum a { foo, | + containingNodeKind === SyntaxKind.VariableStatement || + containingNodeKind === SyntaxKind.EnumDeclaration || // enum a { foo, | isFunctionLikeButNotConstructor(containingNodeKind) || - containingNodeKind === ts.SyntaxKind.InterfaceDeclaration || // interface A= contextToken.pos); - case ts.SyntaxKind.DotToken: - return containingNodeKind === ts.SyntaxKind.ArrayBindingPattern; // var [.| + case SyntaxKind.DotToken: + return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.| - case ts.SyntaxKind.ColonToken: - return containingNodeKind === ts.SyntaxKind.BindingElement; // var {x :html| + case SyntaxKind.ColonToken: + return containingNodeKind === SyntaxKind.BindingElement; // var {x :html| - case ts.SyntaxKind.OpenBracketToken: - return containingNodeKind === ts.SyntaxKind.ArrayBindingPattern; // var [x| + case SyntaxKind.OpenBracketToken: + return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [x| - case ts.SyntaxKind.OpenParenToken: - return containingNodeKind === ts.SyntaxKind.CatchClause || + case SyntaxKind.OpenParenToken: + return containingNodeKind === SyntaxKind.CatchClause || isFunctionLikeButNotConstructor(containingNodeKind); - case ts.SyntaxKind.OpenBraceToken: - return containingNodeKind === ts.SyntaxKind.EnumDeclaration; // enum a { | + case SyntaxKind.OpenBraceToken: + return containingNodeKind === SyntaxKind.EnumDeclaration; // enum a { | - case ts.SyntaxKind.LessThanToken: - return containingNodeKind === ts.SyntaxKind.ClassDeclaration || // class A< | - containingNodeKind === ts.SyntaxKind.ClassExpression || // var C = class D< | - containingNodeKind === ts.SyntaxKind.InterfaceDeclaration || // interface A< | - containingNodeKind === ts.SyntaxKind.TypeAliasDeclaration || // type List< | - ts.isFunctionLikeKind(containingNodeKind); + case SyntaxKind.LessThanToken: + return containingNodeKind === SyntaxKind.ClassDeclaration || // class A< | + containingNodeKind === SyntaxKind.ClassExpression || // var C = class D< | + containingNodeKind === SyntaxKind.InterfaceDeclaration || // interface A< | + containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< | + isFunctionLikeKind(containingNodeKind); - case ts.SyntaxKind.StaticKeyword: - return containingNodeKind === ts.SyntaxKind.PropertyDeclaration && !ts.isClassLike(parent.parent); + case SyntaxKind.StaticKeyword: + return containingNodeKind === SyntaxKind.PropertyDeclaration && !isClassLike(parent.parent); - case ts.SyntaxKind.DotDotDotToken: - return containingNodeKind === ts.SyntaxKind.Parameter || - (!!parent.parent && parent.parent.kind === ts.SyntaxKind.ArrayBindingPattern); // var [...z| + case SyntaxKind.DotDotDotToken: + return containingNodeKind === SyntaxKind.Parameter || + (!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z| - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - return containingNodeKind === ts.SyntaxKind.Parameter && !ts.isConstructorDeclaration(parent.parent); + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + return containingNodeKind === SyntaxKind.Parameter && !isConstructorDeclaration(parent.parent); - case ts.SyntaxKind.AsKeyword: - return containingNodeKind === ts.SyntaxKind.ImportSpecifier || - containingNodeKind === ts.SyntaxKind.ExportSpecifier || - containingNodeKind === ts.SyntaxKind.NamespaceImport; + case SyntaxKind.AsKeyword: + return containingNodeKind === SyntaxKind.ImportSpecifier || + containingNodeKind === SyntaxKind.ExportSpecifier || + containingNodeKind === SyntaxKind.NamespaceImport; - case ts.SyntaxKind.GetKeyword: - case ts.SyntaxKind.SetKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: return !isFromObjectTypeDeclaration(contextToken); - case ts.SyntaxKind.Identifier: - if (containingNodeKind === ts.SyntaxKind.ImportSpecifier && - contextToken === (parent as ts.ImportSpecifier).name && - (contextToken as ts.Identifier).text === "type" + case SyntaxKind.Identifier: + if (containingNodeKind === SyntaxKind.ImportSpecifier && + contextToken === (parent as ImportSpecifier).name && + (contextToken as Identifier).text === "type" ) { // import { type | } return false; } break; - case ts.SyntaxKind.ClassKeyword: - case ts.SyntaxKind.EnumKeyword: - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.VarKeyword: - case ts.SyntaxKind.ImportKeyword: - case ts.SyntaxKind.LetKeyword: - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.InferKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.VarKeyword: + case SyntaxKind.ImportKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.InferKeyword: return true; - case ts.SyntaxKind.TypeKeyword: + case SyntaxKind.TypeKeyword: // import { type foo| } - return containingNodeKind !== ts.SyntaxKind.ImportSpecifier; + return containingNodeKind !== SyntaxKind.ImportSpecifier; - case ts.SyntaxKind.AsteriskToken: - return ts.isFunctionLike(contextToken.parent) && !ts.isMethodDeclaration(contextToken.parent); + case SyntaxKind.AsteriskToken: + return isFunctionLike(contextToken.parent) && !isMethodDeclaration(contextToken.parent); } // If the previous token is keyword corresponding to class member completion keyword @@ -3487,8 +3549,8 @@ function getCompletionData( // - its modifier of the constructor parameter or // - its name of the parameter and not being edited // eg. constructor(a |<- this shouldnt show completion - if (!ts.isIdentifier(contextToken) || - ts.isParameterPropertyModifier(keywordForNode(contextToken)) || + if (!isIdentifier(contextToken) || + isParameterPropertyModifier(keywordForNode(contextToken)) || isCurrentlyEditingNode(contextToken)) { return false; } @@ -3496,71 +3558,71 @@ function getCompletionData( // Previous token may have been a keyword that was converted to an identifier. switch (keywordForNode(contextToken)) { - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.ClassKeyword: - case ts.SyntaxKind.ConstKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.EnumKeyword: - case ts.SyntaxKind.FunctionKeyword: - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.LetKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.StaticKeyword: - case ts.SyntaxKind.VarKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.ClassKeyword: + case SyntaxKind.ConstKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.FunctionKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.LetKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.StaticKeyword: + case SyntaxKind.VarKeyword: return true; - case ts.SyntaxKind.AsyncKeyword: - return ts.isPropertyDeclaration(contextToken.parent); + case SyntaxKind.AsyncKeyword: + return isPropertyDeclaration(contextToken.parent); } // If we are inside a class declaration, and `constructor` is totally not present, // but we request a completion manually at a whitespace... - const ancestorClassLike = ts.findAncestor(contextToken.parent, ts.isClassLike); + const ancestorClassLike = findAncestor(contextToken.parent, isClassLike); if (ancestorClassLike && contextToken === previousToken && isPreviousPropertyDeclarationTerminated(contextToken, position)) { return false; // Don't block completions. } - const ancestorPropertyDeclaraion = ts.getAncestor(contextToken.parent, ts.SyntaxKind.PropertyDeclaration); + const ancestorPropertyDeclaraion = getAncestor(contextToken.parent, SyntaxKind.PropertyDeclaration); // If we are inside a class declaration and typing `constructor` after property declaration... if (ancestorPropertyDeclaraion && contextToken !== previousToken - && ts.isClassLike(previousToken.parent.parent) + && isClassLike(previousToken.parent.parent) // And the cursor is at the token... && position <= previousToken.end) { // If we are sure that the previous property declaration is terminated according to newline or semicolon... if (isPreviousPropertyDeclarationTerminated(contextToken, previousToken.end)) { return false; // Don't block completions. } - else if (contextToken.kind !== ts.SyntaxKind.EqualsToken + else if (contextToken.kind !== SyntaxKind.EqualsToken // Should not block: `class C { blah = c/**/ }` // But should block: `class C { blah = somewhat c/**/ }` and `class C { blah: SomeType c/**/ }` - && (ts.isInitializedProperty(ancestorPropertyDeclaraion as ts.PropertyDeclaration) - || ts.hasType(ancestorPropertyDeclaraion))) { + && (isInitializedProperty(ancestorPropertyDeclaraion as PropertyDeclaration) + || hasType(ancestorPropertyDeclaraion))) { return true; } } - return ts.isDeclarationName(contextToken) - && !ts.isShorthandPropertyAssignment(contextToken.parent) - && !ts.isJsxAttribute(contextToken.parent) + return isDeclarationName(contextToken) + && !isShorthandPropertyAssignment(contextToken.parent) + && !isJsxAttribute(contextToken.parent) // Don't block completions if we're in `class C /**/`, because we're *past* the end of the identifier and might want to complete `extends`. // If `contextToken !== previousToken`, this is `class C ex/**/`. - && !(ts.isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end)); + && !(isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end)); } - function isPreviousPropertyDeclarationTerminated(contextToken: ts.Node, position: number) { - return contextToken.kind !== ts.SyntaxKind.EqualsToken && - (contextToken.kind === ts.SyntaxKind.SemicolonToken - || !ts.positionsAreOnSameLine(contextToken.end, position, sourceFile)); + function isPreviousPropertyDeclarationTerminated(contextToken: Node, position: number) { + return contextToken.kind !== SyntaxKind.EqualsToken && + (contextToken.kind === SyntaxKind.SemicolonToken + || !positionsAreOnSameLine(contextToken.end, position, sourceFile)); } - function isFunctionLikeButNotConstructor(kind: ts.SyntaxKind) { - return ts.isFunctionLikeKind(kind) && kind !== ts.SyntaxKind.Constructor; + function isFunctionLikeButNotConstructor(kind: SyntaxKind) { + return isFunctionLikeKind(kind) && kind !== SyntaxKind.Constructor; } - function isDotOfNumericLiteral(contextToken: ts.Node): boolean { - if (contextToken.kind === ts.SyntaxKind.NumericLiteral) { + function isDotOfNumericLiteral(contextToken: Node): boolean { + if (contextToken.kind === SyntaxKind.NumericLiteral) { const text = contextToken.getFullText(); return text.charAt(text.length - 1) === "."; } @@ -3568,9 +3630,9 @@ function getCompletionData( return false; } - function isVariableDeclarationListButNotTypeArgument(node: ts.Node): boolean { - return node.parent.kind === ts.SyntaxKind.VariableDeclarationList - && !ts.isPossiblyTypeArgumentPosition(node, sourceFile, typeChecker); + function isVariableDeclarationListButNotTypeArgument(node: Node): boolean { + return node.parent.kind === SyntaxKind.VariableDeclarationList + && !isPossiblyTypeArgumentPosition(node, sourceFile, typeChecker); } /** @@ -3579,22 +3641,22 @@ function getCompletionData( * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations * do not occur at the current position and have not otherwise been typed. */ - function filterObjectMembersList(contextualMemberSymbols: ts.Symbol[], existingMembers: readonly ts.Declaration[]): ts.Symbol[] { + function filterObjectMembersList(contextualMemberSymbols: Symbol[], existingMembers: readonly Declaration[]): Symbol[] { if (existingMembers.length === 0) { return contextualMemberSymbols; } - const membersDeclaredBySpreadAssignment = new ts.Set(); - const existingMemberNames = new ts.Set(); + const membersDeclaredBySpreadAssignment = new Set(); + const existingMemberNames = new Set<__String>(); for (const m of existingMembers) { // Ignore omitted expressions for missing members - if (m.kind !== ts.SyntaxKind.PropertyAssignment && - m.kind !== ts.SyntaxKind.ShorthandPropertyAssignment && - m.kind !== ts.SyntaxKind.BindingElement && - m.kind !== ts.SyntaxKind.MethodDeclaration && - m.kind !== ts.SyntaxKind.GetAccessor && - m.kind !== ts.SyntaxKind.SetAccessor && - m.kind !== ts.SyntaxKind.SpreadAssignment) { + if (m.kind !== SyntaxKind.PropertyAssignment && + m.kind !== SyntaxKind.ShorthandPropertyAssignment && + m.kind !== SyntaxKind.BindingElement && + m.kind !== SyntaxKind.MethodDeclaration && + m.kind !== SyntaxKind.GetAccessor && + m.kind !== SyntaxKind.SetAccessor && + m.kind !== SyntaxKind.SpreadAssignment) { continue; } @@ -3603,14 +3665,14 @@ function getCompletionData( continue; } - let existingName: ts.__String | undefined; + let existingName: __String | undefined; - if (ts.isSpreadAssignment(m)) { + if (isSpreadAssignment(m)) { setMembersDeclaredBySpreadAssignment(m, membersDeclaredBySpreadAssignment); } - else if (ts.isBindingElement(m) && m.propertyName) { + else if (isBindingElement(m) && m.propertyName) { // include only identifiers in completion list - if (m.propertyName.kind === ts.SyntaxKind.Identifier) { + if (m.propertyName.kind === SyntaxKind.Identifier) { existingName = m.propertyName.escapedText; } } @@ -3618,8 +3680,8 @@ function getCompletionData( // TODO: Account for computed property name // NOTE: if one only performs this step when m.name is an identifier, // things like '__proto__' are not filtered out. - const name = ts.getNameOfDeclaration(m); - existingName = name && ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined; + const name = getNameOfDeclaration(m); + existingName = name && isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined; } if (existingName !== undefined) { @@ -3633,11 +3695,11 @@ function getCompletionData( return filteredSymbols; } - function setMembersDeclaredBySpreadAssignment(declaration: ts.SpreadAssignment | ts.JsxSpreadAttribute, membersDeclaredBySpreadAssignment: ts.Set) { + function setMembersDeclaredBySpreadAssignment(declaration: SpreadAssignment | JsxSpreadAttribute, membersDeclaredBySpreadAssignment: Set) { const expression = declaration.expression; const symbol = typeChecker.getSymbolAtLocation(expression); const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression); - const properties = type && (type as ts.ObjectType).properties; + const properties = type && (type as ObjectType).properties; if (properties) { properties.forEach(property => { membersDeclaredBySpreadAssignment.add(property.name); @@ -3648,21 +3710,21 @@ function getCompletionData( // Set SortText to OptionalMember if it is an optional member function setSortTextToOptionalMember() { symbols.forEach(m => { - if (m.flags & ts.SymbolFlags.Optional) { - const symbolId = ts.getSymbolId(m); + if (m.flags & SymbolFlags.Optional) { + const symbolId = getSymbolId(m); symbolToSortTextMap[symbolId] = symbolToSortTextMap[symbolId] ?? SortText.OptionalMember; } }); } // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment - function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment: ts.Set, contextualMemberSymbols: ts.Symbol[]): void { + function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment: Set, contextualMemberSymbols: Symbol[]): void { if (membersDeclaredBySpreadAssignment.size === 0) { return; } for (const contextualMemberSymbol of contextualMemberSymbols) { if (membersDeclaredBySpreadAssignment.has(contextualMemberSymbol.name)) { - symbolToSortTextMap[ts.getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment; + symbolToSortTextMap[getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment; } } } @@ -3670,9 +3732,9 @@ function getCompletionData( function transformObjectLiteralMembersSortText(start: number): void { for (let i = start; i < symbols.length; i++) { const symbol = symbols[i]; - const symbolId = ts.getSymbolId(symbol); + const symbolId = getSymbolId(symbol); const origin = symbolToOriginInfoMap?.[i]; - const target = ts.getEmitScriptTarget(compilerOptions); + const target = getEmitScriptTarget(compilerOptions); const displayName = getCompletionEntryDisplayNameForSymbol( symbol, target, @@ -3692,14 +3754,14 @@ function getCompletionData( * * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags */ - function filterClassMembersList(baseSymbols: readonly ts.Symbol[], existingMembers: readonly ts.ClassElement[], currentClassElementModifierFlags: ts.ModifierFlags): ts.Symbol[] { - const existingMemberNames = new ts.Set(); + function filterClassMembersList(baseSymbols: readonly Symbol[], existingMembers: readonly ClassElement[], currentClassElementModifierFlags: ModifierFlags): Symbol[] { + const existingMemberNames = new Set<__String>(); for (const m of existingMembers) { // Ignore omitted expressions for missing members - if (m.kind !== ts.SyntaxKind.PropertyDeclaration && - m.kind !== ts.SyntaxKind.MethodDeclaration && - m.kind !== ts.SyntaxKind.GetAccessor && - m.kind !== ts.SyntaxKind.SetAccessor) { + if (m.kind !== SyntaxKind.PropertyDeclaration && + m.kind !== SyntaxKind.MethodDeclaration && + m.kind !== SyntaxKind.GetAccessor && + m.kind !== SyntaxKind.SetAccessor) { continue; } @@ -3709,16 +3771,16 @@ function getCompletionData( } // Dont filter member even if the name matches if it is declared private in the list - if (ts.hasEffectiveModifier(m, ts.ModifierFlags.Private)) { + if (hasEffectiveModifier(m, ModifierFlags.Private)) { continue; } // do not filter it out if the static presence doesnt match - if (ts.isStatic(m) !== !!(currentClassElementModifierFlags & ts.ModifierFlags.Static)) { + if (isStatic(m) !== !!(currentClassElementModifierFlags & ModifierFlags.Static)) { continue; } - const existingName = ts.getPropertyNameForPropertyNameNode(m.name!); + const existingName = getPropertyNameForPropertyNameNode(m.name!); if (existingName) { existingMemberNames.add(existingName); } @@ -3727,8 +3789,8 @@ function getCompletionData( return baseSymbols.filter(propertySymbol => !existingMemberNames.has(propertySymbol.escapedName) && !!propertySymbol.declarations && - !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & ts.ModifierFlags.Private) && - !(propertySymbol.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(propertySymbol.valueDeclaration))); + !(getDeclarationModifierFlagsFromSymbol(propertySymbol) & ModifierFlags.Private) && + !(propertySymbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(propertySymbol.valueDeclaration))); } /** @@ -3737,19 +3799,19 @@ function getCompletionData( * @returns Symbols to be suggested in a JSX element, barring those whose attributes * do not occur at the current position and have not otherwise been typed. */ - function filterJsxAttributes(symbols: ts.Symbol[], attributes: ts.NodeArray): ts.Symbol[] { - const seenNames = new ts.Set(); - const membersDeclaredBySpreadAssignment = new ts.Set(); + function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { + const seenNames = new Set<__String>(); + const membersDeclaredBySpreadAssignment = new Set(); for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (isCurrentlyEditingNode(attr)) { continue; } - if (attr.kind === ts.SyntaxKind.JsxAttribute) { + if (attr.kind === SyntaxKind.JsxAttribute) { seenNames.add(attr.name.escapedText); } - else if (ts.isJsxSpreadAttribute(attr)) { + else if (isJsxSpreadAttribute(attr)) { setMembersDeclaredBySpreadAssignment(attr, membersDeclaredBySpreadAssignment); } } @@ -3760,7 +3822,7 @@ function getCompletionData( return filteredSymbols; } - function isCurrentlyEditingNode(node: ts.Node): boolean { + function isCurrentlyEditingNode(node: Node): boolean { return node.getStart(sourceFile) <= position && position <= node.getEnd(); } } @@ -3769,20 +3831,20 @@ function getCompletionData( * Returns the immediate owning object literal or binding pattern of a context token, * on the condition that one exists and that the context implies completion should be given. */ -function tryGetObjectLikeCompletionContainer(contextToken: ts.Node | undefined): ts.ObjectLiteralExpression | ts.ObjectBindingPattern | undefined { +function tryGetObjectLikeCompletionContainer(contextToken: Node | undefined): ObjectLiteralExpression | ObjectBindingPattern | undefined { if (contextToken) { const { parent } = contextToken; switch (contextToken.kind) { - case ts.SyntaxKind.OpenBraceToken: // const x = { | - case ts.SyntaxKind.CommaToken: // const x = { a: 0, | - if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) { + case SyntaxKind.OpenBraceToken: // const x = { | + case SyntaxKind.CommaToken: // const x = { a: 0, | + if (isObjectLiteralExpression(parent) || isObjectBindingPattern(parent)) { return parent; } break; - case ts.SyntaxKind.AsteriskToken: - return ts.isMethodDeclaration(parent) ? ts.tryCast(parent.parent, ts.isObjectLiteralExpression) : undefined; - case ts.SyntaxKind.Identifier: - return (contextToken as ts.Identifier).text === "async" && ts.isShorthandPropertyAssignment(contextToken.parent) + case SyntaxKind.AsteriskToken: + return isMethodDeclaration(parent) ? tryCast(parent.parent, isObjectLiteralExpression) : undefined; + case SyntaxKind.Identifier: + return (contextToken as Identifier).text === "async" && isShorthandPropertyAssignment(contextToken.parent) ? contextToken.parent.parent : undefined; } } @@ -3790,30 +3852,30 @@ function tryGetObjectLikeCompletionContainer(contextToken: ts.Node | undefined): return undefined; } -function getRelevantTokens(position: number, sourceFile: ts.SourceFile): { contextToken: ts.Node, previousToken: ts.Node } | { contextToken: undefined, previousToken: undefined } { - const previousToken = ts.findPrecedingToken(position, sourceFile); - if (previousToken && position <= previousToken.end && (ts.isMemberName(previousToken) || ts.isKeyword(previousToken.kind))) { - const contextToken = ts.findPrecedingToken(previousToken.getFullStart(), sourceFile, /*startNode*/ undefined)!; // TODO: GH#18217 +function getRelevantTokens(position: number, sourceFile: SourceFile): { contextToken: Node, previousToken: Node } | { contextToken: undefined, previousToken: undefined } { + const previousToken = findPrecedingToken(position, sourceFile); + if (previousToken && position <= previousToken.end && (isMemberName(previousToken) || isKeyword(previousToken.kind))) { + const contextToken = findPrecedingToken(previousToken.getFullStart(), sourceFile, /*startNode*/ undefined)!; // TODO: GH#18217 return { contextToken, previousToken }; } - return { contextToken: previousToken as ts.Node, previousToken: previousToken as ts.Node }; + return { contextToken: previousToken as Node, previousToken: previousToken as Node }; } -function getAutoImportSymbolFromCompletionEntryData(name: string, data: ts.CompletionEntryData, program: ts.Program, host: ts.LanguageServiceHost): { symbol: ts.Symbol, origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport } | undefined { +function getAutoImportSymbolFromCompletionEntryData(name: string, data: CompletionEntryData, program: Program, host: LanguageServiceHost): { symbol: Symbol, origin: SymbolOriginInfoExport | SymbolOriginInfoResolvedExport } | undefined { const containingProgram = data.isPackageJsonImport ? host.getPackageJsonAutoImportProvider!()! : program; const checker = containingProgram.getTypeChecker(); const moduleSymbol = data.ambientModuleName ? checker.tryFindAmbientModule(data.ambientModuleName) : - data.fileName ? checker.getMergedSymbol(ts.Debug.checkDefined(containingProgram.getSourceFile(data.fileName)).symbol) : + data.fileName ? checker.getMergedSymbol(Debug.checkDefined(containingProgram.getSourceFile(data.fileName)).symbol) : undefined; if (!moduleSymbol) return undefined; - let symbol = data.exportName === ts.InternalSymbolName.ExportEquals + let symbol = data.exportName === InternalSymbolName.ExportEquals ? checker.resolveExternalModuleSymbol(moduleSymbol) : checker.tryGetMemberInModuleExportsAndProperties(data.exportName, moduleSymbol); if (!symbol) return undefined; - const isDefaultExport = data.exportName === ts.InternalSymbolName.Default; - symbol = isDefaultExport && ts.getLocalSymbolForExportDefault(symbol) || symbol; + const isDefaultExport = data.exportName === InternalSymbolName.Default; + symbol = isDefaultExport && getLocalSymbolForExportDefault(symbol) || symbol; return { symbol, origin: completionEntryDataToSymbolOriginInfo(data, name, moduleSymbol) }; } @@ -3822,8 +3884,8 @@ interface CompletionEntryDisplayNameForSymbol { readonly needsConvertPropertyAccess: boolean; } function getCompletionEntryDisplayNameForSymbol( - symbol: ts.Symbol, - target: ts.ScriptTarget, + symbol: Symbol, + target: ScriptTarget, origin: SymbolOriginInfo | undefined, kind: CompletionKind, jsxIdentifierExpected: boolean, @@ -3832,14 +3894,14 @@ function getCompletionEntryDisplayNameForSymbol( if (name === undefined // If the symbol is external module, don't show it in the completion list // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there) - || symbol.flags & ts.SymbolFlags.Module && ts.isSingleOrDoubleQuote(name.charCodeAt(0)) + || symbol.flags & SymbolFlags.Module && isSingleOrDoubleQuote(name.charCodeAt(0)) // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@" - || ts.isKnownSymbol(symbol)) { + || isKnownSymbol(symbol)) { return undefined; } const validNameResult: CompletionEntryDisplayNameForSymbol = { name, needsConvertPropertyAccess: false }; - if (ts.isIdentifierText(name, target, jsxIdentifierExpected ? ts.LanguageVariant.JSX : ts.LanguageVariant.Standard) || symbol.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { + if (isIdentifierText(name, target, jsxIdentifierExpected ? LanguageVariant.JSX : LanguageVariant.Standard) || symbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { return validNameResult; } switch (kind) { @@ -3851,54 +3913,54 @@ function getCompletionEntryDisplayNameForSymbol( case CompletionKind.PropertyAccess: case CompletionKind.Global: // For a 'this.' completion it will be in a global context, but may have a non-identifier name. // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547 - return name.charCodeAt(0) === ts.CharacterCodes.space ? undefined : { name, needsConvertPropertyAccess: true }; + return name.charCodeAt(0) === CharacterCodes.space ? undefined : { name, needsConvertPropertyAccess: true }; case CompletionKind.None: case CompletionKind.String: return validNameResult; default: - ts.Debug.assertNever(kind); + Debug.assertNever(kind); } } // A cache of completion entries for keywords, these do not change between sessions -const _keywordCompletions: ts.CompletionEntry[][] = []; -const allKeywordsCompletions: () => readonly ts.CompletionEntry[] = ts.memoize(() => { - const res: ts.CompletionEntry[] = []; - for (let i = ts.SyntaxKind.FirstKeyword; i <= ts.SyntaxKind.LastKeyword; i++) { +const _keywordCompletions: CompletionEntry[][] = []; +const allKeywordsCompletions: () => readonly CompletionEntry[] = memoize(() => { + const res: CompletionEntry[] = []; + for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) { res.push({ - name: ts.tokenToString(i)!, - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, + name: tokenToString(i)!, + kind: ScriptElementKind.keyword, + kindModifiers: ScriptElementKindModifier.none, sortText: SortText.GlobalsOrKeywords }); } return res; }); -function getKeywordCompletions(keywordFilter: KeywordCompletionFilters, filterOutTsOnlyKeywords: boolean): readonly ts.CompletionEntry[] { +function getKeywordCompletions(keywordFilter: KeywordCompletionFilters, filterOutTsOnlyKeywords: boolean): readonly CompletionEntry[] { if (!filterOutTsOnlyKeywords) return getTypescriptKeywordCompletions(keywordFilter); const index = keywordFilter + KeywordCompletionFilters.Last + 1; return _keywordCompletions[index] || (_keywordCompletions[index] = getTypescriptKeywordCompletions(keywordFilter) - .filter(entry => !isTypeScriptOnlyKeyword(ts.stringToToken(entry.name)!)) + .filter(entry => !isTypeScriptOnlyKeyword(stringToToken(entry.name)!)) ); } -function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters): readonly ts.CompletionEntry[] { +function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters): readonly CompletionEntry[] { return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => { - const kind = ts.stringToToken(entry.name)!; + const kind = stringToToken(entry.name)!; switch (keywordFilter) { case KeywordCompletionFilters.None: return false; case KeywordCompletionFilters.All: return isFunctionLikeBodyKeyword(kind) - || kind === ts.SyntaxKind.DeclareKeyword - || kind === ts.SyntaxKind.ModuleKeyword - || kind === ts.SyntaxKind.TypeKeyword - || kind === ts.SyntaxKind.NamespaceKeyword - || kind === ts.SyntaxKind.AbstractKeyword - || ts.isTypeKeyword(kind) && kind !== ts.SyntaxKind.UndefinedKeyword; + || kind === SyntaxKind.DeclareKeyword + || kind === SyntaxKind.ModuleKeyword + || kind === SyntaxKind.TypeKeyword + || kind === SyntaxKind.NamespaceKeyword + || kind === SyntaxKind.AbstractKeyword + || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword; case KeywordCompletionFilters.FunctionLikeBodyKeywords: return isFunctionLikeBodyKeyword(kind); case KeywordCompletionFilters.ClassElementKeywords: @@ -3906,91 +3968,91 @@ function getTypescriptKeywordCompletions(keywordFilter: KeywordCompletionFilters case KeywordCompletionFilters.InterfaceElementKeywords: return isInterfaceOrTypeLiteralCompletionKeyword(kind); case KeywordCompletionFilters.ConstructorParameterKeywords: - return ts.isParameterPropertyModifier(kind); + return isParameterPropertyModifier(kind); case KeywordCompletionFilters.TypeAssertionKeywords: - return ts.isTypeKeyword(kind) || kind === ts.SyntaxKind.ConstKeyword; + return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword; case KeywordCompletionFilters.TypeKeywords: - return ts.isTypeKeyword(kind); + return isTypeKeyword(kind); case KeywordCompletionFilters.TypeKeyword: - return kind === ts.SyntaxKind.TypeKeyword; + return kind === SyntaxKind.TypeKeyword; default: - return ts.Debug.assertNever(keywordFilter); + return Debug.assertNever(keywordFilter); } })); } -function isTypeScriptOnlyKeyword(kind: ts.SyntaxKind) { +function isTypeScriptOnlyKeyword(kind: SyntaxKind) { switch (kind) { - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.AnyKeyword: - case ts.SyntaxKind.BigIntKeyword: - case ts.SyntaxKind.BooleanKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.EnumKeyword: - case ts.SyntaxKind.GlobalKeyword: - case ts.SyntaxKind.ImplementsKeyword: - case ts.SyntaxKind.InferKeyword: - case ts.SyntaxKind.InterfaceKeyword: - case ts.SyntaxKind.IsKeyword: - case ts.SyntaxKind.KeyOfKeyword: - case ts.SyntaxKind.ModuleKeyword: - case ts.SyntaxKind.NamespaceKeyword: - case ts.SyntaxKind.NeverKeyword: - case ts.SyntaxKind.NumberKeyword: - case ts.SyntaxKind.ObjectKeyword: - case ts.SyntaxKind.OverrideKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.ReadonlyKeyword: - case ts.SyntaxKind.StringKeyword: - case ts.SyntaxKind.SymbolKeyword: - case ts.SyntaxKind.TypeKeyword: - case ts.SyntaxKind.UniqueKeyword: - case ts.SyntaxKind.UnknownKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.BigIntKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.EnumKeyword: + case SyntaxKind.GlobalKeyword: + case SyntaxKind.ImplementsKeyword: + case SyntaxKind.InferKeyword: + case SyntaxKind.InterfaceKeyword: + case SyntaxKind.IsKeyword: + case SyntaxKind.KeyOfKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.ObjectKeyword: + case SyntaxKind.OverrideKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.UniqueKeyword: + case SyntaxKind.UnknownKeyword: return true; default: return false; } } -function isInterfaceOrTypeLiteralCompletionKeyword(kind: ts.SyntaxKind): boolean { - return kind === ts.SyntaxKind.ReadonlyKeyword; +function isInterfaceOrTypeLiteralCompletionKeyword(kind: SyntaxKind): boolean { + return kind === SyntaxKind.ReadonlyKeyword; } -function isClassMemberCompletionKeyword(kind: ts.SyntaxKind) { +function isClassMemberCompletionKeyword(kind: SyntaxKind) { switch (kind) { - case ts.SyntaxKind.AbstractKeyword: - case ts.SyntaxKind.AccessorKeyword: - case ts.SyntaxKind.ConstructorKeyword: - case ts.SyntaxKind.GetKeyword: - case ts.SyntaxKind.SetKeyword: - case ts.SyntaxKind.AsyncKeyword: - case ts.SyntaxKind.DeclareKeyword: - case ts.SyntaxKind.OverrideKeyword: + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AccessorKeyword: + case SyntaxKind.ConstructorKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.OverrideKeyword: return true; default: - return ts.isClassMemberModifier(kind); + return isClassMemberModifier(kind); } } -function isFunctionLikeBodyKeyword(kind: ts.SyntaxKind) { - return kind === ts.SyntaxKind.AsyncKeyword - || kind === ts.SyntaxKind.AwaitKeyword - || kind === ts.SyntaxKind.AsKeyword - || kind === ts.SyntaxKind.SatisfiesKeyword - || kind === ts.SyntaxKind.TypeKeyword - || !ts.isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); +function isFunctionLikeBodyKeyword(kind: SyntaxKind) { + return kind === SyntaxKind.AsyncKeyword + || kind === SyntaxKind.AwaitKeyword + || kind === SyntaxKind.AsKeyword + || kind === SyntaxKind.SatisfiesKeyword + || kind === SyntaxKind.TypeKeyword + || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind); } -function keywordForNode(node: ts.Node): ts.SyntaxKind { - return ts.isIdentifier(node) ? node.originalKeywordKind || ts.SyntaxKind.Unknown : node.kind; +function keywordForNode(node: Node): SyntaxKind { + return isIdentifier(node) ? node.originalKeywordKind || SyntaxKind.Unknown : node.kind; } function getContextualKeywords( - contextToken: ts.Node | undefined, + contextToken: Node | undefined, position: number, -): readonly ts.CompletionEntry[] { +): readonly CompletionEntry[] { const entries = []; /** * An `AssertClause` can come after an import declaration: @@ -4005,13 +4067,13 @@ function getContextualKeywords( const parent = contextToken.parent; const tokenLine = file.getLineAndCharacterOfPosition(contextToken.end).line; const currentLine = file.getLineAndCharacterOfPosition(position).line; - if ((ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent) && parent.moduleSpecifier) + if ((isImportDeclaration(parent) || isExportDeclaration(parent) && parent.moduleSpecifier) && contextToken === parent.moduleSpecifier && tokenLine === currentLine) { entries.push({ - name: ts.tokenToString(ts.SyntaxKind.AssertKeyword)!, - kind: ts.ScriptElementKind.keyword, - kindModifiers: ts.ScriptElementKindModifier.none, + name: tokenToString(SyntaxKind.AssertKeyword)!, + kind: ScriptElementKind.keyword, + kindModifiers: ScriptElementKindModifier.none, sortText: SortText.GlobalsOrKeywords, }); } @@ -4020,85 +4082,85 @@ function getContextualKeywords( } /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */ -function getJsDocTagAtPosition(node: ts.Node, position: number): ts.JSDocTag | undefined { - return ts.findAncestor(node, n => - ts.isJSDocTag(n) && ts.rangeContainsPosition(n, position) ? true : - ts.isJSDoc(n) ? "quit" : false) as ts.JSDocTag | undefined; +function getJsDocTagAtPosition(node: Node, position: number): JSDocTag | undefined { + return findAncestor(node, n => + isJSDocTag(n) && rangeContainsPosition(n, position) ? true : + isJSDoc(n) ? "quit" : false) as JSDocTag | undefined; } /** @internal */ -export function getPropertiesForObjectExpression(contextualType: ts.Type, completionsType: ts.Type | undefined, obj: ts.ObjectLiteralExpression | ts.JsxAttributes, checker: ts.TypeChecker): ts.Symbol[] { +export function getPropertiesForObjectExpression(contextualType: Type, completionsType: Type | undefined, obj: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker): Symbol[] { const hasCompletionsType = completionsType && completionsType !== contextualType; - const type = hasCompletionsType && !(completionsType.flags & ts.TypeFlags.AnyOrUnknown) + const type = hasCompletionsType && !(completionsType.flags & TypeFlags.AnyOrUnknown) ? checker.getUnionType([contextualType, completionsType]) : contextualType; const properties = getApparentProperties(type, obj, checker); return type.isClass() && containsNonPublicProperties(properties) ? [] : - hasCompletionsType ? ts.filter(properties, hasDeclarationOtherThanSelf) : properties; + hasCompletionsType ? filter(properties, hasDeclarationOtherThanSelf) : properties; // Filter out members whose only declaration is the object literal itself to avoid // self-fulfilling completions like: // // function f(x: T) {} // f({ abc/**/: "" }) // `abc` is a member of `T` but only because it declares itself - function hasDeclarationOtherThanSelf(member: ts.Symbol) { - if (!ts.length(member.declarations)) return true; - return ts.some(member.declarations, decl => decl.parent !== obj); + function hasDeclarationOtherThanSelf(member: Symbol) { + if (!length(member.declarations)) return true; + return some(member.declarations, decl => decl.parent !== obj); } } -function getApparentProperties(type: ts.Type, node: ts.ObjectLiteralExpression | ts.JsxAttributes, checker: ts.TypeChecker) { +function getApparentProperties(type: Type, node: ObjectLiteralExpression | JsxAttributes, checker: TypeChecker) { if (!type.isUnion()) return type.getApparentProperties(); - return checker.getAllPossiblePropertiesOfTypes(ts.filter(type.types, memberType => - !(memberType.flags & ts.TypeFlags.Primitive + return checker.getAllPossiblePropertiesOfTypes(filter(type.types, memberType => + !(memberType.flags & TypeFlags.Primitive || checker.isArrayLikeType(memberType) || checker.isTypeInvalidDueToUnionDiscriminant(memberType, node) - || ts.typeHasCallOrConstructSignatures(memberType, checker) + || typeHasCallOrConstructSignatures(memberType, checker) || memberType.isClass() && containsNonPublicProperties(memberType.getApparentProperties())))); } -function containsNonPublicProperties(props: ts.Symbol[]) { - return ts.some(props, p => !!(ts.getDeclarationModifierFlagsFromSymbol(p) & ts.ModifierFlags.NonPublicAccessibilityModifier)); +function containsNonPublicProperties(props: Symbol[]) { + return some(props, p => !!(getDeclarationModifierFlagsFromSymbol(p) & ModifierFlags.NonPublicAccessibilityModifier)); } /** * Gets all properties on a type, but if that type is a union of several types, * excludes array-like types or callable/constructable types. */ -function getPropertiesForCompletion(type: ts.Type, checker: ts.TypeChecker): ts.Symbol[] { +function getPropertiesForCompletion(type: Type, checker: TypeChecker): Symbol[] { return type.isUnion() - ? ts.Debug.checkEachDefined(checker.getAllPossiblePropertiesOfTypes(type.types), "getAllPossiblePropertiesOfTypes() should all be defined") - : ts.Debug.checkEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); + ? Debug.checkEachDefined(checker.getAllPossiblePropertiesOfTypes(type.types), "getAllPossiblePropertiesOfTypes() should all be defined") + : Debug.checkEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined"); } /** * Returns the immediate owning class declaration of a context token, * on the condition that one exists and that the context implies completion should be given. */ -function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: ts.SourceFile, contextToken: ts.Node | undefined, location: ts.Node, position: number): ts.ObjectTypeDeclaration | undefined { +function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, contextToken: Node | undefined, location: Node, position: number): ObjectTypeDeclaration | undefined { // class c { method() { } | method2() { } } switch (location.kind) { - case ts.SyntaxKind.SyntaxList: - return ts.tryCast(location.parent, ts.isObjectTypeDeclaration); - case ts.SyntaxKind.EndOfFileToken: - const cls = ts.tryCast(ts.lastOrUndefined(ts.cast(location.parent, ts.isSourceFile).statements), ts.isObjectTypeDeclaration); - if (cls && !ts.findChildOfKind(cls, ts.SyntaxKind.CloseBraceToken, sourceFile)) { + case SyntaxKind.SyntaxList: + return tryCast(location.parent, isObjectTypeDeclaration); + case SyntaxKind.EndOfFileToken: + const cls = tryCast(lastOrUndefined(cast(location.parent, isSourceFile).statements), isObjectTypeDeclaration); + if (cls && !findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)) { return cls; } break; - case ts.SyntaxKind.Identifier: { - const originalKeywordKind = (location as ts.Identifier).originalKeywordKind; - if (originalKeywordKind && ts.isKeyword(originalKeywordKind)) { + case SyntaxKind.Identifier: { + const originalKeywordKind = (location as Identifier).originalKeywordKind; + if (originalKeywordKind && isKeyword(originalKeywordKind)) { return undefined; } // class c { public prop = c| } - if (ts.isPropertyDeclaration(location.parent) && location.parent.initializer === location) { + if (isPropertyDeclaration(location.parent) && location.parent.initializer === location) { return undefined; } // class c extends React.Component { a: () => 1\n compon| } if (isFromObjectTypeDeclaration(location)) { - return ts.findAncestor(location, ts.isObjectTypeDeclaration); + return findAncestor(location, isObjectTypeDeclaration); } } } @@ -4106,54 +4168,54 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: ts.SourceFil if (!contextToken) return undefined; // class C { blah; constructor/**/ } and so on - if (location.kind === ts.SyntaxKind.ConstructorKeyword + if (location.kind === SyntaxKind.ConstructorKeyword // class C { blah \n constructor/**/ } - || (ts.isIdentifier(contextToken) && ts.isPropertyDeclaration(contextToken.parent) && ts.isClassLike(location))) { - return ts.findAncestor(contextToken, ts.isClassLike) as ts.ObjectTypeDeclaration; + || (isIdentifier(contextToken) && isPropertyDeclaration(contextToken.parent) && isClassLike(location))) { + return findAncestor(contextToken, isClassLike) as ObjectTypeDeclaration; } switch (contextToken.kind) { - case ts.SyntaxKind.EqualsToken: // class c { public prop = | /* global completions */ } + case SyntaxKind.EqualsToken: // class c { public prop = | /* global completions */ } return undefined; - case ts.SyntaxKind.SemicolonToken: // class c {getValue(): number; | } - case ts.SyntaxKind.CloseBraceToken: // class c { method() { } | } + case SyntaxKind.SemicolonToken: // class c {getValue(): number; | } + case SyntaxKind.CloseBraceToken: // class c { method() { } | } // class c { method() { } b| } - return isFromObjectTypeDeclaration(location) && (location.parent as ts.ClassElement | ts.TypeElement).name === location - ? location.parent.parent as ts.ObjectTypeDeclaration - : ts.tryCast(location, ts.isObjectTypeDeclaration); - case ts.SyntaxKind.OpenBraceToken: // class c { | - case ts.SyntaxKind.CommaToken: // class c {getValue(): number, | } - return ts.tryCast(contextToken.parent, ts.isObjectTypeDeclaration); + return isFromObjectTypeDeclaration(location) && (location.parent as ClassElement | TypeElement).name === location + ? location.parent.parent as ObjectTypeDeclaration + : tryCast(location, isObjectTypeDeclaration); + case SyntaxKind.OpenBraceToken: // class c { | + case SyntaxKind.CommaToken: // class c {getValue(): number, | } + return tryCast(contextToken.parent, isObjectTypeDeclaration); default: if (!isFromObjectTypeDeclaration(contextToken)) { // class c extends React.Component { a: () => 1\n| } - if (ts.getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== ts.getLineAndCharacterOfPosition(sourceFile, position).line && ts.isObjectTypeDeclaration(location)) { + if (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line && isObjectTypeDeclaration(location)) { return location; } return undefined; } - const isValidKeyword = ts.isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || contextToken.kind === ts.SyntaxKind.AsteriskToken || ts.isIdentifier(contextToken) && isValidKeyword(ts.stringToToken(contextToken.text)!)) // TODO: GH#18217 - ? contextToken.parent.parent as ts.ObjectTypeDeclaration : undefined; + const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; + return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217 + ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } } -function tryGetTypeLiteralNode(node: ts.Node): ts.TypeLiteralNode | undefined { +function tryGetTypeLiteralNode(node: Node): TypeLiteralNode | undefined { if (!node) return undefined; const parent = node.parent; switch (node.kind) { - case ts.SyntaxKind.OpenBraceToken: - if (ts.isTypeLiteralNode(parent)) { + case SyntaxKind.OpenBraceToken: + if (isTypeLiteralNode(parent)) { return parent; } break; - case ts.SyntaxKind.SemicolonToken: - case ts.SyntaxKind.CommaToken: - case ts.SyntaxKind.Identifier: - if (parent.kind === ts.SyntaxKind.PropertySignature && ts.isTypeLiteralNode(parent.parent)) { + case SyntaxKind.SemicolonToken: + case SyntaxKind.CommaToken: + case SyntaxKind.Identifier: + if (parent.kind === SyntaxKind.PropertySignature && isTypeLiteralNode(parent.parent)) { return parent.parent; } break; @@ -4162,10 +4224,10 @@ function tryGetTypeLiteralNode(node: ts.Node): ts.TypeLiteralNode | undefined { return undefined; } -function getConstraintOfTypeArgumentProperty(node: ts.Node, checker: ts.TypeChecker): ts.Type | undefined { +function getConstraintOfTypeArgumentProperty(node: Node, checker: TypeChecker): Type | undefined { if (!node) return undefined; - if (ts.isTypeNode(node) && ts.isTypeReferenceType(node.parent)) { + if (isTypeNode(node) && isTypeReferenceType(node.parent)) { return checker.getTypeArgumentConstraint(node); } @@ -4173,21 +4235,21 @@ function getConstraintOfTypeArgumentProperty(node: ts.Node, checker: ts.TypeChec if (!t) return undefined; switch (node.kind) { - case ts.SyntaxKind.PropertySignature: + case SyntaxKind.PropertySignature: return checker.getTypeOfPropertyOfContextualType(t, node.symbol.escapedName); - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.TypeLiteral: + case SyntaxKind.UnionType: return t; } } // TODO: GH#19856 Would like to return `node is Node & { parent: (ClassElement | TypeElement) & { parent: ObjectTypeDeclaration } }` but then compilation takes > 10 minutes -function isFromObjectTypeDeclaration(node: ts.Node): boolean { - return node.parent && ts.isClassOrTypeElement(node.parent) && ts.isObjectTypeDeclaration(node.parent.parent); +function isFromObjectTypeDeclaration(node: Node): boolean { + return node.parent && isClassOrTypeElement(node.parent) && isObjectTypeDeclaration(node.parent.parent); } -function isValidTrigger(sourceFile: ts.SourceFile, triggerCharacter: ts.CompletionsTriggerCharacter, contextToken: ts.Node | undefined, position: number): boolean { +function isValidTrigger(sourceFile: SourceFile, triggerCharacter: CompletionsTriggerCharacter, contextToken: Node | undefined, position: number): boolean { switch (triggerCharacter) { case ".": case "@": @@ -4196,61 +4258,61 @@ function isValidTrigger(sourceFile: ts.SourceFile, triggerCharacter: ts.Completi case "'": case "`": // Only automatically bring up completions if this is an opening quote. - return !!contextToken && ts.isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1; + return !!contextToken && isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1; case "#": - return !!contextToken && ts.isPrivateIdentifier(contextToken) && !!ts.getContainingClass(contextToken); + return !!contextToken && isPrivateIdentifier(contextToken) && !!getContainingClass(contextToken); case "<": // Opening JSX tag - return !!contextToken && contextToken.kind === ts.SyntaxKind.LessThanToken && (!ts.isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent)); + return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent)); case "/": - return !!contextToken && (ts.isStringLiteralLike(contextToken) - ? !!ts.tryGetImportFromModuleSpecifier(contextToken) - : contextToken.kind === ts.SyntaxKind.SlashToken && ts.isJsxClosingElement(contextToken.parent)); + return !!contextToken && (isStringLiteralLike(contextToken) + ? !!tryGetImportFromModuleSpecifier(contextToken) + : contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent)); case " ": - return !!contextToken && ts.isImportKeyword(contextToken) && contextToken.parent.kind === ts.SyntaxKind.SourceFile; + return !!contextToken && isImportKeyword(contextToken) && contextToken.parent.kind === SyntaxKind.SourceFile; default: - return ts.Debug.assertNever(triggerCharacter); + return Debug.assertNever(triggerCharacter); } } -function binaryExpressionMayBeOpenTag({ left }: ts.BinaryExpression): boolean { - return ts.nodeIsMissing(left); +function binaryExpressionMayBeOpenTag({ left }: BinaryExpression): boolean { + return nodeIsMissing(left); } /** Determines if a type is exactly the same type resolved by the global 'self', 'global', or 'globalThis'. */ -function isProbablyGlobalType(type: ts.Type, sourceFile: ts.SourceFile, checker: ts.TypeChecker) { +function isProbablyGlobalType(type: Type, sourceFile: SourceFile, checker: TypeChecker) { // The type of `self` and `window` is the same in lib.dom.d.ts, but `window` does not exist in // lib.webworker.d.ts, so checking against `self` is also a check against `window` when it exists. - const selfSymbol = checker.resolveName("self", /*location*/ undefined, ts.SymbolFlags.Value, /*excludeGlobals*/ false); + const selfSymbol = checker.resolveName("self", /*location*/ undefined, SymbolFlags.Value, /*excludeGlobals*/ false); if (selfSymbol && checker.getTypeOfSymbolAtLocation(selfSymbol, sourceFile) === type) { return true; } - const globalSymbol = checker.resolveName("global", /*location*/ undefined, ts.SymbolFlags.Value, /*excludeGlobals*/ false); + const globalSymbol = checker.resolveName("global", /*location*/ undefined, SymbolFlags.Value, /*excludeGlobals*/ false); if (globalSymbol && checker.getTypeOfSymbolAtLocation(globalSymbol, sourceFile) === type) { return true; } - const globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, ts.SymbolFlags.Value, /*excludeGlobals*/ false); + const globalThisSymbol = checker.resolveName("globalThis", /*location*/ undefined, SymbolFlags.Value, /*excludeGlobals*/ false); if (globalThisSymbol && checker.getTypeOfSymbolAtLocation(globalThisSymbol, sourceFile) === type) { return true; } return false; } -function isStaticProperty(symbol: ts.Symbol) { - return !!(symbol.valueDeclaration && ts.getEffectiveModifierFlags(symbol.valueDeclaration) & ts.ModifierFlags.Static && ts.isClassLike(symbol.valueDeclaration.parent)); +function isStaticProperty(symbol: Symbol) { + return !!(symbol.valueDeclaration && getEffectiveModifierFlags(symbol.valueDeclaration) & ModifierFlags.Static && isClassLike(symbol.valueDeclaration.parent)); } -function tryGetObjectLiteralContextualType(node: ts.ObjectLiteralExpression, typeChecker: ts.TypeChecker) { +function tryGetObjectLiteralContextualType(node: ObjectLiteralExpression, typeChecker: TypeChecker) { const type = typeChecker.getContextualType(node); if (type) { return type; } - const parent = ts.walkUpParenthesizedExpressions(node.parent); - if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && node === parent.left) { + const parent = walkUpParenthesizedExpressions(node.parent); + if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken && node === parent.left) { // Object literal is assignment pattern: ({ | } = x) return typeChecker.getTypeAtLocation(parent); } - if (ts.isExpression(parent)) { + if (isExpression(parent)) { // f(() => (({ | }))); return typeChecker.getContextualType(parent); } @@ -4259,49 +4321,49 @@ function tryGetObjectLiteralContextualType(node: ts.ObjectLiteralExpression, typ interface ImportStatementCompletionInfo { isKeywordOnlyCompletion: boolean; - keywordCompletion: ts.TokenSyntaxKind | undefined; + keywordCompletion: TokenSyntaxKind | undefined; isNewIdentifierLocation: boolean; isTopLevelTypeOnly: boolean; couldBeTypeOnlyImportSpecifier: boolean; - replacementSpan: ts.TextSpan | undefined; + replacementSpan: TextSpan | undefined; } -function getImportStatementCompletionInfo(contextToken: ts.Node): ImportStatementCompletionInfo { - let keywordCompletion: ts.TokenSyntaxKind | undefined; +function getImportStatementCompletionInfo(contextToken: Node): ImportStatementCompletionInfo { + let keywordCompletion: TokenSyntaxKind | undefined; let isKeywordOnlyCompletion = false; const candidate = getCandidate(); return { isKeywordOnlyCompletion, keywordCompletion, - isNewIdentifierLocation: !!(candidate || keywordCompletion === ts.SyntaxKind.TypeKeyword), - isTopLevelTypeOnly: !!ts.tryCast(candidate, ts.isImportDeclaration)?.importClause?.isTypeOnly || !!ts.tryCast(candidate, ts.isImportEqualsDeclaration)?.isTypeOnly, + isNewIdentifierLocation: !!(candidate || keywordCompletion === SyntaxKind.TypeKeyword), + isTopLevelTypeOnly: !!tryCast(candidate, isImportDeclaration)?.importClause?.isTypeOnly || !!tryCast(candidate, isImportEqualsDeclaration)?.isTypeOnly, couldBeTypeOnlyImportSpecifier: !!candidate && couldBeTypeOnlyImportSpecifier(candidate, contextToken), replacementSpan: getSingleLineReplacementSpanForImportCompletionNode(candidate), }; function getCandidate() { const parent = contextToken.parent; - if (ts.isImportEqualsDeclaration(parent)) { - keywordCompletion = contextToken.kind === ts.SyntaxKind.TypeKeyword ? undefined : ts.SyntaxKind.TypeKeyword; + if (isImportEqualsDeclaration(parent)) { + keywordCompletion = contextToken.kind === SyntaxKind.TypeKeyword ? undefined : SyntaxKind.TypeKeyword; return isModuleSpecifierMissingOrEmpty(parent.moduleReference) ? parent : undefined; } if (couldBeTypeOnlyImportSpecifier(parent, contextToken) && canCompleteFromNamedBindings(parent.parent)) { return parent; } - if (ts.isNamedImports(parent) || ts.isNamespaceImport(parent)) { + if (isNamedImports(parent) || isNamespaceImport(parent)) { if (!parent.parent.isTypeOnly && ( - contextToken.kind === ts.SyntaxKind.OpenBraceToken || - contextToken.kind === ts.SyntaxKind.ImportKeyword || - contextToken.kind === ts.SyntaxKind.CommaToken + contextToken.kind === SyntaxKind.OpenBraceToken || + contextToken.kind === SyntaxKind.ImportKeyword || + contextToken.kind === SyntaxKind.CommaToken )) { - keywordCompletion = ts.SyntaxKind.TypeKeyword; + keywordCompletion = SyntaxKind.TypeKeyword; } if (canCompleteFromNamedBindings(parent)) { // At `import { ... } |` or `import * as Foo |`, the only possible completion is `from` - if (contextToken.kind === ts.SyntaxKind.CloseBraceToken || contextToken.kind === ts.SyntaxKind.Identifier) { + if (contextToken.kind === SyntaxKind.CloseBraceToken || contextToken.kind === SyntaxKind.Identifier) { isKeywordOnlyCompletion = true; - keywordCompletion = ts.SyntaxKind.FromKeyword; + keywordCompletion = SyntaxKind.FromKeyword; } else { return parent.parent.parent; @@ -4309,35 +4371,35 @@ function getImportStatementCompletionInfo(contextToken: ts.Node): ImportStatemen } return undefined; } - if (ts.isImportKeyword(contextToken) && ts.isSourceFile(parent)) { + if (isImportKeyword(contextToken) && isSourceFile(parent)) { // A lone import keyword with nothing following it does not parse as a statement at all - keywordCompletion = ts.SyntaxKind.TypeKeyword; - return contextToken as ts.Token; + keywordCompletion = SyntaxKind.TypeKeyword; + return contextToken as Token; } - if (ts.isImportKeyword(contextToken) && ts.isImportDeclaration(parent)) { + if (isImportKeyword(contextToken) && isImportDeclaration(parent)) { // `import s| from` - keywordCompletion = ts.SyntaxKind.TypeKeyword; + keywordCompletion = SyntaxKind.TypeKeyword; return isModuleSpecifierMissingOrEmpty(parent.moduleSpecifier) ? parent : undefined; } return undefined; } } -function getSingleLineReplacementSpanForImportCompletionNode(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration | ts.ImportSpecifier | ts.Token | undefined) { +function getSingleLineReplacementSpanForImportCompletionNode(node: ImportDeclaration | ImportEqualsDeclaration | ImportSpecifier | Token | undefined) { if (!node) return undefined; - const top = ts.findAncestor(node, ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration)) ?? node; + const top = findAncestor(node, or(isImportDeclaration, isImportEqualsDeclaration)) ?? node; const sourceFile = top.getSourceFile(); - if (ts.rangeIsOnSingleLine(top, sourceFile)) { - return ts.createTextSpanFromNode(top, sourceFile); + if (rangeIsOnSingleLine(top, sourceFile)) { + return createTextSpanFromNode(top, sourceFile); } // ImportKeyword was necessarily on one line; ImportSpecifier was necessarily parented in an ImportDeclaration - ts.Debug.assert(top.kind !== ts.SyntaxKind.ImportKeyword && top.kind !== ts.SyntaxKind.ImportSpecifier); + Debug.assert(top.kind !== SyntaxKind.ImportKeyword && top.kind !== SyntaxKind.ImportSpecifier); // Guess which point in the import might actually be a later statement parsed as part of the import // during parser recovery - either in the middle of named imports, or the module specifier. - const potentialSplitPoint = top.kind === ts.SyntaxKind.ImportDeclaration + const potentialSplitPoint = top.kind === SyntaxKind.ImportDeclaration ? getPotentiallyInvalidImportSpecifier(top.importClause?.namedBindings) ?? top.moduleSpecifier : top.moduleReference; - const withoutModuleSpecifier: ts.TextRange = { + const withoutModuleSpecifier: TextRange = { pos: top.getFirstToken()!.getStart(), end: potentialSplitPoint.pos, }; @@ -4350,8 +4412,8 @@ function getSingleLineReplacementSpanForImportCompletionNode(node: ts.ImportDecl // But if everything but the "module specifier" is on one line, by this point we can // assume that the "module specifier" is actually just another statement, and return // the single-line range of the import excluding that probable statement. - if (ts.rangeIsOnSingleLine(withoutModuleSpecifier, sourceFile)) { - return ts.createTextSpanFromRange(withoutModuleSpecifier); + if (rangeIsOnSingleLine(withoutModuleSpecifier, sourceFile)) { + return createTextSpanFromRange(withoutModuleSpecifier); } } @@ -4361,24 +4423,24 @@ function getSingleLineReplacementSpanForImportCompletionNode(node: ts.ImportDecl // interface Bar {} // in which `Foo`, `interface`, and `Bar` are all parsed as import specifiers. The caller // will also check if this token is on a separate line from the rest of the import. -function getPotentiallyInvalidImportSpecifier(namedBindings: ts.NamedImportBindings | undefined) { - return ts.find( - ts.tryCast(namedBindings, ts.isNamedImports)?.elements, +function getPotentiallyInvalidImportSpecifier(namedBindings: NamedImportBindings | undefined) { + return find( + tryCast(namedBindings, isNamedImports)?.elements, e => !e.propertyName && - ts.isStringANonContextualKeyword(e.name.text) && - ts.findPrecedingToken(e.name.pos, namedBindings!.getSourceFile(), namedBindings)?.kind !== ts.SyntaxKind.CommaToken); + isStringANonContextualKeyword(e.name.text) && + findPrecedingToken(e.name.pos, namedBindings!.getSourceFile(), namedBindings)?.kind !== SyntaxKind.CommaToken); } -function couldBeTypeOnlyImportSpecifier(importSpecifier: ts.Node, contextToken: ts.Node | undefined): importSpecifier is ts.ImportSpecifier { - return ts.isImportSpecifier(importSpecifier) - && (importSpecifier.isTypeOnly || contextToken === importSpecifier.name && ts.isTypeKeywordTokenOrIdentifier(contextToken)); +function couldBeTypeOnlyImportSpecifier(importSpecifier: Node, contextToken: Node | undefined): importSpecifier is ImportSpecifier { + return isImportSpecifier(importSpecifier) + && (importSpecifier.isTypeOnly || contextToken === importSpecifier.name && isTypeKeywordTokenOrIdentifier(contextToken)); } -function canCompleteFromNamedBindings(namedBindings: ts.NamedImportBindings) { +function canCompleteFromNamedBindings(namedBindings: NamedImportBindings) { if (!isModuleSpecifierMissingOrEmpty(namedBindings.parent.parent.moduleSpecifier) || namedBindings.parent.name) { return false; } - if (ts.isNamedImports(namedBindings)) { + if (isNamedImports(namedBindings)) { // We can only complete on named imports if there are no other named imports already, // but parser recovery sometimes puts later statements in the named imports list, so // we try to only consider the probably-valid ones. @@ -4389,40 +4451,40 @@ function canCompleteFromNamedBindings(namedBindings: ts.NamedImportBindings) { return true; } -function isModuleSpecifierMissingOrEmpty(specifier: ts.ModuleReference | ts.Expression) { - if (ts.nodeIsMissing(specifier)) return true; - return !ts.tryCast(ts.isExternalModuleReference(specifier) ? specifier.expression : specifier, ts.isStringLiteralLike)?.text; +function isModuleSpecifierMissingOrEmpty(specifier: ModuleReference | Expression) { + if (nodeIsMissing(specifier)) return true; + return !tryCast(isExternalModuleReference(specifier) ? specifier.expression : specifier, isStringLiteralLike)?.text; } -function getVariableDeclaration(property: ts.Node): ts.VariableDeclaration | undefined { - const variableDeclaration = ts.findAncestor(property, node => - ts.isFunctionBlock(node) || isArrowFunctionBody(node) || ts.isBindingPattern(node) +function getVariableDeclaration(property: Node): VariableDeclaration | undefined { + const variableDeclaration = findAncestor(property, node => + isFunctionBlock(node) || isArrowFunctionBody(node) || isBindingPattern(node) ? "quit" - : ts.isVariableDeclaration(node)); + : isVariableDeclaration(node)); - return variableDeclaration as ts.VariableDeclaration | undefined; + return variableDeclaration as VariableDeclaration | undefined; } -function isArrowFunctionBody(node: ts.Node) { - return node.parent && ts.isArrowFunction(node.parent) && node.parent.body === node; +function isArrowFunctionBody(node: Node) { + return node.parent && isArrowFunction(node.parent) && node.parent.body === node; } /** True if symbol is a type or a module containing at least one type. */ -function symbolCanBeReferencedAtTypeLocation(symbol: ts.Symbol, checker: ts.TypeChecker, seenModules = new ts.Map()): boolean { +function symbolCanBeReferencedAtTypeLocation(symbol: Symbol, checker: TypeChecker, seenModules = new Map()): boolean { // Since an alias can be merged with a local declaration, we need to test both the alias and its target. // This code used to just test the result of `skipAlias`, but that would ignore any locally introduced meanings. - return nonAliasCanBeReferencedAtTypeLocation(symbol) || nonAliasCanBeReferencedAtTypeLocation(ts.skipAlias(symbol.exportSymbol || symbol, checker)); + return nonAliasCanBeReferencedAtTypeLocation(symbol) || nonAliasCanBeReferencedAtTypeLocation(skipAlias(symbol.exportSymbol || symbol, checker)); - function nonAliasCanBeReferencedAtTypeLocation(symbol: ts.Symbol): boolean { - return !!(symbol.flags & ts.SymbolFlags.Type) || checker.isUnknownSymbol(symbol) || - !!(symbol.flags & ts.SymbolFlags.Module) && ts.addToSeen(seenModules, ts.getSymbolId(symbol)) && + function nonAliasCanBeReferencedAtTypeLocation(symbol: Symbol): boolean { + return !!(symbol.flags & SymbolFlags.Type) || checker.isUnknownSymbol(symbol) || + !!(symbol.flags & SymbolFlags.Module) && addToSeen(seenModules, getSymbolId(symbol)) && checker.getExportsOfModule(symbol).some(e => symbolCanBeReferencedAtTypeLocation(e, checker, seenModules)); } } -function isDeprecated(symbol: ts.Symbol, checker: ts.TypeChecker) { - const declarations = ts.skipAlias(symbol, checker).declarations; - return !!ts.length(declarations) && ts.every(declarations, ts.isDeprecatedDeclaration); +function isDeprecated(symbol: Symbol, checker: TypeChecker) { + const declarations = skipAlias(symbol, checker).declarations; + return !!length(declarations) && every(declarations, isDeprecatedDeclaration); } /** @@ -4456,8 +4518,8 @@ function isDeprecated(symbol: ts.Symbol, checker: ts.TypeChecker) { if (strChar === testChar || strChar === toUpperCharCode(testChar)) { matchedFirstCharacter ||= prevChar === undefined || // Beginning of word - ts.CharacterCodes.a <= prevChar && prevChar <= ts.CharacterCodes.z && ts.CharacterCodes.A <= strChar && strChar <= ts.CharacterCodes.Z || // camelCase transition - prevChar === ts.CharacterCodes._ && strChar !== ts.CharacterCodes._; // snake_case transition + CharacterCodes.a <= prevChar && prevChar <= CharacterCodes.z && CharacterCodes.A <= strChar && strChar <= CharacterCodes.Z || // camelCase transition + prevChar === CharacterCodes._ && strChar !== CharacterCodes._; // snake_case transition if (matchedFirstCharacter) { characterIndex++; } @@ -4473,7 +4535,7 @@ function isDeprecated(symbol: ts.Symbol, checker: ts.TypeChecker) { } function toUpperCharCode(charCode: number) { - if (ts.CharacterCodes.a <= charCode && charCode <= ts.CharacterCodes.z) { + if (CharacterCodes.a <= charCode && charCode <= CharacterCodes.z) { return charCode - 32; } return charCode; diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 5090ca29d94f1..f6a5e2f5eabeb 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,16 +1,29 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, arrayFrom, arrayToMultiMap, Block, BreakOrContinueStatement, CancellationToken, CaseClause, cast, + concatenate, ConstructorDeclaration, contains, createGetCanonicalFileName, createTextSpanFromBounds, + createTextSpanFromNode, Debug, DefaultClause, find, FindAllReferences, findAncestor, findChildOfKind, findModifier, + forEach, forEachChild, forEachReturnStatement, FunctionDeclaration, FunctionLikeDeclaration, getContainingFunction, + getTouchingPropertyName, HighlightSpan, HighlightSpanKind, IfStatement, isAccessor, isAwaitExpression, isBlock, + isBreakOrContinueStatement, isCaseClause, isClassDeclaration, isClassLike, isConstructorDeclaration, isDeclaration, + isDefaultClause, isFunctionBlock, isFunctionLike, isIfStatement, isInterfaceDeclaration, isIterationStatement, + isJsxClosingElement, isJsxOpeningElement, isLabeledStatement, isModifierKind, isModuleDeclaration, + isReturnStatement, isSwitchStatement, isThrowStatement, isTryStatement, isTypeAliasDeclaration, isTypeNode, + isVariableStatement, isWhiteSpaceSingleLine, isYieldExpression, IterationStatement, mapDefined, MethodDeclaration, + Modifier, ModifierFlags, modifierToFlag, ModuleBlock, Node, ObjectLiteralExpression, ObjectTypeDeclaration, Program, + Push, ReturnStatement, Set, SourceFile, SwitchStatement, SyntaxKind, ThrowStatement, toArray, toPath, TryStatement, +} from "./_namespaces/ts"; export interface DocumentHighlights { fileName: string; - highlightSpans: ts.HighlightSpan[]; + highlightSpans: HighlightSpan[]; } /* @internal */ export namespace DocumentHighlights { - export function getDocumentHighlights(program: ts.Program, cancellationToken: ts.CancellationToken, sourceFile: ts.SourceFile, position: number, sourceFilesToSearch: readonly ts.SourceFile[]): DocumentHighlights[] | undefined { - const node = ts.getTouchingPropertyName(sourceFile, position); + export function getDocumentHighlights(program: Program, cancellationToken: CancellationToken, sourceFile: SourceFile, position: number, sourceFilesToSearch: readonly SourceFile[]): DocumentHighlights[] | undefined { + const node = getTouchingPropertyName(sourceFile, position); - if (node.parent && (ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node || ts.isJsxClosingElement(node.parent))) { + if (node.parent && (isJsxOpeningElement(node.parent) && node.parent.tagName === node || isJsxClosingElement(node.parent))) { // For a JSX element, just highlight the matching tag, not all references. const { openingElement, closingElement } = node.parent.parent; const highlightSpans = [openingElement, closingElement].map(({ tagName }) => getHighlightSpanForNode(tagName, sourceFile)); @@ -20,98 +33,98 @@ export namespace DocumentHighlights { return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile); } - function getHighlightSpanForNode(node: ts.Node, sourceFile: ts.SourceFile): ts.HighlightSpan { + function getHighlightSpanForNode(node: Node, sourceFile: SourceFile): HighlightSpan { return { fileName: sourceFile.fileName, - textSpan: ts.createTextSpanFromNode(node, sourceFile), - kind: ts.HighlightSpanKind.none + textSpan: createTextSpanFromNode(node, sourceFile), + kind: HighlightSpanKind.none }; } - function getSemanticDocumentHighlights(position: number, node: ts.Node, program: ts.Program, cancellationToken: ts.CancellationToken, sourceFilesToSearch: readonly ts.SourceFile[]): DocumentHighlights[] | undefined { - const sourceFilesSet = new ts.Set(sourceFilesToSearch.map(f => f.fileName)); - const referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet); + function getSemanticDocumentHighlights(position: number, node: Node, program: Program, cancellationToken: CancellationToken, sourceFilesToSearch: readonly SourceFile[]): DocumentHighlights[] | undefined { + const sourceFilesSet = new Set(sourceFilesToSearch.map(f => f.fileName)); + const referenceEntries = FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken, /*options*/ undefined, sourceFilesSet); if (!referenceEntries) return undefined; - const map = ts.arrayToMultiMap(referenceEntries.map(ts.FindAllReferences.toHighlightSpan), e => e.fileName, e => e.span); - const getCanonicalFileName = ts.createGetCanonicalFileName(program.useCaseSensitiveFileNames()); - return ts.mapDefined(ts.arrayFrom(map.entries()), ([fileName, highlightSpans]) => { + const map = arrayToMultiMap(referenceEntries.map(FindAllReferences.toHighlightSpan), e => e.fileName, e => e.span); + const getCanonicalFileName = createGetCanonicalFileName(program.useCaseSensitiveFileNames()); + return mapDefined(arrayFrom(map.entries()), ([fileName, highlightSpans]) => { if (!sourceFilesSet.has(fileName)) { - if (!program.redirectTargetsMap.has(ts.toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { + if (!program.redirectTargetsMap.has(toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { return undefined; } const redirectTarget = program.getSourceFile(fileName); - const redirect = ts.find(sourceFilesToSearch, f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!; + const redirect = find(sourceFilesToSearch, f => !!f.redirectInfo && f.redirectInfo.redirectTarget === redirectTarget)!; fileName = redirect.fileName; - ts.Debug.assert(sourceFilesSet.has(fileName)); + Debug.assert(sourceFilesSet.has(fileName)); } return { fileName, highlightSpans }; }); } - function getSyntacticDocumentHighlights(node: ts.Node, sourceFile: ts.SourceFile): DocumentHighlights[] | undefined { + function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] | undefined { const highlightSpans = getHighlightSpans(node, sourceFile); return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans }]; } - function getHighlightSpans(node: ts.Node, sourceFile: ts.SourceFile): ts.HighlightSpan[] | undefined { + function getHighlightSpans(node: Node, sourceFile: SourceFile): HighlightSpan[] | undefined { switch (node.kind) { - case ts.SyntaxKind.IfKeyword: - case ts.SyntaxKind.ElseKeyword: - return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined; - case ts.SyntaxKind.ReturnKeyword: - return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences); - case ts.SyntaxKind.ThrowKeyword: - return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences); - case ts.SyntaxKind.TryKeyword: - case ts.SyntaxKind.CatchKeyword: - case ts.SyntaxKind.FinallyKeyword: - const tryStatement = node.kind === ts.SyntaxKind.CatchKeyword ? node.parent.parent : node.parent; - return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences); - case ts.SyntaxKind.SwitchKeyword: - return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); - case ts.SyntaxKind.CaseKeyword: - case ts.SyntaxKind.DefaultKeyword: { - if (ts.isDefaultClause(node.parent) || ts.isCaseClause(node.parent)) { - return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences); + case SyntaxKind.IfKeyword: + case SyntaxKind.ElseKeyword: + return isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined; + case SyntaxKind.ReturnKeyword: + return useParent(node.parent, isReturnStatement, getReturnOccurrences); + case SyntaxKind.ThrowKeyword: + return useParent(node.parent, isThrowStatement, getThrowOccurrences); + case SyntaxKind.TryKeyword: + case SyntaxKind.CatchKeyword: + case SyntaxKind.FinallyKeyword: + const tryStatement = node.kind === SyntaxKind.CatchKeyword ? node.parent.parent : node.parent; + return useParent(tryStatement, isTryStatement, getTryCatchFinallyOccurrences); + case SyntaxKind.SwitchKeyword: + return useParent(node.parent, isSwitchStatement, getSwitchCaseDefaultOccurrences); + case SyntaxKind.CaseKeyword: + case SyntaxKind.DefaultKeyword: { + if (isDefaultClause(node.parent) || isCaseClause(node.parent)) { + return useParent(node.parent.parent.parent, isSwitchStatement, getSwitchCaseDefaultOccurrences); } return undefined; } - case ts.SyntaxKind.BreakKeyword: - case ts.SyntaxKind.ContinueKeyword: - return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences); - case ts.SyntaxKind.ForKeyword: - case ts.SyntaxKind.WhileKeyword: - case ts.SyntaxKind.DoKeyword: - return useParent(node.parent, (n): n is ts.IterationStatement => ts.isIterationStatement(n, /*lookInLabeledStatements*/ true), getLoopBreakContinueOccurrences); - case ts.SyntaxKind.ConstructorKeyword: - return getFromAllDeclarations(ts.isConstructorDeclaration, [ts.SyntaxKind.ConstructorKeyword]); - case ts.SyntaxKind.GetKeyword: - case ts.SyntaxKind.SetKeyword: - return getFromAllDeclarations(ts.isAccessor, [ts.SyntaxKind.GetKeyword, ts.SyntaxKind.SetKeyword]); - case ts.SyntaxKind.AwaitKeyword: - return useParent(node.parent, ts.isAwaitExpression, getAsyncAndAwaitOccurrences); - case ts.SyntaxKind.AsyncKeyword: + case SyntaxKind.BreakKeyword: + case SyntaxKind.ContinueKeyword: + return useParent(node.parent, isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences); + case SyntaxKind.ForKeyword: + case SyntaxKind.WhileKeyword: + case SyntaxKind.DoKeyword: + return useParent(node.parent, (n): n is IterationStatement => isIterationStatement(n, /*lookInLabeledStatements*/ true), getLoopBreakContinueOccurrences); + case SyntaxKind.ConstructorKeyword: + return getFromAllDeclarations(isConstructorDeclaration, [SyntaxKind.ConstructorKeyword]); + case SyntaxKind.GetKeyword: + case SyntaxKind.SetKeyword: + return getFromAllDeclarations(isAccessor, [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword]); + case SyntaxKind.AwaitKeyword: + return useParent(node.parent, isAwaitExpression, getAsyncAndAwaitOccurrences); + case SyntaxKind.AsyncKeyword: return highlightSpans(getAsyncAndAwaitOccurrences(node)); - case ts.SyntaxKind.YieldKeyword: + case SyntaxKind.YieldKeyword: return highlightSpans(getYieldOccurrences(node)); - case ts.SyntaxKind.InKeyword: + case SyntaxKind.InKeyword: return undefined; default: - return ts.isModifierKind(node.kind) && (ts.isDeclaration(node.parent) || ts.isVariableStatement(node.parent)) + return isModifierKind(node.kind) && (isDeclaration(node.parent) || isVariableStatement(node.parent)) ? highlightSpans(getModifierOccurrences(node.kind, node.parent)) : undefined; } - function getFromAllDeclarations(nodeTest: (node: ts.Node) => node is T, keywords: readonly ts.SyntaxKind[]): ts.HighlightSpan[] | undefined { - return useParent(node.parent, nodeTest, decl => ts.mapDefined(decl.symbol.declarations, d => - nodeTest(d) ? ts.find(d.getChildren(sourceFile), c => ts.contains(keywords, c.kind)) : undefined)); + function getFromAllDeclarations(nodeTest: (node: Node) => node is T, keywords: readonly SyntaxKind[]): HighlightSpan[] | undefined { + return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol.declarations, d => + nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined)); } - function useParent(node: ts.Node, nodeTest: (node: ts.Node) => node is T, getNodes: (node: T, sourceFile: ts.SourceFile) => readonly ts.Node[] | undefined): ts.HighlightSpan[] | undefined { + function useParent(node: Node, nodeTest: (node: Node) => node is T, getNodes: (node: T, sourceFile: SourceFile) => readonly Node[] | undefined): HighlightSpan[] | undefined { return nodeTest(node) ? highlightSpans(getNodes(node, sourceFile)) : undefined; } - function highlightSpans(nodes: readonly ts.Node[] | undefined): ts.HighlightSpan[] | undefined { + function highlightSpans(nodes: readonly Node[] | undefined): HighlightSpan[] | undefined { return nodes && nodes.map(node => getHighlightSpanForNode(node, sourceFile)); } } @@ -120,18 +133,18 @@ export namespace DocumentHighlights { * Aggregates all throw-statements within this node *without* crossing * into function boundaries and try-blocks with catch-clauses. */ - function aggregateOwnedThrowStatements(node: ts.Node): readonly ts.ThrowStatement[] | undefined { - if (ts.isThrowStatement(node)) { + function aggregateOwnedThrowStatements(node: Node): readonly ThrowStatement[] | undefined { + if (isThrowStatement(node)) { return [node]; } - else if (ts.isTryStatement(node)) { + else if (isTryStatement(node)) { // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context. - return ts.concatenate( + return concatenate( node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), node.finallyBlock && aggregateOwnedThrowStatements(node.finallyBlock)); } // Do not cross function boundaries. - return ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements); + return isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements); } /** @@ -139,19 +152,19 @@ export namespace DocumentHighlights { * nearest ancestor that is a try-block (whose try statement has a catch clause), * function-block, or source file. */ - function getThrowStatementOwner(throwStatement: ts.ThrowStatement): ts.Node | undefined { - let child: ts.Node = throwStatement; + function getThrowStatementOwner(throwStatement: ThrowStatement): Node | undefined { + let child: Node = throwStatement; while (child.parent) { const parent = child.parent; - if (ts.isFunctionBlock(parent) || parent.kind === ts.SyntaxKind.SourceFile) { + if (isFunctionBlock(parent) || parent.kind === SyntaxKind.SourceFile) { return parent; } // A throw-statement is only owned by a try-statement if the try-statement has // a catch clause, and if the throw-statement occurs within the try block. - if (ts.isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) { + if (isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) { return child; } @@ -161,103 +174,103 @@ export namespace DocumentHighlights { return undefined; } - function aggregateAllBreakAndContinueStatements(node: ts.Node): readonly ts.BreakOrContinueStatement[] | undefined { - return ts.isBreakOrContinueStatement(node) ? [node] : ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements); + function aggregateAllBreakAndContinueStatements(node: Node): readonly BreakOrContinueStatement[] | undefined { + return isBreakOrContinueStatement(node) ? [node] : isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements); } - function flatMapChildren(node: ts.Node, cb: (child: ts.Node) => readonly T[] | T | undefined): readonly T[] { + function flatMapChildren(node: Node, cb: (child: Node) => readonly T[] | T | undefined): readonly T[] { const result: T[] = []; node.forEachChild(child => { const value = cb(child); if (value !== undefined) { - result.push(...ts.toArray(value)); + result.push(...toArray(value)); } }); return result; } - function ownsBreakOrContinueStatement(owner: ts.Node, statement: ts.BreakOrContinueStatement): boolean { + function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean { const actualOwner = getBreakOrContinueOwner(statement); return !!actualOwner && actualOwner === owner; } - function getBreakOrContinueOwner(statement: ts.BreakOrContinueStatement): ts.Node | undefined { - return ts.findAncestor(statement, node => { + function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node | undefined { + return findAncestor(statement, node => { switch (node.kind) { - case ts.SyntaxKind.SwitchStatement: - if (statement.kind === ts.SyntaxKind.ContinueStatement) { + case SyntaxKind.SwitchStatement: + if (statement.kind === SyntaxKind.ContinueStatement) { return false; } // falls through - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.DoStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.DoStatement: return !statement.label || isLabeledBy(node, statement.label.escapedText); default: // Don't cross function boundaries. // TODO: GH#20090 - return ts.isFunctionLike(node) && "quit"; + return isFunctionLike(node) && "quit"; } }); } - function getModifierOccurrences(modifier: ts.Modifier["kind"], declaration: ts.Node): ts.Node[] { - return ts.mapDefined(getNodesToSearchForModifier(declaration, ts.modifierToFlag(modifier)), node => ts.findModifier(node, modifier)); + function getModifierOccurrences(modifier: Modifier["kind"], declaration: Node): Node[] { + return mapDefined(getNodesToSearchForModifier(declaration, modifierToFlag(modifier)), node => findModifier(node, modifier)); } - function getNodesToSearchForModifier(declaration: ts.Node, modifierFlag: ts.ModifierFlags): readonly ts.Node[] | undefined { + function getNodesToSearchForModifier(declaration: Node, modifierFlag: ModifierFlags): readonly Node[] | undefined { // Types of node whose children might have modifiers. - const container = declaration.parent as ts.ModuleBlock | ts.SourceFile | ts.Block | ts.CaseClause | ts.DefaultClause | ts.ConstructorDeclaration | ts.MethodDeclaration | ts.FunctionDeclaration | ts.ObjectTypeDeclaration | ts.ObjectLiteralExpression; + const container = declaration.parent as ModuleBlock | SourceFile | Block | CaseClause | DefaultClause | ConstructorDeclaration | MethodDeclaration | FunctionDeclaration | ObjectTypeDeclaration | ObjectLiteralExpression; switch (container.kind) { - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: + case SyntaxKind.ModuleBlock: + case SyntaxKind.SourceFile: + case SyntaxKind.Block: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: // Container is either a class declaration or the declaration is a classDeclaration - if (modifierFlag & ts.ModifierFlags.Abstract && ts.isClassDeclaration(declaration)) { + if (modifierFlag & ModifierFlags.Abstract && isClassDeclaration(declaration)) { return [...declaration.members, declaration]; } else { return container.statements; } - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - return [...container.parameters, ...(ts.isClassLike(container.parent) ? container.parent.members : [])]; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeLiteral: + case SyntaxKind.Constructor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionDeclaration: + return [...container.parameters, ...(isClassLike(container.parent) ? container.parent.members : [])]; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeLiteral: const nodes = container.members; // If we're an accessibility modifier, we're in an instance member and should search // the constructor's parameter list for instance members as well. - if (modifierFlag & (ts.ModifierFlags.AccessibilityModifier | ts.ModifierFlags.Readonly)) { - const constructor = ts.find(container.members, ts.isConstructorDeclaration); + if (modifierFlag & (ModifierFlags.AccessibilityModifier | ModifierFlags.Readonly)) { + const constructor = find(container.members, isConstructorDeclaration); if (constructor) { return [...nodes, ...constructor.parameters]; } } - else if (modifierFlag & ts.ModifierFlags.Abstract) { + else if (modifierFlag & ModifierFlags.Abstract) { return [...nodes, container]; } return nodes; // Syntactically invalid positions that the parser might produce anyway - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectLiteralExpression: return undefined; default: - ts.Debug.assertNever(container, "Invalid container kind."); + Debug.assertNever(container, "Invalid container kind."); } } - function pushKeywordIf(keywordList: ts.Push, token: ts.Node | undefined, ...expected: ts.SyntaxKind[]): boolean { - if (token && ts.contains(expected, token.kind)) { + function pushKeywordIf(keywordList: Push, token: Node | undefined, ...expected: SyntaxKind[]): boolean { + if (token && contains(expected, token.kind)) { keywordList.push(token); return true; } @@ -265,44 +278,44 @@ export namespace DocumentHighlights { return false; } - function getLoopBreakContinueOccurrences(loopNode: ts.IterationStatement): ts.Node[] { - const keywords: ts.Node[] = []; + function getLoopBreakContinueOccurrences(loopNode: IterationStatement): Node[] { + const keywords: Node[] = []; - if (pushKeywordIf(keywords, loopNode.getFirstToken(), ts.SyntaxKind.ForKeyword, ts.SyntaxKind.WhileKeyword, ts.SyntaxKind.DoKeyword)) { + if (pushKeywordIf(keywords, loopNode.getFirstToken(), SyntaxKind.ForKeyword, SyntaxKind.WhileKeyword, SyntaxKind.DoKeyword)) { // If we succeeded and got a do-while loop, then start looking for a 'while' keyword. - if (loopNode.kind === ts.SyntaxKind.DoStatement) { + if (loopNode.kind === SyntaxKind.DoStatement) { const loopTokens = loopNode.getChildren(); for (let i = loopTokens.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, loopTokens[i], ts.SyntaxKind.WhileKeyword)) { + if (pushKeywordIf(keywords, loopTokens[i], SyntaxKind.WhileKeyword)) { break; } } } } - ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), statement => { + forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), statement => { if (ownsBreakOrContinueStatement(loopNode, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), ts.SyntaxKind.BreakKeyword, ts.SyntaxKind.ContinueKeyword); + pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword); } }); return keywords; } - function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: ts.BreakOrContinueStatement): ts.Node[] | undefined { + function getBreakOrContinueStatementOccurrences(breakOrContinueStatement: BreakOrContinueStatement): Node[] | undefined { const owner = getBreakOrContinueOwner(breakOrContinueStatement); if (owner) { switch (owner.kind) { - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WhileStatement: - return getLoopBreakContinueOccurrences(owner as ts.IterationStatement); - case ts.SyntaxKind.SwitchStatement: - return getSwitchCaseDefaultOccurrences(owner as ts.SwitchStatement); + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + return getLoopBreakContinueOccurrences(owner as IterationStatement); + case SyntaxKind.SwitchStatement: + return getSwitchCaseDefaultOccurrences(owner as SwitchStatement); } } @@ -310,18 +323,18 @@ export namespace DocumentHighlights { return undefined; } - function getSwitchCaseDefaultOccurrences(switchStatement: ts.SwitchStatement): ts.Node[] { - const keywords: ts.Node[] = []; + function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): Node[] { + const keywords: Node[] = []; - pushKeywordIf(keywords, switchStatement.getFirstToken(), ts.SyntaxKind.SwitchKeyword); + pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); // Go through each clause in the switch statement, collecting the 'case'/'default' keywords. - ts.forEach(switchStatement.caseBlock.clauses, clause => { - pushKeywordIf(keywords, clause.getFirstToken(), ts.SyntaxKind.CaseKeyword, ts.SyntaxKind.DefaultKeyword); + forEach(switchStatement.caseBlock.clauses, clause => { + pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword); - ts.forEach(aggregateAllBreakAndContinueStatements(clause), statement => { + forEach(aggregateAllBreakAndContinueStatements(clause), statement => { if (ownsBreakOrContinueStatement(switchStatement, statement)) { - pushKeywordIf(keywords, statement.getFirstToken(), ts.SyntaxKind.BreakKeyword); + pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword); } }); }); @@ -329,84 +342,84 @@ export namespace DocumentHighlights { return keywords; } - function getTryCatchFinallyOccurrences(tryStatement: ts.TryStatement, sourceFile: ts.SourceFile): ts.Node[] { - const keywords: ts.Node[] = []; + function getTryCatchFinallyOccurrences(tryStatement: TryStatement, sourceFile: SourceFile): Node[] { + const keywords: Node[] = []; - pushKeywordIf(keywords, tryStatement.getFirstToken(), ts.SyntaxKind.TryKeyword); + pushKeywordIf(keywords, tryStatement.getFirstToken(), SyntaxKind.TryKeyword); if (tryStatement.catchClause) { - pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), ts.SyntaxKind.CatchKeyword); + pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), SyntaxKind.CatchKeyword); } if (tryStatement.finallyBlock) { - const finallyKeyword = ts.findChildOfKind(tryStatement, ts.SyntaxKind.FinallyKeyword, sourceFile)!; - pushKeywordIf(keywords, finallyKeyword, ts.SyntaxKind.FinallyKeyword); + const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile)!; + pushKeywordIf(keywords, finallyKeyword, SyntaxKind.FinallyKeyword); } return keywords; } - function getThrowOccurrences(throwStatement: ts.ThrowStatement, sourceFile: ts.SourceFile): ts.Node[] | undefined { + function getThrowOccurrences(throwStatement: ThrowStatement, sourceFile: SourceFile): Node[] | undefined { const owner = getThrowStatementOwner(throwStatement); if (!owner) { return undefined; } - const keywords: ts.Node[] = []; + const keywords: Node[] = []; - ts.forEach(aggregateOwnedThrowStatements(owner), throwStatement => { - keywords.push(ts.findChildOfKind(throwStatement, ts.SyntaxKind.ThrowKeyword, sourceFile)!); + forEach(aggregateOwnedThrowStatements(owner), throwStatement => { + keywords.push(findChildOfKind(throwStatement, SyntaxKind.ThrowKeyword, sourceFile)!); }); // If the "owner" is a function, then we equate 'return' and 'throw' statements in their // ability to "jump out" of the function, and include occurrences for both. - if (ts.isFunctionBlock(owner)) { - ts.forEachReturnStatement(owner as ts.Block, returnStatement => { - keywords.push(ts.findChildOfKind(returnStatement, ts.SyntaxKind.ReturnKeyword, sourceFile)!); + if (isFunctionBlock(owner)) { + forEachReturnStatement(owner as Block, returnStatement => { + keywords.push(findChildOfKind(returnStatement, SyntaxKind.ReturnKeyword, sourceFile)!); }); } return keywords; } - function getReturnOccurrences(returnStatement: ts.ReturnStatement, sourceFile: ts.SourceFile): ts.Node[] | undefined { - const func = ts.getContainingFunction(returnStatement) as ts.FunctionLikeDeclaration; + function getReturnOccurrences(returnStatement: ReturnStatement, sourceFile: SourceFile): Node[] | undefined { + const func = getContainingFunction(returnStatement) as FunctionLikeDeclaration; if (!func) { return undefined; } - const keywords: ts.Node[] = []; - ts.forEachReturnStatement(ts.cast(func.body, ts.isBlock), returnStatement => { - keywords.push(ts.findChildOfKind(returnStatement, ts.SyntaxKind.ReturnKeyword, sourceFile)!); + const keywords: Node[] = []; + forEachReturnStatement(cast(func.body, isBlock), returnStatement => { + keywords.push(findChildOfKind(returnStatement, SyntaxKind.ReturnKeyword, sourceFile)!); }); // Include 'throw' statements that do not occur within a try block. - ts.forEach(aggregateOwnedThrowStatements(func.body!), throwStatement => { - keywords.push(ts.findChildOfKind(throwStatement, ts.SyntaxKind.ThrowKeyword, sourceFile)!); + forEach(aggregateOwnedThrowStatements(func.body!), throwStatement => { + keywords.push(findChildOfKind(throwStatement, SyntaxKind.ThrowKeyword, sourceFile)!); }); return keywords; } - function getAsyncAndAwaitOccurrences(node: ts.Node): ts.Node[] | undefined { - const func = ts.getContainingFunction(node) as ts.FunctionLikeDeclaration; + function getAsyncAndAwaitOccurrences(node: Node): Node[] | undefined { + const func = getContainingFunction(node) as FunctionLikeDeclaration; if (!func) { return undefined; } - const keywords: ts.Node[] = []; + const keywords: Node[] = []; if (func.modifiers) { func.modifiers.forEach(modifier => { - pushKeywordIf(keywords, modifier, ts.SyntaxKind.AsyncKeyword); + pushKeywordIf(keywords, modifier, SyntaxKind.AsyncKeyword); }); } - ts.forEachChild(func, child => { + forEachChild(func, child => { traverseWithoutCrossingFunction(child, node => { - if (ts.isAwaitExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), ts.SyntaxKind.AwaitKeyword); + if (isAwaitExpression(node)) { + pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.AwaitKeyword); } }); }); @@ -415,18 +428,18 @@ export namespace DocumentHighlights { return keywords; } - function getYieldOccurrences(node: ts.Node): ts.Node[] | undefined { - const func = ts.getContainingFunction(node) as ts.FunctionDeclaration; + function getYieldOccurrences(node: Node): Node[] | undefined { + const func = getContainingFunction(node) as FunctionDeclaration; if (!func) { return undefined; } - const keywords: ts.Node[] = []; + const keywords: Node[] = []; - ts.forEachChild(func, child => { + forEachChild(func, child => { traverseWithoutCrossingFunction(child, node => { - if (ts.isYieldExpression(node)) { - pushKeywordIf(keywords, node.getFirstToken(), ts.SyntaxKind.YieldKeyword); + if (isYieldExpression(node)) { + pushKeywordIf(keywords, node.getFirstToken(), SyntaxKind.YieldKeyword); } }); }); @@ -435,21 +448,21 @@ export namespace DocumentHighlights { } // Do not cross function/class/interface/module/type boundaries. - function traverseWithoutCrossingFunction(node: ts.Node, cb: (node: ts.Node) => void) { + function traverseWithoutCrossingFunction(node: Node, cb: (node: Node) => void) { cb(node); - if (!ts.isFunctionLike(node) && !ts.isClassLike(node) && !ts.isInterfaceDeclaration(node) && !ts.isModuleDeclaration(node) && !ts.isTypeAliasDeclaration(node) && !ts.isTypeNode(node)) { - ts.forEachChild(node, child => traverseWithoutCrossingFunction(child, cb)); + if (!isFunctionLike(node) && !isClassLike(node) && !isInterfaceDeclaration(node) && !isModuleDeclaration(node) && !isTypeAliasDeclaration(node) && !isTypeNode(node)) { + forEachChild(node, child => traverseWithoutCrossingFunction(child, cb)); } } - function getIfElseOccurrences(ifStatement: ts.IfStatement, sourceFile: ts.SourceFile): ts.HighlightSpan[] { + function getIfElseOccurrences(ifStatement: IfStatement, sourceFile: SourceFile): HighlightSpan[] { const keywords = getIfElseKeywords(ifStatement, sourceFile); - const result: ts.HighlightSpan[] = []; + const result: HighlightSpan[] = []; // We'd like to highlight else/ifs together if they are only separated by whitespace // (i.e. the keywords are separated by no comments, no newlines). for (let i = 0; i < keywords.length; i++) { - if (keywords[i].kind === ts.SyntaxKind.ElseKeyword && i < keywords.length - 1) { + if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) { const elseKeyword = keywords[i]; const ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword. @@ -457,7 +470,7 @@ export namespace DocumentHighlights { // Avoid recalculating getStart() by iterating backwards. for (let j = ifKeyword.getStart(sourceFile) - 1; j >= elseKeyword.end; j--) { - if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { + if (!isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) { shouldCombineElseAndIf = false; break; } @@ -466,8 +479,8 @@ export namespace DocumentHighlights { if (shouldCombineElseAndIf) { result.push({ fileName: sourceFile.fileName, - textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), - kind: ts.HighlightSpanKind.reference + textSpan: createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end), + kind: HighlightSpanKind.reference }); i++; // skip the next keyword continue; @@ -481,27 +494,27 @@ export namespace DocumentHighlights { return result; } - function getIfElseKeywords(ifStatement: ts.IfStatement, sourceFile: ts.SourceFile): ts.Node[] { - const keywords: ts.Node[] = []; + function getIfElseKeywords(ifStatement: IfStatement, sourceFile: SourceFile): Node[] { + const keywords: Node[] = []; // Traverse upwards through all parent if-statements linked by their else-branches. - while (ts.isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) { + while (isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) { ifStatement = ifStatement.parent; } // Now traverse back down through the else branches, aggregating if/else keywords of if-statements. while (true) { const children = ifStatement.getChildren(sourceFile); - pushKeywordIf(keywords, children[0], ts.SyntaxKind.IfKeyword); + pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword); // Generally the 'else' keyword is second-to-last, so we traverse backwards. for (let i = children.length - 1; i >= 0; i--) { - if (pushKeywordIf(keywords, children[i], ts.SyntaxKind.ElseKeyword)) { + if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) { break; } } - if (!ifStatement.elseStatement || !ts.isIfStatement(ifStatement.elseStatement)) { + if (!ifStatement.elseStatement || !isIfStatement(ifStatement.elseStatement)) { break; } @@ -515,7 +528,7 @@ export namespace DocumentHighlights { * Whether or not a 'node' is preceded by a label of the given string. * Note: 'node' cannot be a SourceFile. */ - function isLabeledBy(node: ts.Node, labelName: ts.__String): boolean { - return !!ts.findAncestor(node.parent, owner => !ts.isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName); + function isLabeledBy(node: Node, labelName: __String): boolean { + return !!findAncestor(node.parent, owner => !isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName); } } diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index de55bcdd96815..d9197886cf043 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -1,4 +1,10 @@ -import * as ts from "./_namespaces/ts"; +import { + arrayFrom, CompilerOptions, createGetCanonicalFileName, createLanguageServiceSourceFile, CreateSourceFileOptions, + Debug, ensureScriptKind, ESMap, firstDefinedIterator, forEachEntry, getCompilerOptionValue, getEmitScriptTarget, + getImpliedNodeFormatForFile, getOrUpdate, getSetExternalModuleIndicator, hasProperty, identity, isArray, + IScriptSnapshot, isDeclarationFileName, map, Map, MinimalResolutionCacheHost, ModuleKind, Path, ScriptKind, + ScriptTarget, SourceFile, sourceFileAffectingCompilerOptions, toPath, tracing, updateLanguageServiceSourceFile, +} from "./_namespaces/ts"; /** * The document registry represents a store of SourceFile objects that can be shared between @@ -35,23 +41,23 @@ export interface DocumentRegistry { */ acquireDocument( fileName: string, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, - scriptSnapshot: ts.IScriptSnapshot, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind, - sourceFileOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget, - ): ts.SourceFile; + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; acquireDocumentWithKey( fileName: string, - path: ts.Path, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, - scriptSnapshot: ts.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind, - sourceFileOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget, - ): ts.SourceFile; + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; /** * Request an updated version of an already existing SourceFile with a given fileName @@ -70,25 +76,25 @@ export interface DocumentRegistry { */ updateDocument( fileName: string, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, - scriptSnapshot: ts.IScriptSnapshot, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind, - sourceFileOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget, - ): ts.SourceFile; + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; updateDocumentWithKey( fileName: string, - path: ts.Path, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, - scriptSnapshot: ts.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, - scriptKind?: ts.ScriptKind, - sourceFileOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget, - ): ts.SourceFile; + scriptKind?: ScriptKind, + sourceFileOptions?: CreateSourceFileOptions | ScriptTarget, + ): SourceFile; - getKeyForCompilationSettings(settings: ts.CompilerOptions): DocumentRegistryBucketKey; + getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -100,7 +106,7 @@ export interface DocumentRegistry { * @param scriptKind The script kind of the file to be released */ /**@deprecated pass scriptKind and impliedNodeFormat for correctness */ - releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions, scriptKind?: ts.ScriptKind): void; + releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind?: ScriptKind): void; /** * Informs the DocumentRegistry that a file is not needed any longer. * @@ -112,28 +118,28 @@ export interface DocumentRegistry { * @param scriptKind The script kind of the file to be released * @param impliedNodeFormat The implied source file format of the file to be released */ - releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions, scriptKind: ts.ScriptKind, impliedNodeFormat: ts.SourceFile["impliedNodeFormat"]): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind: ScriptKind, impliedNodeFormat: SourceFile["impliedNodeFormat"]): void; // eslint-disable-line @typescript-eslint/unified-signatures /** * @deprecated pass scriptKind for and impliedNodeFormat correctness */ - releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey, scriptKind?: ts.ScriptKind): void; - releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey, scriptKind: ts.ScriptKind, impliedNodeFormat: ts.SourceFile["impliedNodeFormat"]): void; // eslint-disable-line @typescript-eslint/unified-signatures + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind): void; + releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind: ScriptKind, impliedNodeFormat: SourceFile["impliedNodeFormat"]): void; // eslint-disable-line @typescript-eslint/unified-signatures /*@internal*/ - getLanguageServiceRefCounts(path: ts.Path, scriptKind: ts.ScriptKind): [string, number | undefined][]; + getLanguageServiceRefCounts(path: Path, scriptKind: ScriptKind): [string, number | undefined][]; reportStats(): string; } /*@internal*/ export interface ExternalDocumentCache { - setDocument(key: DocumentRegistryBucketKeyWithMode, path: ts.Path, sourceFile: ts.SourceFile): void; - getDocument(key: DocumentRegistryBucketKeyWithMode, path: ts.Path): ts.SourceFile | undefined; + setDocument(key: DocumentRegistryBucketKeyWithMode, path: Path, sourceFile: SourceFile): void; + getDocument(key: DocumentRegistryBucketKeyWithMode, path: Path): SourceFile | undefined; } export type DocumentRegistryBucketKey = string & { __bucketKey: any }; interface DocumentRegistryEntry { - sourceFile: ts.SourceFile; + sourceFile: SourceFile; // The number of language services that this source file is referenced in. When no more // language services are referencing the file, then the file can be removed from the @@ -141,7 +147,7 @@ interface DocumentRegistryEntry { languageServiceRefCount: number; } -type BucketEntry = DocumentRegistryEntry | ts.ESMap; +type BucketEntry = DocumentRegistryEntry | ESMap; function isDocumentRegistryEntry(entry: BucketEntry): entry is DocumentRegistryEntry { return !!(entry as DocumentRegistryEntry).sourceFile; } @@ -156,13 +162,13 @@ export type DocumentRegistryBucketKeyWithMode = string & { __documentRegistryBuc export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boolean, currentDirectory = "", externalCache?: ExternalDocumentCache): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - const buckets = new ts.Map>(); - const getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames); + const buckets = new Map>(); + const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function reportStats() { - const bucketInfoArray = ts.arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { + const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { const entries = buckets.get(name)!; - const sourceFiles: { name: string; scriptKind: ts.ScriptKind, refCount: number; }[] = []; + const sourceFiles: { name: string; scriptKind: ScriptKind, refCount: number; }[] = []; entries.forEach((entry, name) => { if (isDocumentRegistryEntry(entry)) { sourceFiles.push({ @@ -184,80 +190,80 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole return JSON.stringify(bucketInfoArray, undefined, 2); } - function getCompilationSettings(settingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost) { + function getCompilationSettings(settingsOrHost: CompilerOptions | MinimalResolutionCacheHost) { if (typeof settingsOrHost.getCompilationSettings === "function") { - return (settingsOrHost as ts.MinimalResolutionCacheHost).getCompilationSettings(); + return (settingsOrHost as MinimalResolutionCacheHost).getCompilationSettings(); } - return settingsOrHost as ts.CompilerOptions; + return settingsOrHost as CompilerOptions; } - function acquireDocument(fileName: string, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind, languageVersionOrOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget): ts.SourceFile { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function acquireDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind, languageVersionOrOptions); } - function acquireDocumentWithKey(fileName: string, path: ts.Path, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind, languageVersionOrOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget): ts.SourceFile { + function acquireDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind, languageVersionOrOptions); } - function updateDocument(fileName: string, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind, languageVersionOrOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget): ts.SourceFile { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function updateDocument(fileName: string, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(getCompilationSettings(compilationSettings)); return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind, languageVersionOrOptions); } - function updateDocumentWithKey(fileName: string, path: ts.Path, compilationSettings: ts.CompilerOptions | ts.MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: ts.IScriptSnapshot, version: string, scriptKind?: ts.ScriptKind, languageVersionOrOptions?: ts.CreateSourceFileOptions | ts.ScriptTarget): ts.SourceFile { + function updateDocumentWithKey(fileName: string, path: Path, compilationSettings: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind, languageVersionOrOptions?: CreateSourceFileOptions | ScriptTarget): SourceFile { return acquireOrUpdateDocument(fileName, path, getCompilationSettings(compilationSettings), key, scriptSnapshot, version, /*acquiring*/ false, scriptKind, languageVersionOrOptions); } - function getDocumentRegistryEntry(bucketEntry: BucketEntry, scriptKind: ts.ScriptKind | undefined) { - const entry = isDocumentRegistryEntry(bucketEntry) ? bucketEntry : bucketEntry.get(ts.Debug.checkDefined(scriptKind, "If there are more than one scriptKind's for same document the scriptKind should be provided")); - ts.Debug.assert(scriptKind === undefined || !entry || entry.sourceFile.scriptKind === scriptKind, `Script kind should match provided ScriptKind:${scriptKind} and sourceFile.scriptKind: ${entry?.sourceFile.scriptKind}, !entry: ${!entry}`); + function getDocumentRegistryEntry(bucketEntry: BucketEntry, scriptKind: ScriptKind | undefined) { + const entry = isDocumentRegistryEntry(bucketEntry) ? bucketEntry : bucketEntry.get(Debug.checkDefined(scriptKind, "If there are more than one scriptKind's for same document the scriptKind should be provided")); + Debug.assert(scriptKind === undefined || !entry || entry.sourceFile.scriptKind === scriptKind, `Script kind should match provided ScriptKind:${scriptKind} and sourceFile.scriptKind: ${entry?.sourceFile.scriptKind}, !entry: ${!entry}`); return entry; } function acquireOrUpdateDocument( fileName: string, - path: ts.Path, - compilationSettingsOrHost: ts.CompilerOptions | ts.MinimalResolutionCacheHost, + path: Path, + compilationSettingsOrHost: CompilerOptions | MinimalResolutionCacheHost, key: DocumentRegistryBucketKey, - scriptSnapshot: ts.IScriptSnapshot, + scriptSnapshot: IScriptSnapshot, version: string, acquiring: boolean, - scriptKind: ts.ScriptKind | undefined, - languageVersionOrOptions: ts.CreateSourceFileOptions | ts.ScriptTarget | undefined, - ): ts.SourceFile { - scriptKind = ts.ensureScriptKind(fileName, scriptKind); + scriptKind: ScriptKind | undefined, + languageVersionOrOptions: CreateSourceFileOptions | ScriptTarget | undefined, + ): SourceFile { + scriptKind = ensureScriptKind(fileName, scriptKind); const compilationSettings = getCompilationSettings(compilationSettingsOrHost); - const host: ts.MinimalResolutionCacheHost | undefined = compilationSettingsOrHost === compilationSettings ? undefined : compilationSettingsOrHost as ts.MinimalResolutionCacheHost; - const scriptTarget = scriptKind === ts.ScriptKind.JSON ? ts.ScriptTarget.JSON : ts.getEmitScriptTarget(compilationSettings); - const sourceFileOptions: ts.CreateSourceFileOptions = typeof languageVersionOrOptions === "object" ? + const host: MinimalResolutionCacheHost | undefined = compilationSettingsOrHost === compilationSettings ? undefined : compilationSettingsOrHost as MinimalResolutionCacheHost; + const scriptTarget = scriptKind === ScriptKind.JSON ? ScriptTarget.JSON : getEmitScriptTarget(compilationSettings); + const sourceFileOptions: CreateSourceFileOptions = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions : { languageVersion: scriptTarget, - impliedNodeFormat: host && ts.getImpliedNodeFormatForFile(path, host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), host, compilationSettings), - setExternalModuleIndicator: ts.getSetExternalModuleIndicator(compilationSettings) + impliedNodeFormat: host && getImpliedNodeFormatForFile(path, host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), host, compilationSettings), + setExternalModuleIndicator: getSetExternalModuleIndicator(compilationSettings) }; sourceFileOptions.languageVersion = scriptTarget; const oldBucketCount = buckets.size; const keyWithMode = getDocumentRegistryBucketKeyWithMode(key, sourceFileOptions.impliedNodeFormat); - const bucket = ts.getOrUpdate(buckets, keyWithMode, () => new ts.Map()); - if (ts.tracing) { + const bucket = getOrUpdate(buckets, keyWithMode, () => new Map()); + if (tracing) { if (buckets.size > oldBucketCount) { // It is interesting, but not definitively problematic if a build requires multiple document registry buckets - // perhaps they are for two projects that don't have any overlap. // Bonus: these events can help us interpret the more interesting event below. - ts.tracing.instant(ts.tracing.Phase.Session, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key: keyWithMode }); + tracing.instant(tracing.Phase.Session, "createdDocumentRegistryBucket", { configFilePath: compilationSettings.configFilePath, key: keyWithMode }); } // It is fairly suspicious to have one path in two buckets - you'd expect dependencies to have similar configurations. // If this occurs unexpectedly, the fix is likely to synchronize the project settings. // Skip .d.ts files to reduce noise (should also cover most of node_modules). - const otherBucketKey = !ts.isDeclarationFileName(path) && - ts.forEachEntry(buckets, (bucket, bucketKey) => bucketKey !== keyWithMode && bucket.has(path) && bucketKey); + const otherBucketKey = !isDeclarationFileName(path) && + forEachEntry(buckets, (bucket, bucketKey) => bucketKey !== keyWithMode && bucket.has(path) && bucketKey); if (otherBucketKey) { - ts.tracing.instant(ts.tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: keyWithMode }); + tracing.instant(tracing.Phase.Session, "documentRegistryBucketOverlap", { path, key1: otherBucketKey, key2: keyWithMode }); } } @@ -266,7 +272,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole if (!entry && externalCache) { const sourceFile = externalCache.getDocument(keyWithMode, path); if (sourceFile) { - ts.Debug.assert(acquiring); + Debug.assert(acquiring); entry = { sourceFile, languageServiceRefCount: 0 @@ -277,7 +283,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole if (!entry) { // Have never seen this file with these settings. Create a new source file for it. - const sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, sourceFileOptions, version, /*setNodeParents*/ false, scriptKind); + const sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, sourceFileOptions, version, /*setNodeParents*/ false, scriptKind); if (externalCache) { externalCache.setDocument(keyWithMode, path, sourceFile); } @@ -292,7 +298,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole // the script snapshot. If so, update it appropriately. Otherwise, we can just // return it as is. if (entry.sourceFile.version !== version) { - entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, + entry.sourceFile = updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot!)); // TODO: GH#18217 if (externalCache) { externalCache.setDocument(keyWithMode, path, entry.sourceFile); @@ -308,7 +314,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole entry.languageServiceRefCount++; } } - ts.Debug.assert(entry.languageServiceRefCount !== 0); + Debug.assert(entry.languageServiceRefCount !== 0); return entry.sourceFile; @@ -317,7 +323,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole bucket.set(path, entry!); } else if (isDocumentRegistryEntry(bucketEntry)) { - const scriptKindMap = new ts.Map(); + const scriptKindMap = new Map(); scriptKindMap.set(bucketEntry.sourceFile.scriptKind, bucketEntry); scriptKindMap.set(scriptKind!, entry!); bucket.set(path, scriptKindMap); @@ -328,19 +334,19 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole } } - function releaseDocument(fileName: string, compilationSettings: ts.CompilerOptions, scriptKind?: ts.ScriptKind, impliedNodeFormat?: ts.SourceFile["impliedNodeFormat"]): void { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function releaseDocument(fileName: string, compilationSettings: CompilerOptions, scriptKind?: ScriptKind, impliedNodeFormat?: SourceFile["impliedNodeFormat"]): void { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const key = getKeyForCompilationSettings(compilationSettings); return releaseDocumentWithKey(path, key, scriptKind, impliedNodeFormat); } - function releaseDocumentWithKey(path: ts.Path, key: DocumentRegistryBucketKey, scriptKind?: ts.ScriptKind, impliedNodeFormat?: ts.SourceFile["impliedNodeFormat"]): void { - const bucket = ts.Debug.checkDefined(buckets.get(getDocumentRegistryBucketKeyWithMode(key, impliedNodeFormat))); + function releaseDocumentWithKey(path: Path, key: DocumentRegistryBucketKey, scriptKind?: ScriptKind, impliedNodeFormat?: SourceFile["impliedNodeFormat"]): void { + const bucket = Debug.checkDefined(buckets.get(getDocumentRegistryBucketKeyWithMode(key, impliedNodeFormat))); const bucketEntry = bucket.get(path)!; const entry = getDocumentRegistryEntry(bucketEntry, scriptKind)!; entry.languageServiceRefCount--; - ts.Debug.assert(entry.languageServiceRefCount >= 0); + Debug.assert(entry.languageServiceRefCount >= 0); if (entry.languageServiceRefCount === 0) { if (isDocumentRegistryEntry(bucketEntry)) { bucket.delete(path); @@ -348,14 +354,14 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole else { bucketEntry.delete(scriptKind!); if (bucketEntry.size === 1) { - bucket.set(path, ts.firstDefinedIterator(bucketEntry.values(), ts.identity)!); + bucket.set(path, firstDefinedIterator(bucketEntry.values(), identity)!); } } } } - function getLanguageServiceRefCounts(path: ts.Path, scriptKind: ts.ScriptKind) { - return ts.arrayFrom(buckets.entries(), ([key, bucket]): [string, number | undefined] => { + function getLanguageServiceRefCounts(path: Path, scriptKind: ScriptKind) { + return arrayFrom(buckets.entries(), ([key, bucket]): [string, number | undefined] => { const bucketEntry = bucket.get(path); const entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); return [key, entry && entry.languageServiceRefCount]; @@ -379,22 +385,22 @@ function compilerOptionValueToString(value: unknown): string { if (value === null || typeof value !== "object") { // eslint-disable-line no-null/no-null return "" + value; } - if (ts.isArray(value)) { - return `[${ts.map(value, e => compilerOptionValueToString(e))?.join(",")}]`; + if (isArray(value)) { + return `[${map(value, e => compilerOptionValueToString(e))?.join(",")}]`; } let str = "{"; for (const key in value) { - if (ts.hasProperty(value, key)) { + if (hasProperty(value, key)) { str += `${key}: ${compilerOptionValueToString((value as any)[key])}`; } } return str + "}"; } -function getKeyForCompilationSettings(settings: ts.CompilerOptions): DocumentRegistryBucketKey { - return ts.sourceFileAffectingCompilerOptions.map(option => compilerOptionValueToString(ts.getCompilerOptionValue(settings, option))).join("|") + (settings.pathsBasePath ? `|${settings.pathsBasePath}` : undefined) as DocumentRegistryBucketKey; +function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey { + return sourceFileAffectingCompilerOptions.map(option => compilerOptionValueToString(getCompilerOptionValue(settings, option))).join("|") + (settings.pathsBasePath ? `|${settings.pathsBasePath}` : undefined) as DocumentRegistryBucketKey; } -function getDocumentRegistryBucketKeyWithMode(key: DocumentRegistryBucketKey, mode: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined) { +function getDocumentRegistryBucketKeyWithMode(key: DocumentRegistryBucketKey, mode: ModuleKind.ESNext | ModuleKind.CommonJS | undefined) { return (mode ? `${key}|${mode}` : key) as DocumentRegistryBucketKeyWithMode; } diff --git a/src/services/exportInfoMap.ts b/src/services/exportInfoMap.ts index 0e3ae5e42b18d..b9725329056ad 100644 --- a/src/services/exportInfoMap.ts +++ b/src/services/exportInfoMap.ts @@ -1,4 +1,16 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, addToSeen, arrayIsEqualTo, CancellationToken, CompilerOptions, consumesNodeCoreModules, createMultiMap, + Debug, emptyArray, findIndex, firstDefined, forEachAncestorDirectory, forEachEntry, getBaseFileName, + GetCanonicalFileName, getDirectoryPath, getLocalSymbolForExportDefault, getNameForExportedSymbol, + getNamesForExportedSymbol, getNodeModulePathParts, getPackageNameFromTypesPackageName, getPatternFromSpec, + getRegexFromPattern, getSymbolId, hostGetCanonicalFileName, hostUsesCaseSensitiveFileNames, InternalSymbolName, + isExportAssignment, isExportSpecifier, isExternalModuleNameRelative, isExternalModuleSymbol, + isExternalOrCommonJsModule, isIdentifier, isKnownSymbol, isNonGlobalAmbientModule, isPrivateIdentifierSymbol, + LanguageServiceHost, Map, mapDefined, ModuleSpecifierCache, ModuleSpecifierResolutionHost, moduleSpecifiers, + nodeModulesPathPart, PackageJsonImportFilter, Path, Program, skipAlias, skipOuterExpressions, SourceFile, + startsWith, Statement, stringContains, stripQuotes, Symbol, SymbolFlags, timestamp, tryCast, TypeChecker, + unescapeLeadingUnderscores, unmangleScopedPackageName, UserPreferences, +} from "./_namespaces/ts"; /** @internal */ export const enum ImportKind { @@ -18,12 +30,12 @@ export const enum ExportKind { /** @internal */ export interface SymbolExportInfo { - readonly symbol: ts.Symbol; - readonly moduleSymbol: ts.Symbol; + readonly symbol: Symbol; + readonly moduleSymbol: Symbol; /** Set if `moduleSymbol` is an external module, not an ambient module */ moduleFileName: string | undefined; exportKind: ExportKind; - targetFlags: ts.SymbolFlags; + targetFlags: SymbolFlags; /** True if export was only found via the package.json AutoImportProvider (for telemetry). */ isFromPackageJson: boolean; } @@ -33,45 +45,45 @@ interface CachedSymbolExportInfo { id: number; symbolName: string; capitalizedSymbolName: string | undefined; - symbolTableKey: ts.__String; + symbolTableKey: __String; moduleName: string; - moduleFile: ts.SourceFile | undefined; + moduleFile: SourceFile | undefined; packageName: string | undefined; // SymbolExportInfo, but optional symbols - readonly symbol: ts.Symbol | undefined; - readonly moduleSymbol: ts.Symbol | undefined; + readonly symbol: Symbol | undefined; + readonly moduleSymbol: Symbol | undefined; moduleFileName: string | undefined; exportKind: ExportKind; - targetFlags: ts.SymbolFlags; + targetFlags: SymbolFlags; isFromPackageJson: boolean; } /** @internal */ export interface ExportInfoMap { - isUsableByFile(importingFile: ts.Path): boolean; + isUsableByFile(importingFile: Path): boolean; clear(): void; - add(importingFile: ts.Path, symbol: ts.Symbol, key: ts.__String, moduleSymbol: ts.Symbol, moduleFile: ts.SourceFile | undefined, exportKind: ExportKind, isFromPackageJson: boolean, checker: ts.TypeChecker): void; - get(importingFile: ts.Path, key: string): readonly SymbolExportInfo[] | undefined; - search(importingFile: ts.Path, preferCapitalized: boolean, matches: (name: string, targetFlags: ts.SymbolFlags) => boolean, action: (info: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean, key: string) => T | undefined): T | undefined; + add(importingFile: Path, symbol: Symbol, key: __String, moduleSymbol: Symbol, moduleFile: SourceFile | undefined, exportKind: ExportKind, isFromPackageJson: boolean, checker: TypeChecker): void; + get(importingFile: Path, key: string): readonly SymbolExportInfo[] | undefined; + search(importingFile: Path, preferCapitalized: boolean, matches: (name: string, targetFlags: SymbolFlags) => boolean, action: (info: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean, key: string) => T | undefined): T | undefined; releaseSymbols(): void; isEmpty(): boolean; /** @returns Whether the change resulted in the cache being cleared */ - onFileChanged(oldSourceFile: ts.SourceFile, newSourceFile: ts.SourceFile, typeAcquisitionEnabled: boolean): boolean; + onFileChanged(oldSourceFile: SourceFile, newSourceFile: SourceFile, typeAcquisitionEnabled: boolean): boolean; } /** @internal */ export interface CacheableExportInfoMapHost { - getCurrentProgram(): ts.Program | undefined; - getPackageJsonAutoImportProvider(): ts.Program | undefined; + getCurrentProgram(): Program | undefined; + getPackageJsonAutoImportProvider(): Program | undefined; getGlobalTypingsCacheLocation(): string | undefined; } /** @internal */ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): ExportInfoMap { let exportInfoId = 1; - const exportInfo = ts.createMultiMap(); - const symbols = new ts.Map(); + const exportInfo = createMultiMap(); + const symbols = new Map(); /** * Key: node_modules package name (no @types). * Value: path to deepest node_modules folder seen that is @@ -82,8 +94,8 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): * node_modules folder by seeing if its path starts with the * value stored here. */ - const packages = new ts.Map(); - let usableByFileName: ts.Path | undefined; + const packages = new Map(); + let usableByFileName: Path | undefined; const cache: ExportInfoMap = { isUsableByFile: importingFile => importingFile === usableByFileName, isEmpty: () => !exportInfo.size, @@ -100,15 +112,15 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): let packageName; if (moduleFile) { - const nodeModulesPathParts = ts.getNodeModulePathParts(moduleFile.fileName); + const nodeModulesPathParts = getNodeModulePathParts(moduleFile.fileName); if (nodeModulesPathParts) { const { topLevelNodeModulesIndex, topLevelPackageNameIndex, packageRootIndex } = nodeModulesPathParts; - packageName = ts.unmangleScopedPackageName(ts.getPackageNameFromTypesPackageName(moduleFile.fileName.substring(topLevelPackageNameIndex + 1, packageRootIndex))); - if (ts.startsWith(importingFile, moduleFile.path.substring(0, topLevelNodeModulesIndex))) { + packageName = unmangleScopedPackageName(getPackageNameFromTypesPackageName(moduleFile.fileName.substring(topLevelPackageNameIndex + 1, packageRootIndex))); + if (startsWith(importingFile, moduleFile.path.substring(0, topLevelNodeModulesIndex))) { const prevDeepestNodeModulesPath = packages.get(packageName); const nodeModulesPath = moduleFile.fileName.substring(0, topLevelPackageNameIndex + 1); if (prevDeepestNodeModulesPath) { - const prevDeepestNodeModulesIndex = prevDeepestNodeModulesPath.indexOf(ts.nodeModulesPathPart); + const prevDeepestNodeModulesIndex = prevDeepestNodeModulesPath.indexOf(nodeModulesPathPart); if (topLevelNodeModulesIndex > prevDeepestNodeModulesIndex) { packages.set(packageName, nodeModulesPath); } @@ -121,7 +133,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): } const isDefault = exportKind === ExportKind.Default; - const namedSymbol = isDefault && ts.getLocalSymbolForExportDefault(symbol) || symbol; + const namedSymbol = isDefault && getLocalSymbolForExportDefault(symbol) || symbol; // 1. A named export must be imported by its key in `moduleSymbol.exports` or `moduleSymbol.members`. // 2. A re-export merged with an export from a module augmentation can result in `symbol` // being an external module symbol; the name it is re-exported by will be `symbolTableKey` @@ -129,21 +141,21 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): // 3. Otherwise, we have a default/namespace import that can be imported by any name, and // `symbolTableKey` will be something undesirable like `export=` or `default`, so we try to // get a better name. - const names = exportKind === ExportKind.Named || ts.isExternalModuleSymbol(namedSymbol) - ? ts.unescapeLeadingUnderscores(symbolTableKey) - : ts.getNamesForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined); + const names = exportKind === ExportKind.Named || isExternalModuleSymbol(namedSymbol) + ? unescapeLeadingUnderscores(symbolTableKey) + : getNamesForExportedSymbol(namedSymbol, /*scriptTarget*/ undefined); const symbolName = typeof names === "string" ? names : names[0]; const capitalizedSymbolName = typeof names === "string" ? undefined : names[1]; - const moduleName = ts.stripQuotes(moduleSymbol.name); + const moduleName = stripQuotes(moduleSymbol.name); const id = exportInfoId++; - const target = ts.skipAlias(symbol, checker); - const storedSymbol = symbol.flags & ts.SymbolFlags.Transient ? undefined : symbol; - const storedModuleSymbol = moduleSymbol.flags & ts.SymbolFlags.Transient ? undefined : moduleSymbol; + const target = skipAlias(symbol, checker); + const storedSymbol = symbol.flags & SymbolFlags.Transient ? undefined : symbol; + const storedModuleSymbol = moduleSymbol.flags & SymbolFlags.Transient ? undefined : moduleSymbol; if (!storedSymbol || !storedModuleSymbol) symbols.set(id, [symbol, moduleSymbol]); - exportInfo.add(key(symbolName, symbol, ts.isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), { + exportInfo.add(key(symbolName, symbol, isExternalModuleNameRelative(moduleName) ? undefined : moduleName, checker), { id, symbolTableKey, symbolName, @@ -166,7 +178,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): }, search: (importingFile, preferCapitalized, matches, action) => { if (importingFile !== usableByFileName) return; - return ts.forEachEntry(exportInfo, (info, key) => { + return forEachEntry(exportInfo, (info, key) => { const { symbolName, ambientModuleName } = parseKey(key); const name = preferCapitalized && info[0].capitalizedSymbolName || symbolName; if (matches(name, info[0].targetFlags)) { @@ -182,7 +194,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): releaseSymbols: () => { symbols.clear(); }, - onFileChanged: (oldSourceFile: ts.SourceFile, newSourceFile: ts.SourceFile, typeAcquisitionEnabled: boolean) => { + onFileChanged: (oldSourceFile: SourceFile, newSourceFile: SourceFile, typeAcquisitionEnabled: boolean) => { if (fileIsGlobalOnly(oldSourceFile) && fileIsGlobalOnly(newSourceFile)) { // File is purely global; doesn't affect export map return false; @@ -191,11 +203,11 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): usableByFileName && usableByFileName !== newSourceFile.path || // If ATA is enabled, auto-imports uses existing imports to guess whether you want auto-imports from node. // Adding or removing imports from node could change the outcome of that guess, so could change the suggestions list. - typeAcquisitionEnabled && ts.consumesNodeCoreModules(oldSourceFile) !== ts.consumesNodeCoreModules(newSourceFile) || + typeAcquisitionEnabled && consumesNodeCoreModules(oldSourceFile) !== consumesNodeCoreModules(newSourceFile) || // Module agumentation and ambient module changes can add or remove exports available to be auto-imported. // Changes elsewhere in the file can change the *type* of an export in a module augmentation, // but type info is gathered in getCompletionEntryDetails, which doesn’t use the cache. - !ts.arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations) || + !arrayIsEqualTo(oldSourceFile.moduleAugmentations, newSourceFile.moduleAugmentations) || !ambientModuleDeclarationsAreEqual(oldSourceFile, newSourceFile) ) { cache.clear(); @@ -205,7 +217,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): return false; }, }; - if (ts.Debug.isDebugging) { + if (Debug.isDebugging) { Object.defineProperty(cache, "__cache", { get: () => exportInfo }); } return cache; @@ -213,7 +225,7 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): function rehydrateCachedInfo(info: CachedSymbolExportInfo): SymbolExportInfo { if (info.symbol && info.moduleSymbol) return info as SymbolExportInfo; const { id, exportKind, targetFlags, isFromPackageJson, moduleFileName } = info; - const [cachedSymbol, cachedModuleSymbol] = symbols.get(id) || ts.emptyArray; + const [cachedSymbol, cachedModuleSymbol] = symbols.get(id) || emptyArray; if (cachedSymbol && cachedModuleSymbol) { return { symbol: cachedSymbol, @@ -227,12 +239,12 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): const checker = (isFromPackageJson ? host.getPackageJsonAutoImportProvider()! : host.getCurrentProgram()!).getTypeChecker(); - const moduleSymbol = info.moduleSymbol || cachedModuleSymbol || ts.Debug.checkDefined(info.moduleFile + const moduleSymbol = info.moduleSymbol || cachedModuleSymbol || Debug.checkDefined(info.moduleFile ? checker.getMergedSymbol(info.moduleFile.symbol) : checker.tryFindAmbientModule(info.moduleName)); - const symbol = info.symbol || cachedSymbol || ts.Debug.checkDefined(exportKind === ExportKind.ExportEquals + const symbol = info.symbol || cachedSymbol || Debug.checkDefined(exportKind === ExportKind.ExportEquals ? checker.resolveExternalModuleSymbol(moduleSymbol) - : checker.tryGetMemberInModuleExportsAndProperties(ts.unescapeLeadingUnderscores(info.symbolTableKey), moduleSymbol), + : checker.tryGetMemberInModuleExportsAndProperties(unescapeLeadingUnderscores(info.symbolTableKey), moduleSymbol), `Could not find symbol '${info.symbolName}' by key '${info.symbolTableKey}' in module ${moduleSymbol.name}`); symbols.set(id, [symbol, moduleSymbol]); return { @@ -245,9 +257,9 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): }; } - function key(importedName: string, symbol: ts.Symbol, ambientModuleName: string | undefined, checker: ts.TypeChecker): string { + function key(importedName: string, symbol: Symbol, ambientModuleName: string | undefined, checker: TypeChecker): string { const moduleKey = ambientModuleName || ""; - return `${importedName}|${ts.getSymbolId(ts.skipAlias(symbol, checker))}|${moduleKey}`; + return `${importedName}|${getSymbolId(skipAlias(symbol, checker))}|${moduleKey}`; } function parseKey(key: string) { @@ -257,20 +269,20 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): return { symbolName, ambientModuleName }; } - function fileIsGlobalOnly(file: ts.SourceFile) { + function fileIsGlobalOnly(file: SourceFile) { return !file.commonJsModuleIndicator && !file.externalModuleIndicator && !file.moduleAugmentations && !file.ambientModuleNames; } - function ambientModuleDeclarationsAreEqual(oldSourceFile: ts.SourceFile, newSourceFile: ts.SourceFile) { - if (!ts.arrayIsEqualTo(oldSourceFile.ambientModuleNames, newSourceFile.ambientModuleNames)) { + function ambientModuleDeclarationsAreEqual(oldSourceFile: SourceFile, newSourceFile: SourceFile) { + if (!arrayIsEqualTo(oldSourceFile.ambientModuleNames, newSourceFile.ambientModuleNames)) { return false; } let oldFileStatementIndex = -1; let newFileStatementIndex = -1; for (const ambientModuleName of newSourceFile.ambientModuleNames) { - const isMatchingModuleDeclaration = (node: ts.Statement) => ts.isNonGlobalAmbientModule(node) && node.name.text === ambientModuleName; - oldFileStatementIndex = ts.findIndex(oldSourceFile.statements, isMatchingModuleDeclaration, oldFileStatementIndex + 1); - newFileStatementIndex = ts.findIndex(newSourceFile.statements, isMatchingModuleDeclaration, newFileStatementIndex + 1); + const isMatchingModuleDeclaration = (node: Statement) => isNonGlobalAmbientModule(node) && node.name.text === ambientModuleName; + oldFileStatementIndex = findIndex(oldSourceFile.statements, isMatchingModuleDeclaration, oldFileStatementIndex + 1); + newFileStatementIndex = findIndex(newSourceFile.statements, isMatchingModuleDeclaration, newFileStatementIndex + 1); if (oldSourceFile.statements[oldFileStatementIndex] !== newSourceFile.statements[newFileStatementIndex]) { return false; } @@ -281,21 +293,21 @@ export function createCacheableExportInfoMap(host: CacheableExportInfoMapHost): function isNotShadowedByDeeperNodeModulesPackage(info: SymbolExportInfo, packageName: string | undefined) { if (!packageName || !info.moduleFileName) return true; const typingsCacheLocation = host.getGlobalTypingsCacheLocation(); - if (typingsCacheLocation && ts.startsWith(info.moduleFileName, typingsCacheLocation)) return true; + if (typingsCacheLocation && startsWith(info.moduleFileName, typingsCacheLocation)) return true; const packageDeepestNodeModulesPath = packages.get(packageName); - return !packageDeepestNodeModulesPath || ts.startsWith(info.moduleFileName, packageDeepestNodeModulesPath); + return !packageDeepestNodeModulesPath || startsWith(info.moduleFileName, packageDeepestNodeModulesPath); } } /** @internal */ export function isImportableFile( - program: ts.Program, - from: ts.SourceFile, - to: ts.SourceFile, - preferences: ts.UserPreferences, - packageJsonFilter: ts.PackageJsonImportFilter | undefined, - moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost, - moduleSpecifierCache: ts.ModuleSpecifierCache | undefined, + program: Program, + from: SourceFile, + to: SourceFile, + preferences: UserPreferences, + packageJsonFilter: PackageJsonImportFilter | undefined, + moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost, + moduleSpecifierCache: ModuleSpecifierCache | undefined, ): boolean { if (from === to) return false; const cachedResult = moduleSpecifierCache?.get(from.path, to.path, preferences, {}); @@ -303,9 +315,9 @@ export function isImportableFile( return !cachedResult.isBlockedByPackageJsonDependencies; } - const getCanonicalFileName = ts.hostGetCanonicalFileName(moduleSpecifierResolutionHost); + const getCanonicalFileName = hostGetCanonicalFileName(moduleSpecifierResolutionHost); const globalTypingsCache = moduleSpecifierResolutionHost.getGlobalTypingsCacheLocation?.(); - const hasImportablePath = !!ts.moduleSpecifiers.forEachFileNameOfModule( + const hasImportablePath = !!moduleSpecifiers.forEachFileNameOfModule( from.fileName, to.fileName, moduleSpecifierResolutionHost, @@ -332,57 +344,57 @@ export function isImportableFile( * Don't include something from a `node_modules` that isn't actually reachable by a global import. * A relative import to node_modules is usually a bad idea. */ -function isImportablePath(fromPath: string, toPath: string, getCanonicalFileName: ts.GetCanonicalFileName, globalCachePath?: string): boolean { +function isImportablePath(fromPath: string, toPath: string, getCanonicalFileName: GetCanonicalFileName, globalCachePath?: string): boolean { // If it's in a `node_modules` but is not reachable from here via a global import, don't bother. - const toNodeModules = ts.forEachAncestorDirectory(toPath, ancestor => ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined); - const toNodeModulesParent = toNodeModules && ts.getDirectoryPath(getCanonicalFileName(toNodeModules)); + const toNodeModules = forEachAncestorDirectory(toPath, ancestor => getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined); + const toNodeModulesParent = toNodeModules && getDirectoryPath(getCanonicalFileName(toNodeModules)); return toNodeModulesParent === undefined - || ts.startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) - || (!!globalCachePath && ts.startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); + || startsWith(getCanonicalFileName(fromPath), toNodeModulesParent) + || (!!globalCachePath && startsWith(getCanonicalFileName(globalCachePath), toNodeModulesParent)); } /** @internal */ export function forEachExternalModuleToImportFrom( - program: ts.Program, - host: ts.LanguageServiceHost, - preferences: ts.UserPreferences, + program: Program, + host: LanguageServiceHost, + preferences: UserPreferences, useAutoImportProvider: boolean, - cb: (module: ts.Symbol, moduleFile: ts.SourceFile | undefined, program: ts.Program, isFromPackageJson: boolean) => void, + cb: (module: Symbol, moduleFile: SourceFile | undefined, program: Program, isFromPackageJson: boolean) => void, ) { - const useCaseSensitiveFileNames = ts.hostUsesCaseSensitiveFileNames(host); - const excludePatterns = preferences.autoImportFileExcludePatterns && ts.mapDefined(preferences.autoImportFileExcludePatterns, spec => { + const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); + const excludePatterns = preferences.autoImportFileExcludePatterns && mapDefined(preferences.autoImportFileExcludePatterns, spec => { // The client is expected to send rooted path specs since we don't know // what directory a relative path is relative to. - const pattern = ts.getPatternFromSpec(spec, "", "exclude"); - return pattern ? ts.getRegexFromPattern(pattern, useCaseSensitiveFileNames) : undefined; + const pattern = getPatternFromSpec(spec, "", "exclude"); + return pattern ? getRegexFromPattern(pattern, useCaseSensitiveFileNames) : undefined; }); forEachExternalModule(program.getTypeChecker(), program.getSourceFiles(), excludePatterns, (module, file) => cb(module, file, program, /*isFromPackageJson*/ false)); const autoImportProvider = useAutoImportProvider && host.getPackageJsonAutoImportProvider?.(); if (autoImportProvider) { - const start = ts.timestamp(); + const start = timestamp(); forEachExternalModule(autoImportProvider.getTypeChecker(), autoImportProvider.getSourceFiles(), excludePatterns, (module, file) => cb(module, file, autoImportProvider, /*isFromPackageJson*/ true)); - host.log?.(`forEachExternalModuleToImportFrom autoImportProvider: ${ts.timestamp() - start}`); + host.log?.(`forEachExternalModuleToImportFrom autoImportProvider: ${timestamp() - start}`); } } -function forEachExternalModule(checker: ts.TypeChecker, allSourceFiles: readonly ts.SourceFile[], excludePatterns: readonly RegExp[] | undefined, cb: (module: ts.Symbol, sourceFile: ts.SourceFile | undefined) => void) { +function forEachExternalModule(checker: TypeChecker, allSourceFiles: readonly SourceFile[], excludePatterns: readonly RegExp[] | undefined, cb: (module: Symbol, sourceFile: SourceFile | undefined) => void) { const isExcluded = (fileName: string) => excludePatterns?.some(p => p.test(fileName)); for (const ambient of checker.getAmbientModules()) { - if (!ts.stringContains(ambient.name, "*") && !(excludePatterns && ambient.declarations?.every(d => isExcluded(d.getSourceFile().fileName)))) { + if (!stringContains(ambient.name, "*") && !(excludePatterns && ambient.declarations?.every(d => isExcluded(d.getSourceFile().fileName)))) { cb(ambient, /*sourceFile*/ undefined); } } for (const sourceFile of allSourceFiles) { - if (ts.isExternalOrCommonJsModule(sourceFile) && !isExcluded(sourceFile.fileName)) { + if (isExternalOrCommonJsModule(sourceFile) && !isExcluded(sourceFile.fileName)) { cb(checker.getMergedSymbol(sourceFile.symbol), sourceFile); } } } /** @internal */ -export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.LanguageServiceHost, program: ts.Program, preferences: ts.UserPreferences, cancellationToken: ts.CancellationToken | undefined): ExportInfoMap { - const start = ts.timestamp(); +export function getExportInfoMap(importingFile: SourceFile, host: LanguageServiceHost, program: Program, preferences: UserPreferences, cancellationToken: CancellationToken | undefined): ExportInfoMap { + const start = timestamp(); // Pulling the AutoImportProvider project will trigger its updateGraph if pending, // which will invalidate the export map cache if things change, so pull it before // checking the cache. @@ -404,7 +416,7 @@ export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.Language try { forEachExternalModuleToImportFrom(program, host, preferences, /*useAutoImportProvider*/ true, (moduleSymbol, moduleFile, program, isFromPackageJson) => { if (++moduleCount % 100 === 0) cancellationToken?.throwIfCancellationRequested(); - const seenExports = new ts.Map(); + const seenExports = new Map<__String, true>(); const checker = program.getTypeChecker(); const defaultInfo = getDefaultLikeExportInfo(moduleSymbol, checker, compilerOptions); // Note: I think we shouldn't actually see resolved module symbols here, but weird merges @@ -413,7 +425,7 @@ export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.Language cache.add( importingFile.path, defaultInfo.symbol, - defaultInfo.exportKind === ExportKind.Default ? ts.InternalSymbolName.Default : ts.InternalSymbolName.ExportEquals, + defaultInfo.exportKind === ExportKind.Default ? InternalSymbolName.Default : InternalSymbolName.ExportEquals, moduleSymbol, moduleFile, defaultInfo.exportKind, @@ -421,7 +433,7 @@ export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.Language checker); } checker.forEachExportAndPropertyOfModule(moduleSymbol, (exported, key) => { - if (exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) && ts.addToSeen(seenExports, key)) { + if (exported !== defaultInfo?.symbol && isImportableSymbol(exported, checker) && addToSeen(seenExports, key)) { cache.add( importingFile.path, exported, @@ -441,12 +453,12 @@ export function getExportInfoMap(importingFile: ts.SourceFile, host: ts.Language throw err; } - host.log?.(`getExportInfoMap: done in ${ts.timestamp() - start} ms`); + host.log?.(`getExportInfoMap: done in ${timestamp() - start} ms`); return cache; } /** @internal */ -export function getDefaultLikeExportInfo(moduleSymbol: ts.Symbol, checker: ts.TypeChecker, compilerOptions: ts.CompilerOptions) { +export function getDefaultLikeExportInfo(moduleSymbol: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions) { const exported = getDefaultLikeExportWorker(moduleSymbol, checker); if (!exported) return undefined; const { symbol, exportKind } = exported; @@ -454,25 +466,25 @@ export function getDefaultLikeExportInfo(moduleSymbol: ts.Symbol, checker: ts.Ty return info && { symbol, exportKind, ...info }; } -function isImportableSymbol(symbol: ts.Symbol, checker: ts.TypeChecker) { - return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !ts.isKnownSymbol(symbol) && !ts.isPrivateIdentifierSymbol(symbol); +function isImportableSymbol(symbol: Symbol, checker: TypeChecker) { + return !checker.isUndefinedSymbol(symbol) && !checker.isUnknownSymbol(symbol) && !isKnownSymbol(symbol) && !isPrivateIdentifierSymbol(symbol); } -function getDefaultLikeExportWorker(moduleSymbol: ts.Symbol, checker: ts.TypeChecker): { readonly symbol: ts.Symbol, readonly exportKind: ExportKind } | undefined { +function getDefaultLikeExportWorker(moduleSymbol: Symbol, checker: TypeChecker): { readonly symbol: Symbol, readonly exportKind: ExportKind } | undefined { const exportEquals = checker.resolveExternalModuleSymbol(moduleSymbol); if (exportEquals !== moduleSymbol) return { symbol: exportEquals, exportKind: ExportKind.ExportEquals }; - const defaultExport = checker.tryGetMemberInModuleExports(ts.InternalSymbolName.Default, moduleSymbol); + const defaultExport = checker.tryGetMemberInModuleExports(InternalSymbolName.Default, moduleSymbol); if (defaultExport) return { symbol: defaultExport, exportKind: ExportKind.Default }; } -function getDefaultExportInfoWorker(defaultExport: ts.Symbol, checker: ts.TypeChecker, compilerOptions: ts.CompilerOptions): { readonly symbolForMeaning: ts.Symbol, readonly name: string } | undefined { - const localSymbol = ts.getLocalSymbolForExportDefault(defaultExport); +function getDefaultExportInfoWorker(defaultExport: Symbol, checker: TypeChecker, compilerOptions: CompilerOptions): { readonly symbolForMeaning: Symbol, readonly name: string } | undefined { + const localSymbol = getLocalSymbolForExportDefault(defaultExport); if (localSymbol) return { symbolForMeaning: localSymbol, name: localSymbol.name }; const name = getNameForExportDefault(defaultExport); if (name !== undefined) return { symbolForMeaning: defaultExport, name }; - if (defaultExport.flags & ts.SymbolFlags.Alias) { + if (defaultExport.flags & SymbolFlags.Alias) { const aliased = checker.getImmediateAliasedSymbol(defaultExport); if (aliased && aliased.parent) { // - `aliased` will be undefined if the module is exporting an unresolvable name, @@ -483,20 +495,20 @@ function getDefaultExportInfoWorker(defaultExport: ts.Symbol, checker: ts.TypeCh } } - if (defaultExport.escapedName !== ts.InternalSymbolName.Default && - defaultExport.escapedName !== ts.InternalSymbolName.ExportEquals) { + if (defaultExport.escapedName !== InternalSymbolName.Default && + defaultExport.escapedName !== InternalSymbolName.ExportEquals) { return { symbolForMeaning: defaultExport, name: defaultExport.getName() }; } - return { symbolForMeaning: defaultExport, name: ts.getNameForExportedSymbol(defaultExport, compilerOptions.target) }; + return { symbolForMeaning: defaultExport, name: getNameForExportedSymbol(defaultExport, compilerOptions.target) }; } -function getNameForExportDefault(symbol: ts.Symbol): string | undefined { - return symbol.declarations && ts.firstDefined(symbol.declarations, declaration => { - if (ts.isExportAssignment(declaration)) { - return ts.tryCast(ts.skipOuterExpressions(declaration.expression), ts.isIdentifier)?.text; +function getNameForExportDefault(symbol: Symbol): string | undefined { + return symbol.declarations && firstDefined(symbol.declarations, declaration => { + if (isExportAssignment(declaration)) { + return tryCast(skipOuterExpressions(declaration.expression), isIdentifier)?.text; } - else if (ts.isExportSpecifier(declaration)) { - ts.Debug.assert(declaration.name.text === ts.InternalSymbolName.Default, "Expected the specifier to be a default export"); + else if (isExportSpecifier(declaration)) { + Debug.assert(declaration.name.text === InternalSymbolName.Default, "Expected the specifier to be a default export"); return declaration.propertyName && declaration.propertyName.text; } }); diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 731785b9fc59d..1ccd8d74e0491 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1,4 +1,54 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, addToSeen, append, AssignmentDeclarationKind, BinaryExpression, BindingElement, Block, CallExpression, + CancellationToken, cast, CheckFlags, ClassLikeDeclaration, climbPastPropertyAccess, compareValues, + ConstructorDeclaration, contains, createQueue, createTextSpan, createTextSpanFromBounds, createTextSpanFromRange, + Debug, Declaration, displayPart, DocumentSpan, emptyArray, emptyOptions, escapeLeadingUnderscores, ESMap, + ExportSpecifier, Expression, FileIncludeReason, FileReference, filter, find, findAncestor, findChildOfKind, + findIndex, first, firstDefined, firstOrUndefined, flatMap, forEachChild, forEachReturnStatement, ForInOrOfStatement, + FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, GetAccessorDeclaration, + getAdjustedReferenceLocation, getAdjustedRenameLocation, getAllSuperTypeNodes, getAncestor, + getAssignmentDeclarationKind, getCheckFlags, getContainerNode, getContainingObjectLiteralElement, + getContextualTypeFromParentOrAncestorTypeNode, getDeclarationFromName, getDeclarationOfKind, + getEffectiveModifierFlags, getLocalSymbolForExportDefault, getMeaningFromDeclaration, getMeaningFromLocation, + getModeForUsageLocation, getNameOfDeclaration, getNameTable, getNextJSDocCommentLocation, getNodeId, getNodeKind, + getPropertySymbolFromBindingElement, getPropertySymbolsFromContextualType, getReferencedFileLocation, + getSuperContainer, getSymbolId, getSyntacticModifierFlags, getTargetLabel, getTextOfNode, getThisContainer, + getTouchingPropertyName, GoToDefinition, hasEffectiveModifier, hasInitializer, hasSyntacticModifier, hasType, + HighlightSpan, HighlightSpanKind, Identifier, ImplementationLocation, InterfaceDeclaration, InternalSymbolName, + isAccessExpression, isArrayLiteralOrObjectLiteralDestructuringPattern, isAssertionExpression, isBinaryExpression, + isBindableObjectDefinePropertyCall, isBindingElement, isBreakOrContinueStatement, isCallExpression, + isCallExpressionTarget, isCatchClause, isClassLike, isClassStaticBlockDeclaration, isComputedPropertyName, + isConstructorDeclaration, isDeclaration, isDeclarationName, isExportAssignment, isExportSpecifier, + isExpressionOfExternalModuleImportEqualsDeclaration, isExpressionStatement, isExpressionWithTypeArguments, + isExternalModule, isExternalModuleSymbol, isExternalOrCommonJsModule, isForInOrOfStatement, isFunctionExpression, + isFunctionLike, isFunctionLikeDeclaration, isIdentifier, isIdentifierPart, isImportMeta, isImportOrExportSpecifier, + isImportSpecifier, isImportTypeNode, isInJSFile, isInNonReferenceComment, isInString, isInterfaceDeclaration, + isJSDocMemberName, isJSDocTag, isJsxClosingElement, isJsxOpeningElement, isJsxSelfClosingElement, + isJumpStatementTarget, isLabeledStatement, isLabelOfLabeledStatement, isLiteralComputedPropertyDeclarationName, + isLiteralNameOfPropertyDeclarationOrIndexAccess, isLiteralTypeNode, isMethodOrAccessor, isModuleDeclaration, + isModuleExportsAccessExpression, isModuleOrEnumDeclaration, isModuleSpecifierLike, isNameOfModuleDeclaration, + isNamespaceExportDeclaration, isNewExpressionTarget, isNoSubstitutionTemplateLiteral, + isObjectBindingElementWithoutPropertyName, isObjectLiteralExpression, isObjectLiteralMethod, isParameter, + isParameterPropertyDeclaration, isPrivateIdentifierClassElementDeclaration, isPropertyAccessExpression, + isQualifiedName, isReferencedFile, isReferenceFileLocation, isRightSideOfPropertyAccess, + isShorthandPropertyAssignment, isSourceFile, isStatement, isStatic, isStaticModifier, isStringLiteralLike, + isSuperProperty, isThis, isTypeAliasDeclaration, isTypeElement, isTypeKeyword, isTypeLiteralNode, isTypeNode, + isTypeOperatorNode, isUnionTypeNode, isVariableDeclarationInitializedToBareOrAccessedRequire, + isVariableDeclarationList, isVariableLike, isVariableStatement, isVoidExpression, isWriteAccess, JSDocTag, map, Map, + mapDefined, MethodDeclaration, ModifierFlags, ModuleDeclaration, MultiMap, NamedDeclaration, Node, NodeFlags, + nodeSeenTracker, NumericLiteral, ParameterDeclaration, ParenthesizedExpression, Path, PrivateIdentifier, Program, + PropertyAccessExpression, PropertyAssignment, PropertyDeclaration, punctuationPart, Push, rangeIsOnSingleLine, + ReadonlySet, ReferencedSymbol, ReferencedSymbolDefinitionInfo, ReferencedSymbolEntry, ReferenceEntry, + RenameLocation, ScriptElementKind, ScriptTarget, SemanticMeaning, Set, SetAccessorDeclaration, SignatureDeclaration, + skipAlias, some, SourceFile, Statement, StringLiteral, StringLiteralLike, stripQuotes, Symbol, SymbolDisplay, + SymbolDisplayPart, SymbolDisplayPartKind, SymbolFlags, SymbolId, symbolName, SyntaxKind, textPart, TextSpan, + tokenToString, tryAddToSet, tryCast, tryGetClassExtendingExpressionWithTypeArguments, + tryGetImportFromModuleSpecifier, TypeChecker, VariableDeclaration, +} from "./_namespaces/ts"; +import { + createImportTracker, ExportInfo, ExportKind, findModuleReferences, getExportInfo, getImportOrExportSymbol, + ImportExport, ImportsResult, ImportTracker, ModuleReference, +} from "./_namespaces/ts.FindAllReferences"; /** @internal */ export interface SymbolAndEntries { @@ -10,12 +60,12 @@ export interface SymbolAndEntries { export const enum DefinitionKind { Symbol, Label, Keyword, This, String, TripleSlashReference } /** @internal */ export type Definition = - | { readonly type: DefinitionKind.Symbol; readonly symbol: ts.Symbol } - | { readonly type: DefinitionKind.Label; readonly node: ts.Identifier } - | { readonly type: DefinitionKind.Keyword; readonly node: ts.Node } - | { readonly type: DefinitionKind.This; readonly node: ts.Node } - | { readonly type: DefinitionKind.String; readonly node: ts.StringLiteralLike } - | { readonly type: DefinitionKind.TripleSlashReference; readonly reference: ts.FileReference, readonly file: ts.SourceFile }; + | { readonly type: DefinitionKind.Symbol; readonly symbol: Symbol } + | { readonly type: DefinitionKind.Label; readonly node: Identifier } + | { readonly type: DefinitionKind.Keyword; readonly node: Node } + | { readonly type: DefinitionKind.This; readonly node: Node } + | { readonly type: DefinitionKind.String; readonly node: StringLiteralLike } + | { readonly type: DefinitionKind.TripleSlashReference; readonly reference: FileReference, readonly file: SourceFile }; /** @internal */ export const enum EntryKind { Span, Node, StringLiteral, SearchedLocalFoundProperty, SearchedPropertyFoundLocal } @@ -25,97 +75,97 @@ export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind export type Entry = NodeEntry | SpanEntry; /** @internal */ export interface ContextWithStartAndEndNode { - start: ts.Node; - end: ts.Node; + start: Node; + end: Node; } /** @internal */ -export type ContextNode = ts.Node | ContextWithStartAndEndNode; +export type ContextNode = Node | ContextWithStartAndEndNode; /** @internal */ export interface NodeEntry { readonly kind: NodeEntryKind; - readonly node: ts.Node; + readonly node: Node; readonly context?: ContextNode; } /** @internal */ export interface SpanEntry { readonly kind: EntryKind.Span; readonly fileName: string; - readonly textSpan: ts.TextSpan; + readonly textSpan: TextSpan; } /** @internal */ -export function nodeEntry(node: ts.Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry { +export function nodeEntry(node: Node, kind: NodeEntryKind = EntryKind.Node): NodeEntry { return { kind, - node: (node as ts.NamedDeclaration).name || node, + node: (node as NamedDeclaration).name || node, context: getContextNodeForNodeEntry(node) }; } /** @internal */ export function isContextWithStartAndEndNode(node: ContextNode): node is ContextWithStartAndEndNode { - return node && (node as ts.Node).kind === undefined; + return node && (node as Node).kind === undefined; } -function getContextNodeForNodeEntry(node: ts.Node): ContextNode | undefined { - if (ts.isDeclaration(node)) { +function getContextNodeForNodeEntry(node: Node): ContextNode | undefined { + if (isDeclaration(node)) { return getContextNode(node); } if (!node.parent) return undefined; - if (!ts.isDeclaration(node.parent) && !ts.isExportAssignment(node.parent)) { + if (!isDeclaration(node.parent) && !isExportAssignment(node.parent)) { // Special property assignment in javascript - if (ts.isInJSFile(node)) { - const binaryExpression = ts.isBinaryExpression(node.parent) ? + if (isInJSFile(node)) { + const binaryExpression = isBinaryExpression(node.parent) ? node.parent : - ts.isAccessExpression(node.parent) && - ts.isBinaryExpression(node.parent.parent) && + isAccessExpression(node.parent) && + isBinaryExpression(node.parent.parent) && node.parent.parent.left === node.parent ? node.parent.parent : undefined; - if (binaryExpression && ts.getAssignmentDeclarationKind(binaryExpression) !== ts.AssignmentDeclarationKind.None) { + if (binaryExpression && getAssignmentDeclarationKind(binaryExpression) !== AssignmentDeclarationKind.None) { return getContextNode(binaryExpression); } } // Jsx Tags - if (ts.isJsxOpeningElement(node.parent) || ts.isJsxClosingElement(node.parent)) { + if (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) { return node.parent.parent; } - else if (ts.isJsxSelfClosingElement(node.parent) || - ts.isLabeledStatement(node.parent) || - ts.isBreakOrContinueStatement(node.parent)) { + else if (isJsxSelfClosingElement(node.parent) || + isLabeledStatement(node.parent) || + isBreakOrContinueStatement(node.parent)) { return node.parent; } - else if (ts.isStringLiteralLike(node)) { - const validImport = ts.tryGetImportFromModuleSpecifier(node); + else if (isStringLiteralLike(node)) { + const validImport = tryGetImportFromModuleSpecifier(node); if (validImport) { - const declOrStatement = ts.findAncestor(validImport, node => - ts.isDeclaration(node) || - ts.isStatement(node) || - ts.isJSDocTag(node) - )! as ts.NamedDeclaration | ts.Statement | ts.JSDocTag; - return ts.isDeclaration(declOrStatement) ? + const declOrStatement = findAncestor(validImport, node => + isDeclaration(node) || + isStatement(node) || + isJSDocTag(node) + )! as NamedDeclaration | Statement | JSDocTag; + return isDeclaration(declOrStatement) ? getContextNode(declOrStatement) : declOrStatement; } } // Handle computed property name - const propertyName = ts.findAncestor(node, ts.isComputedPropertyName); + const propertyName = findAncestor(node, isComputedPropertyName); return propertyName ? getContextNode(propertyName.parent) : undefined; } if (node.parent.name === node || // node is name of declaration, use parent - ts.isConstructorDeclaration(node.parent) || - ts.isExportAssignment(node.parent) || + isConstructorDeclaration(node.parent) || + isExportAssignment(node.parent) || // Property name of the import export specifier or binding pattern, use parent - ((ts.isImportOrExportSpecifier(node.parent) || ts.isBindingElement(node.parent)) + ((isImportOrExportSpecifier(node.parent) || isBindingElement(node.parent)) && node.parent.propertyName === node) || // Is default export - (node.kind === ts.SyntaxKind.DefaultKeyword && ts.hasSyntacticModifier(node.parent, ts.ModifierFlags.ExportDefault))) { + (node.kind === SyntaxKind.DefaultKeyword && hasSyntacticModifier(node.parent, ModifierFlags.ExportDefault))) { return getContextNode(node.parent); } @@ -123,51 +173,51 @@ function getContextNodeForNodeEntry(node: ts.Node): ContextNode | undefined { } /** @internal */ -export function getContextNode(node: ts.NamedDeclaration | ts.BinaryExpression | ts.ForInOrOfStatement | undefined): ContextNode | undefined { +export function getContextNode(node: NamedDeclaration | BinaryExpression | ForInOrOfStatement | undefined): ContextNode | undefined { if (!node) return undefined; switch (node.kind) { - case ts.SyntaxKind.VariableDeclaration: - return !ts.isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ? + case SyntaxKind.VariableDeclaration: + return !isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ? node : - ts.isVariableStatement(node.parent.parent) ? + isVariableStatement(node.parent.parent) ? node.parent.parent : - ts.isForInOrOfStatement(node.parent.parent) ? + isForInOrOfStatement(node.parent.parent) ? getContextNode(node.parent.parent) : node.parent; - case ts.SyntaxKind.BindingElement: - return getContextNode(node.parent.parent as ts.NamedDeclaration); + case SyntaxKind.BindingElement: + return getContextNode(node.parent.parent as NamedDeclaration); - case ts.SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportSpecifier: return node.parent.parent.parent; - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.NamespaceImport: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.NamespaceImport: return node.parent.parent; - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceExport: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceExport: return node.parent; - case ts.SyntaxKind.BinaryExpression: - return ts.isExpressionStatement(node.parent) ? + case SyntaxKind.BinaryExpression: + return isExpressionStatement(node.parent) ? node.parent : node; - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForInStatement: return { - start: (node as ts.ForInOrOfStatement).initializer, - end: (node as ts.ForInOrOfStatement).expression + start: (node as ForInOrOfStatement).initializer, + end: (node as ForInOrOfStatement).expression }; - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ? + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + return isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ? getContextNode( - ts.findAncestor(node.parent, node => - ts.isBinaryExpression(node) || ts.isForInOrOfStatement(node) - ) as ts.BinaryExpression | ts.ForInOrOfStatement + findAncestor(node.parent, node => + isBinaryExpression(node) || isForInOrOfStatement(node) + ) as BinaryExpression | ForInOrOfStatement ) : node; @@ -177,7 +227,7 @@ export function getContextNode(node: ts.NamedDeclaration | ts.BinaryExpression | } /** @internal */ -export function toContextSpan(textSpan: ts.TextSpan, sourceFile: ts.SourceFile, context?: ContextNode): { contextSpan: ts.TextSpan } | undefined { +export function toContextSpan(textSpan: TextSpan, sourceFile: SourceFile, context?: ContextNode): { contextSpan: TextSpan } | undefined { if (!context) return undefined; const contextSpan = isContextWithStartAndEndNode(context) ? getTextSpan(context.start, sourceFile, context.end) : @@ -221,15 +271,15 @@ export interface Options { } /** @internal */ -export function findReferencedSymbols(program: ts.Program, cancellationToken: ts.CancellationToken, sourceFiles: readonly ts.SourceFile[], sourceFile: ts.SourceFile, position: number): ts.ReferencedSymbol[] | undefined { - const node = ts.getTouchingPropertyName(sourceFile, position); +export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined { + const node = getTouchingPropertyName(sourceFile, position); const options = { use: FindReferencesUse.References }; const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options); const checker = program.getTypeChecker(); // Unless the starting node is a declaration (vs e.g. JSDoc), don't attempt to compute isDefinition const adjustedNode = Core.getAdjustedNode(node, options); const symbol = isDefinitionForReference(adjustedNode) ? checker.getSymbolAtLocation(adjustedNode) : undefined; - return !referencedSymbols || !referencedSymbols.length ? undefined : ts.mapDefined(referencedSymbols, ({ definition, references }) => + return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) => // Only include referenced symbols that have a valid definition. definition && { definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)), @@ -237,36 +287,36 @@ export function findReferencedSymbols(program: ts.Program, cancellationToken: ts }); } -function isDefinitionForReference(node: ts.Node): boolean { - return node.kind === ts.SyntaxKind.DefaultKeyword - || !!ts.getDeclarationFromName(node) - || ts.isLiteralComputedPropertyDeclarationName(node) - || (node.kind === ts.SyntaxKind.ConstructorKeyword && ts.isConstructorDeclaration(node.parent)); +function isDefinitionForReference(node: Node): boolean { + return node.kind === SyntaxKind.DefaultKeyword + || !!getDeclarationFromName(node) + || isLiteralComputedPropertyDeclarationName(node) + || (node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent)); } /** @internal */ -export function getImplementationsAtPosition(program: ts.Program, cancellationToken: ts.CancellationToken, sourceFiles: readonly ts.SourceFile[], sourceFile: ts.SourceFile, position: number): ts.ImplementationLocation[] | undefined { - const node = ts.getTouchingPropertyName(sourceFile, position); +export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined { + const node = getTouchingPropertyName(sourceFile, position); let referenceEntries: Entry[] | undefined; const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position); if ( - node.parent.kind === ts.SyntaxKind.PropertyAccessExpression - || node.parent.kind === ts.SyntaxKind.BindingElement - || node.parent.kind === ts.SyntaxKind.ElementAccessExpression - || node.kind === ts.SyntaxKind.SuperKeyword + node.parent.kind === SyntaxKind.PropertyAccessExpression + || node.parent.kind === SyntaxKind.BindingElement + || node.parent.kind === SyntaxKind.ElementAccessExpression + || node.kind === SyntaxKind.SuperKeyword ) { referenceEntries = entries && [...entries]; } else if (entries) { - const queue = ts.createQueue(entries); - const seenNodes = new ts.Map(); + const queue = createQueue(entries); + const seenNodes = new Map(); while (!queue.isEmpty()) { const entry = queue.dequeue() as NodeEntry; - if (!ts.addToSeen(seenNodes, ts.getNodeId(entry.node))) { + if (!addToSeen(seenNodes, getNodeId(entry.node))) { continue; } - referenceEntries = ts.append(referenceEntries, entry); + referenceEntries = append(referenceEntries, entry); const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, entry.node, entry.node.pos); if (entries) { queue.enqueue(...entries); @@ -274,23 +324,23 @@ export function getImplementationsAtPosition(program: ts.Program, cancellationTo } } const checker = program.getTypeChecker(); - return ts.map(referenceEntries, entry => toImplementationLocation(entry, checker)); + return map(referenceEntries, entry => toImplementationLocation(entry, checker)); } -function getImplementationReferenceEntries(program: ts.Program, cancellationToken: ts.CancellationToken, sourceFiles: readonly ts.SourceFile[], node: ts.Node, position: number): readonly Entry[] | undefined { - if (node.kind === ts.SyntaxKind.SourceFile) { +function getImplementationReferenceEntries(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], node: Node, position: number): readonly Entry[] | undefined { + if (node.kind === SyntaxKind.SourceFile) { return undefined; } const checker = program.getTypeChecker(); // If invoked directly on a shorthand property assignment, then return // the declaration of the symbol being assigned (not the symbol being assigned to). - if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { const result: NodeEntry[] = []; Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, node => result.push(nodeEntry(node))); return result; } - else if (node.kind === ts.SyntaxKind.SuperKeyword || ts.isSuperProperty(node.parent)) { + else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) { // References to and accesses on the super keyword only have one possible implementation, so no // need to "Find all References" const symbol = checker.getSymbolAtLocation(node)!; @@ -304,41 +354,41 @@ function getImplementationReferenceEntries(program: ts.Program, cancellationToke /** @internal */ export function findReferenceOrRenameEntries( - program: ts.Program, cancellationToken: ts.CancellationToken, sourceFiles: readonly ts.SourceFile[], node: ts.Node, position: number, options: Options | undefined, + program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], node: Node, position: number, options: Options | undefined, convertEntry: ToReferenceOrRenameEntry, ): T[] | undefined { - return ts.map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node, program.getTypeChecker())); + return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node, program.getTypeChecker())); } /** @internal */ -export type ToReferenceOrRenameEntry = (entry: Entry, originalNode: ts.Node, checker: ts.TypeChecker) => T; +export type ToReferenceOrRenameEntry = (entry: Entry, originalNode: Node, checker: TypeChecker) => T; /** @internal */ export function getReferenceEntriesForNode( position: number, - node: ts.Node, - program: ts.Program, - sourceFiles: readonly ts.SourceFile[], - cancellationToken: ts.CancellationToken, + node: Node, + program: Program, + sourceFiles: readonly SourceFile[], + cancellationToken: CancellationToken, options: Options = {}, - sourceFilesSet: ts.ReadonlySet = new ts.Set(sourceFiles.map(f => f.fileName)), + sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName)), ): readonly Entry[] | undefined { return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet)); } function flattenEntries(referenceSymbols: readonly SymbolAndEntries[] | undefined): readonly Entry[] | undefined { - return referenceSymbols && ts.flatMap(referenceSymbols, r => r.references); + return referenceSymbols && flatMap(referenceSymbols, r => r.references); } -function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: ts.TypeChecker, originalNode: ts.Node): ts.ReferencedSymbolDefinitionInfo { - const info = ((): { sourceFile: ts.SourceFile, textSpan: ts.TextSpan, name: string, kind: ts.ScriptElementKind, displayParts: ts.SymbolDisplayPart[], context?: ts.Node | ContextWithStartAndEndNode } => { +function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo { + const info = ((): { sourceFile: SourceFile, textSpan: TextSpan, name: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], context?: Node | ContextWithStartAndEndNode } => { switch (def.type) { case DefinitionKind.Symbol: { const { symbol } = def; const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode); const name = displayParts.map(p => p.text).join(""); - const declaration = symbol.declarations && ts.firstOrUndefined(symbol.declarations); - const node = declaration ? (ts.getNameOfDeclaration(declaration) || declaration) : originalNode; + const declaration = symbol.declarations && firstOrUndefined(symbol.declarations); + const node = declaration ? (getNameOfDeclaration(declaration) || declaration) : originalNode; return { ...getFileAndTextSpanFromNode(node), name, @@ -349,46 +399,46 @@ function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: ts } case DefinitionKind.Label: { const { node } = def; - return { ...getFileAndTextSpanFromNode(node), name: node.text, kind: ts.ScriptElementKind.label, displayParts: [ts.displayPart(node.text, ts.SymbolDisplayPartKind.text)] }; + return { ...getFileAndTextSpanFromNode(node), name: node.text, kind: ScriptElementKind.label, displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)] }; } case DefinitionKind.Keyword: { const { node } = def; - const name = ts.tokenToString(node.kind)!; - return { ...getFileAndTextSpanFromNode(node), name, kind: ts.ScriptElementKind.keyword, displayParts: [{ text: name, kind: ts.ScriptElementKind.keyword }] }; + const name = tokenToString(node.kind)!; + return { ...getFileAndTextSpanFromNode(node), name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] }; } case DefinitionKind.This: { const { node } = def; const symbol = checker.getSymbolAtLocation(node); - const displayParts = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( - checker, symbol, node.getSourceFile(), ts.getContainerNode(node), node).displayParts || [ts.textPart("this")]; - return { ...getFileAndTextSpanFromNode(node), name: "this", kind: ts.ScriptElementKind.variableElement, displayParts }; + const displayParts = symbol && SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind( + checker, symbol, node.getSourceFile(), getContainerNode(node), node).displayParts || [textPart("this")]; + return { ...getFileAndTextSpanFromNode(node), name: "this", kind: ScriptElementKind.variableElement, displayParts }; } case DefinitionKind.String: { const { node } = def; return { ...getFileAndTextSpanFromNode(node), name: node.text, - kind: ts.ScriptElementKind.variableElement, - displayParts: [ts.displayPart(ts.getTextOfNode(node), ts.SymbolDisplayPartKind.stringLiteral)] + kind: ScriptElementKind.variableElement, + displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)] }; } case DefinitionKind.TripleSlashReference: { return { - textSpan: ts.createTextSpanFromRange(def.reference), + textSpan: createTextSpanFromRange(def.reference), sourceFile: def.file, name: def.reference.fileName, - kind: ts.ScriptElementKind.string, - displayParts: [ts.displayPart(`"${def.reference.fileName}"`, ts.SymbolDisplayPartKind.stringLiteral)] + kind: ScriptElementKind.string, + displayParts: [displayPart(`"${def.reference.fileName}"`, SymbolDisplayPartKind.stringLiteral)] }; } default: - return ts.Debug.assertNever(def); + return Debug.assertNever(def); } })(); const { sourceFile, textSpan, name, kind, displayParts, context } = info; return { - containerKind: ts.ScriptElementKind.unknown, + containerKind: ScriptElementKind.unknown, containerName: "", fileName: sourceFile.fileName, kind, @@ -399,28 +449,28 @@ function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: ts }; } -function getFileAndTextSpanFromNode(node: ts.Node) { +function getFileAndTextSpanFromNode(node: Node) { const sourceFile = node.getSourceFile(); return { sourceFile, - textSpan: getTextSpan(ts.isComputedPropertyName(node) ? node.expression : node, sourceFile) + textSpan: getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile) }; } -function getDefinitionKindAndDisplayParts(symbol: ts.Symbol, checker: ts.TypeChecker, node: ts.Node): { displayParts: ts.SymbolDisplayPart[], kind: ts.ScriptElementKind } { +function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } { const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol); - const enclosingDeclaration = symbol.declarations && ts.firstOrUndefined(symbol.declarations) || node; + const enclosingDeclaration = symbol.declarations && firstOrUndefined(symbol.declarations) || node; const { displayParts, symbolKind } = - ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning); + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning); return { displayParts, kind: symbolKind }; } /** @internal */ -export function toRenameLocation(entry: Entry, originalNode: ts.Node, checker: ts.TypeChecker, providePrefixAndSuffixText: boolean): ts.RenameLocation { +export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker, providePrefixAndSuffixText: boolean): RenameLocation { return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) }; } -function toReferencedSymbolEntry(entry: Entry, symbol: ts.Symbol | undefined): ts.ReferencedSymbolEntry { +function toReferencedSymbolEntry(entry: Entry, symbol: Symbol | undefined): ReferencedSymbolEntry { const referenceEntry = toReferenceEntry(entry); if (!symbol) return referenceEntry; return { @@ -430,7 +480,7 @@ function toReferencedSymbolEntry(entry: Entry, symbol: ts.Symbol | undefined): t } /** @internal */ -export function toReferenceEntry(entry: Entry): ts.ReferenceEntry { +export function toReferenceEntry(entry: Entry): ReferenceEntry { const documentSpan = entryToDocumentSpan(entry); if (entry.kind === EntryKind.Span) { return { ...documentSpan, isWriteAccess: false }; @@ -443,7 +493,7 @@ export function toReferenceEntry(entry: Entry): ts.ReferenceEntry { }; } -function entryToDocumentSpan(entry: Entry): ts.DocumentSpan { +function entryToDocumentSpan(entry: Entry): DocumentSpan { if (entry.kind === EntryKind.Span) { return { textSpan: entry.textSpan, fileName: entry.fileName }; } @@ -459,13 +509,13 @@ function entryToDocumentSpan(entry: Entry): ts.DocumentSpan { } interface PrefixAndSuffix { readonly prefixText?: string; readonly suffixText?: string; } -function getPrefixAndSuffixText(entry: Entry, originalNode: ts.Node, checker: ts.TypeChecker): PrefixAndSuffix { - if (entry.kind !== EntryKind.Span && ts.isIdentifier(originalNode)) { +function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeChecker): PrefixAndSuffix { + if (entry.kind !== EntryKind.Span && isIdentifier(originalNode)) { const { node, kind } = entry; const parent = node.parent; const name = originalNode.text; - const isShorthandAssignment = ts.isShorthandPropertyAssignment(parent); - if (isShorthandAssignment || (ts.isObjectBindingElementWithoutPropertyName(parent) && parent.name === node && parent.dotDotDotToken === undefined)) { + const isShorthandAssignment = isShorthandPropertyAssignment(parent); + if (isShorthandAssignment || (isObjectBindingElementWithoutPropertyName(parent) && parent.name === node && parent.dotDotDotToken === undefined)) { const prefixColon: PrefixAndSuffix = { prefixText: name + ": " }; const suffixColon: PrefixAndSuffix = { suffixText: ": " + name }; if (kind === EntryKind.SearchedLocalFoundProperty) { @@ -479,9 +529,9 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: ts.Node, checker: ts // For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol. if (isShorthandAssignment) { const grandParent = parent.parent; - if (ts.isObjectLiteralExpression(grandParent) && - ts.isBinaryExpression(grandParent.parent) && - ts.isModuleExportsAccessExpression(grandParent.parent.left)) { + if (isObjectLiteralExpression(grandParent) && + isBinaryExpression(grandParent.parent) && + isModuleExportsAccessExpression(grandParent.parent.left)) { return prefixColon; } return suffixColon; @@ -490,12 +540,12 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: ts.Node, checker: ts return prefixColon; } } - else if (ts.isImportSpecifier(parent) && !parent.propertyName) { + else if (isImportSpecifier(parent) && !parent.propertyName) { // If the original symbol was using this alias, just rename the alias. - const originalSymbol = ts.isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode); - return ts.contains(originalSymbol!.declarations, parent) ? { prefixText: name + " as " } : ts.emptyOptions; + const originalSymbol = isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode); + return contains(originalSymbol!.declarations, parent) ? { prefixText: name + " as " } : emptyOptions; } - else if (ts.isExportSpecifier(parent) && !parent.propertyName) { + else if (isExportSpecifier(parent) && !parent.propertyName) { // If the symbol for the node is same as declared node symbol use prefix text return originalNode === entry.node || checker.getSymbolAtLocation(originalNode) === checker.getSymbolAtLocation(entry.node) ? { prefixText: name + " as " } : @@ -503,10 +553,10 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: ts.Node, checker: ts } } - return ts.emptyOptions; + return emptyOptions; } -function toImplementationLocation(entry: Entry, checker: ts.TypeChecker): ts.ImplementationLocation { +function toImplementationLocation(entry: Entry, checker: TypeChecker): ImplementationLocation { const documentSpan = entryToDocumentSpan(entry); if (entry.kind !== EntryKind.Span) { const { node } = entry; @@ -516,64 +566,64 @@ function toImplementationLocation(entry: Entry, checker: ts.TypeChecker): ts.Imp }; } else { - return { ...documentSpan, kind: ts.ScriptElementKind.unknown, displayParts: [] }; + return { ...documentSpan, kind: ScriptElementKind.unknown, displayParts: [] }; } } -function implementationKindDisplayParts(node: ts.Node, checker: ts.TypeChecker): { kind: ts.ScriptElementKind, displayParts: ts.SymbolDisplayPart[] } { - const symbol = checker.getSymbolAtLocation(ts.isDeclaration(node) && node.name ? node.name : node); +function implementationKindDisplayParts(node: Node, checker: TypeChecker): { kind: ScriptElementKind, displayParts: SymbolDisplayPart[] } { + const symbol = checker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node); if (symbol) { return getDefinitionKindAndDisplayParts(symbol, checker, node); } - else if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) { + else if (node.kind === SyntaxKind.ObjectLiteralExpression) { return { - kind: ts.ScriptElementKind.interfaceElement, - displayParts: [ts.punctuationPart(ts.SyntaxKind.OpenParenToken), ts.textPart("object literal"), ts.punctuationPart(ts.SyntaxKind.CloseParenToken)] + kind: ScriptElementKind.interfaceElement, + displayParts: [punctuationPart(SyntaxKind.OpenParenToken), textPart("object literal"), punctuationPart(SyntaxKind.CloseParenToken)] }; } - else if (node.kind === ts.SyntaxKind.ClassExpression) { + else if (node.kind === SyntaxKind.ClassExpression) { return { - kind: ts.ScriptElementKind.localClassElement, - displayParts: [ts.punctuationPart(ts.SyntaxKind.OpenParenToken), ts.textPart("anonymous local class"), ts.punctuationPart(ts.SyntaxKind.CloseParenToken)] + kind: ScriptElementKind.localClassElement, + displayParts: [punctuationPart(SyntaxKind.OpenParenToken), textPart("anonymous local class"), punctuationPart(SyntaxKind.CloseParenToken)] }; } else { - return { kind: ts.getNodeKind(node), displayParts: [] }; + return { kind: getNodeKind(node), displayParts: [] }; } } /** @internal */ -export function toHighlightSpan(entry: Entry): { fileName: string, span: ts.HighlightSpan } { +export function toHighlightSpan(entry: Entry): { fileName: string, span: HighlightSpan } { const documentSpan = entryToDocumentSpan(entry); if (entry.kind === EntryKind.Span) { return { fileName: documentSpan.fileName, span: { textSpan: documentSpan.textSpan, - kind: ts.HighlightSpanKind.reference + kind: HighlightSpanKind.reference } }; } const writeAccess = isWriteAccessForReference(entry.node); - const span: ts.HighlightSpan = { + const span: HighlightSpan = { textSpan: documentSpan.textSpan, - kind: writeAccess ? ts.HighlightSpanKind.writtenReference : ts.HighlightSpanKind.reference, + kind: writeAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference, isInString: entry.kind === EntryKind.StringLiteral ? true : undefined, ...documentSpan.contextSpan && { contextSpan: documentSpan.contextSpan } }; return { fileName: documentSpan.fileName, span }; } -function getTextSpan(node: ts.Node, sourceFile: ts.SourceFile, endNode?: ts.Node): ts.TextSpan { +function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSpan { let start = node.getStart(sourceFile); let end = (endNode || node).getEnd(); - if (ts.isStringLiteralLike(node) && (end - start) > 2) { - ts.Debug.assert(endNode === undefined); + if (isStringLiteralLike(node) && (end - start) > 2) { + Debug.assert(endNode === undefined); start += 1; end -= 1; } - return ts.createTextSpanFromBounds(start, end); + return createTextSpanFromBounds(start, end); } /** @internal */ @@ -583,21 +633,21 @@ export function getTextSpanOfEntry(entry: Entry) { } /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */ -function isWriteAccessForReference(node: ts.Node): boolean { - const decl = ts.getDeclarationFromName(node); - return !!decl && declarationIsWriteAccess(decl) || node.kind === ts.SyntaxKind.DefaultKeyword || ts.isWriteAccess(node); +function isWriteAccessForReference(node: Node): boolean { + const decl = getDeclarationFromName(node); + return !!decl && declarationIsWriteAccess(decl) || node.kind === SyntaxKind.DefaultKeyword || isWriteAccess(node); } /** @internal */ /** Whether a reference, `node`, is a definition of the `target` symbol */ -export function isDeclarationOfSymbol(node: ts.Node, target: ts.Symbol | undefined): boolean { +export function isDeclarationOfSymbol(node: Node, target: Symbol | undefined): boolean { if (!target) return false; - const source = ts.getDeclarationFromName(node) || - (node.kind === ts.SyntaxKind.DefaultKeyword ? node.parent - : ts.isLiteralComputedPropertyDeclarationName(node) ? node.parent.parent - : node.kind === ts.SyntaxKind.ConstructorKeyword && ts.isConstructorDeclaration(node.parent) ? node.parent.parent + const source = getDeclarationFromName(node) || + (node.kind === SyntaxKind.DefaultKeyword ? node.parent + : isLiteralComputedPropertyDeclarationName(node) ? node.parent.parent + : node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent) ? node.parent.parent : undefined); - const commonjsSource = source && ts.isBinaryExpression(source) ? source.left as unknown as ts.Declaration : undefined; + const commonjsSource = source && isBinaryExpression(source) ? source.left as unknown as Declaration : undefined; return !!(source && target.declarations?.some(d => d === source || d === commonjsSource)); } @@ -605,60 +655,60 @@ export function isDeclarationOfSymbol(node: ts.Node, target: ts.Symbol | undefin * True if 'decl' provides a value, as in `function f() {}`; * false if 'decl' is just a location for a future write, as in 'let x;' */ -function declarationIsWriteAccess(decl: ts.Declaration): boolean { +function declarationIsWriteAccess(decl: Declaration): boolean { // Consider anything in an ambient declaration to be a write access since it may be coming from JS. - if (!!(decl.flags & ts.NodeFlags.Ambient)) return true; + if (!!(decl.flags & NodeFlags.Ambient)) return true; switch (decl.kind) { - case ts.SyntaxKind.BinaryExpression: - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.DefaultKeyword: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.ImportClause: // default import - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.NamespaceExportDeclaration: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.NamespaceExport: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.TypeParameter: + case SyntaxKind.BinaryExpression: + case SyntaxKind.BindingElement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportClause: // default import + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JsxAttribute: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.NamespaceImport: + case SyntaxKind.NamespaceExport: + case SyntaxKind.Parameter: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeParameter: return true; - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyAssignment: // In `({ x: y } = 0);`, `x` is not a write access. (Won't call this function for `y`.) - return !ts.isArrayLiteralOrObjectLiteralDestructuringPattern((decl as ts.PropertyAssignment).parent); - - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return !!(decl as ts.FunctionDeclaration | ts.FunctionExpression | ts.ConstructorDeclaration | ts.MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration).body; - - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.PropertyDeclaration: - return !!(decl as ts.VariableDeclaration | ts.PropertyDeclaration).initializer || ts.isCatchClause(decl.parent); - - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.JSDocPropertyTag: - case ts.SyntaxKind.JSDocParameterTag: + return !isArrayLiteralOrObjectLiteralDestructuringPattern((decl as PropertyAssignment).parent); + + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.Constructor: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return !!(decl as FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration).body; + + case SyntaxKind.VariableDeclaration: + case SyntaxKind.PropertyDeclaration: + return !!(decl as VariableDeclaration | PropertyDeclaration).initializer || isCatchClause(decl.parent); + + case SyntaxKind.MethodSignature: + case SyntaxKind.PropertySignature: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocParameterTag: return false; default: - return ts.Debug.failBadSyntaxKind(decl); + return Debug.failBadSyntaxKind(decl); } } @@ -666,10 +716,10 @@ function declarationIsWriteAccess(decl: ts.Declaration): boolean { /** Encapsulates the core find-all-references algorithm. */ export namespace Core { /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */ - export function getReferencedSymbolsForNode(position: number, node: ts.Node, program: ts.Program, sourceFiles: readonly ts.SourceFile[], cancellationToken: ts.CancellationToken, options: Options = {}, sourceFilesSet: ts.ReadonlySet = new ts.Set(sourceFiles.map(f => f.fileName))): readonly SymbolAndEntries[] | undefined { + export function getReferencedSymbolsForNode(position: number, node: Node, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options = {}, sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName))): readonly SymbolAndEntries[] | undefined { node = getAdjustedNode(node, options); - if (ts.isSourceFile(node)) { - const resolvedRef = ts.GoToDefinition.getReferenceAtPosition(node, position, program); + if (isSourceFile(node)) { + const resolvedRef = GoToDefinition.getReferenceAtPosition(node, position, program); if (!resolvedRef?.file) { return undefined; } @@ -683,7 +733,7 @@ export namespace Core { } return [{ definition: { type: DefinitionKind.TripleSlashReference, reference: resolvedRef.reference, file: node }, - references: getReferencesForNonModule(resolvedRef.file, fileIncludeReasons, program) || ts.emptyArray + references: getReferencesForNonModule(resolvedRef.file, fileIncludeReasons, program) || emptyArray }]; } @@ -696,18 +746,18 @@ export namespace Core { const checker = program.getTypeChecker(); // constructors should use the class symbol, detected by name, if present - const symbol = checker.getSymbolAtLocation(ts.isConstructorDeclaration(node) && node.parent.name || node); + const symbol = checker.getSymbolAtLocation(isConstructorDeclaration(node) && node.parent.name || node); // Could not find a symbol e.g. unknown identifier if (!symbol) { // String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial. - if (!options.implementations && ts.isStringLiteralLike(node)) { - if (ts.isModuleSpecifierLike(node)) { + if (!options.implementations && isStringLiteralLike(node)) { + if (isModuleSpecifierLike(node)) { const fileIncludeReasons = program.getFileIncludeReasons(); - const referencedFileName = node.getSourceFile().resolvedModules?.get(node.text, ts.getModeForUsageLocation(node.getSourceFile(), node))?.resolvedFileName; + const referencedFileName = node.getSourceFile().resolvedModules?.get(node.text, getModeForUsageLocation(node.getSourceFile(), node))?.resolvedFileName; const referencedFile = referencedFileName ? program.getSourceFile(referencedFileName) : undefined; if (referencedFile) { - return [{ definition: { type: DefinitionKind.String, node }, references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || ts.emptyArray }]; + return [{ definition: { type: DefinitionKind.String, node }, references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray }]; } // Fall through to string literal references. This is not very likely to return // anything useful, but I guess it's better than nothing, and there's an existing @@ -718,12 +768,12 @@ export namespace Core { return undefined; } - if (symbol.escapedName === ts.InternalSymbolName.ExportEquals) { + if (symbol.escapedName === InternalSymbolName.ExportEquals) { return getReferencedSymbolsForModule(program, symbol.parent!, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet); } const moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, cancellationToken, options, sourceFilesSet); - if (moduleReferences && !(symbol.flags & ts.SymbolFlags.Transient)) { + if (moduleReferences && !(symbol.flags & SymbolFlags.Transient)) { return moduleReferences; } @@ -735,38 +785,38 @@ export namespace Core { return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget); } - export function getAdjustedNode(node: ts.Node, options: Options) { + export function getAdjustedNode(node: Node, options: Options) { if (options.use === FindReferencesUse.References) { - node = ts.getAdjustedReferenceLocation(node); + node = getAdjustedReferenceLocation(node); } else if (options.use === FindReferencesUse.Rename) { - node = ts.getAdjustedRenameLocation(node); + node = getAdjustedRenameLocation(node); } return node; } - export function getReferencesForFileName(fileName: string, program: ts.Program, sourceFiles: readonly ts.SourceFile[], sourceFilesSet: ts.ReadonlySet = new ts.Set(sourceFiles.map(f => f.fileName))): readonly Entry[] { + export function getReferencesForFileName(fileName: string, program: Program, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet = new Set(sourceFiles.map(f => f.fileName))): readonly Entry[] { const moduleSymbol = program.getSourceFile(fileName)?.symbol; if (moduleSymbol) { - return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet)[0]?.references || ts.emptyArray; + return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet)[0]?.references || emptyArray; } const fileIncludeReasons = program.getFileIncludeReasons(); const referencedFile = program.getSourceFile(fileName); - return referencedFile && fileIncludeReasons && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || ts.emptyArray; + return referencedFile && fileIncludeReasons && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray; } - function getReferencesForNonModule(referencedFile: ts.SourceFile, refFileMap: ts.MultiMap, program: ts.Program): readonly SpanEntry[] | undefined { + function getReferencesForNonModule(referencedFile: SourceFile, refFileMap: MultiMap, program: Program): readonly SpanEntry[] | undefined { let entries: SpanEntry[] | undefined; - const references = refFileMap.get(referencedFile.path) || ts.emptyArray; + const references = refFileMap.get(referencedFile.path) || emptyArray; for (const ref of references) { - if (ts.isReferencedFile(ref)) { + if (isReferencedFile(ref)) { const referencingFile = program.getSourceFileByPath(ref.file)!; - const location = ts.getReferencedFileLocation(program.getSourceFileByPath, ref); - if (ts.isReferenceFileLocation(location)) { - entries = ts.append(entries, { + const location = getReferencedFileLocation(program.getSourceFileByPath, ref); + if (isReferenceFileLocation(location)) { + entries = append(entries, { kind: EntryKind.Span, fileName: referencingFile.fileName, - textSpan: ts.createTextSpanFromRange(location) + textSpan: createTextSpanFromRange(location) }); } } @@ -774,8 +824,8 @@ export namespace Core { return entries; } - function getMergedAliasedSymbolOfNamespaceExportDeclaration(node: ts.Node, symbol: ts.Symbol, checker: ts.TypeChecker) { - if (node.parent && ts.isNamespaceExportDeclaration(node.parent)) { + function getMergedAliasedSymbolOfNamespaceExportDeclaration(node: Node, symbol: Symbol, checker: TypeChecker) { + if (node.parent && isNamespaceExportDeclaration(node.parent)) { const aliasedSymbol = checker.getAliasedSymbol(symbol); const targetSymbol = checker.getMergedSymbol(aliasedSymbol); if (aliasedSymbol !== targetSymbol) { @@ -785,23 +835,23 @@ export namespace Core { return undefined; } - function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol: ts.Symbol, program: ts.Program, sourceFiles: readonly ts.SourceFile[], cancellationToken: ts.CancellationToken, options: Options, sourceFilesSet: ts.ReadonlySet) { - const moduleSourceFile = (symbol.flags & ts.SymbolFlags.Module) && symbol.declarations && ts.find(symbol.declarations, ts.isSourceFile); + function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol: Symbol, program: Program, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken, options: Options, sourceFilesSet: ReadonlySet) { + const moduleSourceFile = (symbol.flags & SymbolFlags.Module) && symbol.declarations && find(symbol.declarations, isSourceFile); if (!moduleSourceFile) return undefined; - const exportEquals = symbol.exports!.get(ts.InternalSymbolName.ExportEquals); + const exportEquals = symbol.exports!.get(InternalSymbolName.ExportEquals); // If !!exportEquals, we're about to add references to `import("mod")` anyway, so don't double-count them. const moduleReferences = getReferencedSymbolsForModule(program, symbol, !!exportEquals, sourceFiles, sourceFilesSet); if (!exportEquals || !sourceFilesSet.has(moduleSourceFile.fileName)) return moduleReferences; // Continue to get references to 'export ='. const checker = program.getTypeChecker(); - symbol = ts.skipAlias(exportEquals, checker); + symbol = skipAlias(exportEquals, checker); return mergeReferences(program, moduleReferences, getReferencedSymbolsForSymbol(symbol, /*node*/ undefined, sourceFiles, sourceFilesSet, checker, cancellationToken, options)); } /** * Merges the references by sorting them (by file index in sourceFiles and their location in it) that point to same definition symbol */ - function mergeReferences(program: ts.Program, ...referencesToMerge: (SymbolAndEntries[] | undefined)[]): SymbolAndEntries[] | undefined { + function mergeReferences(program: Program, ...referencesToMerge: (SymbolAndEntries[] | undefined)[]): SymbolAndEntries[] | undefined { let result: SymbolAndEntries[] | undefined; for (const references of referencesToMerge) { if (!references || !references.length) continue; @@ -815,7 +865,7 @@ export namespace Core { continue; } const symbol = entry.definition.symbol; - const refIndex = ts.findIndex(result, ref => !!ref.definition && + const refIndex = findIndex(result, ref => !!ref.definition && ref.definition.type === DefinitionKind.Symbol && ref.definition.symbol === symbol); if (refIndex === -1) { @@ -830,14 +880,14 @@ export namespace Core { const entry1File = getSourceFileIndexOfEntry(program, entry1); const entry2File = getSourceFileIndexOfEntry(program, entry2); if (entry1File !== entry2File) { - return ts.compareValues(entry1File, entry2File); + return compareValues(entry1File, entry2File); } const entry1Span = getTextSpanOfEntry(entry1); const entry2Span = getTextSpanOfEntry(entry2); return entry1Span.start !== entry2Span.start ? - ts.compareValues(entry1Span.start, entry2Span.start) : - ts.compareValues(entry1Span.length, entry2Span.length); + compareValues(entry1Span.start, entry2Span.start) : + compareValues(entry1Span.length, entry2Span.length); }) }; } @@ -845,21 +895,21 @@ export namespace Core { return result; } - function getSourceFileIndexOfEntry(program: ts.Program, entry: Entry) { + function getSourceFileIndexOfEntry(program: Program, entry: Entry) { const sourceFile = entry.kind === EntryKind.Span ? program.getSourceFile(entry.fileName)! : entry.node.getSourceFile(); return program.getSourceFiles().indexOf(sourceFile); } - function getReferencedSymbolsForModule(program: ts.Program, symbol: ts.Symbol, excludeImportTypeOfExportEquals: boolean, sourceFiles: readonly ts.SourceFile[], sourceFilesSet: ts.ReadonlySet): SymbolAndEntries[] { - ts.Debug.assert(!!symbol.valueDeclaration); + function getReferencedSymbolsForModule(program: Program, symbol: Symbol, excludeImportTypeOfExportEquals: boolean, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet): SymbolAndEntries[] { + Debug.assert(!!symbol.valueDeclaration); - const references = ts.mapDefined(ts.FindAllReferences.findModuleReferences(program, sourceFiles, symbol), reference => { + const references = mapDefined(findModuleReferences(program, sourceFiles, symbol), reference => { if (reference.kind === "import") { const parent = reference.literal.parent; - if (ts.isLiteralTypeNode(parent)) { - const importType = ts.cast(parent.parent, ts.isImportTypeNode); + if (isLiteralTypeNode(parent)) { + const importType = cast(parent.parent, isImportTypeNode); if (excludeImportTypeOfExportEquals && !importType.qualifier) { return undefined; } @@ -871,7 +921,7 @@ export namespace Core { return { kind: EntryKind.Span, fileName: reference.referencingFile.fileName, - textSpan: ts.createTextSpanFromRange(reference.ref), + textSpan: createTextSpanFromRange(reference.ref), }; } }); @@ -879,56 +929,56 @@ export namespace Core { if (symbol.declarations) { for (const decl of symbol.declarations) { switch (decl.kind) { - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) break; - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.ModuleDeclaration: if (sourceFilesSet.has(decl.getSourceFile().fileName)) { - references.push(nodeEntry((decl as ts.ModuleDeclaration).name)); + references.push(nodeEntry((decl as ModuleDeclaration).name)); } break; default: // This may be merged with something. - ts.Debug.assert(!!(symbol.flags & ts.SymbolFlags.Transient), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); + Debug.assert(!!(symbol.flags & SymbolFlags.Transient), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration."); } } } - const exported = symbol.exports!.get(ts.InternalSymbolName.ExportEquals); + const exported = symbol.exports!.get(InternalSymbolName.ExportEquals); if (exported?.declarations) { for (const decl of exported.declarations) { const sourceFile = decl.getSourceFile(); if (sourceFilesSet.has(sourceFile.fileName)) { // At `module.exports = ...`, reference node is `module` - const node = ts.isBinaryExpression(decl) && ts.isPropertyAccessExpression(decl.left) ? decl.left.expression : - ts.isExportAssignment(decl) ? ts.Debug.checkDefined(ts.findChildOfKind(decl, ts.SyntaxKind.ExportKeyword, sourceFile)) : - ts.getNameOfDeclaration(decl) || decl; + const node = isBinaryExpression(decl) && isPropertyAccessExpression(decl.left) ? decl.left.expression : + isExportAssignment(decl) ? Debug.checkDefined(findChildOfKind(decl, SyntaxKind.ExportKeyword, sourceFile)) : + getNameOfDeclaration(decl) || decl; references.push(nodeEntry(node)); } } } - return references.length ? [{ definition: { type: DefinitionKind.Symbol, symbol }, references }] : ts.emptyArray; + return references.length ? [{ definition: { type: DefinitionKind.Symbol, symbol }, references }] : emptyArray; } /** As in a `readonly prop: any` or `constructor(readonly prop: any)`, not a `readonly any[]`. */ - function isReadonlyTypeOperator(node: ts.Node): boolean { - return node.kind === ts.SyntaxKind.ReadonlyKeyword - && ts.isTypeOperatorNode(node.parent) - && node.parent.operator === ts.SyntaxKind.ReadonlyKeyword; + function isReadonlyTypeOperator(node: Node): boolean { + return node.kind === SyntaxKind.ReadonlyKeyword + && isTypeOperatorNode(node.parent) + && node.parent.operator === SyntaxKind.ReadonlyKeyword; } /** getReferencedSymbols for special node kinds. */ - function getReferencedSymbolsSpecial(node: ts.Node, sourceFiles: readonly ts.SourceFile[], cancellationToken: ts.CancellationToken): SymbolAndEntries[] | undefined { - if (ts.isTypeKeyword(node.kind)) { + function getReferencedSymbolsSpecial(node: Node, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { + if (isTypeKeyword(node.kind)) { // A void expression (i.e., `void foo()`) is not special, but the `void` type is. - if (node.kind === ts.SyntaxKind.VoidKeyword && ts.isVoidExpression(node.parent)) { + if (node.kind === SyntaxKind.VoidKeyword && isVoidExpression(node.parent)) { return undefined; } // A modifier readonly (like on a property declaration) is not special; // a readonly type keyword (like `readonly string[]`) is. - if (node.kind === ts.SyntaxKind.ReadonlyKeyword && !isReadonlyTypeOperator(node)) { + if (node.kind === SyntaxKind.ReadonlyKeyword && !isReadonlyTypeOperator(node)) { return undefined; } // Likewise, when we *are* looking for a special keyword, make sure we @@ -937,34 +987,34 @@ export namespace Core { sourceFiles, node.kind, cancellationToken, - node.kind === ts.SyntaxKind.ReadonlyKeyword ? isReadonlyTypeOperator : undefined); + node.kind === SyntaxKind.ReadonlyKeyword ? isReadonlyTypeOperator : undefined); } - if (ts.isImportMeta(node.parent) && node.parent.name === node) { + if (isImportMeta(node.parent) && node.parent.name === node) { return getAllReferencesForImportMeta(sourceFiles, cancellationToken); } - if (ts.isStaticModifier(node) && ts.isClassStaticBlockDeclaration(node.parent)) { + if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { return [{ definition: { type: DefinitionKind.Keyword, node }, references: [nodeEntry(node)] }]; } // Labels - if (ts.isJumpStatementTarget(node)) { - const labelDefinition = ts.getTargetLabel(node.parent, node.text); + if (isJumpStatementTarget(node)) { + const labelDefinition = getTargetLabel(node.parent, node.text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition); } - else if (ts.isLabelOfLabeledStatement(node)) { + else if (isLabelOfLabeledStatement(node)) { // it is a label definition and not a target, search within the parent labeledStatement return getLabelReferencesInNode(node.parent, node); } - if (ts.isThis(node)) { + if (isThis(node)) { return getReferencesForThisKeyword(node, sourceFiles, cancellationToken); } - if (node.kind === ts.SyntaxKind.SuperKeyword) { + if (node.kind === SyntaxKind.SuperKeyword) { return getReferencesForSuperKeyword(node); } @@ -972,22 +1022,22 @@ export namespace Core { } /** Core find-all-references algorithm for a normal symbol. */ - function getReferencedSymbolsForSymbol(originalSymbol: ts.Symbol, node: ts.Node | undefined, sourceFiles: readonly ts.SourceFile[], sourceFilesSet: ts.ReadonlySet, checker: ts.TypeChecker, cancellationToken: ts.CancellationToken, options: Options): SymbolAndEntries[] { + function getReferencedSymbolsForSymbol(originalSymbol: Symbol, node: Node | undefined, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] { const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options)) || originalSymbol; // Compute the meaning from the location and the symbol it references - const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : ts.SemanticMeaning.All; + const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : SemanticMeaning.All; const result: SymbolAndEntries[] = []; const state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : SpecialSearchKind.None, checker, cancellationToken, searchMeaning, options, result); - const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) || !symbol.declarations ? undefined : ts.find(symbol.declarations, ts.isExportSpecifier); + const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) || !symbol.declarations ? undefined : find(symbol.declarations, isExportSpecifier); if (exportSpecifier) { // When renaming at an export specifier, rename the export and not the thing being exported. getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true); } - else if (node && node.kind === ts.SyntaxKind.DefaultKeyword && symbol.escapedName === ts.InternalSymbolName.Default && symbol.parent) { + else if (node && node.kind === SyntaxKind.DefaultKeyword && symbol.escapedName === InternalSymbolName.Default && symbol.parent) { addReference(node, symbol, state); - searchForImportsOfExport(node, symbol, { exportingModuleSymbol: symbol.parent, exportKind: ts.FindAllReferences.ExportKind.Default }, state); + searchForImportsOfExport(node, symbol, { exportingModuleSymbol: symbol.parent, exportKind: ExportKind.Default }, state); } else { const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.use === FindReferencesUse.Rename, !!options.providePrefixAndSuffixTextForRename, !!options.implementations) : [symbol] }); @@ -997,12 +1047,12 @@ export namespace Core { return result; } - function getReferencesInContainerOrFiles(symbol: ts.Symbol, state: State, search: Search): void { + function getReferencesInContainerOrFiles(symbol: Symbol, state: State, search: Search): void { // Try to get the smallest valid scope that we can limit our search to; // otherwise we'll need to search globally (i.e. include each file). const scope = getSymbolScope(symbol); if (scope) { - getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(ts.isSourceFile(scope) && !ts.contains(state.sourceFiles, scope))); + getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(isSourceFile(scope) && !contains(state.sourceFiles, scope))); } else { // Global search @@ -1013,14 +1063,14 @@ export namespace Core { } } - function getSpecialSearchKind(node: ts.Node): SpecialSearchKind { + function getSpecialSearchKind(node: Node): SpecialSearchKind { switch (node.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructorKeyword: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorKeyword: return SpecialSearchKind.Constructor; - case ts.SyntaxKind.Identifier: - if (ts.isClassLike(node.parent)) { - ts.Debug.assert(node.parent.name === node); + case SyntaxKind.Identifier: + if (isClassLike(node.parent)) { + Debug.assert(node.parent.name === node); return SpecialSearchKind.Class; } // falls through @@ -1030,20 +1080,20 @@ export namespace Core { } /** Handle a few special cases relating to export/import specifiers. */ - function skipPastExportOrImportSpecifierOrUnion(symbol: ts.Symbol, node: ts.Node, checker: ts.TypeChecker, useLocalSymbolForExportSpecifier: boolean): ts.Symbol | undefined { + function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker, useLocalSymbolForExportSpecifier: boolean): Symbol | undefined { const { parent } = node; - if (ts.isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) { - return getLocalSymbolForExportSpecifier(node as ts.Identifier, symbol, parent, checker); + if (isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) { + return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker); } // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references. - return ts.firstDefined(symbol.declarations, decl => { + return firstDefined(symbol.declarations, decl => { if (!decl.parent) { // Ignore UMD module and global merge - if (symbol.flags & ts.SymbolFlags.Transient) return undefined; + if (symbol.flags & SymbolFlags.Transient) return undefined; // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. - ts.Debug.fail(`Unexpected symbol at ${ts.Debug.formatSyntaxKind(node.kind)}: ${ts.Debug.formatSymbol(symbol)}`); + Debug.fail(`Unexpected symbol at ${Debug.formatSyntaxKind(node.kind)}: ${Debug.formatSymbol(symbol)}`); } - return ts.isTypeLiteralNode(decl.parent) && ts.isUnionTypeNode(decl.parent.parent) + return isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent) ? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name) : undefined; }); @@ -1055,20 +1105,20 @@ export namespace Core { */ interface Search { /** If coming from an export, we will not recursively search for the imported symbol (since that's where we came from). */ - readonly comingFrom?: ts.FindAllReferences.ImportExport; + readonly comingFrom?: ImportExport; - readonly symbol: ts.Symbol; + readonly symbol: Symbol; readonly text: string; - readonly escapedText: ts.__String; + readonly escapedText: __String; /** Only set if `options.implementations` is true. These are the symbols checked to get the implementations of a property access. */ - readonly parents: readonly ts.Symbol[] | undefined; - readonly allSearchSymbols: readonly ts.Symbol[]; + readonly parents: readonly Symbol[] | undefined; + readonly allSearchSymbols: readonly Symbol[]; /** * Whether a symbol is in the search set. * Do not compare directly to `symbol` because there may be related symbols to search for. See `populateSearchSymbolSet`. */ - includes(symbol: ts.Symbol): boolean; + includes(symbol: Symbol): boolean; } const enum SpecialSearchKind { @@ -1077,9 +1127,9 @@ export namespace Core { Class, } - function getNonModuleSymbolOfMergedModuleSymbol(symbol: ts.Symbol) { - if (!(symbol.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Transient))) return undefined; - const decl = symbol.declarations && ts.find(symbol.declarations, d => !ts.isSourceFile(d) && !ts.isModuleDeclaration(d)); + function getNonModuleSymbolOfMergedModuleSymbol(symbol: Symbol) { + if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Transient))) return undefined; + const decl = symbol.declarations && find(symbol.declarations, d => !isSourceFile(d) && !isModuleDeclaration(d)); return decl && decl.symbol; } @@ -1089,7 +1139,7 @@ export namespace Core { */ class State { /** Cache for `explicitlyinheritsFrom`. */ - readonly inheritsFromCache = new ts.Map(); + readonly inheritsFromCache = new Map(); /** * Type nodes can contain multiple references to the same type. For example: @@ -1098,7 +1148,7 @@ export namespace Core { * duplicate entries would be returned here as each of the type references is part of * the same implementation. For that reason, check before we add a new entry. */ - readonly markSeenContainingTypeReference = ts.nodeSeenTracker(); + readonly markSeenContainingTypeReference = nodeSeenTracker(); /** * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once. @@ -1111,43 +1161,43 @@ export namespace Core { * But another reference to it may appear in the same source file. * See `tests/cases/fourslash/transitiveExportImports3.ts`. */ - readonly markSeenReExportRHS = ts.nodeSeenTracker(); + readonly markSeenReExportRHS = nodeSeenTracker(); constructor( - readonly sourceFiles: readonly ts.SourceFile[], - readonly sourceFilesSet: ts.ReadonlySet, + readonly sourceFiles: readonly SourceFile[], + readonly sourceFilesSet: ReadonlySet, readonly specialSearchKind: SpecialSearchKind, - readonly checker: ts.TypeChecker, - readonly cancellationToken: ts.CancellationToken, - readonly searchMeaning: ts.SemanticMeaning, + readonly checker: TypeChecker, + readonly cancellationToken: CancellationToken, + readonly searchMeaning: SemanticMeaning, readonly options: Options, - private readonly result: ts.Push) { + private readonly result: Push) { } - includesSourceFile(sourceFile: ts.SourceFile): boolean { + includesSourceFile(sourceFile: SourceFile): boolean { return this.sourceFilesSet.has(sourceFile.fileName); } - private importTracker: ts.FindAllReferences.ImportTracker | undefined; + private importTracker: ImportTracker | undefined; /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */ - getImportSearches(exportSymbol: ts.Symbol, exportInfo: ts.FindAllReferences.ExportInfo): ts.FindAllReferences.ImportsResult { - if (!this.importTracker) this.importTracker = ts.FindAllReferences.createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); + getImportSearches(exportSymbol: Symbol, exportInfo: ExportInfo): ImportsResult { + if (!this.importTracker) this.importTracker = createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken); return this.importTracker(exportSymbol, exportInfo, this.options.use === FindReferencesUse.Rename); } /** @param allSearchSymbols set of additional symbols for use by `includes`. */ - createSearch(location: ts.Node | undefined, symbol: ts.Symbol, comingFrom: ts.FindAllReferences.ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: ts.Symbol[] } = {}): Search { + createSearch(location: Node | undefined, symbol: Symbol, comingFrom: ImportExport | undefined, searchOptions: { text?: string, allSearchSymbols?: Symbol[] } = {}): Search { // Note: if this is an external module symbol, the name doesn't include quotes. // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`. // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form // here appears to be intentional). const { - text = ts.stripQuotes(ts.symbolName(ts.getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)), + text = stripQuotes(symbolName(getLocalSymbolForExportDefault(symbol) || getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)), allSearchSymbols = [symbol], } = searchOptions; - const escapedText = ts.escapeLeadingUnderscores(text); + const escapedText = escapeLeadingUnderscores(text); const parents = this.options.implementations && location ? getParentSymbolsOfPropertyAccess(location, symbol, this.checker) : undefined; - return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => ts.contains(allSearchSymbols, sym) }; + return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) }; } private readonly symbolIdToReferences: Entry[][] = []; @@ -1155,8 +1205,8 @@ export namespace Core { * Callback to add references for a particular searched symbol. * This initializes a reference group, so only call this if you will add at least one reference. */ - referenceAdder(searchSymbol: ts.Symbol): (node: ts.Node, kind?: NodeEntryKind) => void { - const symbolId = ts.getSymbolId(searchSymbol); + referenceAdder(searchSymbol: Symbol): (node: Node, kind?: NodeEntryKind) => void { + const symbolId = getSymbolId(searchSymbol); let references = this.symbolIdToReferences[symbolId]; if (!references) { references = this.symbolIdToReferences[symbolId] = []; @@ -1166,7 +1216,7 @@ export namespace Core { } /** Add a reference with no associated definition. */ - addStringOrCommentReference(fileName: string, textSpan: ts.TextSpan): void { + addStringOrCommentReference(fileName: string, textSpan: TextSpan): void { this.result.push({ definition: undefined, references: [{ kind: EntryKind.Span, fileName, textSpan }] @@ -1174,22 +1224,22 @@ export namespace Core { } // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. - private readonly sourceFileToSeenSymbols: ts.Set[] = []; + private readonly sourceFileToSeenSymbols: Set[] = []; /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ - markSearchedSymbols(sourceFile: ts.SourceFile, symbols: readonly ts.Symbol[]): boolean { - const sourceId = ts.getNodeId(sourceFile); - const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = new ts.Set()); + markSearchedSymbols(sourceFile: SourceFile, symbols: readonly Symbol[]): boolean { + const sourceId = getNodeId(sourceFile); + const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = new Set()); let anyNewSymbols = false; for (const sym of symbols) { - anyNewSymbols = ts.tryAddToSet(seenSymbols, ts.getSymbolId(sym)) || anyNewSymbols; + anyNewSymbols = tryAddToSet(seenSymbols, getSymbolId(sym)) || anyNewSymbols; } return anyNewSymbols; } } /** Search for all imports of a given exported symbol using `State.getImportSearches`. */ - function searchForImportsOfExport(exportLocation: ts.Node, exportSymbol: ts.Symbol, exportInfo: ts.FindAllReferences.ExportInfo, state: State): void { + function searchForImportsOfExport(exportLocation: Node, exportSymbol: Symbol, exportInfo: ExportInfo, state: State): void { const { importSearches, singleReferences, indirectUsers } = state.getImportSearches(exportSymbol, exportInfo); // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file. @@ -1202,20 +1252,20 @@ export namespace Core { // For each import, find all references to that import in its source file. for (const [importLocation, importSymbol] of importSearches) { - getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, ts.FindAllReferences.ImportExport.Export), state); + getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, ImportExport.Export), state); } if (indirectUsers.length) { let indirectSearch: Search | undefined; switch (exportInfo.exportKind) { - case ts.FindAllReferences.ExportKind.Named: - indirectSearch = state.createSearch(exportLocation, exportSymbol, ts.FindAllReferences.ImportExport.Export); + case ExportKind.Named: + indirectSearch = state.createSearch(exportLocation, exportSymbol, ImportExport.Export); break; - case ts.FindAllReferences.ExportKind.Default: + case ExportKind.Default: // Search for a property access to '.default'. This can't be renamed. - indirectSearch = state.options.use === FindReferencesUse.Rename ? undefined : state.createSearch(exportLocation, exportSymbol, ts.FindAllReferences.ImportExport.Export, { text: "default" }); + indirectSearch = state.options.use === FindReferencesUse.Rename ? undefined : state.createSearch(exportLocation, exportSymbol, ImportExport.Export, { text: "default" }); break; - case ts.FindAllReferences.ExportKind.ExportEquals: + case ExportKind.ExportEquals: break; } if (indirectSearch) { @@ -1227,22 +1277,22 @@ export namespace Core { } export function eachExportReference( - sourceFiles: readonly ts.SourceFile[], - checker: ts.TypeChecker, - cancellationToken: ts.CancellationToken | undefined, - exportSymbol: ts.Symbol, - exportingModuleSymbol: ts.Symbol, + sourceFiles: readonly SourceFile[], + checker: TypeChecker, + cancellationToken: CancellationToken | undefined, + exportSymbol: Symbol, + exportingModuleSymbol: Symbol, exportName: string, isDefaultExport: boolean, - cb: (ref: ts.Identifier) => void, + cb: (ref: Identifier) => void, ): void { - const importTracker = ts.FindAllReferences.createImportTracker(sourceFiles, new ts.Set(sourceFiles.map(f => f.fileName)), checker, cancellationToken); - const { importSearches, indirectUsers, singleReferences } = importTracker(exportSymbol, { exportKind: isDefaultExport ? ts.FindAllReferences.ExportKind.Default : ts.FindAllReferences.ExportKind.Named, exportingModuleSymbol }, /*isForRename*/ false); + const importTracker = createImportTracker(sourceFiles, new Set(sourceFiles.map(f => f.fileName)), checker, cancellationToken); + const { importSearches, indirectUsers, singleReferences } = importTracker(exportSymbol, { exportKind: isDefaultExport ? ExportKind.Default : ExportKind.Named, exportingModuleSymbol }, /*isForRename*/ false); for (const [importLocation] of importSearches) { cb(importLocation); } for (const singleReference of singleReferences) { - if (ts.isIdentifier(singleReference) && ts.isImportTypeNode(singleReference.parent)) { + if (isIdentifier(singleReference) && isImportTypeNode(singleReference.parent)) { cb(singleReference); } } @@ -1250,44 +1300,44 @@ export namespace Core { for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) { // Import specifiers should be handled by importSearches const symbol = checker.getSymbolAtLocation(node); - const hasExportAssignmentDeclaration = ts.some(symbol?.declarations, d => ts.tryCast(d, ts.isExportAssignment) ? true : false); - if (ts.isIdentifier(node) && !ts.isImportOrExportSpecifier(node.parent) && (symbol === exportSymbol || hasExportAssignmentDeclaration)) { + const hasExportAssignmentDeclaration = some(symbol?.declarations, d => tryCast(d, isExportAssignment) ? true : false); + if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && (symbol === exportSymbol || hasExportAssignmentDeclaration)) { cb(node); } } } } - function shouldAddSingleReference(singleRef: ts.Identifier | ts.StringLiteral, state: State): boolean { + function shouldAddSingleReference(singleRef: Identifier | StringLiteral, state: State): boolean { if (!hasMatchingMeaning(singleRef, state)) return false; if (state.options.use !== FindReferencesUse.Rename) return true; // Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;` - if (!ts.isIdentifier(singleRef)) return false; + if (!isIdentifier(singleRef)) return false; // At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename. - return !(ts.isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === ts.InternalSymbolName.Default); + return !(isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === InternalSymbolName.Default); } // Go to the symbol we imported from and find references for it. - function searchForImportedSymbol(symbol: ts.Symbol, state: State): void { + function searchForImportedSymbol(symbol: Symbol, state: State): void { if (!symbol.declarations) return; for (const declaration of symbol.declarations) { const exportingFile = declaration.getSourceFile(); // Need to search in the file even if it's not in the search-file set, because it might export the symbol. - getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, ts.FindAllReferences.ImportExport.Import), state, state.includesSourceFile(exportingFile)); + getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, ImportExport.Import), state, state.includesSourceFile(exportingFile)); } } /** Search for all occurrences of an identifier in a source file (and filter out the ones that match). */ - function searchForName(sourceFile: ts.SourceFile, search: Search, state: State): void { - if (ts.getNameTable(sourceFile).get(search.escapedText) !== undefined) { + function searchForName(sourceFile: SourceFile, search: Search, state: State): void { + if (getNameTable(sourceFile).get(search.escapedText) !== undefined) { getReferencesInSourceFile(sourceFile, search, state); } } - function getPropertySymbolOfDestructuringAssignment(location: ts.Node, checker: ts.TypeChecker): ts.Symbol | undefined { - return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) - ? checker.getPropertySymbolOfDestructuringAssignment(location as ts.Identifier) + function getPropertySymbolOfDestructuringAssignment(location: Node, checker: TypeChecker): Symbol | undefined { + return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) + ? checker.getPropertySymbolOfDestructuringAssignment(location as Identifier) : undefined; } @@ -1299,11 +1349,11 @@ export namespace Core { * @returns undefined if the scope cannot be determined, implying that * a reference to a symbol can occur anywhere. */ - function getSymbolScope(symbol: ts.Symbol): ts.Node | undefined { + function getSymbolScope(symbol: Symbol): Node | undefined { // If this is the symbol of a named function expression or named class expression, // then named references are limited to its own scope. const { declarations, flags, parent, valueDeclaration } = symbol; - if (valueDeclaration && (valueDeclaration.kind === ts.SyntaxKind.FunctionExpression || valueDeclaration.kind === ts.SyntaxKind.ClassExpression)) { + if (valueDeclaration && (valueDeclaration.kind === SyntaxKind.FunctionExpression || valueDeclaration.kind === SyntaxKind.ClassExpression)) { return valueDeclaration; } @@ -1312,10 +1362,10 @@ export namespace Core { } // If this is private property or method, the scope is the containing class - if (flags & (ts.SymbolFlags.Property | ts.SymbolFlags.Method)) { - const privateDeclaration = ts.find(declarations, d => ts.hasEffectiveModifier(d, ts.ModifierFlags.Private) || ts.isPrivateIdentifierClassElementDeclaration(d)); + if (flags & (SymbolFlags.Property | SymbolFlags.Method)) { + const privateDeclaration = find(declarations, d => hasEffectiveModifier(d, ModifierFlags.Private) || isPrivateIdentifierClassElementDeclaration(d)); if (privateDeclaration) { - return ts.getAncestor(privateDeclaration, ts.SyntaxKind.ClassDeclaration); + return getAncestor(privateDeclaration, SyntaxKind.ClassDeclaration); } // Else this is a public property and could be accessed from anywhere. return undefined; @@ -1323,7 +1373,7 @@ export namespace Core { // If symbol is of object binding pattern element without property name we would want to // look for property too and that could be anywhere - if (declarations.some(ts.isObjectBindingElementWithoutPropertyName)) { + if (declarations.some(isObjectBindingElementWithoutPropertyName)) { return undefined; } @@ -1334,29 +1384,29 @@ export namespace Core { - The parent is an external module: then we should only search in the module (and recurse on the export later). - But if the parent has `export as namespace`, the symbol is globally visible through that namespace. */ - const exposedByParent = parent && !(symbol.flags & ts.SymbolFlags.TypeParameter); - if (exposedByParent && !(ts.isExternalModuleSymbol(parent) && !parent.globalExports)) { + const exposedByParent = parent && !(symbol.flags & SymbolFlags.TypeParameter); + if (exposedByParent && !(isExternalModuleSymbol(parent) && !parent.globalExports)) { return undefined; } - let scope: ts.Node | undefined; + let scope: Node | undefined; for (const declaration of declarations) { - const container = ts.getContainerNode(declaration); + const container = getContainerNode(declaration); if (scope && scope !== container) { // Different declarations have different containers, bail out return undefined; } - if (!container || container.kind === ts.SyntaxKind.SourceFile && !ts.isExternalOrCommonJsModule(container as ts.SourceFile)) { + if (!container || container.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(container as SourceFile)) { // This is a global variable and not an external module, any declaration defined // within this scope is visible outside the file return undefined; } scope = container; - if (ts.isFunctionExpression(scope)) { - let next: ts.Node | undefined; - while (next = ts.getNextJSDocCommentLocation(scope)) { + if (isFunctionExpression(scope)) { + let next: Node | undefined; + while (next = getNextJSDocCommentLocation(scope)) { scope = next; } } @@ -1371,32 +1421,32 @@ export namespace Core { } /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */ - export function isSymbolReferencedInFile(definition: ts.Identifier, checker: ts.TypeChecker, sourceFile: ts.SourceFile, searchContainer: ts.Node = sourceFile): boolean { + export function isSymbolReferencedInFile(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, searchContainer: Node = sourceFile): boolean { return eachSymbolReferenceInFile(definition, checker, sourceFile, () => true, searchContainer) || false; } - export function eachSymbolReferenceInFile(definition: ts.Identifier, checker: ts.TypeChecker, sourceFile: ts.SourceFile, cb: (token: ts.Identifier) => T, searchContainer: ts.Node = sourceFile): T | undefined { - const symbol = ts.isParameterPropertyDeclaration(definition.parent, definition.parent.parent) - ? ts.first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text)) + export function eachSymbolReferenceInFile(definition: Identifier, checker: TypeChecker, sourceFile: SourceFile, cb: (token: Identifier) => T, searchContainer: Node = sourceFile): T | undefined { + const symbol = isParameterPropertyDeclaration(definition.parent, definition.parent.parent) + ? first(checker.getSymbolsOfParameterPropertyDeclaration(definition.parent, definition.text)) : checker.getSymbolAtLocation(definition); if (!symbol) return undefined; for (const token of getPossibleSymbolReferenceNodes(sourceFile, symbol.name, searchContainer)) { - if (!ts.isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) continue; + if (!isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText) continue; const referenceSymbol = checker.getSymbolAtLocation(token)!; if (referenceSymbol === symbol || checker.getShorthandAssignmentValueSymbol(token.parent) === symbol - || ts.isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) { + || isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) { const res = cb(token); if (res) return res; } } } - export function getTopMostDeclarationNamesInFile(declarationName: string, sourceFile: ts.SourceFile): readonly ts.Node[] { - const candidates = ts.filter(getPossibleSymbolReferenceNodes(sourceFile, declarationName), name => !!ts.getDeclarationFromName(name)); + export function getTopMostDeclarationNamesInFile(declarationName: string, sourceFile: SourceFile): readonly Node[] { + const candidates = filter(getPossibleSymbolReferenceNodes(sourceFile, declarationName), name => !!getDeclarationFromName(name)); return candidates.reduce((topMost, decl) => { const depth = getDepth(decl); - if (!ts.some(topMost.declarationNames) || depth === topMost.depth) { + if (!some(topMost.declarationNames) || depth === topMost.depth) { topMost.declarationNames.push(decl); topMost.depth = depth; } @@ -1405,12 +1455,12 @@ export namespace Core { topMost.depth = depth; } return topMost; - }, { depth: Infinity, declarationNames: [] as ts.Node[] }).declarationNames; + }, { depth: Infinity, declarationNames: [] as Node[] }).declarationNames; - function getDepth(declaration: ts.Node | undefined) { + function getDepth(declaration: Node | undefined) { let depth = 0; while (declaration) { - declaration = ts.getContainerNode(declaration); + declaration = getContainerNode(declaration); depth++; } return depth; @@ -1418,20 +1468,20 @@ export namespace Core { } export function someSignatureUsage( - signature: ts.SignatureDeclaration, - sourceFiles: readonly ts.SourceFile[], - checker: ts.TypeChecker, - cb: (name: ts.Identifier, call?: ts.CallExpression) => boolean + signature: SignatureDeclaration, + sourceFiles: readonly SourceFile[], + checker: TypeChecker, + cb: (name: Identifier, call?: CallExpression) => boolean ): boolean { - if (!signature.name || !ts.isIdentifier(signature.name)) return false; + if (!signature.name || !isIdentifier(signature.name)) return false; - const symbol = ts.Debug.checkDefined(checker.getSymbolAtLocation(signature.name)); + const symbol = Debug.checkDefined(checker.getSymbolAtLocation(signature.name)); for (const sourceFile of sourceFiles) { for (const name of getPossibleSymbolReferenceNodes(sourceFile, symbol.name)) { - if (!ts.isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText) continue; - const called = ts.climbPastPropertyAccess(name); - const call = ts.isCallExpression(called.parent) && called.parent.expression === called ? called.parent : undefined; + if (!isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText) continue; + const called = climbPastPropertyAccess(name); + const call = isCallExpression(called.parent) && called.parent.expression === called ? called.parent : undefined; const referenceSymbol = checker.getSymbolAtLocation(name); if (referenceSymbol && checker.getRootSymbols(referenceSymbol).some(s => s === symbol)) { if (cb(name, call)) { @@ -1443,11 +1493,11 @@ export namespace Core { return false; } - function getPossibleSymbolReferenceNodes(sourceFile: ts.SourceFile, symbolName: string, container: ts.Node = sourceFile): readonly ts.Node[] { - return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => ts.getTouchingPropertyName(sourceFile, pos)); + function getPossibleSymbolReferenceNodes(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): readonly Node[] { + return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => getTouchingPropertyName(sourceFile, pos)); } - function getPossibleSymbolReferencePositions(sourceFile: ts.SourceFile, symbolName: string, container: ts.Node = sourceFile): readonly number[] { + function getPossibleSymbolReferencePositions(sourceFile: SourceFile, symbolName: string, container: Node = sourceFile): readonly number[] { const positions: number[] = []; /// TODO: Cache symbol existence for files to save text search @@ -1471,8 +1521,8 @@ export namespace Core { // before and after it have to be a non-identifier char). const endPosition = position + symbolNameLength; - if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), ts.ScriptTarget.Latest)) && - (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), ts.ScriptTarget.Latest))) { + if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) && + (endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) { // Found a real match. Keep searching. positions.push(position); } @@ -1482,36 +1532,36 @@ export namespace Core { return positions; } - function getLabelReferencesInNode(container: ts.Node, targetLabel: ts.Identifier): SymbolAndEntries[] { + function getLabelReferencesInNode(container: Node, targetLabel: Identifier): SymbolAndEntries[] { const sourceFile = container.getSourceFile(); const labelName = targetLabel.text; - const references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), node => + const references = mapDefined(getPossibleSymbolReferenceNodes(sourceFile, labelName, container), node => // Only pick labels that are either the target label, or have a target that is the target label - node === targetLabel || (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel) ? nodeEntry(node) : undefined); + node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel) ? nodeEntry(node) : undefined); return [{ definition: { type: DefinitionKind.Label, node: targetLabel }, references }]; } - function isValidReferencePosition(node: ts.Node, searchSymbolName: string): boolean { + function isValidReferencePosition(node: Node, searchSymbolName: string): boolean { // Compare the length so we filter out strict superstrings of the symbol we are looking for switch (node.kind) { - case ts.SyntaxKind.PrivateIdentifier: - if (ts.isJSDocMemberName(node.parent)) { + case SyntaxKind.PrivateIdentifier: + if (isJSDocMemberName(node.parent)) { return true; } // falls through I guess - case ts.SyntaxKind.Identifier: - return (node as ts.PrivateIdentifier | ts.Identifier).text.length === searchSymbolName.length; - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.StringLiteral: { - const str = node as ts.StringLiteralLike; - return (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node) || (ts.isCallExpression(node.parent) && ts.isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) && + case SyntaxKind.Identifier: + return (node as PrivateIdentifier | Identifier).text.length === searchSymbolName.length; + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: { + const str = node as StringLiteralLike; + return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || (isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) && str.text.length === searchSymbolName.length; } - case ts.SyntaxKind.NumericLiteral: - return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node as ts.NumericLiteral) && (node as ts.NumericLiteral).text.length === searchSymbolName.length; + case SyntaxKind.NumericLiteral: + return isLiteralNameOfPropertyDeclarationOrIndexAccess(node as NumericLiteral) && (node as NumericLiteral).text.length === searchSymbolName.length; - case ts.SyntaxKind.DefaultKeyword: + case SyntaxKind.DefaultKeyword: return "default".length === searchSymbolName.length; default: @@ -1519,12 +1569,12 @@ export namespace Core { } } - function getAllReferencesForImportMeta(sourceFiles: readonly ts.SourceFile[], cancellationToken: ts.CancellationToken): SymbolAndEntries[] | undefined { - const references = ts.flatMap(sourceFiles, sourceFile => { + function getAllReferencesForImportMeta(sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { + const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "meta", sourceFile), node => { + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "meta", sourceFile), node => { const parent = node.parent; - if (ts.isImportMeta(parent)) { + if (isImportMeta(parent)) { return nodeEntry(parent); } }); @@ -1532,10 +1582,10 @@ export namespace Core { return references.length ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; } - function getAllReferencesForKeyword(sourceFiles: readonly ts.SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: ts.CancellationToken, filter?: (node: ts.Node) => boolean): SymbolAndEntries[] | undefined { - const references = ts.flatMap(sourceFiles, sourceFile => { + function getAllReferencesForKeyword(sourceFiles: readonly SourceFile[], keywordKind: SyntaxKind, cancellationToken: CancellationToken, filter?: (node: Node) => boolean): SymbolAndEntries[] | undefined { + const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, ts.tokenToString(keywordKind)!, sourceFile), referenceLocation => { + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind)!, sourceFile), referenceLocation => { if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) { return nodeEntry(referenceLocation); } @@ -1544,7 +1594,7 @@ export namespace Core { return references.length ? [{ definition: { type: DefinitionKind.Keyword, node: references[0].node }, references }] : undefined; } - function getReferencesInSourceFile(sourceFile: ts.SourceFile, search: Search, state: State, addReferencesHere = true): void { + function getReferencesInSourceFile(sourceFile: SourceFile, search: Search, state: State, addReferencesHere = true): void { state.cancellationToken.throwIfCancellationRequested(); return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere); } @@ -1554,7 +1604,7 @@ export namespace Core { * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). * searchLocation: a node where the search value */ - function getReferencesInContainer(container: ts.Node, sourceFile: ts.SourceFile, search: Search, state: State, addReferencesHere: boolean): void { + function getReferencesInContainer(container: Node, sourceFile: SourceFile, search: Search, state: State, addReferencesHere: boolean): void { if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) { return; } @@ -1564,23 +1614,23 @@ export namespace Core { } } - function hasMatchingMeaning(referenceLocation: ts.Node, state: State): boolean { - return !!(ts.getMeaningFromLocation(referenceLocation) & state.searchMeaning); + function hasMatchingMeaning(referenceLocation: Node, state: State): boolean { + return !!(getMeaningFromLocation(referenceLocation) & state.searchMeaning); } - function getReferencesAtLocation(sourceFile: ts.SourceFile, position: number, search: Search, state: State, addReferencesHere: boolean): void { - const referenceLocation = ts.getTouchingPropertyName(sourceFile, position); + function getReferencesAtLocation(sourceFile: SourceFile, position: number, search: Search, state: State, addReferencesHere: boolean): void { + const referenceLocation = getTouchingPropertyName(sourceFile, position); if (!isValidReferencePosition(referenceLocation, search.text)) { // This wasn't the start of a token. Check to see if it might be a // match in a comment or string if that's what the caller is asking // for. - if (!state.options.implementations && (state.options.findInStrings && ts.isInString(sourceFile, position) || state.options.findInComments && ts.isInNonReferenceComment(sourceFile, position))) { + if (!state.options.implementations && (state.options.findInStrings && isInString(sourceFile, position) || state.options.findInComments && isInNonReferenceComment(sourceFile, position))) { // In the case where we're looking inside comments/strings, we don't have // an actual definition. So just use 'undefined' here. Features like // 'Rename' won't care (as they ignore the definitions), and features like // 'FindReferences' will just filter out these results. - state.addStringOrCommentReference(sourceFile.fileName, ts.createTextSpan(position, search.text.length)); + state.addStringOrCommentReference(sourceFile.fileName, createTextSpan(position, search.text.length)); } return; @@ -1594,14 +1644,14 @@ export namespace Core { } const parent = referenceLocation.parent; - if (ts.isImportSpecifier(parent) && parent.propertyName === referenceLocation) { + if (isImportSpecifier(parent) && parent.propertyName === referenceLocation) { // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again. return; } - if (ts.isExportSpecifier(parent)) { - ts.Debug.assert(referenceLocation.kind === ts.SyntaxKind.Identifier); - getReferencesAtExportSpecifier(referenceLocation as ts.Identifier, referenceSymbol, parent, search, state, addReferencesHere); + if (isExportSpecifier(parent)) { + Debug.assert(referenceLocation.kind === SyntaxKind.Identifier); + getReferencesAtExportSpecifier(referenceLocation as Identifier, referenceSymbol, parent, search, state, addReferencesHere); return; } @@ -1622,13 +1672,13 @@ export namespace Core { addClassStaticThisReferences(referenceLocation, search, state); break; default: - ts.Debug.assertNever(state.specialSearchKind); + Debug.assertNever(state.specialSearchKind); } // Use the parent symbol if the location is commonjs require syntax on javascript files only. - if (ts.isInJSFile(referenceLocation) - && referenceLocation.parent.kind === ts.SyntaxKind.BindingElement - && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(referenceLocation.parent.parent.parent)) { + if (isInJSFile(referenceLocation) + && referenceLocation.parent.kind === SyntaxKind.BindingElement + && isVariableDeclarationInitializedToBareOrAccessedRequire(referenceLocation.parent.parent.parent)) { referenceSymbol = referenceLocation.parent.symbol; // The parent will not have a symbol if it's an ObjectBindingPattern (when destructuring is used). In // this case, just skip it, since the bound identifiers are not an alias of the import. @@ -1639,15 +1689,15 @@ export namespace Core { } function getReferencesAtExportSpecifier( - referenceLocation: ts.Identifier, - referenceSymbol: ts.Symbol, - exportSpecifier: ts.ExportSpecifier, + referenceLocation: Identifier, + referenceSymbol: Symbol, + exportSpecifier: ExportSpecifier, search: Search, state: State, addReferencesHere: boolean, alwaysGetReferences?: boolean, ): void { - ts.Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled"); + Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled"); const { parent, propertyName, name } = exportSpecifier; const exportDeclaration = parent.parent; @@ -1658,7 +1708,7 @@ export namespace Core { if (!propertyName) { // Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export) - if (!(state.options.use === FindReferencesUse.Rename && (name.escapedText === ts.InternalSymbolName.Default))) { + if (!(state.options.use === FindReferencesUse.Rename && (name.escapedText === InternalSymbolName.Default))) { addRef(); } } @@ -1670,7 +1720,7 @@ export namespace Core { } if (addReferencesHere && state.options.use !== FindReferencesUse.Rename && state.markSeenReExportRHS(name)) { - addReference(name, ts.Debug.checkDefined(exportSpecifier.symbol), state); + addReference(name, Debug.checkDefined(exportSpecifier.symbol), state); } } else { @@ -1681,18 +1731,18 @@ export namespace Core { // For `export { foo as bar }`, rename `foo`, but not `bar`. if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) { - const isDefaultExport = referenceLocation.originalKeywordKind === ts.SyntaxKind.DefaultKeyword - || exportSpecifier.name.originalKeywordKind === ts.SyntaxKind.DefaultKeyword; - const exportKind = isDefaultExport ? ts.FindAllReferences.ExportKind.Default : ts.FindAllReferences.ExportKind.Named; - const exportSymbol = ts.Debug.checkDefined(exportSpecifier.symbol); - const exportInfo = ts.FindAllReferences.getExportInfo(exportSymbol, exportKind, state.checker); + const isDefaultExport = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword + || exportSpecifier.name.originalKeywordKind === SyntaxKind.DefaultKeyword; + const exportKind = isDefaultExport ? ExportKind.Default : ExportKind.Named; + const exportSymbol = Debug.checkDefined(exportSpecifier.symbol); + const exportInfo = getExportInfo(exportSymbol, exportKind, state.checker); if (exportInfo) { searchForImportsOfExport(referenceLocation, exportSymbol, exportInfo, state); } } // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`. - if (search.comingFrom !== ts.FindAllReferences.ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) { + if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) { const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (imported) searchForImportedSymbol(imported, state); } @@ -1702,13 +1752,13 @@ export namespace Core { } } - function getLocalSymbolForExportSpecifier(referenceLocation: ts.Identifier, referenceSymbol: ts.Symbol, exportSpecifier: ts.ExportSpecifier, checker: ts.TypeChecker): ts.Symbol { + function getLocalSymbolForExportSpecifier(referenceLocation: Identifier, referenceSymbol: Symbol, exportSpecifier: ExportSpecifier, checker: TypeChecker): Symbol { return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol; } - function isExportSpecifierAlias(referenceLocation: ts.Identifier, exportSpecifier: ts.ExportSpecifier): boolean { + function isExportSpecifierAlias(referenceLocation: Identifier, exportSpecifier: ExportSpecifier): boolean { const { parent, propertyName, name } = exportSpecifier; - ts.Debug.assert(propertyName === referenceLocation || name === referenceLocation); + Debug.assert(propertyName === referenceLocation || name === referenceLocation); if (propertyName) { // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol. return propertyName === referenceLocation; @@ -1720,13 +1770,13 @@ export namespace Core { } } - function getImportOrExportReferences(referenceLocation: ts.Node, referenceSymbol: ts.Symbol, search: Search, state: State): void { - const importOrExport = ts.FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === ts.FindAllReferences.ImportExport.Export); + function getImportOrExportReferences(referenceLocation: Node, referenceSymbol: Symbol, search: Search, state: State): void { + const importOrExport = getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === ImportExport.Export); if (!importOrExport) return; const { symbol } = importOrExport; - if (importOrExport.kind === ts.FindAllReferences.ImportExport.Import) { + if (importOrExport.kind === ImportExport.Import) { if (!(isForRenameWithPrefixAndSuffixText(state.options))) { searchForImportedSymbol(symbol, state); } @@ -1736,9 +1786,9 @@ export namespace Core { } } - function getReferenceForShorthandProperty({ flags, valueDeclaration }: ts.Symbol, search: Search, state: State): void { + function getReferenceForShorthandProperty({ flags, valueDeclaration }: Symbol, search: Search, state: State): void { const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration)!; - const name = valueDeclaration && ts.getNameOfDeclaration(valueDeclaration); + const name = valueDeclaration && getNameOfDeclaration(valueDeclaration); /* * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment * has two meanings: property name and property value. Therefore when we do findAllReference at the position where @@ -1746,16 +1796,16 @@ export namespace Core { * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the * position of property accessing, the referenceEntry of such position will be handled in the first case. */ - if (!(flags & ts.SymbolFlags.Transient) && name && search.includes(shorthandValueSymbol)) { + if (!(flags & SymbolFlags.Transient) && name && search.includes(shorthandValueSymbol)) { addReference(name, shorthandValueSymbol, state); } } - function addReference(referenceLocation: ts.Node, relatedSymbol: ts.Symbol | RelatedSymbol, state: State): void { + function addReference(referenceLocation: Node, relatedSymbol: Symbol | RelatedSymbol, state: State): void { const { kind, symbol } = "kind" in relatedSymbol ? relatedSymbol : { kind: undefined, symbol: relatedSymbol }; // eslint-disable-line local/no-in-operator // if rename symbol from default export anonymous function, for example `export default function() {}`, we do not need to add reference - if (state.options.use === FindReferencesUse.Rename && referenceLocation.kind === ts.SyntaxKind.DefaultKeyword) { + if (state.options.use === FindReferencesUse.Rename && referenceLocation.kind === SyntaxKind.DefaultKeyword) { return; } @@ -1769,15 +1819,15 @@ export namespace Core { } /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */ - function addConstructorReferences(referenceLocation: ts.Node, sourceFile: ts.SourceFile, search: Search, state: State): void { - if (ts.isNewExpressionTarget(referenceLocation)) { + function addConstructorReferences(referenceLocation: Node, sourceFile: SourceFile, search: Search, state: State): void { + if (isNewExpressionTarget(referenceLocation)) { addReference(referenceLocation, search.symbol, state); } const pusher = () => state.referenceAdder(search.symbol); - if (ts.isClassLike(referenceLocation.parent)) { - ts.Debug.assert(referenceLocation.kind === ts.SyntaxKind.DefaultKeyword || referenceLocation.parent.name === referenceLocation); + if (isClassLike(referenceLocation.parent)) { + Debug.assert(referenceLocation.kind === SyntaxKind.DefaultKeyword || referenceLocation.parent.name === referenceLocation); // This is the class declaration containing the constructor. findOwnConstructorReferences(search.symbol, sourceFile, pusher()); } @@ -1791,22 +1841,22 @@ export namespace Core { } } - function addClassStaticThisReferences(referenceLocation: ts.Node, search: Search, state: State): void { + function addClassStaticThisReferences(referenceLocation: Node, search: Search, state: State): void { addReference(referenceLocation, search.symbol, state); const classLike = referenceLocation.parent; - if (state.options.use === FindReferencesUse.Rename || !ts.isClassLike(classLike)) return; - ts.Debug.assert(classLike.name === referenceLocation); + if (state.options.use === FindReferencesUse.Rename || !isClassLike(classLike)) return; + Debug.assert(classLike.name === referenceLocation); const addRef = state.referenceAdder(search.symbol); for (const member of classLike.members) { - if (!(ts.isMethodOrAccessor(member) && ts.isStatic(member))) { + if (!(isMethodOrAccessor(member) && isStatic(member))) { continue; } if (member.body) { member.body.forEachChild(function cb(node) { - if (node.kind === ts.SyntaxKind.ThisKeyword) { + if (node.kind === SyntaxKind.ThisKeyword) { addRef(node); } - else if (!ts.isFunctionLike(node) && !ts.isClassLike(node)) { + else if (!isFunctionLike(node) && !isClassLike(node)) { node.forEachChild(cb); } }); @@ -1818,12 +1868,12 @@ export namespace Core { * `classSymbol` is the class where the constructor was defined. * Reference the constructor and all calls to `new this()`. */ - function findOwnConstructorReferences(classSymbol: ts.Symbol, sourceFile: ts.SourceFile, addNode: (node: ts.Node) => void): void { + function findOwnConstructorReferences(classSymbol: Symbol, sourceFile: SourceFile, addNode: (node: Node) => void): void { const constructorSymbol = getClassConstructorSymbol(classSymbol); if (constructorSymbol && constructorSymbol.declarations) { for (const decl of constructorSymbol.declarations) { - const ctrKeyword = ts.findChildOfKind(decl, ts.SyntaxKind.ConstructorKeyword, sourceFile)!; - ts.Debug.assert(decl.kind === ts.SyntaxKind.Constructor && !!ctrKeyword); + const ctrKeyword = findChildOfKind(decl, SyntaxKind.ConstructorKeyword, sourceFile)!; + Debug.assert(decl.kind === SyntaxKind.Constructor && !!ctrKeyword); addNode(ctrKeyword); } } @@ -1831,11 +1881,11 @@ export namespace Core { if (classSymbol.exports) { classSymbol.exports.forEach(member => { const decl = member.valueDeclaration; - if (decl && decl.kind === ts.SyntaxKind.MethodDeclaration) { - const body = (decl as ts.MethodDeclaration).body; + if (decl && decl.kind === SyntaxKind.MethodDeclaration) { + const body = (decl as MethodDeclaration).body; if (body) { - forEachDescendantOfKind(body, ts.SyntaxKind.ThisKeyword, thisKeyword => { - if (ts.isNewExpressionTarget(thisKeyword)) { + forEachDescendantOfKind(body, SyntaxKind.ThisKeyword, thisKeyword => { + if (isNewExpressionTarget(thisKeyword)) { addNode(thisKeyword); } }); @@ -1845,23 +1895,23 @@ export namespace Core { } } - function getClassConstructorSymbol(classSymbol: ts.Symbol): ts.Symbol | undefined { - return classSymbol.members && classSymbol.members.get(ts.InternalSymbolName.Constructor); + function getClassConstructorSymbol(classSymbol: Symbol): Symbol | undefined { + return classSymbol.members && classSymbol.members.get(InternalSymbolName.Constructor); } /** Find references to `super` in the constructor of an extending class. */ - function findSuperConstructorAccesses(classDeclaration: ts.ClassLikeDeclaration, addNode: (node: ts.Node) => void): void { + function findSuperConstructorAccesses(classDeclaration: ClassLikeDeclaration, addNode: (node: Node) => void): void { const constructor = getClassConstructorSymbol(classDeclaration.symbol); if (!(constructor && constructor.declarations)) { return; } for (const decl of constructor.declarations) { - ts.Debug.assert(decl.kind === ts.SyntaxKind.Constructor); - const body = (decl as ts.ConstructorDeclaration).body; + Debug.assert(decl.kind === SyntaxKind.Constructor); + const body = (decl as ConstructorDeclaration).body; if (body) { - forEachDescendantOfKind(body, ts.SyntaxKind.SuperKeyword, node => { - if (ts.isCallExpressionTarget(node)) { + forEachDescendantOfKind(body, SyntaxKind.SuperKeyword, node => { + if (isCallExpressionTarget(node)) { addNode(node); } }); @@ -1869,29 +1919,29 @@ export namespace Core { } } - function hasOwnConstructor(classDeclaration: ts.ClassLikeDeclaration): boolean { + function hasOwnConstructor(classDeclaration: ClassLikeDeclaration): boolean { return !!getClassConstructorSymbol(classDeclaration.symbol); } - function findInheritedConstructorReferences(classDeclaration: ts.ClassLikeDeclaration, state: State): void { + function findInheritedConstructorReferences(classDeclaration: ClassLikeDeclaration, state: State): void { if (hasOwnConstructor(classDeclaration)) return; const classSymbol = classDeclaration.symbol; const search = state.createSearch(/*location*/ undefined, classSymbol, /*comingFrom*/ undefined); getReferencesInContainerOrFiles(classSymbol, state, search); } - function addImplementationReferences(refNode: ts.Node, addReference: (node: ts.Node) => void, state: State): void { + function addImplementationReferences(refNode: Node, addReference: (node: Node) => void, state: State): void { // Check if we found a function/propertyAssignment/method with an implementation or initializer - if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) { + if (isDeclarationName(refNode) && isImplementation(refNode.parent)) { addReference(refNode); return; } - if (refNode.kind !== ts.SyntaxKind.Identifier) { + if (refNode.kind !== SyntaxKind.Identifier) { return; } - if (refNode.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + if (refNode.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { // Go ahead and dereference the shorthand assignment by going to its definition getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference); } @@ -1905,16 +1955,16 @@ export namespace Core { // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface // Find the first node whose parent isn't a type node -- i.e., the highest type node. - const typeNode = ts.findAncestor(refNode, a => !ts.isQualifiedName(a.parent) && !ts.isTypeNode(a.parent) && !ts.isTypeElement(a.parent))!; + const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent))!; const typeHavingNode = typeNode.parent; - if (ts.hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { - if (ts.hasInitializer(typeHavingNode)) { + if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) { + if (hasInitializer(typeHavingNode)) { addIfImplementation(typeHavingNode.initializer!); } - else if (ts.isFunctionLike(typeHavingNode) && (typeHavingNode as ts.FunctionLikeDeclaration).body) { - const body = (typeHavingNode as ts.FunctionLikeDeclaration).body!; - if (body.kind === ts.SyntaxKind.Block) { - ts.forEachReturnStatement(body as ts.Block, returnStatement => { + else if (isFunctionLike(typeHavingNode) && (typeHavingNode as FunctionLikeDeclaration).body) { + const body = (typeHavingNode as FunctionLikeDeclaration).body!; + if (body.kind === SyntaxKind.Block) { + forEachReturnStatement(body as Block, returnStatement => { if (returnStatement.expression) addIfImplementation(returnStatement.expression); }); } @@ -1922,33 +1972,33 @@ export namespace Core { addIfImplementation(body); } } - else if (ts.isAssertionExpression(typeHavingNode)) { + else if (isAssertionExpression(typeHavingNode)) { addIfImplementation(typeHavingNode.expression); } } - function addIfImplementation(e: ts.Expression): void { + function addIfImplementation(e: Expression): void { if (isImplementationExpression(e)) addReference(e); } } - function getContainingClassIfInHeritageClause(node: ts.Node): ts.ClassLikeDeclaration | ts.InterfaceDeclaration | undefined { - return ts.isIdentifier(node) || ts.isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) - : ts.isExpressionWithTypeArguments(node) ? ts.tryCast(node.parent.parent, ts.isClassLike) : undefined; + function getContainingClassIfInHeritageClause(node: Node): ClassLikeDeclaration | InterfaceDeclaration | undefined { + return isIdentifier(node) || isPropertyAccessExpression(node) ? getContainingClassIfInHeritageClause(node.parent) + : isExpressionWithTypeArguments(node) ? tryCast(node.parent.parent, isClassLike) : undefined; } /** * Returns true if this is an expression that can be considered an implementation */ - function isImplementationExpression(node: ts.Expression): boolean { + function isImplementationExpression(node: Expression): boolean { switch (node.kind) { - case ts.SyntaxKind.ParenthesizedExpression: - return isImplementationExpression((node as ts.ParenthesizedExpression).expression); - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ParenthesizedExpression: + return isImplementationExpression((node as ParenthesizedExpression).expression); + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.ArrayLiteralExpression: return true; default: return false; @@ -1974,12 +2024,12 @@ export namespace Core { * @param parent Another class or interface Symbol * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results */ - function explicitlyInheritsFrom(symbol: ts.Symbol, parent: ts.Symbol, cachedResults: ts.ESMap, checker: ts.TypeChecker): boolean { + function explicitlyInheritsFrom(symbol: Symbol, parent: Symbol, cachedResults: ESMap, checker: TypeChecker): boolean { if (symbol === parent) { return true; } - const key = ts.getSymbolId(symbol) + "," + ts.getSymbolId(parent); + const key = getSymbolId(symbol) + "," + getSymbolId(parent); const cached = cachedResults.get(key); if (cached !== undefined) { return cached; @@ -1989,7 +2039,7 @@ export namespace Core { cachedResults.set(key, false); const inherits = !!symbol.declarations && symbol.declarations.some(declaration => - ts.getAllSuperTypeNodes(declaration).some(typeReference => { + getAllSuperTypeNodes(declaration).some(typeReference => { const type = checker.getTypeAtLocation(typeReference); return !!type && !!type.symbol && explicitlyInheritsFrom(type.symbol, parent, cachedResults, checker); })); @@ -1997,23 +2047,23 @@ export namespace Core { return inherits; } - function getReferencesForSuperKeyword(superKeyword: ts.Node): SymbolAndEntries[] | undefined { - let searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false); + function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined { + let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } // Whether 'super' occurs in a static context within a class. - let staticFlag = ts.ModifierFlags.Static; + let staticFlag = ModifierFlags.Static; switch (searchSpaceNode.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - staticFlag &= ts.getSyntacticModifierFlags(searchSpaceNode); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + staticFlag &= getSyntacticModifierFlags(searchSpaceNode); searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; default: @@ -2021,56 +2071,56 @@ export namespace Core { } const sourceFile = searchSpaceNode.getSourceFile(); - const references = ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), node => { - if (node.kind !== ts.SyntaxKind.SuperKeyword) { + const references = mapDefined(getPossibleSymbolReferenceNodes(sourceFile, "super", searchSpaceNode), node => { + if (node.kind !== SyntaxKind.SuperKeyword) { return; } - const container = ts.getSuperContainer(node, /*stopOnFunctions*/ false); + const container = getSuperContainer(node, /*stopOnFunctions*/ false); // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space // and has the same static qualifier as the original 'super's owner. - return container && ts.isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined; + return container && isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined; }); return [{ definition: { type: DefinitionKind.Symbol, symbol: searchSpaceNode.symbol }, references }]; } - function isParameterName(node: ts.Node) { - return node.kind === ts.SyntaxKind.Identifier && node.parent.kind === ts.SyntaxKind.Parameter && (node.parent as ts.ParameterDeclaration).name === node; + function isParameterName(node: Node) { + return node.kind === SyntaxKind.Identifier && node.parent.kind === SyntaxKind.Parameter && (node.parent as ParameterDeclaration).name === node; } - function getReferencesForThisKeyword(thisOrSuperKeyword: ts.Node, sourceFiles: readonly ts.SourceFile[], cancellationToken: ts.CancellationToken): SymbolAndEntries[] | undefined { - let searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { + let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); // Whether 'this' occurs in a static context within a class. - let staticFlag = ts.ModifierFlags.Static; + let staticFlag = ModifierFlags.Static; switch (searchSpaceNode.kind) { - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - if (ts.isObjectLiteralMethod(searchSpaceNode)) { - staticFlag &= ts.getSyntacticModifierFlags(searchSpaceNode); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + if (isObjectLiteralMethod(searchSpaceNode)) { + staticFlag &= getSyntacticModifierFlags(searchSpaceNode); searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning object literals break; } // falls through - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - staticFlag &= ts.getSyntacticModifierFlags(searchSpaceNode); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + staticFlag &= getSyntacticModifierFlags(searchSpaceNode); searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class break; - case ts.SyntaxKind.SourceFile: - if (ts.isExternalModule(searchSpaceNode as ts.SourceFile) || isParameterName(thisOrSuperKeyword)) { + case SyntaxKind.SourceFile: + if (isExternalModule(searchSpaceNode as SourceFile) || isParameterName(thisOrSuperKeyword)) { return undefined; } // falls through - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: break; // Computed properties in classes are not handled here because references to this are illegal, // so there is no point finding references to them. @@ -2078,53 +2128,53 @@ export namespace Core { return undefined; } - const references = ts.flatMap(searchSpaceNode.kind === ts.SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()], sourceFile => { + const references = flatMap(searchSpaceNode.kind === SyntaxKind.SourceFile ? sourceFiles : [searchSpaceNode.getSourceFile()], sourceFile => { cancellationToken.throwIfCancellationRequested(); - return getPossibleSymbolReferenceNodes(sourceFile, "this", ts.isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(node => { - if (!ts.isThis(node)) { + return getPossibleSymbolReferenceNodes(sourceFile, "this", isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode).filter(node => { + if (!isThis(node)) { return false; } - const container = ts.getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false); switch (searchSpaceNode.kind) { - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: return searchSpaceNode.symbol === container.symbol; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - return ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ObjectLiteralExpression: // Make sure the container belongs to the same class/object literals // and has the appropriate static modifier from the original container. - return container.parent && searchSpaceNode.symbol === container.parent.symbol && ts.isStatic(container) === !!staticFlag; - case ts.SyntaxKind.SourceFile: - return container.kind === ts.SyntaxKind.SourceFile && !ts.isExternalModule(container as ts.SourceFile) && !isParameterName(node); + return container.parent && searchSpaceNode.symbol === container.parent.symbol && isStatic(container) === !!staticFlag; + case SyntaxKind.SourceFile: + return container.kind === SyntaxKind.SourceFile && !isExternalModule(container as SourceFile) && !isParameterName(node); } }); }).map(n => nodeEntry(n)); - const thisParameter = ts.firstDefined(references, r => ts.isParameter(r.node.parent) ? r.node : undefined); + const thisParameter = firstDefined(references, r => isParameter(r.node.parent) ? r.node : undefined); return [{ definition: { type: DefinitionKind.This, node: thisParameter || thisOrSuperKeyword }, references }]; } - function getReferencesForStringLiteral(node: ts.StringLiteralLike, sourceFiles: readonly ts.SourceFile[], checker: ts.TypeChecker, cancellationToken: ts.CancellationToken): SymbolAndEntries[] { - const type = ts.getContextualTypeFromParentOrAncestorTypeNode(node, checker); - const references = ts.flatMap(sourceFiles, sourceFile => { + function getReferencesForStringLiteral(node: StringLiteralLike, sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken): SymbolAndEntries[] { + const type = getContextualTypeFromParentOrAncestorTypeNode(node, checker); + const references = flatMap(sourceFiles, sourceFile => { cancellationToken.throwIfCancellationRequested(); - return ts.mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref => { - if (ts.isStringLiteralLike(ref) && ref.text === node.text) { + return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref => { + if (isStringLiteralLike(ref) && ref.text === node.text) { if (type) { - const refType = ts.getContextualTypeFromParentOrAncestorTypeNode(ref, checker); + const refType = getContextualTypeFromParentOrAncestorTypeNode(ref, checker); if (type !== checker.getStringType() && type === refType) { return nodeEntry(ref, EntryKind.StringLiteral); } } else { - return ts.isNoSubstitutionTemplateLiteral(ref) && !ts.rangeIsOnSingleLine(ref, sourceFile) ? undefined : + return isNoSubstitutionTemplateLiteral(ref) && !rangeIsOnSingleLine(ref, sourceFile) ? undefined : nodeEntry(ref, EntryKind.StringLiteral); } } @@ -2139,8 +2189,8 @@ export namespace Core { // For certain symbol kinds, we need to include other symbols in the search set. // This is not needed when searching for re-exports. - function populateSearchSymbolSet(symbol: ts.Symbol, location: ts.Node, checker: ts.TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): ts.Symbol[] { - const result: ts.Symbol[] = []; + function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): Symbol[] { + const result: Symbol[] = []; forEachRelatedSymbol(symbol, location, checker, isForRename, !(isForRename && providePrefixAndSuffixText), (sym, root, base) => { // static method/property and instance method/property might have the same name. Only include static or only include instance. @@ -2160,14 +2210,14 @@ export namespace Core { * @param allowBaseTypes return true means it would try to find in base class or interface. */ function forEachRelatedSymbol( - symbol: ts.Symbol, location: ts.Node, checker: ts.TypeChecker, isForRenamePopulateSearchSymbolSet: boolean, onlyIncludeBindingElementAtReferenceLocation: boolean, + symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean, onlyIncludeBindingElementAtReferenceLocation: boolean, /** * @param baseSymbol This symbol means one property/mehtod from base class or interface when it is not null or undefined, */ - cbSymbol: (symbol: ts.Symbol, rootSymbol?: ts.Symbol, baseSymbol?: ts.Symbol, kind?: NodeEntryKind) => T | undefined, - allowBaseTypes: (rootSymbol: ts.Symbol) => boolean, + cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol, kind?: NodeEntryKind) => T | undefined, + allowBaseTypes: (rootSymbol: Symbol) => boolean, ): T | undefined { - const containingObjectLiteralElement = ts.getContainingObjectLiteralElement(location); + const containingObjectLiteralElement = getContainingObjectLiteralElement(location); if (containingObjectLiteralElement) { /* Because in short-hand property assignment, location has two meaning : property name and as value of the property * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of @@ -2190,8 +2240,8 @@ export namespace Core { // to get a contextual type for it, and add the property symbol from the contextual // type to the search set const contextualType = checker.getContextualType(containingObjectLiteralElement.parent); - const res = contextualType && ts.firstDefined( - ts.getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), + const res = contextualType && firstDefined( + getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), sym => fromRoot(sym, EntryKind.SearchedPropertyFoundLocal)); if (res) return res; @@ -2216,14 +2266,14 @@ export namespace Core { const res = fromRoot(symbol); if (res) return res; - if (symbol.valueDeclaration && ts.isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent)) { + if (symbol.valueDeclaration && isParameterPropertyDeclaration(symbol.valueDeclaration, symbol.valueDeclaration.parent)) { // For a parameter property, now try on the other symbol (property if this was a parameter, parameter if this was a property). - const paramProps = checker.getSymbolsOfParameterPropertyDeclaration(ts.cast(symbol.valueDeclaration, ts.isParameter), symbol.name); - ts.Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & ts.SymbolFlags.FunctionScopedVariable) && !!(paramProps[1].flags & ts.SymbolFlags.Property)); // is [parameter, property] - return fromRoot(symbol.flags & ts.SymbolFlags.FunctionScopedVariable ? paramProps[1] : paramProps[0]); + const paramProps = checker.getSymbolsOfParameterPropertyDeclaration(cast(symbol.valueDeclaration, isParameter), symbol.name); + Debug.assert(paramProps.length === 2 && !!(paramProps[0].flags & SymbolFlags.FunctionScopedVariable) && !!(paramProps[1].flags & SymbolFlags.Property)); // is [parameter, property] + return fromRoot(symbol.flags & SymbolFlags.FunctionScopedVariable ? paramProps[1] : paramProps[0]); } - const exportSpecifier = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ExportSpecifier); + const exportSpecifier = getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier); if (!isForRenamePopulateSearchSymbolSet || exportSpecifier && !exportSpecifier.propertyName) { const localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier); if (localSymbol) { @@ -2235,9 +2285,9 @@ export namespace Core { // symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property. // Don't do this when populating search set for a rename when prefix and suffix text will be provided -- just rename the local. if (!isForRenamePopulateSearchSymbolSet) { - let bindingElementPropertySymbol: ts.Symbol | undefined; + let bindingElementPropertySymbol: Symbol | undefined; if (onlyIncludeBindingElementAtReferenceLocation) { - bindingElementPropertySymbol = ts.isObjectBindingElementWithoutPropertyName(location.parent) ? ts.getPropertySymbolFromBindingElement(checker, location.parent) : undefined; + bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined; } else { bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker); @@ -2245,7 +2295,7 @@ export namespace Core { return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); } - ts.Debug.assert(isForRenamePopulateSearchSymbolSet); + Debug.assert(isForRenamePopulateSearchSymbolSet); // due to the above assert and the arguments at the uses of this function, // (onlyIncludeBindingElementAtReferenceLocation <=> !providePrefixAndSuffixTextForRename) holds const includeOriginalSymbolOfBindingElement = onlyIncludeBindingElementAtReferenceLocation; @@ -2255,25 +2305,25 @@ export namespace Core { return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal); } - function fromRoot(sym: ts.Symbol, kind?: NodeEntryKind): T | undefined { + function fromRoot(sym: Symbol, kind?: NodeEntryKind): T | undefined { // If this is a union property: // - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types. // - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search. // If the symbol is an instantiation from a another symbol (e.g. widened symbol): // - In populateSearchSymbolsSet, add the root the list // - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.) - return ts.firstDefined(checker.getRootSymbols(sym), rootSymbol => + return firstDefined(checker.getRootSymbols(sym), rootSymbol => cbSymbol(sym, rootSymbol, /*baseSymbol*/ undefined, kind) // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions - || (rootSymbol.parent && rootSymbol.parent.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface) && allowBaseTypes(rootSymbol) + || (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface) && allowBaseTypes(rootSymbol) ? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base, kind)) : undefined)); } - function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol | undefined { - const bindingElement = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.BindingElement); - if (bindingElement && ts.isObjectBindingElementWithoutPropertyName(bindingElement)) { - return ts.getPropertySymbolFromBindingElement(checker, bindingElement); + function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined { + const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement); + if (bindingElement && isObjectBindingElementWithoutPropertyName(bindingElement)) { + return getPropertySymbolFromBindingElement(checker, bindingElement); } } } @@ -2286,38 +2336,38 @@ export namespace Core { * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. * The value of previousIterationSymbol is undefined when the function is first called. */ - function getPropertySymbolsFromBaseTypes(symbol: ts.Symbol, propertyName: string, checker: ts.TypeChecker, cb: (symbol: ts.Symbol) => T | undefined): T | undefined { - const seen = new ts.Map(); + function getPropertySymbolsFromBaseTypes(symbol: Symbol, propertyName: string, checker: TypeChecker, cb: (symbol: Symbol) => T | undefined): T | undefined { + const seen = new Map(); return recur(symbol); - function recur(symbol: ts.Symbol): T | undefined { + function recur(symbol: Symbol): T | undefined { // Use `addToSeen` to ensure we don't infinitely recurse in this situation: // interface C extends C { // /*findRef*/propName: string; // } - if (!(symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface)) || !ts.addToSeen(seen, ts.getSymbolId(symbol))) return; + if (!(symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) || !addToSeen(seen, getSymbolId(symbol))) return; - return ts.firstDefined(symbol.declarations, declaration => ts.firstDefined(ts.getAllSuperTypeNodes(declaration), typeReference => { + return firstDefined(symbol.declarations, declaration => firstDefined(getAllSuperTypeNodes(declaration), typeReference => { const type = checker.getTypeAtLocation(typeReference); const propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName); // Visit the typeReference as well to see if it directly or indirectly uses that property - return type && propertySymbol && (ts.firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); + return type && propertySymbol && (firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol)); })); } } interface RelatedSymbol { - readonly symbol: ts.Symbol; + readonly symbol: Symbol; readonly kind: NodeEntryKind | undefined; } - function isStaticSymbol(symbol: ts.Symbol): boolean { + function isStaticSymbol(symbol: Symbol): boolean { if (!symbol.valueDeclaration) return false; - const modifierFlags = ts.getEffectiveModifierFlags(symbol.valueDeclaration); - return !!(modifierFlags & ts.ModifierFlags.Static); + const modifierFlags = getEffectiveModifierFlags(symbol.valueDeclaration); + return !!(modifierFlags & ModifierFlags.Static); } - function getRelatedSymbol(search: Search, referenceSymbol: ts.Symbol, referenceLocation: ts.Node, state: State): RelatedSymbol | undefined { + function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined { const { checker } = state; return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false, /*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== FindReferencesUse.Rename || !!state.options.providePrefixAndSuffixTextForRename, @@ -2331,7 +2381,7 @@ export namespace Core { } return search.includes(baseSymbol || rootSymbol || sym) // For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol. - ? { symbol: rootSymbol && !(ts.getCheckFlags(sym) & ts.CheckFlags.Synthetic) ? rootSymbol : sym, kind } + ? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind } : undefined; }, /*allowBaseTypes*/ rootSymbol => @@ -2347,11 +2397,11 @@ export namespace Core { * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module) * do not intersect in any of the three spaces. */ - export function getIntersectingMeaningFromDeclarations(node: ts.Node, symbol: ts.Symbol): ts.SemanticMeaning { - let meaning = ts.getMeaningFromLocation(node); + export function getIntersectingMeaningFromDeclarations(node: Node, symbol: Symbol): SemanticMeaning { + let meaning = getMeaningFromLocation(node); const { declarations } = symbol; if (declarations) { - let lastIterationMeaning: ts.SemanticMeaning; + let lastIterationMeaning: SemanticMeaning; do { // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module] // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module @@ -2362,7 +2412,7 @@ export namespace Core { lastIterationMeaning = meaning; for (const declaration of declarations) { - const declarationMeaning = ts.getMeaningFromDeclaration(declaration); + const declarationMeaning = getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -2374,28 +2424,28 @@ export namespace Core { return meaning; } - function isImplementation(node: ts.Node): boolean { - return !!(node.flags & ts.NodeFlags.Ambient) ? !(ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) : - (ts.isVariableLike(node) ? ts.hasInitializer(node) : - ts.isFunctionLikeDeclaration(node) ? !!node.body : - ts.isClassLike(node) || ts.isModuleOrEnumDeclaration(node)); + function isImplementation(node: Node): boolean { + return !!(node.flags & NodeFlags.Ambient) ? !(isInterfaceDeclaration(node) || isTypeAliasDeclaration(node)) : + (isVariableLike(node) ? hasInitializer(node) : + isFunctionLikeDeclaration(node) ? !!node.body : + isClassLike(node) || isModuleOrEnumDeclaration(node)); } - export function getReferenceEntriesForShorthandPropertyAssignment(node: ts.Node, checker: ts.TypeChecker, addReference: (node: ts.Node) => void): void { + export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, checker: TypeChecker, addReference: (node: Node) => void): void { const refSymbol = checker.getSymbolAtLocation(node)!; const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); if (shorthandSymbol) { for (const declaration of shorthandSymbol.getDeclarations()!) { - if (ts.getMeaningFromDeclaration(declaration) & ts.SemanticMeaning.Value) { + if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) { addReference(declaration); } } } } - function forEachDescendantOfKind(node: ts.Node, kind: ts.SyntaxKind, action: (node: ts.Node) => void): void { - ts.forEachChild(node, child => { + function forEachDescendantOfKind(node: Node, kind: SyntaxKind, action: (node: Node) => void): void { + forEachChild(node, child => { if (child.kind === kind) { action(child); } @@ -2404,8 +2454,8 @@ export namespace Core { } /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */ - function tryGetClassByExtendingIdentifier(node: ts.Node): ts.ClassLikeDeclaration | undefined { - return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent); + function tryGetClassByExtendingIdentifier(node: Node): ClassLikeDeclaration | undefined { + return tryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).parent); } /** @@ -2414,11 +2464,11 @@ export namespace Core { * symbol may have a different parent symbol if the local type's symbol does not declare the property * being accessed (i.e. it is declared in some parent class or interface) */ - function getParentSymbolsOfPropertyAccess(location: ts.Node, symbol: ts.Symbol, checker: ts.TypeChecker): readonly ts.Symbol[] | undefined { - const propertyAccessExpression = ts.isRightSideOfPropertyAccess(location) ? location.parent as ts.PropertyAccessExpression : undefined; + function getParentSymbolsOfPropertyAccess(location: Node, symbol: Symbol, checker: TypeChecker): readonly Symbol[] | undefined { + const propertyAccessExpression = isRightSideOfPropertyAccess(location) ? location.parent as PropertyAccessExpression : undefined; const lhsType = propertyAccessExpression && checker.getTypeAtLocation(propertyAccessExpression.expression); - const res = ts.mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), t => - t.symbol && t.symbol.flags & (ts.SymbolFlags.Class | ts.SymbolFlags.Interface) ? t.symbol : undefined); + const res = mapDefined(lhsType && (lhsType.isUnionOrIntersection() ? lhsType.types : lhsType.symbol === symbol.parent ? undefined : [lhsType]), t => + t.symbol && t.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? t.symbol : undefined); return res.length === 0 ? undefined : res; } diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 2cfd59a44daaf..b3913f66ed82f 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -1,19 +1,35 @@ -import * as ts from "../_namespaces/ts"; +import { + Block, CallExpression, canHaveModifiers, CatchClause, CharacterCodes, ClassDeclaration, CommentRange, concatenate, + createTextChangeFromStartLength, Debug, Declaration, Diagnostic, EditorSettings, find, findAncestor, findIndex, + findPrecedingToken, forEachChild, forEachRight, FormatCodeSettings, FormattingHost, FunctionDeclaration, + getEndLinePosition, getLeadingCommentRangesOfNode, getLineStartPositionForPosition, getNameOfDeclaration, + getNewLineOrDefaultFromHost, getNonDecoratorTokenPosOfNode, getStartPositionOfLine, getTokenAtPosition, + getTrailingCommentRanges, hasDecorators, InterfaceDeclaration, isComment, isDecorator, isJSDoc, isLineBreak, + isModifier, isNodeArray, isStringOrRegularExpressionOrTemplateLiteral, isToken, isWhiteSpaceSingleLine, + LanguageVariant, last, LineAndCharacter, MethodDeclaration, ModuleDeclaration, Node, NodeArray, nodeIsMissing, + nodeIsSynthesized, rangeContainsPositionExclusive, rangeContainsRange, rangeContainsStartEnd, + rangeOverlapsWithStartEnd, repeatString, SourceFile, SourceFileLike, startEndContainsRange, + startEndOverlapsWithStartEnd, SyntaxKind, TextChange, TextRange, TriviaSyntaxKind, TypeReferenceNode, +} from "../_namespaces/ts"; +import { + FormattingContext, FormattingRequestKind, FormattingScanner, getFormattingScanner, Rule, RuleAction, RuleFlags, + RulesMap, SmartIndenter, +} from "../_namespaces/ts.formatting"; /** @internal */ export interface FormatContext { - readonly options: ts.FormatCodeSettings; - readonly getRules: ts.formatting.RulesMap; - readonly host: ts.FormattingHost; + readonly options: FormatCodeSettings; + readonly getRules: RulesMap; + readonly host: FormattingHost; } /** @internal */ -export interface TextRangeWithKind extends ts.TextRange { +export interface TextRangeWithKind extends TextRange { kind: T; } /** @internal */ -export type TextRangeWithTriviaKind = TextRangeWithKind; +export type TextRangeWithTriviaKind = TextRangeWithKind; /** @internal */ export interface TokenInfo { @@ -23,11 +39,11 @@ export interface TokenInfo { } /** @internal */ -export function createTextRangeWithKind(pos: number, end: number, kind: T): TextRangeWithKind { +export function createTextRangeWithKind(pos: number, end: number, kind: T): TextRangeWithKind { const textRangeWithKind: TextRangeWithKind = { pos, end, kind }; - if (ts.Debug.isDebugging) { + if (Debug.isDebugging) { Object.defineProperty(textRangeWithKind, "__debugKind", { - get: () => ts.Debug.formatSyntaxKind(kind), + get: () => Debug.formatSyntaxKind(kind), }); } return textRangeWithKind; @@ -48,8 +64,8 @@ const enum Constants { * the first token in line so it should be indented */ interface DynamicIndentation { - getIndentationForToken(tokenLine: number, tokenKind: ts.SyntaxKind, container: ts.Node, suppressDelta: boolean): number; - getIndentationForComment(owningToken: ts.SyntaxKind, tokenIndentation: number, container: ts.Node): number; + getIndentationForToken(tokenLine: number, tokenKind: SyntaxKind, container: Node, suppressDelta: boolean): number; + getIndentationForComment(owningToken: SyntaxKind, tokenIndentation: number, container: Node): number; /** * Indentation for open and close tokens of the node if it is block or another node that needs special indentation * ... { @@ -76,11 +92,11 @@ interface DynamicIndentation { * Formatter calls this function when rule adds or deletes new lines from the text * so indentation scope can adjust values of indentation and delta. */ - recomputeIndentation(lineAddedByFormatting: boolean, parent: ts.Node): void; + recomputeIndentation(lineAddedByFormatting: boolean, parent: Node): void; } /** @internal */ -export function formatOnEnter(position: number, sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { +export function formatOnEnter(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const line = sourceFile.getLineAndCharacterOfPosition(position).line; if (line === 0) { return []; @@ -90,34 +106,34 @@ export function formatOnEnter(position: number, sourceFile: ts.SourceFile, forma // trailing whitespaces. So the end of the formatting span should be the later one between: // 1. the end of the previous line // 2. the last non-whitespace character in the current line - let endOfFormatSpan = ts.getEndLinePosition(line, sourceFile); - while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { + let endOfFormatSpan = getEndLinePosition(line, sourceFile); + while (isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the // previous character before the end of format span is line break character as well. - if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { + if (isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) { endOfFormatSpan--; } const span = { // get start position for the previous line - pos: ts.getStartPositionOfLine(line - 1, sourceFile), + pos: getStartPositionOfLine(line - 1, sourceFile), // end value is exclusive so add 1 to the result end: endOfFormatSpan + 1 }; - return formatSpan(span, sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatOnEnter); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatOnEnter); } /** @internal */ -export function formatOnSemicolon(position: number, sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { - const semicolon = findImmediatelyPrecedingTokenOfKind(position, ts.SyntaxKind.SemicolonToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatOnSemicolon); +export function formatOnSemicolon(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { + const semicolon = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.SemicolonToken, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, FormattingRequestKind.FormatOnSemicolon); } /** @internal */ -export function formatOnOpeningCurly(position: number, sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { - const openingCurly = findImmediatelyPrecedingTokenOfKind(position, ts.SyntaxKind.OpenBraceToken, sourceFile); +export function formatOnOpeningCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { + const openingCurly = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.OpenBraceToken, sourceFile); if (!openingCurly) { return []; } @@ -136,45 +152,45 @@ export function formatOnOpeningCurly(position: number, sourceFile: ts.SourceFile * ``` * and we wouldn't want to move the closing brace. */ - const textRange: ts.TextRange = { - pos: ts.getLineStartPositionForPosition(outermostNode!.getStart(sourceFile), sourceFile), // TODO: GH#18217 + const textRange: TextRange = { + pos: getLineStartPositionForPosition(outermostNode!.getStart(sourceFile), sourceFile), // TODO: GH#18217 end: position }; - return formatSpan(textRange, sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatOnOpeningCurlyBrace); + return formatSpan(textRange, sourceFile, formatContext, FormattingRequestKind.FormatOnOpeningCurlyBrace); } /** @internal */ -export function formatOnClosingCurly(position: number, sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { - const precedingToken = findImmediatelyPrecedingTokenOfKind(position, ts.SyntaxKind.CloseBraceToken, sourceFile); - return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatOnClosingCurlyBrace); +export function formatOnClosingCurly(position: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { + const precedingToken = findImmediatelyPrecedingTokenOfKind(position, SyntaxKind.CloseBraceToken, sourceFile); + return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, FormattingRequestKind.FormatOnClosingCurlyBrace); } /** @internal */ -export function formatDocument(sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { +export function formatDocument(sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { const span = { pos: 0, end: sourceFile.text.length }; - return formatSpan(span, sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatDocument); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatDocument); } /** @internal */ -export function formatSelection(start: number, end: number, sourceFile: ts.SourceFile, formatContext: FormatContext): ts.TextChange[] { +export function formatSelection(start: number, end: number, sourceFile: SourceFile, formatContext: FormatContext): TextChange[] { // format from the beginning of the line const span = { - pos: ts.getLineStartPositionForPosition(start, sourceFile), + pos: getLineStartPositionForPosition(start, sourceFile), end, }; - return formatSpan(span, sourceFile, formatContext, ts.formatting.FormattingRequestKind.FormatSelection); + return formatSpan(span, sourceFile, formatContext, FormattingRequestKind.FormatSelection); } /** * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment). * @param expectedTokenKind The kind of the last token constituting the desired parent node. */ -function findImmediatelyPrecedingTokenOfKind(end: number, expectedTokenKind: ts.SyntaxKind, sourceFile: ts.SourceFile): ts.Node | undefined { - const precedingToken = ts.findPrecedingToken(end, sourceFile); +function findImmediatelyPrecedingTokenOfKind(end: number, expectedTokenKind: SyntaxKind, sourceFile: SourceFile): Node | undefined { + const precedingToken = findPrecedingToken(end, sourceFile); return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ? precedingToken : @@ -194,7 +210,7 @@ function findImmediatelyPrecedingTokenOfKind(end: number, expectedTokenKind: ts. * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding * variable declaration. */ -function findOutermostNodeWithinListLevel(node: ts.Node | undefined) { +function findOutermostNodeWithinListLevel(node: Node | undefined) { let current = node; while (current && current.parent && @@ -208,31 +224,31 @@ function findOutermostNodeWithinListLevel(node: ts.Node | undefined) { // Returns true if node is a element in some list in parent // i.e. parent is class declaration with the list of members and node is one of members. -function isListElement(parent: ts.Node, node: ts.Node): boolean { +function isListElement(parent: Node, node: Node): boolean { switch (parent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - return ts.rangeContainsRange((parent as ts.InterfaceDeclaration).members, node); - case ts.SyntaxKind.ModuleDeclaration: - const body = (parent as ts.ModuleDeclaration).body; - return !!body && body.kind === ts.SyntaxKind.ModuleBlock && ts.rangeContainsRange(body.statements, node); - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - return ts.rangeContainsRange((parent as ts.Block).statements, node); - case ts.SyntaxKind.CatchClause: - return ts.rangeContainsRange((parent as ts.CatchClause).block.statements, node); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + return rangeContainsRange((parent as InterfaceDeclaration).members, node); + case SyntaxKind.ModuleDeclaration: + const body = (parent as ModuleDeclaration).body; + return !!body && body.kind === SyntaxKind.ModuleBlock && rangeContainsRange(body.statements, node); + case SyntaxKind.SourceFile: + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + return rangeContainsRange((parent as Block).statements, node); + case SyntaxKind.CatchClause: + return rangeContainsRange((parent as CatchClause).block.statements, node); } return false; } /** find node that fully contains given text range */ -function findEnclosingNode(range: ts.TextRange, sourceFile: ts.SourceFile): ts.Node { +function findEnclosingNode(range: TextRange, sourceFile: SourceFile): Node { return find(sourceFile); - function find(n: ts.Node): ts.Node { - const candidate = ts.forEachChild(n, c => ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c); + function find(n: Node): Node { + const candidate = forEachChild(n, c => startEndContainsRange(c.getStart(sourceFile), c.end, range) && c); if (candidate) { const result = find(candidate); if (result) { @@ -248,14 +264,14 @@ function findEnclosingNode(range: ts.TextRange, sourceFile: ts.SourceFile): ts.N * This function will return a predicate that for a given text range will tell * if there are any parse errors that overlap with the range. */ -function prepareRangeContainsErrorFunction(errors: readonly ts.Diagnostic[], originalRange: ts.TextRange): (r: ts.TextRange) => boolean { +function prepareRangeContainsErrorFunction(errors: readonly Diagnostic[], originalRange: TextRange): (r: TextRange) => boolean { if (!errors.length) { return rangeHasNoErrors; } // pick only errors that fall in range const sorted = errors - .filter(d => ts.rangeOverlapsWithStartEnd(originalRange, d.start!, d.start! + d.length!)) // TODO: GH#18217 + .filter(d => rangeOverlapsWithStartEnd(originalRange, d.start!, d.start! + d.length!)) // TODO: GH#18217 .sort((e1, e2) => e1.start! - e2.start!); if (!sorted.length) { @@ -279,7 +295,7 @@ function prepareRangeContainsErrorFunction(errors: readonly ts.Diagnostic[], ori return false; } - if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start!, error.start! + error.length!)) { + if (startEndOverlapsWithStartEnd(r.pos, r.end, error.start!, error.start! + error.length!)) { // specified range overlaps with error range return true; } @@ -298,13 +314,13 @@ function prepareRangeContainsErrorFunction(errors: readonly ts.Diagnostic[], ori * This function will look for token that is located before the start of target range * and return its end as start position for the scanner. */ -function getScanStartPosition(enclosingNode: ts.Node, originalRange: ts.TextRange, sourceFile: ts.SourceFile): number { +function getScanStartPosition(enclosingNode: Node, originalRange: TextRange, sourceFile: SourceFile): number { const start = enclosingNode.getStart(sourceFile); if (start === originalRange.pos && enclosingNode.end === originalRange.end) { return start; } - const precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile); + const precedingToken = findPrecedingToken(originalRange.pos, sourceFile); if (!precedingToken) { // no preceding token found - start from the beginning of enclosing node return enclosingNode.pos; @@ -334,16 +350,16 @@ function getScanStartPosition(enclosingNode: ts.Node, originalRange: ts.TextRang * if parent is on the different line - its delta was already contributed * to the initial indentation. */ -function getOwnOrInheritedDelta(n: ts.Node, options: ts.FormatCodeSettings, sourceFile: ts.SourceFile): number { +function getOwnOrInheritedDelta(n: Node, options: FormatCodeSettings, sourceFile: SourceFile): number { let previousLine = Constants.Unknown; - let child: ts.Node | undefined; + let child: Node | undefined; while (n) { const line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line; if (previousLine !== Constants.Unknown && line !== previousLine) { break; } - if (ts.formatting.SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { + if (SmartIndenter.shouldIndentChildNode(options, n, child, sourceFile)) { return options.indentSize!; } @@ -355,37 +371,37 @@ function getOwnOrInheritedDelta(n: ts.Node, options: ts.FormatCodeSettings, sour } /** @internal */ -export function formatNodeGivenIndentation(node: ts.Node, sourceFileLike: ts.SourceFileLike, languageVariant: ts.LanguageVariant, initialIndentation: number, delta: number, formatContext: FormatContext): ts.TextChange[] { +export function formatNodeGivenIndentation(node: Node, sourceFileLike: SourceFileLike, languageVariant: LanguageVariant, initialIndentation: number, delta: number, formatContext: FormatContext): TextChange[] { const range = { pos: node.pos, end: node.end }; - return ts.formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, scanner => formatSpanWorker( + return getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, scanner => formatSpanWorker( range, node, initialIndentation, delta, scanner, formatContext, - ts.formatting.FormattingRequestKind.FormatSelection, + FormattingRequestKind.FormatSelection, _ => false, // assume that node does not have any errors sourceFileLike)); } -function formatNodeLines(node: ts.Node | undefined, sourceFile: ts.SourceFile, formatContext: FormatContext, requestKind: ts.formatting.FormattingRequestKind): ts.TextChange[] { +function formatNodeLines(node: Node | undefined, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { if (!node) { return []; } const span = { - pos: ts.getLineStartPositionForPosition(node.getStart(sourceFile), sourceFile), + pos: getLineStartPositionForPosition(node.getStart(sourceFile), sourceFile), end: node.end }; return formatSpan(span, sourceFile, formatContext, requestKind); } -function formatSpan(originalRange: ts.TextRange, sourceFile: ts.SourceFile, formatContext: FormatContext, requestKind: ts.formatting.FormattingRequestKind): ts.TextChange[] { +function formatSpan(originalRange: TextRange, sourceFile: SourceFile, formatContext: FormatContext, requestKind: FormattingRequestKind): TextChange[] { // find the smallest node that fully wraps the range and compute the initial indentation for the node const enclosingNode = findEnclosingNode(originalRange, sourceFile); - return ts.formatting.getFormattingScanner( + return getFormattingScanner( sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), @@ -393,7 +409,7 @@ function formatSpan(originalRange: ts.TextRange, sourceFile: ts.SourceFile, form scanner => formatSpanWorker( originalRange, enclosingNode, - ts.formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), + SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, @@ -403,42 +419,42 @@ function formatSpan(originalRange: ts.TextRange, sourceFile: ts.SourceFile, form } function formatSpanWorker( - originalRange: ts.TextRange, - enclosingNode: ts.Node, + originalRange: TextRange, + enclosingNode: Node, initialIndentation: number, delta: number, - formattingScanner: ts.formatting.FormattingScanner, + formattingScanner: FormattingScanner, { options, getRules, host }: FormatContext, - requestKind: ts.formatting.FormattingRequestKind, - rangeContainsError: (r: ts.TextRange) => boolean, - sourceFile: ts.SourceFileLike): ts.TextChange[] { + requestKind: FormattingRequestKind, + rangeContainsError: (r: TextRange) => boolean, + sourceFile: SourceFileLike): TextChange[] { // formatting context is used by rules provider - const formattingContext = new ts.formatting.FormattingContext(sourceFile, requestKind, options); + const formattingContext = new FormattingContext(sourceFile, requestKind, options); let previousRangeTriviaEnd: number; let previousRange: TextRangeWithKind; - let previousParent: ts.Node; + let previousParent: Node; let previousRangeStartLine: number; let lastIndentedLine: number; let indentationOnLastIndentedLine = Constants.Unknown; - const edits: ts.TextChange[] = []; + const edits: TextChange[] = []; formattingScanner.advance(); if (formattingScanner.isOnToken()) { const startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line; let undecoratedStartLine = startLine; - if (ts.hasDecorators(enclosingNode)) { - undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; + if (hasDecorators(enclosingNode)) { + undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line; } processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta); } if (!formattingScanner.isOnToken()) { - const indentation = ts.formatting.SmartIndenter.nodeWillIndentChild(options, enclosingNode, /*child*/ undefined, sourceFile, /*indentByDefault*/ false) + const indentation = SmartIndenter.nodeWillIndentChild(options, enclosingNode, /*child*/ undefined, sourceFile, /*indentByDefault*/ false) ? initialIndentation + options.indentSize! : initialIndentation; const leadingTrivia = formattingScanner.getCurrentLeadingTrivia(); @@ -478,7 +494,7 @@ function formatSpanWorker( // to perform a trailing edit at the end of the selection range: but there can be no valid // edit in the middle of a token where the range ended, so if we have a non-contiguous // pair here, we're already done and we can ignore it. - const parent = ts.findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)?.parent || previousParent!; + const parent = findPrecedingToken(tokenInfo.end, sourceFile, enclosingNode)?.parent || previousParent!; processPair( tokenInfo, sourceFile.getLineAndCharacterOfPosition(tokenInfo.pos).line, @@ -505,11 +521,11 @@ function formatSpanWorker( function tryComputeIndentationForListItem(startPos: number, endPos: number, parentStartLine: number, - range: ts.TextRange, + range: TextRange, inheritedIndentation: number): number { - if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) || - ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { + if (rangeOverlapsWithStartEnd(range, startPos, endPos) || + rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) { if (inheritedIndentation !== Constants.Unknown) { return inheritedIndentation; @@ -517,12 +533,12 @@ function formatSpanWorker( } else { const startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line; - const startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile); - const column = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); + const startLinePosition = getLineStartPositionForPosition(startPos, sourceFile); + const column = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options); if (startLine !== parentStartLine || startPos === column) { // Use the base indent size if it is greater than // the indentation of the inherited predecessor. - const baseIndentSize = ts.formatting.SmartIndenter.getBaseIndentation(options); + const baseIndentSize = SmartIndenter.getBaseIndentation(options); return baseIndentSize > column ? baseIndentSize : column; } } @@ -534,11 +550,11 @@ function formatSpanWorker( node: TextRangeWithKind, startLine: number, inheritedIndentation: number, - parent: ts.Node, + parent: Node, parentDynamicIndentation: DynamicIndentation, effectiveParentStartLine: number ): { indentation: number, delta: number; } { - const delta = ts.formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; + const delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; if (effectiveParentStartLine === startLine) { // if node is located on the same line with the parent @@ -550,15 +566,15 @@ function formatSpanWorker( }; } else if (inheritedIndentation === Constants.Unknown) { - if (node.kind === ts.SyntaxKind.OpenParenToken && startLine === lastIndentedLine) { + if (node.kind === SyntaxKind.OpenParenToken && startLine === lastIndentedLine) { // the is used for chaining methods formatting // - we need to get the indentation on last line and the delta of parent return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) }; } else if ( - ts.formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile) || - ts.formatting.SmartIndenter.childIsUnindentedBranchOfConditionalExpression(parent, node, startLine, sourceFile) || - ts.formatting.SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile) + SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile) || + SmartIndenter.childIsUnindentedBranchOfConditionalExpression(parent, node, startLine, sourceFile) || + SmartIndenter.argumentStartsOnSameLineAsPreviousArgument(parent, node, startLine, sourceFile) ) { return { indentation: parentDynamicIndentation.getIndentation(), delta }; } @@ -571,35 +587,35 @@ function formatSpanWorker( } } - function getFirstNonDecoratorTokenOfNode(node: ts.Node) { - if (ts.canHaveModifiers(node)) { - const modifier = ts.find(node.modifiers, ts.isModifier, ts.findIndex(node.modifiers, ts.isDecorator)); + function getFirstNonDecoratorTokenOfNode(node: Node) { + if (canHaveModifiers(node)) { + const modifier = find(node.modifiers, isModifier, findIndex(node.modifiers, isDecorator)); if (modifier) return modifier.kind; } switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: return ts.SyntaxKind.ClassKeyword; - case ts.SyntaxKind.InterfaceDeclaration: return ts.SyntaxKind.InterfaceKeyword; - case ts.SyntaxKind.FunctionDeclaration: return ts.SyntaxKind.FunctionKeyword; - case ts.SyntaxKind.EnumDeclaration: return ts.SyntaxKind.EnumDeclaration; - case ts.SyntaxKind.GetAccessor: return ts.SyntaxKind.GetKeyword; - case ts.SyntaxKind.SetAccessor: return ts.SyntaxKind.SetKeyword; - case ts.SyntaxKind.MethodDeclaration: - if ((node as ts.MethodDeclaration).asteriskToken) { - return ts.SyntaxKind.AsteriskToken; + case SyntaxKind.ClassDeclaration: return SyntaxKind.ClassKeyword; + case SyntaxKind.InterfaceDeclaration: return SyntaxKind.InterfaceKeyword; + case SyntaxKind.FunctionDeclaration: return SyntaxKind.FunctionKeyword; + case SyntaxKind.EnumDeclaration: return SyntaxKind.EnumDeclaration; + case SyntaxKind.GetAccessor: return SyntaxKind.GetKeyword; + case SyntaxKind.SetAccessor: return SyntaxKind.SetKeyword; + case SyntaxKind.MethodDeclaration: + if ((node as MethodDeclaration).asteriskToken) { + return SyntaxKind.AsteriskToken; } // falls through - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.Parameter: - const name = ts.getNameOfDeclaration(node as ts.Declaration); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.Parameter: + const name = getNameOfDeclaration(node as Declaration); if (name) { return name.kind; } } } - function getDynamicIndentation(node: ts.Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation { + function getDynamicIndentation(node: Node, nodeStartLine: number, indentation: number, delta: number): DynamicIndentation { return { getIndentationForComment: (kind, tokenIndentation, container) => { switch (kind) { @@ -607,9 +623,9 @@ function formatSpanWorker( // .. { // // comment // } - case ts.SyntaxKind.CloseBraceToken: - case ts.SyntaxKind.CloseBracketToken: - case ts.SyntaxKind.CloseParenToken: + case SyntaxKind.CloseBraceToken: + case SyntaxKind.CloseBracketToken: + case SyntaxKind.CloseParenToken: return indentation + getDelta(container); } return tokenIndentation !== Constants.Unknown ? tokenIndentation : indentation; @@ -629,35 +645,35 @@ function formatSpanWorker( getIndentation: () => indentation, getDelta, recomputeIndentation: (lineAdded, parent) => { - if (ts.formatting.SmartIndenter.shouldIndentChildNode(options, parent, node, sourceFile)) { + if (SmartIndenter.shouldIndentChildNode(options, parent, node, sourceFile)) { indentation += lineAdded ? options.indentSize! : -options.indentSize!; - delta = ts.formatting.SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; + delta = SmartIndenter.shouldIndentChildNode(options, node) ? options.indentSize! : 0; } } }; - function shouldAddDelta(line: number, kind: ts.SyntaxKind, container: ts.Node): boolean { + function shouldAddDelta(line: number, kind: SyntaxKind, container: Node): boolean { switch (kind) { // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent - case ts.SyntaxKind.OpenBraceToken: - case ts.SyntaxKind.CloseBraceToken: - case ts.SyntaxKind.CloseParenToken: - case ts.SyntaxKind.ElseKeyword: - case ts.SyntaxKind.WhileKeyword: - case ts.SyntaxKind.AtToken: + case SyntaxKind.OpenBraceToken: + case SyntaxKind.CloseBraceToken: + case SyntaxKind.CloseParenToken: + case SyntaxKind.ElseKeyword: + case SyntaxKind.WhileKeyword: + case SyntaxKind.AtToken: return false; - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.GreaterThanToken: + case SyntaxKind.SlashToken: + case SyntaxKind.GreaterThanToken: switch (container.kind) { - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxClosingElement: - case ts.SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxSelfClosingElement: return false; } break; - case ts.SyntaxKind.OpenBracketToken: - case ts.SyntaxKind.CloseBracketToken: - if (container.kind !== ts.SyntaxKind.MappedType) { + case SyntaxKind.OpenBracketToken: + case SyntaxKind.CloseBracketToken: + if (container.kind !== SyntaxKind.MappedType) { return false; } break; @@ -665,17 +681,17 @@ function formatSpanWorker( // if token line equals to the line of containing node (this is a first token in the node) - use node indentation return nodeStartLine !== line // if this token is the first token following the list of decorators, we do not need to indent - && !(ts.hasDecorators(node) && kind === getFirstNonDecoratorTokenOfNode(node)); + && !(hasDecorators(node) && kind === getFirstNonDecoratorTokenOfNode(node)); } function getDelta(child: TextRangeWithKind) { // Delta value should be zero when the node explicitly prevents indentation of the child node - return ts.formatting.SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; + return SmartIndenter.nodeWillIndentChild(options, node, child, sourceFile, /*indentByDefault*/ true) ? delta : 0; } } - function processNode(node: ts.Node, contextNode: ts.Node, nodeStartLine: number, undecoratedNodeStartLine: number, indentation: number, delta: number) { - if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { + function processNode(node: Node, contextNode: Node, nodeStartLine: number, undecoratedNodeStartLine: number, indentation: number, delta: number) { + if (!rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) { return; } @@ -697,7 +713,7 @@ function formatSpanWorker( // if there are any tokens that logically belong to node and interleave child nodes // such tokens will be consumed in processChildNode for the child that follows them - ts.forEachChild( + forEachChild( node, child => { processChildNode(child, /*inheritedIndentation*/ Constants.Unknown, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false); @@ -716,17 +732,17 @@ function formatSpanWorker( } function processChildNode( - child: ts.Node, + child: Node, inheritedIndentation: number, - parent: ts.Node, + parent: Node, parentDynamicIndentation: DynamicIndentation, parentStartLine: number, undecoratedParentStartLine: number, isListItem: boolean, isFirstListItem?: boolean): number { - ts.Debug.assert(!ts.nodeIsSynthesized(child)); + Debug.assert(!nodeIsSynthesized(child)); - if (ts.nodeIsMissing(child)) { + if (nodeIsMissing(child)) { return inheritedIndentation; } @@ -735,14 +751,14 @@ function formatSpanWorker( const childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line; let undecoratedChildStartLine = childStartLine; - if (ts.hasDecorators(child)) { - undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line; + if (hasDecorators(child)) { + undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(getNonDecoratorTokenPosOfNode(child, sourceFile)).line; } // if child is a list item - try to get its indentation, only if parent is within the original range. let childIndentationAmount = Constants.Unknown; - if (isListItem && ts.rangeContainsRange(originalRange, parent)) { + if (isListItem && rangeContainsRange(originalRange, parent)) { childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation); if (childIndentationAmount !== Constants.Unknown) { inheritedIndentation = childIndentationAmount; @@ -750,7 +766,7 @@ function formatSpanWorker( } // child node is outside the target range - do not dive inside - if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { + if (!rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) { if (child.end < originalRange.pos) { formattingScanner.skipToEndOf(child); } @@ -782,51 +798,51 @@ function formatSpanWorker( return inheritedIndentation; } - if (ts.isToken(child)) { + if (isToken(child)) { // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules const tokenInfo = formattingScanner.readTokenInfo(child); // JSX text shouldn't affect indenting - if (child.kind !== ts.SyntaxKind.JsxText) { - ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); + if (child.kind !== SyntaxKind.JsxText) { + Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); return inheritedIndentation; } } - const effectiveParentStartLine = child.kind === ts.SyntaxKind.Decorator ? childStartLine : undecoratedParentStartLine; + const effectiveParentStartLine = child.kind === SyntaxKind.Decorator ? childStartLine : undecoratedParentStartLine; const childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine); processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta); childContextNode = node; - if (isFirstListItem && parent.kind === ts.SyntaxKind.ArrayLiteralExpression && inheritedIndentation === Constants.Unknown) { + if (isFirstListItem && parent.kind === SyntaxKind.ArrayLiteralExpression && inheritedIndentation === Constants.Unknown) { inheritedIndentation = childIndentation.indentation; } return inheritedIndentation; } - function processChildNodes(nodes: ts.NodeArray, - parent: ts.Node, + function processChildNodes(nodes: NodeArray, + parent: Node, parentStartLine: number, parentDynamicIndentation: DynamicIndentation): void { - ts.Debug.assert(ts.isNodeArray(nodes)); - ts.Debug.assert(!ts.nodeIsSynthesized(nodes)); + Debug.assert(isNodeArray(nodes)); + Debug.assert(!nodeIsSynthesized(nodes)); const listStartToken = getOpenTokenForList(parent, nodes); let listDynamicIndentation = parentDynamicIndentation; let startLine = parentStartLine; // node range is outside the target range - do not dive inside - if (!ts.rangeOverlapsWithStartEnd(originalRange, nodes.pos, nodes.end)) { + if (!rangeOverlapsWithStartEnd(originalRange, nodes.pos, nodes.end)) { if (nodes.end < originalRange.pos) { formattingScanner.skipToEndOf(nodes); } return; } - if (listStartToken !== ts.SyntaxKind.Unknown) { + if (listStartToken !== SyntaxKind.Unknown) { // introduce a new indentation scope for lists (including list start and end tokens) while (formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) { const tokenInfo = formattingScanner.readTokenInfo(parent); @@ -849,8 +865,8 @@ function formatSpanWorker( indentationOnListStartToken = indentationOnLastIndentedLine; } else { - const startLinePosition = ts.getLineStartPositionForPosition(tokenInfo.token.pos, sourceFile); - indentationOnListStartToken = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, tokenInfo.token.pos, sourceFile, options); + const startLinePosition = getLineStartPositionForPosition(tokenInfo.token.pos, sourceFile); + indentationOnListStartToken = SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, tokenInfo.token.pos, sourceFile, options); } listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentationOnListStartToken, options.indentSize!); // TODO: GH#18217 @@ -869,9 +885,9 @@ function formatSpanWorker( } const listEndToken = getCloseTokenForOpenToken(listStartToken); - if (listEndToken !== ts.SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) { + if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) { let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent); - if (tokenInfo.token.kind === ts.SyntaxKind.CommaToken) { + if (tokenInfo.token.kind === SyntaxKind.CommaToken) { // consume the comma consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent); tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined; @@ -881,15 +897,15 @@ function formatSpanWorker( // there might be the case when current token matches end token but does not considered as one // function (x: function) <-- // without this check close paren will be interpreted as list end token for function expression which is wrong - if (tokenInfo && tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) { + if (tokenInfo && tokenInfo.token.kind === listEndToken && rangeContainsRange(parent, tokenInfo.token)) { // consume list end token consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent, /*isListEndToken*/ true); } } } - function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: ts.Node, dynamicIndentation: DynamicIndentation, container: ts.Node, isListEndToken?: boolean): void { - ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token)); + function consumeTokenAndAdvanceScanner(currentTokenInfo: TokenInfo, parent: Node, dynamicIndentation: DynamicIndentation, container: Node, isListEndToken?: boolean): void { + Debug.assert(rangeContainsRange(parent, currentTokenInfo.token)); const lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine(); let indentToken = false; @@ -899,7 +915,7 @@ function formatSpanWorker( } let lineAction = LineAction.None; - const isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token); + const isTokenInRange = rangeContainsRange(originalRange, currentTokenInfo.token); const tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos); if (isTokenInRange) { @@ -921,7 +937,7 @@ function formatSpanWorker( } if (currentTokenInfo.trailingTrivia) { - previousRangeTriviaEnd = ts.last(currentTokenInfo.trailingTrivia).end; + previousRangeTriviaEnd = last(currentTokenInfo.trailingTrivia).end; processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation); } @@ -958,21 +974,21 @@ function formatSpanWorker( indentNextTokenOrTrivia: boolean, indentSingleLine: (item: TextRangeWithKind) => void) { for (const triviaItem of trivia) { - const triviaInRange = ts.rangeContainsRange(originalRange, triviaItem); + const triviaInRange = rangeContainsRange(originalRange, triviaItem); switch (triviaItem.kind) { - case ts.SyntaxKind.MultiLineCommentTrivia: + case SyntaxKind.MultiLineCommentTrivia: if (triviaInRange) { indentMultilineComment(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia); } indentNextTokenOrTrivia = false; break; - case ts.SyntaxKind.SingleLineCommentTrivia: + case SyntaxKind.SingleLineCommentTrivia: if (indentNextTokenOrTrivia && triviaInRange) { indentSingleLine(triviaItem); } indentNextTokenOrTrivia = false; break; - case ts.SyntaxKind.NewLineTrivia: + case SyntaxKind.NewLineTrivia: indentNextTokenOrTrivia = true; break; } @@ -980,9 +996,9 @@ function formatSpanWorker( return indentNextTokenOrTrivia; } - function processTrivia(trivia: TextRangeWithKind[], parent: ts.Node, contextNode: ts.Node, dynamicIndentation: DynamicIndentation): void { + function processTrivia(trivia: TextRangeWithKind[], parent: Node, contextNode: Node, dynamicIndentation: DynamicIndentation): void { for (const triviaItem of trivia) { - if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) { + if (isComment(triviaItem.kind) && rangeContainsRange(originalRange, triviaItem)) { const triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos); processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation); } @@ -990,9 +1006,9 @@ function formatSpanWorker( } function processRange(range: TextRangeWithKind, - rangeStart: ts.LineAndCharacter, - parent: ts.Node, - contextNode: ts.Node, + rangeStart: LineAndCharacter, + parent: Node, + contextNode: Node, dynamicIndentation: DynamicIndentation): LineAction { const rangeHasError = rangeContainsError(range); @@ -1019,11 +1035,11 @@ function formatSpanWorker( function processPair(currentItem: TextRangeWithKind, currentStartLine: number, - currentParent: ts.Node, + currentParent: Node, previousItem: TextRangeWithKind, previousStartLine: number, - previousParent: ts.Node, - contextNode: ts.Node, + previousParent: Node, + contextNode: Node, dynamicIndentation: DynamicIndentation | undefined): LineAction { formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode); @@ -1035,7 +1051,7 @@ function formatSpanWorker( if (rules) { // Apply rules in reverse order so that higher priority rules (which are first in the array) // win in a conflict with lower priority rules. - ts.forEachRight(rules, rule => { + forEachRight(rules, rule => { lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine); if (dynamicIndentation) { switch (lineAction) { @@ -1055,16 +1071,16 @@ function formatSpanWorker( } break; default: - ts.Debug.assert(lineAction === LineAction.None); + Debug.assert(lineAction === LineAction.None); } } // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line - trimTrailingWhitespaces = trimTrailingWhitespaces && !(rule.action & ts.formatting.RuleAction.DeleteSpace) && rule.flags !== ts.formatting.RuleFlags.CanDeleteNewLines; + trimTrailingWhitespaces = trimTrailingWhitespaces && !(rule.action & RuleAction.DeleteSpace) && rule.flags !== RuleFlags.CanDeleteNewLines; }); } else { - trimTrailingWhitespaces = trimTrailingWhitespaces && currentItem.kind !== ts.SyntaxKind.EndOfFileToken; + trimTrailingWhitespaces = trimTrailingWhitespaces && currentItem.kind !== SyntaxKind.EndOfFileToken; } if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) { @@ -1084,7 +1100,7 @@ function formatSpanWorker( } else { const tokenStart = sourceFile.getLineAndCharacterOfPosition(pos); - const startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile); + const startLinePosition = getStartPositionOfLine(tokenStart.line, sourceFile); if (indentation !== characterToColumn(startLinePosition, tokenStart.character) || indentationIsDifferent(indentationString, startLinePosition)) { recordReplace(startLinePosition, tokenStart.character, indentationString); } @@ -1094,7 +1110,7 @@ function formatSpanWorker( function characterToColumn(startLinePosition: number, characterInLine: number): number { let column = 0; for (let i = 0; i < characterInLine; i++) { - if (sourceFile.text.charCodeAt(startLinePosition + i) === ts.CharacterCodes.tab) { + if (sourceFile.text.charCodeAt(startLinePosition + i) === CharacterCodes.tab) { column += options.tabSize! - column % options.tabSize!; } else { @@ -1108,7 +1124,7 @@ function formatSpanWorker( return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length); } - function indentMultilineComment(commentRange: ts.TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true) { + function indentMultilineComment(commentRange: TextRange, indentation: number, firstLineIsIndented: boolean, indentFinalLine = true) { // split comment in lines let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line; const endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line; @@ -1120,12 +1136,12 @@ function formatSpanWorker( return; } - const parts: ts.TextRange[] = []; + const parts: TextRange[] = []; let startPos = commentRange.pos; for (let line = startLine; line < endLine; line++) { - const endOfLine = ts.getEndLinePosition(line, sourceFile); + const endOfLine = getEndLinePosition(line, sourceFile); parts.push({ pos: startPos, end: endOfLine }); - startPos = ts.getStartPositionOfLine(line + 1, sourceFile); + startPos = getStartPositionOfLine(line + 1, sourceFile); } if (indentFinalLine) { @@ -1134,10 +1150,10 @@ function formatSpanWorker( if (parts.length === 0) return; - const startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); + const startLinePos = getStartPositionOfLine(startLine, sourceFile); const nonWhitespaceColumnInFirstPart = - ts.formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); + SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options); let startIndex = 0; if (firstLineIsIndented) { @@ -1148,11 +1164,11 @@ function formatSpanWorker( // shift all parts on the delta size const delta = indentation - nonWhitespaceColumnInFirstPart.column; for (let i = startIndex; i < parts.length; i++ , startLine++) { - const startLinePos = ts.getStartPositionOfLine(startLine, sourceFile); + const startLinePos = getStartPositionOfLine(startLine, sourceFile); const nonWhitespaceCharacterAndColumn = i === 0 ? nonWhitespaceColumnInFirstPart - : ts.formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); + : SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options); const newIndentation = nonWhitespaceCharacterAndColumn.column + delta; if (newIndentation > 0) { const indentationString = getIndentationString(newIndentation, options); @@ -1166,17 +1182,17 @@ function formatSpanWorker( function trimTrailingWhitespacesForLines(line1: number, line2: number, range?: TextRangeWithKind) { for (let line = line1; line < line2; line++) { - const lineStartPosition = ts.getStartPositionOfLine(line, sourceFile); - const lineEndPosition = ts.getEndLinePosition(line, sourceFile); + const lineStartPosition = getStartPositionOfLine(line, sourceFile); + const lineEndPosition = getEndLinePosition(line, sourceFile); // do not trim whitespaces in comments or template expression - if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { + if (range && (isComment(range.kind) || isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) { continue; } const whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition); if (whitespaceStart !== -1) { - ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); + Debug.assert(whitespaceStart === lineStartPosition || !isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1))); recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart); } } @@ -1188,7 +1204,7 @@ function formatSpanWorker( */ function getTrailingWhitespaceStartPosition(start: number, end: number) { let pos = end; - while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { + while (pos >= start && isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) { pos--; } if (pos !== end) { @@ -1201,10 +1217,10 @@ function formatSpanWorker( * Trimming will be done for lines after the previous range. * Exclude comments as they had been previously processed. */ - function trimTrailingWhitespacesForRemainingRange(trivias: TextRangeWithKind[]) { + function trimTrailingWhitespacesForRemainingRange(trivias: TextRangeWithKind[]) { let startPos = previousRange ? previousRange.end : originalRange.pos; for (const trivia of trivias) { - if (ts.isComment(trivia.kind)) { + if (isComment(trivia.kind)) { if (startPos < trivia.pos) { trimTrailingWitespacesForPositions(startPos, trivia.pos - 1, previousRange); } @@ -1227,23 +1243,23 @@ function formatSpanWorker( function recordDelete(start: number, len: number) { if (len) { - edits.push(ts.createTextChangeFromStartLength(start, len, "")); + edits.push(createTextChangeFromStartLength(start, len, "")); } } function recordReplace(start: number, len: number, newText: string) { if (len || newText) { - edits.push(ts.createTextChangeFromStartLength(start, len, newText)); + edits.push(createTextChangeFromStartLength(start, len, newText)); } } function recordInsert(start: number, text: string) { if (text) { - edits.push(ts.createTextChangeFromStartLength(start, 0, text)); + edits.push(createTextChangeFromStartLength(start, 0, text)); } } - function applyRuleEdits(rule: ts.formatting.Rule, + function applyRuleEdits(rule: Rule, previousRange: TextRangeWithKind, previousStartLine: number, currentRange: TextRangeWithKind, @@ -1251,47 +1267,47 @@ function formatSpanWorker( ): LineAction { const onLaterLine = currentStartLine !== previousStartLine; switch (rule.action) { - case ts.formatting.RuleAction.StopProcessingSpaceActions: + case RuleAction.StopProcessingSpaceActions: // no action required return LineAction.None; - case ts.formatting.RuleAction.DeleteSpace: + case RuleAction.DeleteSpace: if (previousRange.end !== currentRange.pos) { // delete characters starting from t1.end up to t2.pos exclusive recordDelete(previousRange.end, currentRange.pos - previousRange.end); return onLaterLine ? LineAction.LineRemoved : LineAction.None; } break; - case ts.formatting.RuleAction.DeleteToken: + case RuleAction.DeleteToken: recordDelete(previousRange.pos, previousRange.end - previousRange.pos); break; - case ts.formatting.RuleAction.InsertNewLine: + case RuleAction.InsertNewLine: // exit early if we on different lines and rule cannot change number of newlines // if line1 and line2 are on subsequent lines then no edits are required - ok to exit // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines - if (rule.flags !== ts.formatting.RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { + if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { return LineAction.None; } // edit should not be applied if we have one line feed between elements const lineDelta = currentStartLine - previousStartLine; if (lineDelta !== 1) { - recordReplace(previousRange.end, currentRange.pos - previousRange.end, ts.getNewLineOrDefaultFromHost(host, options)); + recordReplace(previousRange.end, currentRange.pos - previousRange.end, getNewLineOrDefaultFromHost(host, options)); return onLaterLine ? LineAction.None : LineAction.LineAdded; } break; - case ts.formatting.RuleAction.InsertSpace: + case RuleAction.InsertSpace: // exit early if we on different lines and rule cannot change number of newlines - if (rule.flags !== ts.formatting.RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { + if (rule.flags !== RuleFlags.CanDeleteNewLines && previousStartLine !== currentStartLine) { return LineAction.None; } const posDelta = currentRange.pos - previousRange.end; - if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== ts.CharacterCodes.space) { + if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== CharacterCodes.space) { recordReplace(previousRange.end, currentRange.pos - previousRange.end, " "); return onLaterLine ? LineAction.LineRemoved : LineAction.None; } break; - case ts.formatting.RuleAction.InsertTrailingSemicolon: + case RuleAction.InsertTrailingSemicolon: recordInsert(previousRange.end, ";"); } return LineAction.None; @@ -1305,12 +1321,12 @@ const enum LineAction { None, LineAdded, LineRemoved } * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`. */ export function getRangeOfEnclosingComment( - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, - precedingToken?: ts.Node | null, - tokenAtPosition = ts.getTokenAtPosition(sourceFile, position), -): ts.CommentRange | undefined { - const jsdoc = ts.findAncestor(tokenAtPosition, ts.isJSDoc); + precedingToken?: Node | null, + tokenAtPosition = getTokenAtPosition(sourceFile, position), +): CommentRange | undefined { + const jsdoc = findAncestor(tokenAtPosition, isJSDoc); if (jsdoc) tokenAtPosition = jsdoc.parent; const tokenStart = tokenAtPosition.getStart(sourceFile); if (tokenStart <= position && position < tokenAtPosition.getEnd()) { @@ -1318,14 +1334,14 @@ export function getRangeOfEnclosingComment( } // eslint-disable-next-line no-null/no-null - precedingToken = precedingToken === null ? undefined : precedingToken === undefined ? ts.findPrecedingToken(position, sourceFile) : precedingToken; + precedingToken = precedingToken === null ? undefined : precedingToken === undefined ? findPrecedingToken(position, sourceFile) : precedingToken; // Between two consecutive tokens, all comments are either trailing on the former // or leading on the latter (and none are in both lists). - const trailingRangesOfPreviousToken = precedingToken && ts.getTrailingCommentRanges(sourceFile.text, precedingToken.end); - const leadingCommentRangesOfNextToken = ts.getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); - const commentRanges = ts.concatenate(trailingRangesOfPreviousToken, leadingCommentRangesOfNextToken); - return commentRanges && ts.find(commentRanges, range => ts.rangeContainsPositionExclusive(range, position) || + const trailingRangesOfPreviousToken = precedingToken && getTrailingCommentRanges(sourceFile.text, precedingToken.end); + const leadingCommentRangesOfNextToken = getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile); + const commentRanges = concatenate(trailingRangesOfPreviousToken, leadingCommentRangesOfNextToken); + return commentRanges && find(commentRanges, range => rangeContainsPositionExclusive(range, position) || // The end marker of a single-line comment does not include the newline character. // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position): // @@ -1339,74 +1355,74 @@ export function getRangeOfEnclosingComment( // // Internally, we represent the end of the comment at the newline and closing '/', respectively. // - position === range.end && (range.kind === ts.SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth())); + position === range.end && (range.kind === SyntaxKind.SingleLineCommentTrivia || position === sourceFile.getFullWidth())); } -function getOpenTokenForList(node: ts.Node, list: readonly ts.Node[]) { +function getOpenTokenForList(node: Node, list: readonly Node[]) { switch (node.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - if ((node as ts.FunctionDeclaration).typeParameters === list) { - return ts.SyntaxKind.LessThanToken; + case SyntaxKind.Constructor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ArrowFunction: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + if ((node as FunctionDeclaration).typeParameters === list) { + return SyntaxKind.LessThanToken; } - else if ((node as ts.FunctionDeclaration).parameters === list) { - return ts.SyntaxKind.OpenParenToken; + else if ((node as FunctionDeclaration).parameters === list) { + return SyntaxKind.OpenParenToken; } break; - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - if ((node as ts.CallExpression).typeArguments === list) { - return ts.SyntaxKind.LessThanToken; + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + if ((node as CallExpression).typeArguments === list) { + return SyntaxKind.LessThanToken; } - else if ((node as ts.CallExpression).arguments === list) { - return ts.SyntaxKind.OpenParenToken; + else if ((node as CallExpression).arguments === list) { + return SyntaxKind.OpenParenToken; } break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - if ((node as ts.ClassDeclaration).typeParameters === list) { - return ts.SyntaxKind.LessThanToken; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + if ((node as ClassDeclaration).typeParameters === list) { + return SyntaxKind.LessThanToken; } break; - case ts.SyntaxKind.TypeReference: - case ts.SyntaxKind.TaggedTemplateExpression: - case ts.SyntaxKind.TypeQuery: - case ts.SyntaxKind.ExpressionWithTypeArguments: - case ts.SyntaxKind.ImportType: - if ((node as ts.TypeReferenceNode).typeArguments === list) { - return ts.SyntaxKind.LessThanToken; + case SyntaxKind.TypeReference: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.TypeQuery: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.ImportType: + if ((node as TypeReferenceNode).typeArguments === list) { + return SyntaxKind.LessThanToken; } break; - case ts.SyntaxKind.TypeLiteral: - return ts.SyntaxKind.OpenBraceToken; + case SyntaxKind.TypeLiteral: + return SyntaxKind.OpenBraceToken; } - return ts.SyntaxKind.Unknown; + return SyntaxKind.Unknown; } -function getCloseTokenForOpenToken(kind: ts.SyntaxKind) { +function getCloseTokenForOpenToken(kind: SyntaxKind) { switch (kind) { - case ts.SyntaxKind.OpenParenToken: - return ts.SyntaxKind.CloseParenToken; - case ts.SyntaxKind.LessThanToken: - return ts.SyntaxKind.GreaterThanToken; - case ts.SyntaxKind.OpenBraceToken: - return ts.SyntaxKind.CloseBraceToken; + case SyntaxKind.OpenParenToken: + return SyntaxKind.CloseParenToken; + case SyntaxKind.LessThanToken: + return SyntaxKind.GreaterThanToken; + case SyntaxKind.OpenBraceToken: + return SyntaxKind.CloseBraceToken; } - return ts.SyntaxKind.Unknown; + return SyntaxKind.Unknown; } let internedSizes: { tabSize: number; indentSize: number; }; @@ -1414,7 +1430,7 @@ let internedTabsIndentation: string[] | undefined; let internedSpacesIndentation: string[] | undefined; /** @internal */ -export function getIndentationString(indentation: number, options: ts.EditorSettings): string { +export function getIndentationString(indentation: number, options: EditorSettings): string { // reset interned strings if FormatCodeOptions were changed const resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize); @@ -1434,13 +1450,13 @@ export function getIndentationString(indentation: number, options: ts.EditorSett } if (internedTabsIndentation[tabs] === undefined) { - internedTabsIndentation[tabs] = tabString = ts.repeatString("\t", tabs); + internedTabsIndentation[tabs] = tabString = repeatString("\t", tabs); } else { tabString = internedTabsIndentation[tabs]; } - return spaces ? tabString + ts.repeatString(" ", spaces) : tabString; + return spaces ? tabString + repeatString(" ", spaces) : tabString; } else { let spacesString: string; @@ -1451,13 +1467,13 @@ export function getIndentationString(indentation: number, options: ts.EditorSett } if (internedSpacesIndentation[quotient] === undefined) { - spacesString = ts.repeatString(" ", options.indentSize! * quotient); + spacesString = repeatString(" ", options.indentSize! * quotient); internedSpacesIndentation[quotient] = spacesString; } else { spacesString = internedSpacesIndentation[quotient]; } - return remainder ? spacesString + ts.repeatString(" ", remainder) : spacesString; + return remainder ? spacesString + repeatString(" ", remainder) : spacesString; } } diff --git a/src/services/formatting/formattingContext.ts b/src/services/formatting/formattingContext.ts index e8e83bba014e8..c42ff32dedacd 100644 --- a/src/services/formatting/formattingContext.ts +++ b/src/services/formatting/formattingContext.ts @@ -1,4 +1,5 @@ -import * as ts from "../_namespaces/ts"; +import { TextRangeWithKind } from "../_namespaces/ts.formatting"; +import { Debug, findChildOfKind, FormatCodeSettings, Node, SourceFileLike, SyntaxKind } from "../_namespaces/ts"; /** @internal */ export const enum FormattingRequestKind { @@ -12,11 +13,11 @@ export const enum FormattingRequestKind { /** @internal */ export class FormattingContext { - public currentTokenSpan!: ts.formatting.TextRangeWithKind; - public nextTokenSpan!: ts.formatting.TextRangeWithKind; - public contextNode!: ts.Node; - public currentTokenParent!: ts.Node; - public nextTokenParent!: ts.Node; + public currentTokenSpan!: TextRangeWithKind; + public nextTokenSpan!: TextRangeWithKind; + public contextNode!: Node; + public currentTokenParent!: Node; + public nextTokenParent!: Node; private contextNodeAllOnSameLine: boolean | undefined; private nextNodeAllOnSameLine: boolean | undefined; @@ -24,15 +25,15 @@ export class FormattingContext { private contextNodeBlockIsOnOneLine: boolean | undefined; private nextNodeBlockIsOnOneLine: boolean | undefined; - constructor(public readonly sourceFile: ts.SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: ts.FormatCodeSettings) { + constructor(public readonly sourceFile: SourceFileLike, public formattingRequestKind: FormattingRequestKind, public options: FormatCodeSettings) { } - public updateContext(currentRange: ts.formatting.TextRangeWithKind, currentTokenParent: ts.Node, nextRange: ts.formatting.TextRangeWithKind, nextTokenParent: ts.Node, commonParent: ts.Node) { - this.currentTokenSpan = ts.Debug.checkDefined(currentRange); - this.currentTokenParent = ts.Debug.checkDefined(currentTokenParent); - this.nextTokenSpan = ts.Debug.checkDefined(nextRange); - this.nextTokenParent = ts.Debug.checkDefined(nextTokenParent); - this.contextNode = ts.Debug.checkDefined(commonParent); + public updateContext(currentRange: TextRangeWithKind, currentTokenParent: Node, nextRange: TextRangeWithKind, nextTokenParent: Node, commonParent: Node) { + this.currentTokenSpan = Debug.checkDefined(currentRange); + this.currentTokenParent = Debug.checkDefined(currentTokenParent); + this.nextTokenSpan = Debug.checkDefined(nextRange); + this.nextTokenParent = Debug.checkDefined(nextTokenParent); + this.contextNode = Debug.checkDefined(commonParent); // drop cached results this.contextNodeAllOnSameLine = undefined; @@ -84,15 +85,15 @@ export class FormattingContext { return this.nextNodeBlockIsOnOneLine; } - private NodeIsOnOneLine(node: ts.Node): boolean { + private NodeIsOnOneLine(node: Node): boolean { const startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line; const endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line; return startLine === endLine; } - private BlockIsOnOneLine(node: ts.Node): boolean { - const openBrace = ts.findChildOfKind(node, ts.SyntaxKind.OpenBraceToken, this.sourceFile); - const closeBrace = ts.findChildOfKind(node, ts.SyntaxKind.CloseBraceToken, this.sourceFile); + private BlockIsOnOneLine(node: Node): boolean { + const openBrace = findChildOfKind(node, SyntaxKind.OpenBraceToken, this.sourceFile); + const closeBrace = findChildOfKind(node, SyntaxKind.CloseBraceToken, this.sourceFile); if (openBrace && closeBrace) { const startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line; const endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line; diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index cd2f83b8c9d74..0941d277d2ac3 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -1,7 +1,13 @@ -import * as ts from "../_namespaces/ts"; +import { + append, createScanner, Debug, isJsxAttribute, isJsxElement, isJsxText, isKeyword, isToken, isTrivia, + LanguageVariant, last, Node, NodeArray, ScriptTarget, SyntaxKind, +} from "../_namespaces/ts"; +import { + createTextRangeWithKind, TextRangeWithKind, TextRangeWithTriviaKind, TokenInfo, +} from "../_namespaces/ts.formatting"; -const standardScanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ false, ts.LanguageVariant.Standard); -const jsxScanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ false, ts.LanguageVariant.JSX); +const standardScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard); +const jsxScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.JSX); /** @internal */ export interface FormattingScanner { @@ -9,12 +15,12 @@ export interface FormattingScanner { getStartPos(): number; isOnToken(): boolean; isOnEOF(): boolean; - readTokenInfo(n: ts.Node): ts.formatting.TokenInfo; - readEOFTokenRange(): ts.formatting.TextRangeWithKind; - getCurrentLeadingTrivia(): ts.formatting.TextRangeWithKind[] | undefined; + readTokenInfo(n: Node): TokenInfo; + readEOFTokenRange(): TextRangeWithKind; + getCurrentLeadingTrivia(): TextRangeWithKind[] | undefined; lastTrailingTriviaWasNewLine(): boolean; - skipToEndOf(node: ts.Node | ts.NodeArray): void; - skipToStartOf(node: ts.Node): void; + skipToEndOf(node: Node | NodeArray): void; + skipToStartOf(node: Node): void; } const enum ScanAction { @@ -28,19 +34,19 @@ const enum ScanAction { } /** @internal */ -export function getFormattingScanner(text: string, languageVariant: ts.LanguageVariant, startPos: number, endPos: number, cb: (scanner: FormattingScanner) => T): T { - const scanner = languageVariant === ts.LanguageVariant.JSX ? jsxScanner : standardScanner; +export function getFormattingScanner(text: string, languageVariant: LanguageVariant, startPos: number, endPos: number, cb: (scanner: FormattingScanner) => T): T { + const scanner = languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner; scanner.setText(text); scanner.setTextPos(startPos); let wasNewLine = true; - let leadingTrivia: ts.formatting.TextRangeWithTriviaKind[] | undefined; - let trailingTrivia: ts.formatting.TextRangeWithTriviaKind[] | undefined; + let leadingTrivia: TextRangeWithTriviaKind[] | undefined; + let trailingTrivia: TextRangeWithTriviaKind[] | undefined; let savedPos: number; let lastScanAction: ScanAction | undefined; - let lastTokenInfo: ts.formatting.TokenInfo | undefined; + let lastTokenInfo: TokenInfo | undefined; const res = cb({ advance, @@ -65,7 +71,7 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua const isStarted = scanner.getStartPos() !== startPos; if (isStarted) { - wasNewLine = !!trailingTrivia && ts.last(trailingTrivia).kind === ts.SyntaxKind.NewLineTrivia; + wasNewLine = !!trailingTrivia && last(trailingTrivia).kind === SyntaxKind.NewLineTrivia; } else { scanner.scan(); @@ -79,13 +85,13 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua // Read leading trivia and token while (pos < endPos) { const t = scanner.getToken(); - if (!ts.isTrivia(t)) { + if (!isTrivia(t)) { break; } // consume leading trivia scanner.scan(); - const item: ts.formatting.TextRangeWithTriviaKind = { + const item: TextRangeWithTriviaKind = { pos, end: scanner.getStartPos(), kind: t @@ -93,63 +99,63 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua pos = scanner.getStartPos(); - leadingTrivia = ts.append(leadingTrivia, item); + leadingTrivia = append(leadingTrivia, item); } savedPos = scanner.getStartPos(); } - function shouldRescanGreaterThanToken(node: ts.Node): boolean { + function shouldRescanGreaterThanToken(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.GreaterThanEqualsToken: - case ts.SyntaxKind.GreaterThanGreaterThanEqualsToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: - case ts.SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: return true; } return false; } - function shouldRescanJsxIdentifier(node: ts.Node): boolean { + function shouldRescanJsxIdentifier(node: Node): boolean { if (node.parent) { switch (node.parent.kind) { - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxClosingElement: - case ts.SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxClosingElement: + case SyntaxKind.JsxSelfClosingElement: // May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier. - return ts.isKeyword(node.kind) || node.kind === ts.SyntaxKind.Identifier; + return isKeyword(node.kind) || node.kind === SyntaxKind.Identifier; } } return false; } - function shouldRescanJsxText(node: ts.Node): boolean { - return ts.isJsxText(node) || ts.isJsxElement(node) && lastTokenInfo?.token.kind === ts.SyntaxKind.JsxText; + function shouldRescanJsxText(node: Node): boolean { + return isJsxText(node) || isJsxElement(node) && lastTokenInfo?.token.kind === SyntaxKind.JsxText; } - function shouldRescanSlashToken(container: ts.Node): boolean { - return container.kind === ts.SyntaxKind.RegularExpressionLiteral; + function shouldRescanSlashToken(container: Node): boolean { + return container.kind === SyntaxKind.RegularExpressionLiteral; } - function shouldRescanTemplateToken(container: ts.Node): boolean { - return container.kind === ts.SyntaxKind.TemplateMiddle || - container.kind === ts.SyntaxKind.TemplateTail; + function shouldRescanTemplateToken(container: Node): boolean { + return container.kind === SyntaxKind.TemplateMiddle || + container.kind === SyntaxKind.TemplateTail; } - function shouldRescanJsxAttributeValue(node: ts.Node): boolean { - return node.parent && ts.isJsxAttribute(node.parent) && node.parent.initializer === node; + function shouldRescanJsxAttributeValue(node: Node): boolean { + return node.parent && isJsxAttribute(node.parent) && node.parent.initializer === node; } - function startsWithSlashToken(t: ts.SyntaxKind): boolean { - return t === ts.SyntaxKind.SlashToken || t === ts.SyntaxKind.SlashEqualsToken; + function startsWithSlashToken(t: SyntaxKind): boolean { + return t === SyntaxKind.SlashToken || t === SyntaxKind.SlashEqualsToken; } - function readTokenInfo(n: ts.Node): ts.formatting.TokenInfo { - ts.Debug.assert(isOnToken()); + function readTokenInfo(n: Node): TokenInfo { + Debug.assert(isOnToken()); // normally scanner returns the smallest available token // check the kind of context node to determine if scanner should have more greedy behavior and consume more text. @@ -172,7 +178,7 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua } if (scanner.getStartPos() !== savedPos) { - ts.Debug.assert(lastTokenInfo !== undefined); + Debug.assert(lastTokenInfo !== undefined); // readTokenInfo was called before but scan action differs - rescan text scanner.setTextPos(savedPos); scanner.scan(); @@ -180,7 +186,7 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua let currentToken = getNextToken(n, expectedScanAction); - const token = ts.formatting.createTextRangeWithKind( + const token = createTextRangeWithKind( scanner.getStartPos(), scanner.getTextPos(), currentToken, @@ -192,10 +198,10 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua } while (scanner.getStartPos() < endPos) { currentToken = scanner.scan(); - if (!ts.isTrivia(currentToken)) { + if (!isTrivia(currentToken)) { break; } - const trivia = ts.formatting.createTextRangeWithKind( + const trivia = createTextRangeWithKind( scanner.getStartPos(), scanner.getTextPos(), currentToken, @@ -207,7 +213,7 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua trailingTrivia.push(trivia); - if (currentToken === ts.SyntaxKind.NewLineTrivia) { + if (currentToken === SyntaxKind.NewLineTrivia) { // move past new line scanner.scan(); break; @@ -219,15 +225,15 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua return fixTokenKind(lastTokenInfo, n); } - function getNextToken(n: ts.Node, expectedScanAction: ScanAction): ts.SyntaxKind { + function getNextToken(n: Node, expectedScanAction: ScanAction): SyntaxKind { const token = scanner.getToken(); lastScanAction = ScanAction.Scan; switch (expectedScanAction) { case ScanAction.RescanGreaterThanToken: - if (token === ts.SyntaxKind.GreaterThanToken) { + if (token === SyntaxKind.GreaterThanToken) { lastScanAction = ScanAction.RescanGreaterThanToken; const newToken = scanner.reScanGreaterToken(); - ts.Debug.assert(n.kind === newToken); + Debug.assert(n.kind === newToken); return newToken; } break; @@ -235,12 +241,12 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua if (startsWithSlashToken(token)) { lastScanAction = ScanAction.RescanSlashToken; const newToken = scanner.reScanSlashToken(); - ts.Debug.assert(n.kind === newToken); + Debug.assert(n.kind === newToken); return newToken; } break; case ScanAction.RescanTemplateToken: - if (token === ts.SyntaxKind.CloseBraceToken) { + if (token === SyntaxKind.CloseBraceToken) { lastScanAction = ScanAction.RescanTemplateToken; return scanner.reScanTemplateToken(/* isTaggedTemplate */ false); } @@ -257,38 +263,38 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua case ScanAction.Scan: break; default: - ts.Debug.assertNever(expectedScanAction); + Debug.assertNever(expectedScanAction); } return token; } - function readEOFTokenRange(): ts.formatting.TextRangeWithKind { - ts.Debug.assert(isOnEOF()); - return ts.formatting.createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), ts.SyntaxKind.EndOfFileToken); + function readEOFTokenRange(): TextRangeWithKind { + Debug.assert(isOnEOF()); + return createTextRangeWithKind(scanner.getStartPos(), scanner.getTextPos(), SyntaxKind.EndOfFileToken); } function isOnToken(): boolean { const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); - return current !== ts.SyntaxKind.EndOfFileToken && !ts.isTrivia(current); + return current !== SyntaxKind.EndOfFileToken && !isTrivia(current); } function isOnEOF(): boolean { const current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken(); - return current === ts.SyntaxKind.EndOfFileToken; + return current === SyntaxKind.EndOfFileToken; } // when containing node in the tree is token // but its kind differs from the kind that was returned by the scanner, // then kind needs to be fixed. This might happen in cases // when parser interprets token differently, i.e keyword treated as identifier - function fixTokenKind(tokenInfo: ts.formatting.TokenInfo, container: ts.Node): ts.formatting.TokenInfo { - if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) { + function fixTokenKind(tokenInfo: TokenInfo, container: Node): TokenInfo { + if (isToken(container) && tokenInfo.token.kind !== container.kind) { tokenInfo.token.kind = container.kind; } return tokenInfo; } - function skipToEndOf(node: ts.Node | ts.NodeArray): void { + function skipToEndOf(node: Node | NodeArray): void { scanner.setTextPos(node.end); savedPos = scanner.getStartPos(); lastScanAction = undefined; @@ -298,7 +304,7 @@ export function getFormattingScanner(text: string, languageVariant: ts.Langua trailingTrivia = undefined; } - function skipToStartOf(node: ts.Node): void { + function skipToStartOf(node: Node): void { scanner.setTextPos(node.pos); savedPos = scanner.getStartPos(); lastScanAction = undefined; diff --git a/src/services/formatting/rule.ts b/src/services/formatting/rule.ts index 4802a6f815560..ed4e96232d5d1 100644 --- a/src/services/formatting/rule.ts +++ b/src/services/formatting/rule.ts @@ -1,4 +1,5 @@ -import * as ts from "../_namespaces/ts"; +import { FormattingContext } from "../_namespaces/ts.formatting"; +import { emptyArray, SyntaxKind } from "../_namespaces/ts"; /** @internal */ export interface Rule { @@ -10,9 +11,9 @@ export interface Rule { } /** @internal */ -export type ContextPredicate = (context: ts.formatting.FormattingContext) => boolean; +export type ContextPredicate = (context: FormattingContext) => boolean; /** @internal */ -export const anyContext: readonly ContextPredicate[] = ts.emptyArray; +export const anyContext: readonly ContextPredicate[] = emptyArray; /** @internal */ export const enum RuleAction { @@ -37,6 +38,6 @@ export const enum RuleFlags { /** @internal */ export interface TokenRange { - readonly tokens: readonly ts.SyntaxKind[]; + readonly tokens: readonly SyntaxKind[]; readonly isSpecific: boolean; } diff --git a/src/services/formatting/rules.ts b/src/services/formatting/rules.ts index 972147ef1b948..df1cfeb76a992 100644 --- a/src/services/formatting/rules.ts +++ b/src/services/formatting/rules.ts @@ -1,359 +1,368 @@ -import * as ts from "../_namespaces/ts"; +import { + anyContext, ContextPredicate, FormattingContext, FormattingRequestKind, Rule, RuleAction, RuleFlags, + TextRangeWithKind, TokenRange, +} from "../_namespaces/ts.formatting"; +import { + BinaryExpression, contains, findAncestor, findNextToken, FormatCodeSettings, hasDecorators, hasProperty, isArray, + isExpression, isFunctionLikeKind, isNumericLiteral, isPropertyAccessExpression, isPropertyDeclaration, + isPropertySignature, isTrivia, Node, positionIsASICandidate, SemicolonPreference, SyntaxKind, typeKeywords, + YieldExpression, +} from "../_namespaces/ts"; /** @internal */ export interface RuleSpec { - readonly leftTokenRange: ts.formatting.TokenRange; - readonly rightTokenRange: ts.formatting.TokenRange; - readonly rule: ts.formatting.Rule; + readonly leftTokenRange: TokenRange; + readonly rightTokenRange: TokenRange; + readonly rule: Rule; } /** @internal */ export function getAllRules(): RuleSpec[] { - const allTokens: ts.SyntaxKind[] = []; - for (let token = ts.SyntaxKind.FirstToken; token <= ts.SyntaxKind.LastToken; token++) { - if (token !== ts.SyntaxKind.EndOfFileToken) { + const allTokens: SyntaxKind[] = []; + for (let token = SyntaxKind.FirstToken; token <= SyntaxKind.LastToken; token++) { + if (token !== SyntaxKind.EndOfFileToken) { allTokens.push(token); } } - function anyTokenExcept(...tokens: ts.SyntaxKind[]): ts.formatting.TokenRange { + function anyTokenExcept(...tokens: SyntaxKind[]): TokenRange { return { tokens: allTokens.filter(t => !tokens.some(t2 => t2 === t)), isSpecific: false }; } - const anyToken: ts.formatting.TokenRange = { tokens: allTokens, isSpecific: false }; - const anyTokenIncludingMultilineComments = tokenRangeFrom([...allTokens, ts.SyntaxKind.MultiLineCommentTrivia]); - const anyTokenIncludingEOF = tokenRangeFrom([...allTokens, ts.SyntaxKind.EndOfFileToken]); - const keywords = tokenRangeFromRange(ts.SyntaxKind.FirstKeyword, ts.SyntaxKind.LastKeyword); - const binaryOperators = tokenRangeFromRange(ts.SyntaxKind.FirstBinaryOperator, ts.SyntaxKind.LastBinaryOperator); - const binaryKeywordOperators = [ts.SyntaxKind.InKeyword, ts.SyntaxKind.InstanceOfKeyword, ts.SyntaxKind.OfKeyword, ts.SyntaxKind.AsKeyword, ts.SyntaxKind.IsKeyword]; - const unaryPrefixOperators = [ts.SyntaxKind.PlusPlusToken, ts.SyntaxKind.MinusMinusToken, ts.SyntaxKind.TildeToken, ts.SyntaxKind.ExclamationToken]; + const anyToken: TokenRange = { tokens: allTokens, isSpecific: false }; + const anyTokenIncludingMultilineComments = tokenRangeFrom([...allTokens, SyntaxKind.MultiLineCommentTrivia]); + const anyTokenIncludingEOF = tokenRangeFrom([...allTokens, SyntaxKind.EndOfFileToken]); + const keywords = tokenRangeFromRange(SyntaxKind.FirstKeyword, SyntaxKind.LastKeyword); + const binaryOperators = tokenRangeFromRange(SyntaxKind.FirstBinaryOperator, SyntaxKind.LastBinaryOperator); + const binaryKeywordOperators = [SyntaxKind.InKeyword, SyntaxKind.InstanceOfKeyword, SyntaxKind.OfKeyword, SyntaxKind.AsKeyword, SyntaxKind.IsKeyword]; + const unaryPrefixOperators = [SyntaxKind.PlusPlusToken, SyntaxKind.MinusMinusToken, SyntaxKind.TildeToken, SyntaxKind.ExclamationToken]; const unaryPrefixExpressions = [ - ts.SyntaxKind.NumericLiteral, ts.SyntaxKind.BigIntLiteral, ts.SyntaxKind.Identifier, ts.SyntaxKind.OpenParenToken, - ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.ThisKeyword, ts.SyntaxKind.NewKeyword]; - const unaryPreincrementExpressions = [ts.SyntaxKind.Identifier, ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.ThisKeyword, ts.SyntaxKind.NewKeyword]; - const unaryPostincrementExpressions = [ts.SyntaxKind.Identifier, ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.CloseBracketToken, ts.SyntaxKind.NewKeyword]; - const unaryPredecrementExpressions = [ts.SyntaxKind.Identifier, ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.ThisKeyword, ts.SyntaxKind.NewKeyword]; - const unaryPostdecrementExpressions = [ts.SyntaxKind.Identifier, ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.CloseBracketToken, ts.SyntaxKind.NewKeyword]; - const comments = [ts.SyntaxKind.SingleLineCommentTrivia, ts.SyntaxKind.MultiLineCommentTrivia]; - const typeNames = [ts.SyntaxKind.Identifier, ...ts.typeKeywords]; + SyntaxKind.NumericLiteral, SyntaxKind.BigIntLiteral, SyntaxKind.Identifier, SyntaxKind.OpenParenToken, + SyntaxKind.OpenBracketToken, SyntaxKind.OpenBraceToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPreincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPostincrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; + const unaryPredecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.OpenParenToken, SyntaxKind.ThisKeyword, SyntaxKind.NewKeyword]; + const unaryPostdecrementExpressions = [SyntaxKind.Identifier, SyntaxKind.CloseParenToken, SyntaxKind.CloseBracketToken, SyntaxKind.NewKeyword]; + const comments = [SyntaxKind.SingleLineCommentTrivia, SyntaxKind.MultiLineCommentTrivia]; + const typeNames = [SyntaxKind.Identifier, ...typeKeywords]; // Place a space before open brace in a function declaration // TypeScript: Function can have return types, which can be made of tons of different token kinds const functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments; // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc) - const typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([ts.SyntaxKind.Identifier, ts.SyntaxKind.MultiLineCommentTrivia, ts.SyntaxKind.ClassKeyword, ts.SyntaxKind.ExportKeyword, ts.SyntaxKind.ImportKeyword]); + const typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.Identifier, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.ClassKeyword, SyntaxKind.ExportKeyword, SyntaxKind.ImportKeyword]); // Place a space before open brace in a control flow construct - const controlOpenBraceLeftTokenRange = tokenRangeFrom([ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.MultiLineCommentTrivia, ts.SyntaxKind.DoKeyword, ts.SyntaxKind.TryKeyword, ts.SyntaxKind.FinallyKeyword, ts.SyntaxKind.ElseKeyword]); + const controlOpenBraceLeftTokenRange = tokenRangeFrom([SyntaxKind.CloseParenToken, SyntaxKind.MultiLineCommentTrivia, SyntaxKind.DoKeyword, SyntaxKind.TryKeyword, SyntaxKind.FinallyKeyword, SyntaxKind.ElseKeyword]); // These rules are higher in priority than user-configurable const highPriorityCommonRules = [ // Leave comments alone - rule("IgnoreBeforeComment", anyToken, comments, ts.formatting.anyContext, ts.formatting.RuleAction.StopProcessingSpaceActions), - rule("IgnoreAfterLineComment", ts.SyntaxKind.SingleLineCommentTrivia, anyToken, ts.formatting.anyContext, ts.formatting.RuleAction.StopProcessingSpaceActions), + rule("IgnoreBeforeComment", anyToken, comments, anyContext, RuleAction.StopProcessingSpaceActions), + rule("IgnoreAfterLineComment", SyntaxKind.SingleLineCommentTrivia, anyToken, anyContext, RuleAction.StopProcessingSpaceActions), - rule("NotSpaceBeforeColon", anyToken, ts.SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceAfterColon", ts.SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeQuestionMark", anyToken, ts.SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], ts.formatting.RuleAction.DeleteSpace), + rule("NotSpaceBeforeColon", anyToken, SyntaxKind.ColonToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.DeleteSpace), + rule("SpaceAfterColon", SyntaxKind.ColonToken, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeQuestionMark", anyToken, SyntaxKind.QuestionToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], RuleAction.DeleteSpace), // insert space after '?' only when it is used in conditional operator - rule("SpaceAfterQuestionMarkInConditionalOperator", ts.SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterQuestionMarkInConditionalOperator", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], RuleAction.InsertSpace), // in other cases there should be no space between '?' and next token - rule("NoSpaceAfterQuestionMark", ts.SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceAfterQuestionMark", SyntaxKind.QuestionToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBeforeDot", anyToken, [ts.SyntaxKind.DotToken, ts.SyntaxKind.QuestionDotToken], [isNonJsxSameLineTokenContext, isNotPropertyAccessOnIntegerLiteral], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterDot", [ts.SyntaxKind.DotToken, ts.SyntaxKind.QuestionDotToken], anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBeforeDot", anyToken, [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], [isNonJsxSameLineTokenContext, isNotPropertyAccessOnIntegerLiteral], RuleAction.DeleteSpace), + rule("NoSpaceAfterDot", [SyntaxKind.DotToken, SyntaxKind.QuestionDotToken], anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("NoSpaceBetweenImportParenInImportType", ts.SyntaxKind.ImportKeyword, ts.SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isImportTypeContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBetweenImportParenInImportType", SyntaxKind.ImportKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isImportTypeContext], RuleAction.DeleteSpace), // Special handling of unary operators. // Prefix operators generally shouldn't have a space between // them and their target unary expression. - rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterUnaryPreincrementOperator", ts.SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterUnaryPredecrementOperator", ts.SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, ts.SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, ts.SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPreincrementOperator", SyntaxKind.PlusPlusToken, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterUnaryPredecrementOperator", SyntaxKind.MinusMinusToken, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isNotStatementConditionContext], RuleAction.DeleteSpace), // More unary operator special-casing. // DevDiv 181814: Be careful when removing leading whitespace // around unary operators. Examples: // 1 - -2 --X--> 1--2 // a + ++b --X--> a+++b - rule("SpaceAfterPostincrementWhenFollowedByAdd", ts.SyntaxKind.PlusPlusToken, ts.SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterAddWhenFollowedByUnaryPlus", ts.SyntaxKind.PlusToken, ts.SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterAddWhenFollowedByPreincrement", ts.SyntaxKind.PlusToken, ts.SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterPostdecrementWhenFollowedBySubtract", ts.SyntaxKind.MinusMinusToken, ts.SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", ts.SyntaxKind.MinusToken, ts.SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterSubtractWhenFollowedByPredecrement", ts.SyntaxKind.MinusToken, ts.SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - - rule("NoSpaceAfterCloseBrace", ts.SyntaxKind.CloseBraceToken, [ts.SyntaxKind.CommaToken, ts.SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterPostincrementWhenFollowedByAdd", SyntaxKind.PlusPlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterAddWhenFollowedByUnaryPlus", SyntaxKind.PlusToken, SyntaxKind.PlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterAddWhenFollowedByPreincrement", SyntaxKind.PlusToken, SyntaxKind.PlusPlusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterPostdecrementWhenFollowedBySubtract", SyntaxKind.MinusMinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", SyntaxKind.MinusToken, SyntaxKind.MinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterSubtractWhenFollowedByPredecrement", SyntaxKind.MinusToken, SyntaxKind.MinusMinusToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + + rule("NoSpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, [SyntaxKind.CommaToken, SyntaxKind.SemicolonToken], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // For functions and control block place } on a new line [multi-line rule] - rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, ts.SyntaxKind.CloseBraceToken, [isMultilineBlockContext], ts.formatting.RuleAction.InsertNewLine), + rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, SyntaxKind.CloseBraceToken, [isMultilineBlockContext], RuleAction.InsertNewLine), // Space/new line after }. - rule("SpaceAfterCloseBrace", ts.SyntaxKind.CloseBraceToken, anyTokenExcept(ts.SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterCloseBrace", SyntaxKind.CloseBraceToken, anyTokenExcept(SyntaxKind.CloseParenToken), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], RuleAction.InsertSpace), // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied // Also should not apply to }) - rule("SpaceBetweenCloseBraceAndElse", ts.SyntaxKind.CloseBraceToken, ts.SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBetweenCloseBraceAndWhile", ts.SyntaxKind.CloseBraceToken, ts.SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBetweenCloseBraceAndElse", SyntaxKind.CloseBraceToken, SyntaxKind.ElseKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBetweenCloseBraceAndWhile", SyntaxKind.CloseBraceToken, SyntaxKind.WhileKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace), // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];' - rule("SpaceAfterConditionalClosingParen", ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.OpenBracketToken, [isControlDeclContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterConditionalClosingParen", SyntaxKind.CloseParenToken, SyntaxKind.OpenBracketToken, [isControlDeclContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenFunctionKeywordAndStar", ts.SyntaxKind.FunctionKeyword, ts.SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceAfterStarInGeneratorDeclaration", ts.SyntaxKind.AsteriskToken, ts.SyntaxKind.Identifier, [isFunctionDeclarationOrFunctionExpressionContext], ts.formatting.RuleAction.InsertSpace), + rule("NoSpaceBetweenFunctionKeywordAndStar", SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.DeleteSpace), + rule("SpaceAfterStarInGeneratorDeclaration", SyntaxKind.AsteriskToken, SyntaxKind.Identifier, [isFunctionDeclarationOrFunctionExpressionContext], RuleAction.InsertSpace), - rule("SpaceAfterFunctionInFuncDecl", ts.SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterFunctionInFuncDecl", SyntaxKind.FunctionKeyword, anyToken, [isFunctionDeclContext], RuleAction.InsertSpace), // Insert new line after { and before } in multi-line contexts. - rule("NewLineAfterOpenBraceInBlockContext", ts.SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], ts.formatting.RuleAction.InsertNewLine), + rule("NewLineAfterOpenBraceInBlockContext", SyntaxKind.OpenBraceToken, anyToken, [isMultilineBlockContext], RuleAction.InsertNewLine), // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token. // Though, we do extra check on the context to make sure we are dealing with get/set node. Example: // get x() {} // set x(val) {} - rule("SpaceAfterGetSetInMember", [ts.SyntaxKind.GetKeyword, ts.SyntaxKind.SetKeyword], ts.SyntaxKind.Identifier, [isFunctionDeclContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterGetSetInMember", [SyntaxKind.GetKeyword, SyntaxKind.SetKeyword], SyntaxKind.Identifier, [isFunctionDeclContext], RuleAction.InsertSpace), - rule("NoSpaceBetweenYieldKeywordAndStar", ts.SyntaxKind.YieldKeyword, ts.SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceBetweenYieldOrYieldStarAndOperand", [ts.SyntaxKind.YieldKeyword, ts.SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], ts.formatting.RuleAction.InsertSpace), + rule("NoSpaceBetweenYieldKeywordAndStar", SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.DeleteSpace), + rule("SpaceBetweenYieldOrYieldStarAndOperand", [SyntaxKind.YieldKeyword, SyntaxKind.AsteriskToken], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], RuleAction.InsertSpace), - rule("NoSpaceBetweenReturnAndSemicolon", ts.SyntaxKind.ReturnKeyword, ts.SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceAfterCertainKeywords", [ts.SyntaxKind.VarKeyword, ts.SyntaxKind.ThrowKeyword, ts.SyntaxKind.NewKeyword, ts.SyntaxKind.DeleteKeyword, ts.SyntaxKind.ReturnKeyword, ts.SyntaxKind.TypeOfKeyword, ts.SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterLetConstInVariableDeclaration", [ts.SyntaxKind.LetKeyword, ts.SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, ts.SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBetweenReturnAndSemicolon", SyntaxKind.ReturnKeyword, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("SpaceAfterCertainKeywords", [SyntaxKind.VarKeyword, SyntaxKind.ThrowKeyword, SyntaxKind.NewKeyword, SyntaxKind.DeleteKeyword, SyntaxKind.ReturnKeyword, SyntaxKind.TypeOfKeyword, SyntaxKind.AwaitKeyword], anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceAfterLetConstInVariableDeclaration", [SyntaxKind.LetKeyword, SyntaxKind.ConstKeyword], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], RuleAction.InsertSpace), + rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], RuleAction.DeleteSpace), // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options. - rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), - rule("SpaceAfterVoidOperator", ts.SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterVoidOperator", SyntaxKind.VoidKeyword, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], RuleAction.InsertSpace), // Async-await - rule("SpaceBetweenAsyncAndOpenParen", ts.SyntaxKind.AsyncKeyword, ts.SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBetweenAsyncAndFunctionKeyword", ts.SyntaxKind.AsyncKeyword, [ts.SyntaxKind.FunctionKeyword, ts.SyntaxKind.Identifier], [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceBetweenAsyncAndOpenParen", SyntaxKind.AsyncKeyword, SyntaxKind.OpenParenToken, [isArrowFunctionContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBetweenAsyncAndFunctionKeyword", SyntaxKind.AsyncKeyword, [SyntaxKind.FunctionKeyword, SyntaxKind.Identifier], [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), // Template string - rule("NoSpaceBetweenTagAndTemplateString", [ts.SyntaxKind.Identifier, ts.SyntaxKind.CloseParenToken], [ts.SyntaxKind.NoSubstitutionTemplateLiteral, ts.SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBetweenTagAndTemplateString", [SyntaxKind.Identifier, SyntaxKind.CloseParenToken], [SyntaxKind.NoSubstitutionTemplateLiteral, SyntaxKind.TemplateHead], [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // JSX opening elements - rule("SpaceBeforeJsxAttribute", anyToken, ts.SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, ts.SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", ts.SyntaxKind.SlashToken, ts.SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, ts.SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterEqualInJsxAttribute", ts.SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBeforeJsxAttribute", anyToken, SyntaxKind.Identifier, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, SyntaxKind.SlashToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", SyntaxKind.SlashToken, SyntaxKind.GreaterThanToken, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, SyntaxKind.EqualsToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterEqualInJsxAttribute", SyntaxKind.EqualsToken, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // TypeScript-specific rules // Use of module as a function call. e.g.: import m2 = module("m2"); - rule("NoSpaceAfterModuleImport", [ts.SyntaxKind.ModuleKeyword, ts.SyntaxKind.RequireKeyword], ts.SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceAfterModuleImport", [SyntaxKind.ModuleKeyword, SyntaxKind.RequireKeyword], SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Add a space around certain TypeScript keywords rule( "SpaceAfterCertainTypeScriptKeywords", [ - ts.SyntaxKind.AbstractKeyword, - ts.SyntaxKind.AccessorKeyword, - ts.SyntaxKind.ClassKeyword, - ts.SyntaxKind.DeclareKeyword, - ts.SyntaxKind.DefaultKeyword, - ts.SyntaxKind.EnumKeyword, - ts.SyntaxKind.ExportKeyword, - ts.SyntaxKind.ExtendsKeyword, - ts.SyntaxKind.GetKeyword, - ts.SyntaxKind.ImplementsKeyword, - ts.SyntaxKind.ImportKeyword, - ts.SyntaxKind.InterfaceKeyword, - ts.SyntaxKind.ModuleKeyword, - ts.SyntaxKind.NamespaceKeyword, - ts.SyntaxKind.PrivateKeyword, - ts.SyntaxKind.PublicKeyword, - ts.SyntaxKind.ProtectedKeyword, - ts.SyntaxKind.ReadonlyKeyword, - ts.SyntaxKind.SetKeyword, - ts.SyntaxKind.StaticKeyword, - ts.SyntaxKind.TypeKeyword, - ts.SyntaxKind.FromKeyword, - ts.SyntaxKind.KeyOfKeyword, - ts.SyntaxKind.InferKeyword, + SyntaxKind.AbstractKeyword, + SyntaxKind.AccessorKeyword, + SyntaxKind.ClassKeyword, + SyntaxKind.DeclareKeyword, + SyntaxKind.DefaultKeyword, + SyntaxKind.EnumKeyword, + SyntaxKind.ExportKeyword, + SyntaxKind.ExtendsKeyword, + SyntaxKind.GetKeyword, + SyntaxKind.ImplementsKeyword, + SyntaxKind.ImportKeyword, + SyntaxKind.InterfaceKeyword, + SyntaxKind.ModuleKeyword, + SyntaxKind.NamespaceKeyword, + SyntaxKind.PrivateKeyword, + SyntaxKind.PublicKeyword, + SyntaxKind.ProtectedKeyword, + SyntaxKind.ReadonlyKeyword, + SyntaxKind.SetKeyword, + SyntaxKind.StaticKeyword, + SyntaxKind.TypeKeyword, + SyntaxKind.FromKeyword, + SyntaxKind.KeyOfKeyword, + SyntaxKind.InferKeyword, ], anyToken, [isNonJsxSameLineTokenContext], - ts.formatting.RuleAction.InsertSpace), + RuleAction.InsertSpace), rule( "SpaceBeforeCertainTypeScriptKeywords", anyToken, - [ts.SyntaxKind.ExtendsKeyword, ts.SyntaxKind.ImplementsKeyword, ts.SyntaxKind.FromKeyword], + [SyntaxKind.ExtendsKeyword, SyntaxKind.ImplementsKeyword, SyntaxKind.FromKeyword], [isNonJsxSameLineTokenContext], - ts.formatting.RuleAction.InsertSpace), + RuleAction.InsertSpace), // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" { - rule("SpaceAfterModuleName", ts.SyntaxKind.StringLiteral, ts.SyntaxKind.OpenBraceToken, [isModuleDeclContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterModuleName", SyntaxKind.StringLiteral, SyntaxKind.OpenBraceToken, [isModuleDeclContext], RuleAction.InsertSpace), // Lambda expressions - rule("SpaceBeforeArrow", anyToken, ts.SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterArrow", ts.SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceBeforeArrow", anyToken, SyntaxKind.EqualsGreaterThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceAfterArrow", SyntaxKind.EqualsGreaterThanToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), // Optional parameters and let args - rule("NoSpaceAfterEllipsis", ts.SyntaxKind.DotDotDotToken, ts.SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterOptionalParameters", ts.SyntaxKind.QuestionToken, [ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceAfterEllipsis", SyntaxKind.DotDotDotToken, SyntaxKind.Identifier, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterOptionalParameters", SyntaxKind.QuestionToken, [SyntaxKind.CloseParenToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], RuleAction.DeleteSpace), // Remove spaces in empty interface literals. e.g.: x: {} - rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectTypeContext], RuleAction.DeleteSpace), // generics and type assertions - rule("NoSpaceBeforeOpenAngularBracket", typeNames, ts.SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBetweenCloseParenAndAngularBracket", ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenAngularBracket", ts.SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseAngularBracket", anyToken, ts.SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBeforeOpenAngularBracket", typeNames, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), + rule("NoSpaceBetweenCloseParenAndAngularBracket", SyntaxKind.CloseParenToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenAngularBracket", SyntaxKind.LessThanToken, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseAngularBracket", anyToken, SyntaxKind.GreaterThanToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], RuleAction.DeleteSpace), rule("NoSpaceAfterCloseAngularBracket", - ts.SyntaxKind.GreaterThanToken, - [ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.GreaterThanToken, ts.SyntaxKind.CommaToken], + SyntaxKind.GreaterThanToken, + [SyntaxKind.OpenParenToken, SyntaxKind.OpenBracketToken, SyntaxKind.GreaterThanToken, SyntaxKind.CommaToken], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext, isNotFunctionDeclContext /*To prevent an interference with the SpaceBeforeOpenParenInFuncDecl rule*/], - ts.formatting.RuleAction.DeleteSpace), + RuleAction.DeleteSpace), // decorators - rule("SpaceBeforeAt", [ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.Identifier], ts.SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterAt", ts.SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBeforeAt", [SyntaxKind.CloseParenToken, SyntaxKind.Identifier], SyntaxKind.AtToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceAfterAt", SyntaxKind.AtToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert space after @ in decorator rule("SpaceAfterDecorator", anyToken, [ - ts.SyntaxKind.AbstractKeyword, - ts.SyntaxKind.Identifier, - ts.SyntaxKind.ExportKeyword, - ts.SyntaxKind.DefaultKeyword, - ts.SyntaxKind.ClassKeyword, - ts.SyntaxKind.StaticKeyword, - ts.SyntaxKind.PublicKeyword, - ts.SyntaxKind.PrivateKeyword, - ts.SyntaxKind.ProtectedKeyword, - ts.SyntaxKind.GetKeyword, - ts.SyntaxKind.SetKeyword, - ts.SyntaxKind.OpenBracketToken, - ts.SyntaxKind.AsteriskToken, + SyntaxKind.AbstractKeyword, + SyntaxKind.Identifier, + SyntaxKind.ExportKeyword, + SyntaxKind.DefaultKeyword, + SyntaxKind.ClassKeyword, + SyntaxKind.StaticKeyword, + SyntaxKind.PublicKeyword, + SyntaxKind.PrivateKeyword, + SyntaxKind.ProtectedKeyword, + SyntaxKind.GetKeyword, + SyntaxKind.SetKeyword, + SyntaxKind.OpenBracketToken, + SyntaxKind.AsteriskToken, ], [isEndOfDecoratorContextOnSameLine], - ts.formatting.RuleAction.InsertSpace), + RuleAction.InsertSpace), - rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, ts.SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterNewKeywordOnConstructorSignature", ts.SyntaxKind.NewKeyword, ts.SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceLessThanAndNonJSXTypeAnnotation", ts.SyntaxKind.LessThanToken, ts.SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, SyntaxKind.ExclamationToken, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterNewKeywordOnConstructorSignature", SyntaxKind.NewKeyword, SyntaxKind.OpenParenToken, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], RuleAction.DeleteSpace), + rule("SpaceLessThanAndNonJSXTypeAnnotation", SyntaxKind.LessThanToken, SyntaxKind.LessThanToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), ]; // These rules are applied after high priority const userConfigurableRules = [ // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses - rule("SpaceAfterConstructor", ts.SyntaxKind.ConstructorKeyword, ts.SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterConstructor", ts.SyntaxKind.ConstructorKeyword, ts.SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceAfterConstructor", SyntaxKind.ConstructorKeyword, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("SpaceAfterComma", ts.SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket, isNextTokenNotCloseParen], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterComma", ts.SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket, isNextTokenNotCloseParen], RuleAction.InsertSpace), + rule("NoSpaceAfterComma", SyntaxKind.CommaToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], RuleAction.DeleteSpace), // Insert space after function keyword for anonymous functions - rule("SpaceAfterAnonymousFunctionKeyword", [ts.SyntaxKind.FunctionKeyword, ts.SyntaxKind.AsteriskToken], ts.SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterAnonymousFunctionKeyword", [ts.SyntaxKind.FunctionKeyword, ts.SyntaxKind.AsteriskToken], ts.SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.InsertSpace), + rule("NoSpaceAfterAnonymousFunctionKeyword", [SyntaxKind.FunctionKeyword, SyntaxKind.AsteriskToken], SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], RuleAction.DeleteSpace), // Insert space after keywords in control flow statements - rule("SpaceAfterKeywordInControl", keywords, ts.SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterKeywordInControl", keywords, ts.SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.InsertSpace), + rule("NoSpaceAfterKeywordInControl", keywords, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], RuleAction.DeleteSpace), // Insert space after opening and before closing nonempty parenthesis - rule("SpaceAfterOpenParen", ts.SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBeforeCloseParen", anyToken, ts.SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBetweenOpenParens", ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBetweenParens", ts.SyntaxKind.OpenParenToken, ts.SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenParen", ts.SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseParen", anyToken, ts.SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBetweenOpenParens", SyntaxKind.OpenParenToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceBetweenParens", SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenParen", SyntaxKind.OpenParenToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseParen", anyToken, SyntaxKind.CloseParenToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert space after opening and before closing nonempty brackets - rule("SpaceAfterOpenBracket", ts.SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBeforeCloseBracket", anyToken, ts.SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBetweenBrackets", ts.SyntaxKind.OpenBracketToken, ts.SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenBracket", ts.SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBracket", anyToken, ts.SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceBetweenBrackets", SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenBracket", SyntaxKind.OpenBracketToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBracket", anyToken, SyntaxKind.CloseBracketToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}. - rule("SpaceAfterOpenBrace", ts.SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBeforeCloseBrace", anyToken, ts.SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterOpenBrace", ts.SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBrace", anyToken, ts.SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isNonJsxSameLineTokenContext, isObjectContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterOpenBrace", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBrace", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert a space after opening and before closing empty brace brackets - rule("SpaceBetweenEmptyBraceBrackets", ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces")], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBetweenEmptyBraceBrackets", ts.SyntaxKind.OpenBraceToken, ts.SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces")], RuleAction.InsertSpace), + rule("NoSpaceBetweenEmptyBraceBrackets", SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingEmptyBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // Insert space after opening and before closing template string braces - rule("SpaceAfterTemplateHeadAndMiddle", [ts.SyntaxKind.TemplateHead, ts.SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], ts.formatting.RuleAction.InsertSpace, ts.formatting.RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [ts.SyntaxKind.TemplateMiddle, ts.SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterTemplateHeadAndMiddle", [ts.SyntaxKind.TemplateHead, ts.SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], ts.formatting.RuleAction.DeleteSpace, ts.formatting.RuleFlags.CanDeleteNewLines), - rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [ts.SyntaxKind.TemplateMiddle, ts.SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.InsertSpace), + rule("NoSpaceAfterTemplateHeadAndMiddle", [SyntaxKind.TemplateHead, SyntaxKind.TemplateMiddle], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxTextContext], RuleAction.DeleteSpace, RuleFlags.CanDeleteNewLines), + rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [SyntaxKind.TemplateMiddle, SyntaxKind.TemplateTail], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // No space after { and before } in JSX expression - rule("SpaceAfterOpenBraceInJsxExpression", ts.SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, ts.SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterOpenBraceInJsxExpression", ts.SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, ts.SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace), + rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.InsertSpace), + rule("NoSpaceAfterOpenBraceInJsxExpression", SyntaxKind.OpenBraceToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace), + rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, SyntaxKind.CloseBraceToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], RuleAction.DeleteSpace), // Insert space after semicolon in for statement - rule("SpaceAfterSemicolonInFor", ts.SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterSemicolonInFor", ts.SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.InsertSpace), + rule("NoSpaceAfterSemicolonInFor", SyntaxKind.SemicolonToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], RuleAction.DeleteSpace), // Insert space before and after binary operators - rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], RuleAction.DeleteSpace), - rule("SpaceBeforeOpenParenInFuncDecl", anyToken, ts.SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, ts.SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, SyntaxKind.OpenParenToken, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], RuleAction.DeleteSpace), // Open Brace braces after control block - rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], ts.formatting.RuleAction.InsertNewLine, ts.formatting.RuleFlags.CanDeleteNewLines), + rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), // Open Brace braces after function // TypeScript: Function can have return types, which can be made of tons of different token kinds - rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], ts.formatting.RuleAction.InsertNewLine, ts.formatting.RuleFlags.CanDeleteNewLines), + rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), // Open Brace braces after TypeScript module/class/interface - rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], ts.formatting.RuleAction.InsertNewLine, ts.formatting.RuleFlags.CanDeleteNewLines), + rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], RuleAction.InsertNewLine, RuleFlags.CanDeleteNewLines), - rule("SpaceAfterTypeAssertion", ts.SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceAfterTypeAssertion", ts.SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.InsertSpace), + rule("NoSpaceAfterTypeAssertion", SyntaxKind.GreaterThanToken, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], RuleAction.DeleteSpace), - rule("SpaceBeforeTypeAnnotation", anyToken, [ts.SyntaxKind.QuestionToken, ts.SyntaxKind.ColonToken], [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], ts.formatting.RuleAction.InsertSpace), - rule("NoSpaceBeforeTypeAnnotation", anyToken, [ts.SyntaxKind.QuestionToken, ts.SyntaxKind.ColonToken], [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], ts.formatting.RuleAction.DeleteSpace), + rule("SpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.InsertSpace), + rule("NoSpaceBeforeTypeAnnotation", anyToken, [SyntaxKind.QuestionToken, SyntaxKind.ColonToken], [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], RuleAction.DeleteSpace), - rule("NoOptionalSemicolon", ts.SyntaxKind.SemicolonToken, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Remove), isSemicolonDeletionContext], ts.formatting.RuleAction.DeleteToken), - rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", ts.SemicolonPreference.Insert), isSemicolonInsertionContext], ts.formatting.RuleAction.InsertTrailingSemicolon), + rule("NoOptionalSemicolon", SyntaxKind.SemicolonToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Remove), isSemicolonDeletionContext], RuleAction.DeleteToken), + rule("OptionalSemicolon", anyToken, anyTokenIncludingEOF, [optionEquals("semicolons", SemicolonPreference.Insert), isSemicolonInsertionContext], RuleAction.InsertTrailingSemicolon), ]; // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list. const lowPriorityCommonRules = [ // Space after keyword but not before ; or : or ? - rule("NoSpaceBeforeSemicolon", anyToken, ts.SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBeforeSemicolon", anyToken, SyntaxKind.SemicolonToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), - rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], ts.formatting.RuleAction.InsertSpace, ts.formatting.RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], ts.formatting.RuleAction.InsertSpace, ts.formatting.RuleFlags.CanDeleteNewLines), - rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, ts.SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], ts.formatting.RuleAction.InsertSpace, ts.formatting.RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), + rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, SyntaxKind.OpenBraceToken, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], RuleAction.InsertSpace, RuleFlags.CanDeleteNewLines), - rule("NoSpaceBeforeComma", anyToken, ts.SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), + rule("NoSpaceBeforeComma", anyToken, SyntaxKind.CommaToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), // No space before and after indexer `x[]` - rule("NoSpaceBeforeOpenBracket", anyTokenExcept(ts.SyntaxKind.AsyncKeyword, ts.SyntaxKind.CaseKeyword), ts.SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.DeleteSpace), - rule("NoSpaceAfterCloseBracket", ts.SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], ts.formatting.RuleAction.DeleteSpace), - rule("SpaceAfterSemicolon", ts.SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("NoSpaceBeforeOpenBracket", anyTokenExcept(SyntaxKind.AsyncKeyword, SyntaxKind.CaseKeyword), SyntaxKind.OpenBracketToken, [isNonJsxSameLineTokenContext], RuleAction.DeleteSpace), + rule("NoSpaceAfterCloseBracket", SyntaxKind.CloseBracketToken, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], RuleAction.DeleteSpace), + rule("SpaceAfterSemicolon", SyntaxKind.SemicolonToken, anyToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), // Remove extra space between for and await - rule("SpaceBetweenForAndAwaitKeyword", ts.SyntaxKind.ForKeyword, ts.SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceBetweenForAndAwaitKeyword", SyntaxKind.ForKeyword, SyntaxKind.AwaitKeyword, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), // Add a space between statements. All keywords except (do,else,case) has open/close parens after them. // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any] rule( "SpaceBetweenStatements", - [ts.SyntaxKind.CloseParenToken, ts.SyntaxKind.DoKeyword, ts.SyntaxKind.ElseKeyword, ts.SyntaxKind.CaseKeyword], + [SyntaxKind.CloseParenToken, SyntaxKind.DoKeyword, SyntaxKind.ElseKeyword, SyntaxKind.CaseKeyword], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], - ts.formatting.RuleAction.InsertSpace), + RuleAction.InsertSpace), // This low-pri rule takes care of "try {", "catch {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter. - rule("SpaceAfterTryCatchFinally", [ts.SyntaxKind.TryKeyword, ts.SyntaxKind.CatchKeyword, ts.SyntaxKind.FinallyKeyword], ts.SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], ts.formatting.RuleAction.InsertSpace), + rule("SpaceAfterTryCatchFinally", [SyntaxKind.TryKeyword, SyntaxKind.CatchKeyword, SyntaxKind.FinallyKeyword], SyntaxKind.OpenBraceToken, [isNonJsxSameLineTokenContext], RuleAction.InsertSpace), ]; return [ @@ -377,27 +386,27 @@ export function getAllRules(): RuleSpec[] { */ function rule( debugName: string, - left: ts.SyntaxKind | readonly ts.SyntaxKind[] | ts.formatting.TokenRange, - right: ts.SyntaxKind | readonly ts.SyntaxKind[] | ts.formatting.TokenRange, - context: readonly ts.formatting.ContextPredicate[], - action: ts.formatting.RuleAction, - flags: ts.formatting.RuleFlags = ts.formatting.RuleFlags.None, + left: SyntaxKind | readonly SyntaxKind[] | TokenRange, + right: SyntaxKind | readonly SyntaxKind[] | TokenRange, + context: readonly ContextPredicate[], + action: RuleAction, + flags: RuleFlags = RuleFlags.None, ): RuleSpec { return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName, context, action, flags } }; } -function tokenRangeFrom(tokens: readonly ts.SyntaxKind[]): ts.formatting.TokenRange { +function tokenRangeFrom(tokens: readonly SyntaxKind[]): TokenRange { return { tokens, isSpecific: true }; } -function toTokenRange(arg: ts.SyntaxKind | readonly ts.SyntaxKind[] | ts.formatting.TokenRange): ts.formatting.TokenRange { - return typeof arg === "number" ? tokenRangeFrom([arg]) : ts.isArray(arg) ? tokenRangeFrom(arg) : arg; +function toTokenRange(arg: SyntaxKind | readonly SyntaxKind[] | TokenRange): TokenRange { + return typeof arg === "number" ? tokenRangeFrom([arg]) : isArray(arg) ? tokenRangeFrom(arg) : arg; } -function tokenRangeFromRange(from: ts.SyntaxKind, to: ts.SyntaxKind, except: readonly ts.SyntaxKind[] = []): ts.formatting.TokenRange { - const tokens: ts.SyntaxKind[] = []; +function tokenRangeFromRange(from: SyntaxKind, to: SyntaxKind, except: readonly SyntaxKind[] = []): TokenRange { + const tokens: SyntaxKind[] = []; for (let token = from; token <= to; token++) { - if (!ts.contains(except, token)) { + if (!contains(except, token)) { tokens.push(token); } } @@ -408,227 +417,227 @@ function tokenRangeFromRange(from: ts.SyntaxKind, to: ts.SyntaxKind, except: rea /// Contexts /// -function optionEquals(optionName: K, optionValue: ts.FormatCodeSettings[K]): (context: ts.formatting.FormattingContext) => boolean { +function optionEquals(optionName: K, optionValue: FormatCodeSettings[K]): (context: FormattingContext) => boolean { return (context) => context.options && context.options[optionName] === optionValue; } -function isOptionEnabled(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { - return (context) => context.options && ts.hasProperty(context.options, optionName) && !!context.options[optionName]; +function isOptionEnabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => context.options && hasProperty(context.options, optionName) && !!context.options[optionName]; } -function isOptionDisabled(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { - return (context) => context.options && ts.hasProperty(context.options, optionName) && !context.options[optionName]; +function isOptionDisabled(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => context.options && hasProperty(context.options, optionName) && !context.options[optionName]; } -function isOptionDisabledOrUndefined(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { - return (context) => !context.options || !ts.hasProperty(context.options, optionName) || !context.options[optionName]; +function isOptionDisabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !hasProperty(context.options, optionName) || !context.options[optionName]; } -function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { - return (context) => !context.options || !ts.hasProperty(context.options, optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); +function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !hasProperty(context.options, optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); } -function isOptionEnabledOrUndefined(optionName: keyof ts.FormatCodeSettings): (context: ts.formatting.FormattingContext) => boolean { - return (context) => !context.options || !ts.hasProperty(context.options, optionName) || !!context.options[optionName]; +function isOptionEnabledOrUndefined(optionName: keyof FormatCodeSettings): (context: FormattingContext) => boolean { + return (context) => !context.options || !hasProperty(context.options, optionName) || !!context.options[optionName]; } -function isForContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ForStatement; +function isForContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ForStatement; } -function isNotForContext(context: ts.formatting.FormattingContext): boolean { +function isNotForContext(context: FormattingContext): boolean { return !isForContext(context); } -function isBinaryOpContext(context: ts.formatting.FormattingContext): boolean { +function isBinaryOpContext(context: FormattingContext): boolean { switch (context.contextNode.kind) { - case ts.SyntaxKind.BinaryExpression: - return (context.contextNode as ts.BinaryExpression).operatorToken.kind !== ts.SyntaxKind.CommaToken; - case ts.SyntaxKind.ConditionalExpression: - case ts.SyntaxKind.ConditionalType: - case ts.SyntaxKind.AsExpression: - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.TypePredicate: - case ts.SyntaxKind.UnionType: - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.SatisfiesExpression: + case SyntaxKind.BinaryExpression: + return (context.contextNode as BinaryExpression).operatorToken.kind !== SyntaxKind.CommaToken; + case SyntaxKind.ConditionalExpression: + case SyntaxKind.ConditionalType: + case SyntaxKind.AsExpression: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.TypePredicate: + case SyntaxKind.UnionType: + case SyntaxKind.IntersectionType: + case SyntaxKind.SatisfiesExpression: return true; // equals in binding elements: function foo([[x, y] = [1, 2]]) - case ts.SyntaxKind.BindingElement: + case SyntaxKind.BindingElement: // equals in type X = ... // falls through - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeAliasDeclaration: // equal in import a = module('a'); // falls through - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: // equal in export = 1 // falls through - case ts.SyntaxKind.ExportAssignment: + case SyntaxKind.ExportAssignment: // equal in let a = 0 // falls through - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableDeclaration: // equal in p = 0 // falls through - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - return context.currentTokenSpan.kind === ts.SyntaxKind.EqualsToken || context.nextTokenSpan.kind === ts.SyntaxKind.EqualsToken; + case SyntaxKind.Parameter: + case SyntaxKind.EnumMember: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + return context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; // "in" keyword in for (let x in []) { } - case ts.SyntaxKind.ForInStatement: + case SyntaxKind.ForInStatement: // "in" keyword in [P in keyof T]: T[P] // falls through - case ts.SyntaxKind.TypeParameter: - return context.currentTokenSpan.kind === ts.SyntaxKind.InKeyword || context.nextTokenSpan.kind === ts.SyntaxKind.InKeyword || context.currentTokenSpan.kind === ts.SyntaxKind.EqualsToken || context.nextTokenSpan.kind === ts.SyntaxKind.EqualsToken; + case SyntaxKind.TypeParameter: + return context.currentTokenSpan.kind === SyntaxKind.InKeyword || context.nextTokenSpan.kind === SyntaxKind.InKeyword || context.currentTokenSpan.kind === SyntaxKind.EqualsToken || context.nextTokenSpan.kind === SyntaxKind.EqualsToken; // Technically, "of" is not a binary operator, but format it the same way as "in" - case ts.SyntaxKind.ForOfStatement: - return context.currentTokenSpan.kind === ts.SyntaxKind.OfKeyword || context.nextTokenSpan.kind === ts.SyntaxKind.OfKeyword; + case SyntaxKind.ForOfStatement: + return context.currentTokenSpan.kind === SyntaxKind.OfKeyword || context.nextTokenSpan.kind === SyntaxKind.OfKeyword; } return false; } -function isNotBinaryOpContext(context: ts.formatting.FormattingContext): boolean { +function isNotBinaryOpContext(context: FormattingContext): boolean { return !isBinaryOpContext(context); } -function isNotTypeAnnotationContext(context: ts.formatting.FormattingContext): boolean { +function isNotTypeAnnotationContext(context: FormattingContext): boolean { return !isTypeAnnotationContext(context); } -function isTypeAnnotationContext(context: ts.formatting.FormattingContext): boolean { +function isTypeAnnotationContext(context: FormattingContext): boolean { const contextKind = context.contextNode.kind; - return contextKind === ts.SyntaxKind.PropertyDeclaration || - contextKind === ts.SyntaxKind.PropertySignature || - contextKind === ts.SyntaxKind.Parameter || - contextKind === ts.SyntaxKind.VariableDeclaration || - ts.isFunctionLikeKind(contextKind); + return contextKind === SyntaxKind.PropertyDeclaration || + contextKind === SyntaxKind.PropertySignature || + contextKind === SyntaxKind.Parameter || + contextKind === SyntaxKind.VariableDeclaration || + isFunctionLikeKind(contextKind); } -function isConditionalOperatorContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ConditionalExpression || - context.contextNode.kind === ts.SyntaxKind.ConditionalType; +function isConditionalOperatorContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConditionalExpression || + context.contextNode.kind === SyntaxKind.ConditionalType; } -function isSameLineTokenOrBeforeBlockContext(context: ts.formatting.FormattingContext): boolean { +function isSameLineTokenOrBeforeBlockContext(context: FormattingContext): boolean { return context.TokensAreOnSameLine() || isBeforeBlockContext(context); } -function isBraceWrappedContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ObjectBindingPattern || - context.contextNode.kind === ts.SyntaxKind.MappedType || +function isBraceWrappedContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ObjectBindingPattern || + context.contextNode.kind === SyntaxKind.MappedType || isSingleLineBlockContext(context); } // This check is done before an open brace in a control construct, a function, or a typescript block declaration -function isBeforeMultilineBlockContext(context: ts.formatting.FormattingContext): boolean { +function isBeforeMultilineBlockContext(context: FormattingContext): boolean { return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine()); } -function isMultilineBlockContext(context: ts.formatting.FormattingContext): boolean { +function isMultilineBlockContext(context: FormattingContext): boolean { return isBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); } -function isSingleLineBlockContext(context: ts.formatting.FormattingContext): boolean { +function isSingleLineBlockContext(context: FormattingContext): boolean { return isBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine()); } -function isBlockContext(context: ts.formatting.FormattingContext): boolean { +function isBlockContext(context: FormattingContext): boolean { return nodeIsBlockContext(context.contextNode); } -function isBeforeBlockContext(context: ts.formatting.FormattingContext): boolean { +function isBeforeBlockContext(context: FormattingContext): boolean { return nodeIsBlockContext(context.nextTokenParent); } // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children -function nodeIsBlockContext(node: ts.Node): boolean { +function nodeIsBlockContext(node: Node): boolean { if (nodeIsTypeScriptDeclWithBlockContext(node)) { // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc). return true; } switch (node.kind) { - case ts.SyntaxKind.Block: - case ts.SyntaxKind.CaseBlock: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ModuleBlock: + case SyntaxKind.Block: + case SyntaxKind.CaseBlock: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ModuleBlock: return true; } return false; } -function isFunctionDeclContext(context: ts.formatting.FormattingContext): boolean { +function isFunctionDeclContext(context: FormattingContext): boolean { switch (context.contextNode.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: // case SyntaxKind.MemberFunctionDeclaration: // falls through - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: // case SyntaxKind.MethodSignature: // falls through - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.CallSignature: + case SyntaxKind.FunctionExpression: + case SyntaxKind.Constructor: + case SyntaxKind.ArrowFunction: // case SyntaxKind.ConstructorDeclaration: // case SyntaxKind.SimpleArrowFunctionExpression: // case SyntaxKind.ParenthesizedArrowFunctionExpression: // falls through - case ts.SyntaxKind.InterfaceDeclaration: // This one is not truly a function, but for formatting purposes, it acts just like one + case SyntaxKind.InterfaceDeclaration: // This one is not truly a function, but for formatting purposes, it acts just like one return true; } return false; } -function isNotFunctionDeclContext(context: ts.formatting.FormattingContext): boolean { +function isNotFunctionDeclContext(context: FormattingContext): boolean { return !isFunctionDeclContext(context); } -function isFunctionDeclarationOrFunctionExpressionContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.FunctionDeclaration || context.contextNode.kind === ts.SyntaxKind.FunctionExpression; +function isFunctionDeclarationOrFunctionExpressionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.FunctionDeclaration || context.contextNode.kind === SyntaxKind.FunctionExpression; } -function isTypeScriptDeclWithBlockContext(context: ts.formatting.FormattingContext): boolean { +function isTypeScriptDeclWithBlockContext(context: FormattingContext): boolean { return nodeIsTypeScriptDeclWithBlockContext(context.contextNode); } -function nodeIsTypeScriptDeclWithBlockContext(node: ts.Node): boolean { +function nodeIsTypeScriptDeclWithBlockContext(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.NamedExports: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.NamedImports: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeLiteral: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.NamedExports: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.NamedImports: return true; } return false; } -function isAfterCodeBlockContext(context: ts.formatting.FormattingContext): boolean { +function isAfterCodeBlockContext(context: FormattingContext): boolean { switch (context.currentTokenParent.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.CatchClause: - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.SwitchStatement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.CatchClause: + case SyntaxKind.ModuleBlock: + case SyntaxKind.SwitchStatement: return true; - case ts.SyntaxKind.Block: { + case SyntaxKind.Block: { const blockParent = context.currentTokenParent.parent; // In a codefix scenario, we can't rely on parents being set. So just always return true. - if (!blockParent || blockParent.kind !== ts.SyntaxKind.ArrowFunction && blockParent.kind !== ts.SyntaxKind.FunctionExpression) { + if (!blockParent || blockParent.kind !== SyntaxKind.ArrowFunction && blockParent.kind !== SyntaxKind.FunctionExpression) { return true; } } @@ -636,21 +645,21 @@ function isAfterCodeBlockContext(context: ts.formatting.FormattingContext): bool return false; } -function isControlDeclContext(context: ts.formatting.FormattingContext): boolean { +function isControlDeclContext(context: FormattingContext): boolean { switch (context.contextNode.kind) { - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.SwitchStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.TryStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WithStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WithStatement: // TODO // case SyntaxKind.ElseClause: // falls through - case ts.SyntaxKind.CatchClause: + case SyntaxKind.CatchClause: return true; default: @@ -658,130 +667,130 @@ function isControlDeclContext(context: ts.formatting.FormattingContext): boolean } } -function isObjectContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ObjectLiteralExpression; +function isObjectContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ObjectLiteralExpression; } -function isFunctionCallContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.CallExpression; +function isFunctionCallContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.CallExpression; } -function isNewContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.NewExpression; +function isNewContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.NewExpression; } -function isFunctionCallOrNewContext(context: ts.formatting.FormattingContext): boolean { +function isFunctionCallOrNewContext(context: FormattingContext): boolean { return isFunctionCallContext(context) || isNewContext(context); } -function isPreviousTokenNotComma(context: ts.formatting.FormattingContext): boolean { - return context.currentTokenSpan.kind !== ts.SyntaxKind.CommaToken; +function isPreviousTokenNotComma(context: FormattingContext): boolean { + return context.currentTokenSpan.kind !== SyntaxKind.CommaToken; } -function isNextTokenNotCloseBracket(context: ts.formatting.FormattingContext): boolean { - return context.nextTokenSpan.kind !== ts.SyntaxKind.CloseBracketToken; +function isNextTokenNotCloseBracket(context: FormattingContext): boolean { + return context.nextTokenSpan.kind !== SyntaxKind.CloseBracketToken; } -function isNextTokenNotCloseParen(context: ts.formatting.FormattingContext): boolean { - return context.nextTokenSpan.kind !== ts.SyntaxKind.CloseParenToken; +function isNextTokenNotCloseParen(context: FormattingContext): boolean { + return context.nextTokenSpan.kind !== SyntaxKind.CloseParenToken; } -function isArrowFunctionContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ArrowFunction; +function isArrowFunctionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ArrowFunction; } -function isImportTypeContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ImportType; +function isImportTypeContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ImportType; } -function isNonJsxSameLineTokenContext(context: ts.formatting.FormattingContext): boolean { - return context.TokensAreOnSameLine() && context.contextNode.kind !== ts.SyntaxKind.JsxText; +function isNonJsxSameLineTokenContext(context: FormattingContext): boolean { + return context.TokensAreOnSameLine() && context.contextNode.kind !== SyntaxKind.JsxText; } -function isNonJsxTextContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind !== ts.SyntaxKind.JsxText; +function isNonJsxTextContext(context: FormattingContext): boolean { + return context.contextNode.kind !== SyntaxKind.JsxText; } -function isNonJsxElementOrFragmentContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind !== ts.SyntaxKind.JsxElement && context.contextNode.kind !== ts.SyntaxKind.JsxFragment; +function isNonJsxElementOrFragmentContext(context: FormattingContext): boolean { + return context.contextNode.kind !== SyntaxKind.JsxElement && context.contextNode.kind !== SyntaxKind.JsxFragment; } -function isJsxExpressionContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.JsxExpression || context.contextNode.kind === ts.SyntaxKind.JsxSpreadAttribute; +function isJsxExpressionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxExpression || context.contextNode.kind === SyntaxKind.JsxSpreadAttribute; } -function isNextTokenParentJsxAttribute(context: ts.formatting.FormattingContext): boolean { - return context.nextTokenParent.kind === ts.SyntaxKind.JsxAttribute; +function isNextTokenParentJsxAttribute(context: FormattingContext): boolean { + return context.nextTokenParent.kind === SyntaxKind.JsxAttribute; } -function isJsxAttributeContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.JsxAttribute; +function isJsxAttributeContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxAttribute; } -function isJsxSelfClosingElementContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.JsxSelfClosingElement; +function isJsxSelfClosingElementContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.JsxSelfClosingElement; } -function isNotBeforeBlockInFunctionDeclarationContext(context: ts.formatting.FormattingContext): boolean { +function isNotBeforeBlockInFunctionDeclarationContext(context: FormattingContext): boolean { return !isFunctionDeclContext(context) && !isBeforeBlockContext(context); } -function isEndOfDecoratorContextOnSameLine(context: ts.formatting.FormattingContext): boolean { +function isEndOfDecoratorContextOnSameLine(context: FormattingContext): boolean { return context.TokensAreOnSameLine() && - ts.hasDecorators(context.contextNode) && + hasDecorators(context.contextNode) && nodeIsInDecoratorContext(context.currentTokenParent) && !nodeIsInDecoratorContext(context.nextTokenParent); } -function nodeIsInDecoratorContext(node: ts.Node): boolean { - while (node && ts.isExpression(node)) { +function nodeIsInDecoratorContext(node: Node): boolean { + while (node && isExpression(node)) { node = node.parent; } - return node && node.kind === ts.SyntaxKind.Decorator; + return node && node.kind === SyntaxKind.Decorator; } -function isStartOfVariableDeclarationList(context: ts.formatting.FormattingContext): boolean { - return context.currentTokenParent.kind === ts.SyntaxKind.VariableDeclarationList && +function isStartOfVariableDeclarationList(context: FormattingContext): boolean { + return context.currentTokenParent.kind === SyntaxKind.VariableDeclarationList && context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos; } -function isNotFormatOnEnter(context: ts.formatting.FormattingContext): boolean { - return context.formattingRequestKind !== ts.formatting.FormattingRequestKind.FormatOnEnter; +function isNotFormatOnEnter(context: FormattingContext): boolean { + return context.formattingRequestKind !== FormattingRequestKind.FormatOnEnter; } -function isModuleDeclContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ModuleDeclaration; +function isModuleDeclContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ModuleDeclaration; } -function isObjectTypeContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.TypeLiteral; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; +function isObjectTypeContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeLiteral; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration; } -function isConstructorSignatureContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.ConstructSignature; +function isConstructorSignatureContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.ConstructSignature; } -function isTypeArgumentOrParameterOrAssertion(token: ts.formatting.TextRangeWithKind, parent: ts.Node): boolean { - if (token.kind !== ts.SyntaxKind.LessThanToken && token.kind !== ts.SyntaxKind.GreaterThanToken) { +function isTypeArgumentOrParameterOrAssertion(token: TextRangeWithKind, parent: Node): boolean { + if (token.kind !== SyntaxKind.LessThanToken && token.kind !== SyntaxKind.GreaterThanToken) { return false; } switch (parent.kind) { - case ts.SyntaxKind.TypeReference: - case ts.SyntaxKind.TypeAssertionExpression: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.TypeReference: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.ExpressionWithTypeArguments: return true; default: return false; @@ -789,39 +798,39 @@ function isTypeArgumentOrParameterOrAssertion(token: ts.formatting.TextRangeWith } } -function isTypeArgumentOrParameterOrAssertionContext(context: ts.formatting.FormattingContext): boolean { +function isTypeArgumentOrParameterOrAssertionContext(context: FormattingContext): boolean { return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) || isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent); } -function isTypeAssertionContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.TypeAssertionExpression; +function isTypeAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.TypeAssertionExpression; } -function isVoidOpContext(context: ts.formatting.FormattingContext): boolean { - return context.currentTokenSpan.kind === ts.SyntaxKind.VoidKeyword && context.currentTokenParent.kind === ts.SyntaxKind.VoidExpression; +function isVoidOpContext(context: FormattingContext): boolean { + return context.currentTokenSpan.kind === SyntaxKind.VoidKeyword && context.currentTokenParent.kind === SyntaxKind.VoidExpression; } -function isYieldOrYieldStarWithOperand(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.YieldExpression && (context.contextNode as ts.YieldExpression).expression !== undefined; +function isYieldOrYieldStarWithOperand(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.YieldExpression && (context.contextNode as YieldExpression).expression !== undefined; } -function isNonNullAssertionContext(context: ts.formatting.FormattingContext): boolean { - return context.contextNode.kind === ts.SyntaxKind.NonNullExpression; +function isNonNullAssertionContext(context: FormattingContext): boolean { + return context.contextNode.kind === SyntaxKind.NonNullExpression; } -function isNotStatementConditionContext(context: ts.formatting.FormattingContext): boolean { +function isNotStatementConditionContext(context: FormattingContext): boolean { return !isStatementConditionContext(context); } -function isStatementConditionContext(context: ts.formatting.FormattingContext): boolean { +function isStatementConditionContext(context: FormattingContext): boolean { switch (context.contextNode.kind) { - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WhileStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: return true; default: @@ -829,14 +838,14 @@ function isStatementConditionContext(context: ts.formatting.FormattingContext): } } -function isSemicolonDeletionContext(context: ts.formatting.FormattingContext): boolean { +function isSemicolonDeletionContext(context: FormattingContext): boolean { let nextTokenKind = context.nextTokenSpan.kind; let nextTokenStart = context.nextTokenSpan.pos; - if (ts.isTrivia(nextTokenKind)) { + if (isTrivia(nextTokenKind)) { const nextRealToken = context.nextTokenParent === context.currentTokenParent - ? ts.findNextToken( + ? findNextToken( context.currentTokenParent, - ts.findAncestor(context.currentTokenParent, a => !a.parent)!, + findAncestor(context.currentTokenParent, a => !a.parent)!, context.sourceFile) : context.nextTokenParent.getFirstToken(context.sourceFile); if (!nextRealToken) { @@ -849,18 +858,18 @@ function isSemicolonDeletionContext(context: ts.formatting.FormattingContext): b const startLine = context.sourceFile.getLineAndCharacterOfPosition(context.currentTokenSpan.pos).line; const endLine = context.sourceFile.getLineAndCharacterOfPosition(nextTokenStart).line; if (startLine === endLine) { - return nextTokenKind === ts.SyntaxKind.CloseBraceToken - || nextTokenKind === ts.SyntaxKind.EndOfFileToken; + return nextTokenKind === SyntaxKind.CloseBraceToken + || nextTokenKind === SyntaxKind.EndOfFileToken; } - if (nextTokenKind === ts.SyntaxKind.SemicolonClassElement || - nextTokenKind === ts.SyntaxKind.SemicolonToken + if (nextTokenKind === SyntaxKind.SemicolonClassElement || + nextTokenKind === SyntaxKind.SemicolonToken ) { return false; } - if (context.contextNode.kind === ts.SyntaxKind.InterfaceDeclaration || - context.contextNode.kind === ts.SyntaxKind.TypeAliasDeclaration + if (context.contextNode.kind === SyntaxKind.InterfaceDeclaration || + context.contextNode.kind === SyntaxKind.TypeAliasDeclaration ) { // Can’t remove semicolon after `foo`; it would parse as a method declaration: // @@ -868,37 +877,37 @@ function isSemicolonDeletionContext(context: ts.formatting.FormattingContext): b // foo; // (): void // } - return !ts.isPropertySignature(context.currentTokenParent) + return !isPropertySignature(context.currentTokenParent) || !!context.currentTokenParent.type - || nextTokenKind !== ts.SyntaxKind.OpenParenToken; + || nextTokenKind !== SyntaxKind.OpenParenToken; } - if (ts.isPropertyDeclaration(context.currentTokenParent)) { + if (isPropertyDeclaration(context.currentTokenParent)) { return !context.currentTokenParent.initializer; } - return context.currentTokenParent.kind !== ts.SyntaxKind.ForStatement - && context.currentTokenParent.kind !== ts.SyntaxKind.EmptyStatement - && context.currentTokenParent.kind !== ts.SyntaxKind.SemicolonClassElement - && nextTokenKind !== ts.SyntaxKind.OpenBracketToken - && nextTokenKind !== ts.SyntaxKind.OpenParenToken - && nextTokenKind !== ts.SyntaxKind.PlusToken - && nextTokenKind !== ts.SyntaxKind.MinusToken - && nextTokenKind !== ts.SyntaxKind.SlashToken - && nextTokenKind !== ts.SyntaxKind.RegularExpressionLiteral - && nextTokenKind !== ts.SyntaxKind.CommaToken - && nextTokenKind !== ts.SyntaxKind.TemplateExpression - && nextTokenKind !== ts.SyntaxKind.TemplateHead - && nextTokenKind !== ts.SyntaxKind.NoSubstitutionTemplateLiteral - && nextTokenKind !== ts.SyntaxKind.DotToken; -} - -function isSemicolonInsertionContext(context: ts.formatting.FormattingContext): boolean { - return ts.positionIsASICandidate(context.currentTokenSpan.end, context.currentTokenParent, context.sourceFile); -} - -function isNotPropertyAccessOnIntegerLiteral(context: ts.formatting.FormattingContext): boolean { - return !ts.isPropertyAccessExpression(context.contextNode) - || !ts.isNumericLiteral(context.contextNode.expression) + return context.currentTokenParent.kind !== SyntaxKind.ForStatement + && context.currentTokenParent.kind !== SyntaxKind.EmptyStatement + && context.currentTokenParent.kind !== SyntaxKind.SemicolonClassElement + && nextTokenKind !== SyntaxKind.OpenBracketToken + && nextTokenKind !== SyntaxKind.OpenParenToken + && nextTokenKind !== SyntaxKind.PlusToken + && nextTokenKind !== SyntaxKind.MinusToken + && nextTokenKind !== SyntaxKind.SlashToken + && nextTokenKind !== SyntaxKind.RegularExpressionLiteral + && nextTokenKind !== SyntaxKind.CommaToken + && nextTokenKind !== SyntaxKind.TemplateExpression + && nextTokenKind !== SyntaxKind.TemplateHead + && nextTokenKind !== SyntaxKind.NoSubstitutionTemplateLiteral + && nextTokenKind !== SyntaxKind.DotToken; +} + +function isSemicolonInsertionContext(context: FormattingContext): boolean { + return positionIsASICandidate(context.currentTokenSpan.end, context.currentTokenParent, context.sourceFile); +} + +function isNotPropertyAccessOnIntegerLiteral(context: FormattingContext): boolean { + return !isPropertyAccessExpression(context.contextNode) + || !isNumericLiteral(context.contextNode.expression) || context.contextNode.expression.getText().indexOf(".") !== -1; } diff --git a/src/services/formatting/rulesMap.ts b/src/services/formatting/rulesMap.ts index 84f838a7f0669..4cdd1b4ca0864 100644 --- a/src/services/formatting/rulesMap.ts +++ b/src/services/formatting/rulesMap.ts @@ -1,7 +1,10 @@ -import * as ts from "../_namespaces/ts"; +import { Debug, every, FormatCodeSettings, FormattingHost, SyntaxKind } from "../_namespaces/ts"; +import { + anyContext, FormatContext, FormattingContext, getAllRules, Rule, RuleAction, RuleSpec, +} from "../_namespaces/ts.formatting"; /** @internal */ -export function getFormatContext(options: ts.FormatCodeSettings, host: ts.FormattingHost): ts.formatting.FormatContext { +export function getFormatContext(options: FormatCodeSettings, host: FormattingHost): FormatContext { return { options, getRules: getRulesMap(), host }; } @@ -9,7 +12,7 @@ let rulesMapCache: RulesMap | undefined; function getRulesMap(): RulesMap { if (rulesMapCache === undefined) { - rulesMapCache = createRulesMap(ts.formatting.getAllRules()); + rulesMapCache = createRulesMap(getAllRules()); } return rulesMapCache; } @@ -18,35 +21,35 @@ function getRulesMap(): RulesMap { * For a given rule action, gets a mask of other rule actions that * cannot be applied at the same position. */ -function getRuleActionExclusion(ruleAction: ts.formatting.RuleAction): ts.formatting.RuleAction { - let mask: ts.formatting.RuleAction = 0; - if (ruleAction & ts.formatting.RuleAction.StopProcessingSpaceActions) { - mask |= ts.formatting.RuleAction.ModifySpaceAction; +function getRuleActionExclusion(ruleAction: RuleAction): RuleAction { + let mask: RuleAction = 0; + if (ruleAction & RuleAction.StopProcessingSpaceActions) { + mask |= RuleAction.ModifySpaceAction; } - if (ruleAction & ts.formatting.RuleAction.StopProcessingTokenActions) { - mask |= ts.formatting.RuleAction.ModifyTokenAction; + if (ruleAction & RuleAction.StopProcessingTokenActions) { + mask |= RuleAction.ModifyTokenAction; } - if (ruleAction & ts.formatting.RuleAction.ModifySpaceAction) { - mask |= ts.formatting.RuleAction.ModifySpaceAction; + if (ruleAction & RuleAction.ModifySpaceAction) { + mask |= RuleAction.ModifySpaceAction; } - if (ruleAction & ts.formatting.RuleAction.ModifyTokenAction) { - mask |= ts.formatting.RuleAction.ModifyTokenAction; + if (ruleAction & RuleAction.ModifyTokenAction) { + mask |= RuleAction.ModifyTokenAction; } return mask; } /** @internal */ -export type RulesMap = (context: ts.formatting.FormattingContext) => readonly ts.formatting.Rule[] | undefined; -function createRulesMap(rules: readonly ts.formatting.RuleSpec[]): RulesMap { +export type RulesMap = (context: FormattingContext) => readonly Rule[] | undefined; +function createRulesMap(rules: readonly RuleSpec[]): RulesMap { const map = buildMap(rules); return context => { const bucket = map[getRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind)]; if (bucket) { - const rules: ts.formatting.Rule[] = []; - let ruleActionMask: ts.formatting.RuleAction = 0; + const rules: Rule[] = []; + let ruleActionMask: RuleAction = 0; for (const rule of bucket) { const acceptRuleActions = ~getRuleActionExclusion(ruleActionMask); - if (rule.action & acceptRuleActions && ts.every(rule.context, c => c(context))) { + if (rule.action & acceptRuleActions && every(rule.context, c => c(context))) { rules.push(rule); ruleActionMask |= rule.action; } @@ -58,9 +61,9 @@ function createRulesMap(rules: readonly ts.formatting.RuleSpec[]): RulesMap { }; } -function buildMap(rules: readonly ts.formatting.RuleSpec[]): readonly (readonly ts.formatting.Rule[])[] { +function buildMap(rules: readonly RuleSpec[]): readonly (readonly Rule[])[] { // Map from bucket index to array of rules - const map: ts.formatting.Rule[][] = new Array(mapRowLength * mapRowLength); + const map: Rule[][] = new Array(mapRowLength * mapRowLength); // This array is used only during construction of the rulesbucket in the map const rulesBucketConstructionStateList = new Array(map.length); for (const rule of rules) { @@ -81,13 +84,13 @@ function buildMap(rules: readonly ts.formatting.RuleSpec[]): readonly (readonly } function getRuleBucketIndex(row: number, column: number): number { - ts.Debug.assert(row <= ts.SyntaxKind.LastKeyword && column <= ts.SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); + Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); return (row * mapRowLength) + column; } const maskBitSize = 5; const mask = 0b11111; // MaskBitSize bits -const mapRowLength = ts.SyntaxKind.LastToken + 1; +const mapRowLength = SyntaxKind.LastToken + 1; enum RulesPosition { StopRulesSpecific = 0, @@ -113,10 +116,10 @@ enum RulesPosition { // Example: // In order to insert a rule to the end of sub-bucket (3), we get the index by adding // the values in the bitmap segments 3rd, 2nd, and 1st. -function addRule(rules: ts.formatting.Rule[], rule: ts.formatting.Rule, specificTokens: boolean, constructionState: number[], rulesBucketIndex: number): void { - const position = rule.action & ts.formatting.RuleAction.StopAction ? +function addRule(rules: Rule[], rule: Rule, specificTokens: boolean, constructionState: number[], rulesBucketIndex: number): void { + const position = rule.action & RuleAction.StopAction ? specificTokens ? RulesPosition.StopRulesSpecific : RulesPosition.StopRulesAny : - rule.context !== ts.formatting.anyContext ? + rule.context !== anyContext ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny : specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny; @@ -136,6 +139,6 @@ function getInsertionIndex(indexBitmap: number, maskPosition: RulesPosition) { function increaseInsertionIndex(indexBitmap: number, maskPosition: RulesPosition): number { const value = ((indexBitmap >> maskPosition) & mask) + 1; - ts.Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); + Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules."); return (indexBitmap & ~(mask << maskPosition)) | (value << maskPosition); } diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 9d43456f199ff..bc522163651de 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -1,4 +1,16 @@ -import * as ts from "../_namespaces/ts"; +import { + ArrayBindingPattern, ArrayLiteralExpression, CallExpression, CharacterCodes, ClassDeclaration, ClassExpression, + CommentRange, contains, Debug, EditorSettings, find, findChildOfKind, findListItemInfo, findNextToken, + findPrecedingToken, FormatCodeSettings, GetAccessorDeclaration, getLineAndCharacterOfPosition, + getLineStartPositionForPosition, getStartPositionOfLine, getTokenAtPosition, IfStatement, ImportClause, IndentStyle, + InterfaceDeclaration, isCallExpression, isCallOrNewExpression, isConditionalExpression, isDeclaration, + isStatementButNotDeclaration, isStringOrRegularExpressionOrTemplateLiteral, isWhiteSpaceLike, + isWhiteSpaceSingleLine, JSDocTemplateTag, LineAndCharacter, NamedImportsOrExports, Node, NodeArray, + ObjectBindingPattern, ObjectLiteralExpression, positionBelongsToNode, rangeContainsRange, rangeContainsStartEnd, + SignatureDeclaration, skipTrivia, SourceFile, SourceFileLike, SyntaxKind, TextRange, TypeAliasDeclaration, + TypeLiteralNode, TypeReferenceNode, VariableDeclarationList, +} from "../_namespaces/ts"; +import { getRangeOfEnclosingComment, TextRangeWithKind } from "../_namespaces/ts.formatting"; /** @internal */ export namespace SmartIndenter { @@ -22,22 +34,22 @@ export namespace SmartIndenter { * When inserting some text after an open brace, we would like to get indentation as if a newline was already there. * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior. */ - export function getIndentation(position: number, sourceFile: ts.SourceFile, options: ts.EditorSettings, assumeNewLineBeforeCloseBrace = false): number { + export function getIndentation(position: number, sourceFile: SourceFile, options: EditorSettings, assumeNewLineBeforeCloseBrace = false): number { if (position > sourceFile.text.length) { return getBaseIndentation(options); // past EOF } // no indentation when the indent style is set to none, // so we can return fast - if (options.indentStyle === ts.IndentStyle.None) { + if (options.indentStyle === IndentStyle.None) { return 0; } - const precedingToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined, /*excludeJsdoc*/ true); + const precedingToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined, /*excludeJsdoc*/ true); // eslint-disable-next-line no-null/no-null - const enclosingCommentRange = ts.formatting.getRangeOfEnclosingComment(sourceFile, position, precedingToken || null); - if (enclosingCommentRange && enclosingCommentRange.kind === ts.SyntaxKind.MultiLineCommentTrivia) { + const enclosingCommentRange = getRangeOfEnclosingComment(sourceFile, position, precedingToken || null); + if (enclosingCommentRange && enclosingCommentRange.kind === SyntaxKind.MultiLineCommentTrivia) { return getCommentIndent(sourceFile, position, options, enclosingCommentRange); } @@ -46,7 +58,7 @@ export namespace SmartIndenter { } // no indentation in string \regex\template literals - const precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); + const precedingTokenIsLiteral = isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind); if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) { return 0; } @@ -56,7 +68,7 @@ export namespace SmartIndenter { // indentation is first non-whitespace character in a previous line // for block indentation, we should look for a line which contains something that's not // whitespace. - const currentToken = ts.getTokenAtPosition(sourceFile, position); + const currentToken = getTokenAtPosition(sourceFile, position); // For object literals, we want indentation to work just like with blocks. // If the `{` starts in any position (even in the middle of a line), then // the following indentation should treat `{` as the start of that line (including leading whitespace). @@ -77,12 +89,12 @@ export namespace SmartIndenter { // y: undefined, // } // ``` - const isObjectLiteral = currentToken.kind === ts.SyntaxKind.OpenBraceToken && currentToken.parent.kind === ts.SyntaxKind.ObjectLiteralExpression; - if (options.indentStyle === ts.IndentStyle.Block || isObjectLiteral) { + const isObjectLiteral = currentToken.kind === SyntaxKind.OpenBraceToken && currentToken.parent.kind === SyntaxKind.ObjectLiteralExpression; + if (options.indentStyle === IndentStyle.Block || isObjectLiteral) { return getBlockIndent(sourceFile, position, options); } - if (precedingToken.kind === ts.SyntaxKind.CommaToken && precedingToken.parent.kind !== ts.SyntaxKind.BinaryExpression) { + if (precedingToken.kind === SyntaxKind.CommaToken && precedingToken.parent.kind !== SyntaxKind.BinaryExpression) { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it const actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options); if (actualIndentation !== Value.Unknown) { @@ -92,8 +104,8 @@ export namespace SmartIndenter { const containerList = getListByPosition(position, precedingToken.parent, sourceFile); // use list position if the preceding token is before any list items - if (containerList && !ts.rangeContainsRange(containerList, precedingToken)) { - const useTheSameBaseIndentation = [ts.SyntaxKind.FunctionExpression, ts.SyntaxKind.ArrowFunction].indexOf(currentToken.parent.kind) !== -1; + if (containerList && !rangeContainsRange(containerList, precedingToken)) { + const useTheSameBaseIndentation = [SyntaxKind.FunctionExpression, SyntaxKind.ArrowFunction].indexOf(currentToken.parent.kind) !== -1; const indentSize = useTheSameBaseIndentation ? 0 : options.indentSize!; return getActualIndentationForListStartLine(containerList, sourceFile, options) + indentSize; // TODO: GH#18217 } @@ -101,17 +113,17 @@ export namespace SmartIndenter { return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options); } - function getCommentIndent(sourceFile: ts.SourceFile, position: number, options: ts.EditorSettings, enclosingCommentRange: ts.CommentRange): number { - const previousLine = ts.getLineAndCharacterOfPosition(sourceFile, position).line - 1; - const commentStartLine = ts.getLineAndCharacterOfPosition(sourceFile, enclosingCommentRange.pos).line; + function getCommentIndent(sourceFile: SourceFile, position: number, options: EditorSettings, enclosingCommentRange: CommentRange): number { + const previousLine = getLineAndCharacterOfPosition(sourceFile, position).line - 1; + const commentStartLine = getLineAndCharacterOfPosition(sourceFile, enclosingCommentRange.pos).line; - ts.Debug.assert(commentStartLine >= 0); + Debug.assert(commentStartLine >= 0); if (previousLine <= commentStartLine) { - return findFirstNonWhitespaceColumn(ts.getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options); + return findFirstNonWhitespaceColumn(getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options); } - const startPositionOfLine = ts.getStartPositionOfLine(previousLine, sourceFile); + const startPositionOfLine = getStartPositionOfLine(previousLine, sourceFile); const { column, character } = findFirstNonWhitespaceCharacterAndColumn(startPositionOfLine, position, sourceFile, options); if (column === 0) { @@ -119,33 +131,33 @@ export namespace SmartIndenter { } const firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPositionOfLine + character); - return firstNonWhitespaceCharacterCode === ts.CharacterCodes.asterisk ? column - 1 : column; + return firstNonWhitespaceCharacterCode === CharacterCodes.asterisk ? column - 1 : column; } - function getBlockIndent(sourceFile: ts.SourceFile, position: number, options: ts.EditorSettings): number { + function getBlockIndent(sourceFile: SourceFile, position: number, options: EditorSettings): number { // move backwards until we find a line with a non-whitespace character, // then find the first non-whitespace character for that line. let current = position; while (current > 0) { const char = sourceFile.text.charCodeAt(current); - if (!ts.isWhiteSpaceLike(char)) { + if (!isWhiteSpaceLike(char)) { break; } current--; } - const lineStart = ts.getLineStartPositionForPosition(current, sourceFile); + const lineStart = getLineStartPositionForPosition(current, sourceFile); return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options); } - function getSmartIndent(sourceFile: ts.SourceFile, position: number, precedingToken: ts.Node, lineAtPosition: number, assumeNewLineBeforeCloseBrace: boolean, options: ts.EditorSettings): number { + function getSmartIndent(sourceFile: SourceFile, position: number, precedingToken: Node, lineAtPosition: number, assumeNewLineBeforeCloseBrace: boolean, options: EditorSettings): number { // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken' // if such node is found - compute initial indentation for 'position' inside this node - let previous: ts.Node | undefined; + let previous: Node | undefined; let current = precedingToken; while (current) { - if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { + if (positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(options, current, previous, sourceFile, /*isNextChild*/ true)) { const currentStart = getStartLineAndCharacterForNode(current, sourceFile); const nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile); const indentationDelta = nextTokenKind !== NextTokenKind.Unknown @@ -171,23 +183,23 @@ export namespace SmartIndenter { return getBaseIndentation(options); } - export function getIndentationForNode(n: ts.Node, ignoreActualIndentationRange: ts.TextRange, sourceFile: ts.SourceFile, options: ts.EditorSettings): number { + export function getIndentationForNode(n: Node, ignoreActualIndentationRange: TextRange, sourceFile: SourceFile, options: EditorSettings): number { const start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options); } - export function getBaseIndentation(options: ts.EditorSettings) { + export function getBaseIndentation(options: EditorSettings) { return options.baseIndentSize || 0; } function getIndentationForNodeWorker( - current: ts.Node, - currentStart: ts.LineAndCharacter, - ignoreActualIndentationRange: ts.TextRange | undefined, + current: Node, + currentStart: LineAndCharacter, + ignoreActualIndentationRange: TextRange | undefined, indentationDelta: number, - sourceFile: ts.SourceFile, + sourceFile: SourceFile, isNextChild: boolean, - options: ts.EditorSettings): number { + options: EditorSettings): number { let parent = current.parent; // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if @@ -262,7 +274,7 @@ export namespace SmartIndenter { return indentationDelta + getBaseIndentation(options); } - function getContainingListOrParentStart(parent: ts.Node, child: ts.Node, sourceFile: ts.SourceFile): ts.LineAndCharacter { + function getContainingListOrParentStart(parent: Node, child: Node, sourceFile: SourceFile): LineAndCharacter { const containingList = getContainingList(child, sourceFile); const startPos = containingList ? containingList.pos : parent.getStart(sourceFile); return sourceFile.getLineAndCharacterOfPosition(startPos); @@ -271,9 +283,9 @@ export namespace SmartIndenter { /* * Function returns Value.Unknown if indentation cannot be determined */ - function getActualIndentationForListItemBeforeComma(commaToken: ts.Node, sourceFile: ts.SourceFile, options: ts.EditorSettings): number { + function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: EditorSettings): number { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - const commaItemInfo = ts.findListItemInfo(commaToken); + const commaItemInfo = findListItemInfo(commaToken); if (commaItemInfo && commaItemInfo.listItemIndex > 0) { return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } @@ -286,19 +298,19 @@ export namespace SmartIndenter { /* * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression) */ - function getActualIndentationForNode(current: ts.Node, - parent: ts.Node, - currentLineAndChar: ts.LineAndCharacter, + function getActualIndentationForNode(current: Node, + parent: Node, + currentLineAndChar: LineAndCharacter, parentAndChildShareLine: boolean, - sourceFile: ts.SourceFile, - options: ts.EditorSettings): number { + sourceFile: SourceFile, + options: EditorSettings): number { // actual indentation is used for statements\declarations if one of cases below is true: // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually // - parent and child are not on the same line const useActualIndentation = - (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) && - (parent.kind === ts.SyntaxKind.SourceFile || !parentAndChildShareLine); + (isDeclaration(current) || isStatementButNotDeclaration(current)) && + (parent.kind === SyntaxKind.SourceFile || !parentAndChildShareLine); if (!useActualIndentation) { return Value.Unknown; @@ -313,17 +325,17 @@ export namespace SmartIndenter { CloseBrace } - function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: ts.Node, current: ts.Node, lineAtPosition: number, sourceFile: ts.SourceFile): NextTokenKind { - const nextToken = ts.findNextToken(precedingToken, current, sourceFile); + function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): NextTokenKind { + const nextToken = findNextToken(precedingToken, current, sourceFile); if (!nextToken) { return NextTokenKind.Unknown; } - if (nextToken.kind === ts.SyntaxKind.OpenBraceToken) { + if (nextToken.kind === SyntaxKind.OpenBraceToken) { // open braces are always indented at the parent level return NextTokenKind.OpenBrace; } - else if (nextToken.kind === ts.SyntaxKind.CloseBraceToken) { + else if (nextToken.kind === SyntaxKind.CloseBraceToken) { // close braces are indented at the parent level if they are located on the same line with cursor // this means that if new line will be added at $ position, this case will be indented // class A { @@ -340,24 +352,24 @@ export namespace SmartIndenter { return NextTokenKind.Unknown; } - function getStartLineAndCharacterForNode(n: ts.Node, sourceFile: ts.SourceFileLike): ts.LineAndCharacter { + function getStartLineAndCharacterForNode(n: Node, sourceFile: SourceFileLike): LineAndCharacter { return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)); } - export function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent: ts.Node, child: ts.Node, childStartLine: number, sourceFile: ts.SourceFileLike): boolean { - if (!(ts.isCallExpression(parent) && ts.contains(parent.arguments, child))) { + export function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent: Node, child: Node, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (!(isCallExpression(parent) && contains(parent.arguments, child))) { return false; } const expressionOfCallExpressionEnd = parent.expression.getEnd(); - const expressionOfCallExpressionEndLine = ts.getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; + const expressionOfCallExpressionEndLine = getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line; return expressionOfCallExpressionEndLine === childStartLine; } - export function childStartsOnTheSameLineWithElseInIfStatement(parent: ts.Node, child: ts.formatting.TextRangeWithKind, childStartLine: number, sourceFile: ts.SourceFileLike): boolean { - if (parent.kind === ts.SyntaxKind.IfStatement && (parent as ts.IfStatement).elseStatement === child) { - const elseKeyword = ts.findChildOfKind(parent, ts.SyntaxKind.ElseKeyword, sourceFile)!; - ts.Debug.assert(elseKeyword !== undefined); + export function childStartsOnTheSameLineWithElseInIfStatement(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (parent.kind === SyntaxKind.IfStatement && (parent as IfStatement).elseStatement === child) { + const elseKeyword = findChildOfKind(parent, SyntaxKind.ElseKeyword, sourceFile)!; + Debug.assert(elseKeyword !== undefined); const elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line; return elseKeywordStartLine === childStartLine; @@ -387,9 +399,9 @@ export namespace SmartIndenter { // whenTrue and whenFalse children to avoid double-indenting their contents. To identify this scenario, // we check for the whenTrue branch beginning on the line that the condition ends, and the whenFalse // branch beginning on the line that the whenTrue branch ends. - export function childIsUnindentedBranchOfConditionalExpression(parent: ts.Node, child: ts.formatting.TextRangeWithKind, childStartLine: number, sourceFile: ts.SourceFileLike): boolean { - if (ts.isConditionalExpression(parent) && (child === parent.whenTrue || child === parent.whenFalse)) { - const conditionEndLine = ts.getLineAndCharacterOfPosition(sourceFile, parent.condition.end).line; + export function childIsUnindentedBranchOfConditionalExpression(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (isConditionalExpression(parent) && (child === parent.whenTrue || child === parent.whenFalse)) { + const conditionEndLine = getLineAndCharacterOfPosition(sourceFile, parent.condition.end).line; if (child === parent.whenTrue) { return childStartLine === conditionEndLine; } @@ -402,24 +414,24 @@ export namespace SmartIndenter { // 0 L2: indented two stops, one because whenTrue was indented // ); and one because of the parentheses spanning multiple lines const trueStartLine = getStartLineAndCharacterForNode(parent.whenTrue, sourceFile).line; - const trueEndLine = ts.getLineAndCharacterOfPosition(sourceFile, parent.whenTrue.end).line; + const trueEndLine = getLineAndCharacterOfPosition(sourceFile, parent.whenTrue.end).line; return conditionEndLine === trueStartLine && trueEndLine === childStartLine; } } return false; } - export function argumentStartsOnSameLineAsPreviousArgument(parent: ts.Node, child: ts.formatting.TextRangeWithKind, childStartLine: number, sourceFile: ts.SourceFileLike): boolean { - if (ts.isCallOrNewExpression(parent)) { + export function argumentStartsOnSameLineAsPreviousArgument(parent: Node, child: TextRangeWithKind, childStartLine: number, sourceFile: SourceFileLike): boolean { + if (isCallOrNewExpression(parent)) { if (!parent.arguments) return false; - const currentNode = ts.find(parent.arguments, arg => arg.pos === child.pos); + const currentNode = find(parent.arguments, arg => arg.pos === child.pos); // If it's not one of the arguments, don't look past this if (!currentNode) return false; const currentIndex = parent.arguments.indexOf(currentNode); if (currentIndex === 0) return false; // Can't look at previous node if first const previousNode = parent.arguments[currentIndex - 1]; - const lineOfPreviousNode = ts.getLineAndCharacterOfPosition(sourceFile, previousNode.getEnd()).line; + const lineOfPreviousNode = getLineAndCharacterOfPosition(sourceFile, previousNode.getEnd()).line; if (childStartLine === lineOfPreviousNode) { return true; @@ -429,61 +441,61 @@ export namespace SmartIndenter { return false; } - export function getContainingList(node: ts.Node, sourceFile: ts.SourceFile): ts.NodeArray | undefined { + export function getContainingList(node: Node, sourceFile: SourceFile): NodeArray | undefined { return node.parent && getListByRange(node.getStart(sourceFile), node.getEnd(), node.parent, sourceFile); } - function getListByPosition(pos: number, node: ts.Node, sourceFile: ts.SourceFile): ts.NodeArray | undefined { + function getListByPosition(pos: number, node: Node, sourceFile: SourceFile): NodeArray | undefined { return node && getListByRange(pos, pos, node, sourceFile); } - function getListByRange(start: number, end: number, node: ts.Node, sourceFile: ts.SourceFile): ts.NodeArray | undefined { + function getListByRange(start: number, end: number, node: Node, sourceFile: SourceFile): NodeArray | undefined { switch (node.kind) { - case ts.SyntaxKind.TypeReference: - return getList((node as ts.TypeReferenceNode).typeArguments); - case ts.SyntaxKind.ObjectLiteralExpression: - return getList((node as ts.ObjectLiteralExpression).properties); - case ts.SyntaxKind.ArrayLiteralExpression: - return getList((node as ts.ArrayLiteralExpression).elements); - case ts.SyntaxKind.TypeLiteral: - return getList((node as ts.TypeLiteralNode).members); - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ConstructSignature: - return getList((node as ts.SignatureDeclaration).typeParameters) || getList((node as ts.SignatureDeclaration).parameters); - case ts.SyntaxKind.GetAccessor: - return getList((node as ts.GetAccessorDeclaration).parameters); - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.JSDocTemplateTag: - return getList((node as ts.ClassDeclaration | ts.ClassExpression | ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.JSDocTemplateTag).typeParameters); - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.CallExpression: - return getList((node as ts.CallExpression).typeArguments) || getList((node as ts.CallExpression).arguments); - case ts.SyntaxKind.VariableDeclarationList: - return getList((node as ts.VariableDeclarationList).declarations); - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.NamedExports: - return getList((node as ts.NamedImportsOrExports).elements); - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.ArrayBindingPattern: - return getList((node as ts.ObjectBindingPattern | ts.ArrayBindingPattern).elements); - } - - function getList(list: ts.NodeArray | undefined): ts.NodeArray | undefined { - return list && ts.rangeContainsStartEnd(getVisualListRange(node, list, sourceFile), start, end) ? list : undefined; - } - } - - function getVisualListRange(node: ts.Node, list: ts.TextRange, sourceFile: ts.SourceFile): ts.TextRange { + case SyntaxKind.TypeReference: + return getList((node as TypeReferenceNode).typeArguments); + case SyntaxKind.ObjectLiteralExpression: + return getList((node as ObjectLiteralExpression).properties); + case SyntaxKind.ArrayLiteralExpression: + return getList((node as ArrayLiteralExpression).elements); + case SyntaxKind.TypeLiteral: + return getList((node as TypeLiteralNode).members); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + return getList((node as SignatureDeclaration).typeParameters) || getList((node as SignatureDeclaration).parameters); + case SyntaxKind.GetAccessor: + return getList((node as GetAccessorDeclaration).parameters); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.JSDocTemplateTag: + return getList((node as ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration | JSDocTemplateTag).typeParameters); + case SyntaxKind.NewExpression: + case SyntaxKind.CallExpression: + return getList((node as CallExpression).typeArguments) || getList((node as CallExpression).arguments); + case SyntaxKind.VariableDeclarationList: + return getList((node as VariableDeclarationList).declarations); + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + return getList((node as NamedImportsOrExports).elements); + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + return getList((node as ObjectBindingPattern | ArrayBindingPattern).elements); + } + + function getList(list: NodeArray | undefined): NodeArray | undefined { + return list && rangeContainsStartEnd(getVisualListRange(node, list, sourceFile), start, end) ? list : undefined; + } + } + + function getVisualListRange(node: Node, list: TextRange, sourceFile: SourceFile): TextRange { const children = node.getChildren(sourceFile); for (let i = 1; i < children.length - 1; i++) { if (children[i].pos === list.pos && children[i].end === list.end) { @@ -493,15 +505,15 @@ export namespace SmartIndenter { return list; } - function getActualIndentationForListStartLine(list: ts.NodeArray, sourceFile: ts.SourceFile, options: ts.EditorSettings): number { + function getActualIndentationForListStartLine(list: NodeArray, sourceFile: SourceFile, options: EditorSettings): number { if (!list) { return Value.Unknown; } return findColumnForFirstNonWhitespaceCharacterInLine(sourceFile.getLineAndCharacterOfPosition(list.pos), sourceFile, options); } - function getActualIndentationForListItem(node: ts.Node, sourceFile: ts.SourceFile, options: ts.EditorSettings, listIndentsChild: boolean): number { - if (node.parent && node.parent.kind === ts.SyntaxKind.VariableDeclarationList) { + function getActualIndentationForListItem(node: Node, sourceFile: SourceFile, options: EditorSettings, listIndentsChild: boolean): number { + if (node.parent && node.parent.kind === SyntaxKind.VariableDeclarationList) { // VariableDeclarationList has no wrapping tokens return Value.Unknown; } @@ -519,15 +531,15 @@ export namespace SmartIndenter { return Value.Unknown; } - function deriveActualIndentationFromList(list: readonly ts.Node[], index: number, sourceFile: ts.SourceFile, options: ts.EditorSettings): number { - ts.Debug.assert(index >= 0 && index < list.length); + function deriveActualIndentationFromList(list: readonly Node[], index: number, sourceFile: SourceFile, options: EditorSettings): number { + Debug.assert(index >= 0 && index < list.length); const node = list[index]; // walk toward the start of the list starting from current node and check if the line is the same for all items. // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i] let lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile); for (let i = index - 1; i >= 0; i--) { - if (list[i].kind === ts.SyntaxKind.CommaToken) { + if (list[i].kind === SyntaxKind.CommaToken) { continue; } // skip list items that ends on the same line with the current list element @@ -541,7 +553,7 @@ export namespace SmartIndenter { return Value.Unknown; } - function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: ts.LineAndCharacter, sourceFile: ts.SourceFile, options: ts.EditorSettings): number { + function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter: LineAndCharacter, sourceFile: SourceFile, options: EditorSettings): number { const lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0); return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options); } @@ -553,16 +565,16 @@ export namespace SmartIndenter { * value of 'character' for '$' is 3 * value of 'column' for '$' is 6 (assuming that tab size is 4) */ - export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: ts.SourceFileLike, options: ts.EditorSettings) { + export function findFirstNonWhitespaceCharacterAndColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings) { let character = 0; let column = 0; for (let pos = startPos; pos < endPos; pos++) { const ch = sourceFile.text.charCodeAt(pos); - if (!ts.isWhiteSpaceSingleLine(ch)) { + if (!isWhiteSpaceSingleLine(ch)) { break; } - if (ch === ts.CharacterCodes.tab) { + if (ch === CharacterCodes.tab) { column += options.tabSize! + (column % options.tabSize!); } else { @@ -574,104 +586,104 @@ export namespace SmartIndenter { return { column, character }; } - export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: ts.SourceFileLike, options: ts.EditorSettings): number { + export function findFirstNonWhitespaceColumn(startPos: number, endPos: number, sourceFile: SourceFileLike, options: EditorSettings): number { return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column; } - export function nodeWillIndentChild(settings: ts.FormatCodeSettings, parent: ts.formatting.TextRangeWithKind, child: ts.formatting.TextRangeWithKind | undefined, sourceFile: ts.SourceFileLike | undefined, indentByDefault: boolean): boolean { - const childKind = child ? child.kind : ts.SyntaxKind.Unknown; + export function nodeWillIndentChild(settings: FormatCodeSettings, parent: TextRangeWithKind, child: TextRangeWithKind | undefined, sourceFile: SourceFileLike | undefined, indentByDefault: boolean): boolean { + const childKind = child ? child.kind : SyntaxKind.Unknown; switch (parent.kind) { - case ts.SyntaxKind.ExpressionStatement: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ArrayLiteralExpression: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.MappedType: - case ts.SyntaxKind.TupleType: - case ts.SyntaxKind.CaseBlock: - case ts.SyntaxKind.DefaultClause: - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.ReturnStatement: - case ts.SyntaxKind.ConditionalExpression: - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.JsxOpeningElement: - case ts.SyntaxKind.JsxOpeningFragment: - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxExpression: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ParenthesizedType: - case ts.SyntaxKind.TaggedTemplateExpression: - case ts.SyntaxKind.AwaitExpression: - case ts.SyntaxKind.NamedExports: - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.PropertyDeclaration: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TypeLiteral: + case SyntaxKind.MappedType: + case SyntaxKind.TupleType: + case SyntaxKind.CaseBlock: + case SyntaxKind.DefaultClause: + case SyntaxKind.CaseClause: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.VariableStatement: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ReturnStatement: + case SyntaxKind.ConditionalExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.JsxOpeningElement: + case SyntaxKind.JsxOpeningFragment: + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxExpression: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.Parameter: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.ParenthesizedType: + case SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.NamedExports: + case SyntaxKind.NamedImports: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.PropertyDeclaration: return true; - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.BinaryExpression: - if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === ts.SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217 + case SyntaxKind.VariableDeclaration: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.BinaryExpression: + if (!settings.indentMultiLineObjectLiteralBeginningOnBlankLine && sourceFile && childKind === SyntaxKind.ObjectLiteralExpression) { // TODO: GH#18217 return rangeIsOnOneLine(sourceFile, child!); } - if (parent.kind === ts.SyntaxKind.BinaryExpression && sourceFile && child && childKind === ts.SyntaxKind.JsxElement) { - const parentStartLine = sourceFile.getLineAndCharacterOfPosition(ts.skipTrivia(sourceFile.text, parent.pos)).line; - const childStartLine = sourceFile.getLineAndCharacterOfPosition(ts.skipTrivia(sourceFile.text, child.pos)).line; + if (parent.kind === SyntaxKind.BinaryExpression && sourceFile && child && childKind === SyntaxKind.JsxElement) { + const parentStartLine = sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, parent.pos)).line; + const childStartLine = sourceFile.getLineAndCharacterOfPosition(skipTrivia(sourceFile.text, child.pos)).line; return parentStartLine !== childStartLine; } - if (parent.kind !== ts.SyntaxKind.BinaryExpression) { + if (parent.kind !== SyntaxKind.BinaryExpression) { return true; } break; - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return childKind !== ts.SyntaxKind.Block; - case ts.SyntaxKind.ArrowFunction: - if (sourceFile && childKind === ts.SyntaxKind.ParenthesizedExpression) { + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return childKind !== SyntaxKind.Block; + case SyntaxKind.ArrowFunction: + if (sourceFile && childKind === SyntaxKind.ParenthesizedExpression) { return rangeIsOnOneLine(sourceFile, child!); } - return childKind !== ts.SyntaxKind.Block; - case ts.SyntaxKind.ExportDeclaration: - return childKind !== ts.SyntaxKind.NamedExports; - case ts.SyntaxKind.ImportDeclaration: - return childKind !== ts.SyntaxKind.ImportClause || - (!!(child as ts.ImportClause).namedBindings && (child as ts.ImportClause).namedBindings!.kind !== ts.SyntaxKind.NamedImports); - case ts.SyntaxKind.JsxElement: - return childKind !== ts.SyntaxKind.JsxClosingElement; - case ts.SyntaxKind.JsxFragment: - return childKind !== ts.SyntaxKind.JsxClosingFragment; - case ts.SyntaxKind.IntersectionType: - case ts.SyntaxKind.UnionType: - if (childKind === ts.SyntaxKind.TypeLiteral || childKind === ts.SyntaxKind.TupleType) { + return childKind !== SyntaxKind.Block; + case SyntaxKind.ExportDeclaration: + return childKind !== SyntaxKind.NamedExports; + case SyntaxKind.ImportDeclaration: + return childKind !== SyntaxKind.ImportClause || + (!!(child as ImportClause).namedBindings && (child as ImportClause).namedBindings!.kind !== SyntaxKind.NamedImports); + case SyntaxKind.JsxElement: + return childKind !== SyntaxKind.JsxClosingElement; + case SyntaxKind.JsxFragment: + return childKind !== SyntaxKind.JsxClosingFragment; + case SyntaxKind.IntersectionType: + case SyntaxKind.UnionType: + if (childKind === SyntaxKind.TypeLiteral || childKind === SyntaxKind.TupleType) { return false; } break; @@ -680,13 +692,13 @@ export namespace SmartIndenter { return indentByDefault; } - function isControlFlowEndingStatement(kind: ts.SyntaxKind, parent: ts.formatting.TextRangeWithKind): boolean { + function isControlFlowEndingStatement(kind: SyntaxKind, parent: TextRangeWithKind): boolean { switch (kind) { - case ts.SyntaxKind.ReturnStatement: - case ts.SyntaxKind.ThrowStatement: - case ts.SyntaxKind.ContinueStatement: - case ts.SyntaxKind.BreakStatement: - return parent.kind !== ts.SyntaxKind.Block; + case SyntaxKind.ReturnStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + return parent.kind !== SyntaxKind.Block; default: return false; } @@ -696,13 +708,13 @@ export namespace SmartIndenter { * True when the parent node should indent the given child by an explicit rule. * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child. */ - export function shouldIndentChildNode(settings: ts.FormatCodeSettings, parent: ts.formatting.TextRangeWithKind, child?: ts.Node, sourceFile?: ts.SourceFileLike, isNextChild = false): boolean { + export function shouldIndentChildNode(settings: FormatCodeSettings, parent: TextRangeWithKind, child?: Node, sourceFile?: SourceFileLike, isNextChild = false): boolean { return nodeWillIndentChild(settings, parent, child, sourceFile, /*indentByDefault*/ false) && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent)); } - function rangeIsOnOneLine(sourceFile: ts.SourceFileLike, range: ts.formatting.TextRangeWithKind) { - const rangeStart = ts.skipTrivia(sourceFile.text, range.pos); + function rangeIsOnOneLine(sourceFile: SourceFileLike, range: TextRangeWithKind) { + const rangeStart = skipTrivia(sourceFile.text, range.pos); const startLine = sourceFile.getLineAndCharacterOfPosition(rangeStart).line; const endLine = sourceFile.getLineAndCharacterOfPosition(range.end).line; return startLine === endLine; diff --git a/src/services/getEditsForFileRename.ts b/src/services/getEditsForFileRename.ts index 961d77aad62d0..bdd1ac357d6f9 100644 --- a/src/services/getEditsForFileRename.ts +++ b/src/services/getEditsForFileRename.ts @@ -1,20 +1,30 @@ -import * as ts from "./_namespaces/ts"; +import { + combinePaths, createGetCanonicalFileName, createModuleSpecifierResolutionHost, createRange, Debug, emptyArray, + endsWith, ensurePathIsNonModuleName, Expression, factory, FileTextChanges, find, forEach, formatting, + GetCanonicalFileName, getDirectoryPath, getFileMatcherPatterns, getModeForUsageLocation, getOptionFromName, + getRegexFromPattern, getRelativePathFromDirectory, getRelativePathFromFile, getTsConfigObjectLiteralExpression, + hostUsesCaseSensitiveFileNames, isAmbientModule, isArrayLiteralExpression, isObjectLiteralExpression, + isPropertyAssignment, isSourceFile, isStringLiteral, LanguageServiceHost, last, mapDefined, ModuleResolutionHost, + moduleSpecifiers, normalizePath, Path, pathIsRelative, Program, PropertyAssignment, + ResolvedModuleWithFailedLookupLocations, resolveModuleName, SourceFile, SourceFileLike, SourceMapper, + StringLiteralLike, Symbol, textChanges, TextRange, tryRemoveDirectoryPrefix, UserPreferences, +} from "./_namespaces/ts"; /** @internal */ export function getEditsForFileRename( - program: ts.Program, + program: Program, oldFileOrDirPath: string, newFileOrDirPath: string, - host: ts.LanguageServiceHost, - formatContext: ts.formatting.FormatContext, - preferences: ts.UserPreferences, - sourceMapper: ts.SourceMapper, -): readonly ts.FileTextChanges[] { - const useCaseSensitiveFileNames = ts.hostUsesCaseSensitiveFileNames(host); - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + host: LanguageServiceHost, + formatContext: formatting.FormatContext, + preferences: UserPreferences, + sourceMapper: SourceMapper, +): readonly FileTextChanges[] { + const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); const oldToNew = getPathUpdater(oldFileOrDirPath, newFileOrDirPath, getCanonicalFileName, sourceMapper); const newToOld = getPathUpdater(newFileOrDirPath, oldFileOrDirPath, getCanonicalFileName, sourceMapper); - return ts.textChanges.ChangeTracker.with({ host, formatContext, preferences }, changeTracker => { + return textChanges.ChangeTracker.with({ host, formatContext, preferences }, changeTracker => { updateTsconfigFiles(program, changeTracker, oldToNew, oldFileOrDirPath, newFileOrDirPath, host.getCurrentDirectory(), useCaseSensitiveFileNames); updateImports(program, changeTracker, oldToNew, newToOld, host, getCanonicalFileName); }); @@ -24,7 +34,7 @@ export function getEditsForFileRename( type PathUpdater = (path: string) => string | undefined; // exported for tests /** @internal */ -export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: string, getCanonicalFileName: ts.GetCanonicalFileName, sourceMapper: ts.SourceMapper | undefined): PathUpdater { +export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: string, getCanonicalFileName: GetCanonicalFileName, sourceMapper: SourceMapper | undefined): PathUpdater { const canonicalOldPath = getCanonicalFileName(oldFileOrDirPath); return path => { const originalPath = sourceMapper && sourceMapper.tryGetSourcePosition({ fileName: path, pos: 0 }); @@ -36,23 +46,23 @@ export function getPathUpdater(oldFileOrDirPath: string, newFileOrDirPath: strin function getUpdatedPath(pathToUpdate: string): string | undefined { if (getCanonicalFileName(pathToUpdate) === canonicalOldPath) return newFileOrDirPath; - const suffix = ts.tryRemoveDirectoryPrefix(pathToUpdate, canonicalOldPath, getCanonicalFileName); + const suffix = tryRemoveDirectoryPrefix(pathToUpdate, canonicalOldPath, getCanonicalFileName); return suffix === undefined ? undefined : newFileOrDirPath + "/" + suffix; } } // Relative path from a0 to b0 should be same as relative path from a1 to b1. Returns b1. -function makeCorrespondingRelativeChange(a0: string, b0: string, a1: string, getCanonicalFileName: ts.GetCanonicalFileName): string { - const rel = ts.getRelativePathFromFile(a0, b0, getCanonicalFileName); - return combinePathsSafe(ts.getDirectoryPath(a1), rel); +function makeCorrespondingRelativeChange(a0: string, b0: string, a1: string, getCanonicalFileName: GetCanonicalFileName): string { + const rel = getRelativePathFromFile(a0, b0, getCanonicalFileName); + return combinePathsSafe(getDirectoryPath(a1), rel); } -function updateTsconfigFiles(program: ts.Program, changeTracker: ts.textChanges.ChangeTracker, oldToNew: PathUpdater, oldFileOrDirPath: string, newFileOrDirPath: string, currentDirectory: string, useCaseSensitiveFileNames: boolean): void { +function updateTsconfigFiles(program: Program, changeTracker: textChanges.ChangeTracker, oldToNew: PathUpdater, oldFileOrDirPath: string, newFileOrDirPath: string, currentDirectory: string, useCaseSensitiveFileNames: boolean): void { const { configFile } = program.getCompilerOptions(); if (!configFile) return; - const configDir = ts.getDirectoryPath(configFile.fileName); + const configDir = getDirectoryPath(configFile.fileName); - const jsonObjectLiteral = ts.getTsConfigObjectLiteralExpression(configFile); + const jsonObjectLiteral = getTsConfigObjectLiteralExpression(configFile); if (!jsonObjectLiteral) return; forEachProperty(jsonObjectLiteral, (property, propertyName) => { @@ -61,26 +71,26 @@ function updateTsconfigFiles(program: ts.Program, changeTracker: ts.textChanges. case "include": case "exclude": { const foundExactMatch = updatePaths(property); - if (foundExactMatch || propertyName !== "include" || !ts.isArrayLiteralExpression(property.initializer)) return; - const includes = ts.mapDefined(property.initializer.elements, e => ts.isStringLiteral(e) ? e.text : undefined); + if (foundExactMatch || propertyName !== "include" || !isArrayLiteralExpression(property.initializer)) return; + const includes = mapDefined(property.initializer.elements, e => isStringLiteral(e) ? e.text : undefined); if (includes.length === 0) return; - const matchers = ts.getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory); + const matchers = getFileMatcherPatterns(configDir, /*excludes*/ [], includes, useCaseSensitiveFileNames, currentDirectory); // If there isn't some include for this, add a new one. - if (ts.getRegexFromPattern(ts.Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) && - !ts.getRegexFromPattern(ts.Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) { - changeTracker.insertNodeAfter(configFile, ts.last(property.initializer.elements), ts.factory.createStringLiteral(relativePath(newFileOrDirPath))); + if (getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) && + !getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) { + changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), factory.createStringLiteral(relativePath(newFileOrDirPath))); } return; } case "compilerOptions": forEachProperty(property.initializer, (property, propertyName) => { - const option = ts.getOptionFromName(propertyName); + const option = getOptionFromName(propertyName); if (option && (option.isFilePath || option.type === "list" && option.element.isFilePath)) { updatePaths(property); } else if (propertyName === "paths") { forEachProperty(property.initializer, (pathsProperty) => { - if (!ts.isArrayLiteralExpression(pathsProperty.initializer)) return; + if (!isArrayLiteralExpression(pathsProperty.initializer)) return; for (const e of pathsProperty.initializer.elements) { tryUpdateString(e); } @@ -91,8 +101,8 @@ function updateTsconfigFiles(program: ts.Program, changeTracker: ts.textChanges. } }); - function updatePaths(property: ts.PropertyAssignment): boolean { - const elements = ts.isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer]; + function updatePaths(property: PropertyAssignment): boolean { + const elements = isArrayLiteralExpression(property.initializer) ? property.initializer.elements : [property.initializer]; let foundExactMatch = false; for (const element of elements) { foundExactMatch = tryUpdateString(element) || foundExactMatch; @@ -100,8 +110,8 @@ function updateTsconfigFiles(program: ts.Program, changeTracker: ts.textChanges. return foundExactMatch; } - function tryUpdateString(element: ts.Expression): boolean { - if (!ts.isStringLiteral(element)) return false; + function tryUpdateString(element: Expression): boolean { + if (!isStringLiteral(element)) return false; const elementFileName = combinePathsSafe(configDir, element.text); const updated = oldToNew(elementFileName); @@ -113,62 +123,62 @@ function updateTsconfigFiles(program: ts.Program, changeTracker: ts.textChanges. } function relativePath(path: string): string { - return ts.getRelativePathFromDirectory(configDir, path, /*ignoreCase*/ !useCaseSensitiveFileNames); + return getRelativePathFromDirectory(configDir, path, /*ignoreCase*/ !useCaseSensitiveFileNames); } } function updateImports( - program: ts.Program, - changeTracker: ts.textChanges.ChangeTracker, + program: Program, + changeTracker: textChanges.ChangeTracker, oldToNew: PathUpdater, newToOld: PathUpdater, - host: ts.LanguageServiceHost, - getCanonicalFileName: ts.GetCanonicalFileName, + host: LanguageServiceHost, + getCanonicalFileName: GetCanonicalFileName, ): void { const allFiles = program.getSourceFiles(); for (const sourceFile of allFiles) { const newFromOld = oldToNew(sourceFile.fileName); const newImportFromPath = newFromOld ?? sourceFile.fileName; - const newImportFromDirectory = ts.getDirectoryPath(newImportFromPath); + const newImportFromDirectory = getDirectoryPath(newImportFromPath); const oldFromNew: string | undefined = newToOld(sourceFile.fileName); const oldImportFromPath: string = oldFromNew || sourceFile.fileName; - const oldImportFromDirectory = ts.getDirectoryPath(oldImportFromPath); + const oldImportFromDirectory = getDirectoryPath(oldImportFromPath); const importingSourceFileMoved = newFromOld !== undefined || oldFromNew !== undefined; updateImportsWorker(sourceFile, changeTracker, referenceText => { - if (!ts.pathIsRelative(referenceText)) return undefined; + if (!pathIsRelative(referenceText)) return undefined; const oldAbsolute = combinePathsSafe(oldImportFromDirectory, referenceText); const newAbsolute = oldToNew(oldAbsolute); - return newAbsolute === undefined ? undefined : ts.ensurePathIsNonModuleName(ts.getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName)); + return newAbsolute === undefined ? undefined : ensurePathIsNonModuleName(getRelativePathFromDirectory(newImportFromDirectory, newAbsolute, getCanonicalFileName)); }, importLiteral => { const importedModuleSymbol = program.getTypeChecker().getSymbolAtLocation(importLiteral); // No need to update if it's an ambient module^M - if (importedModuleSymbol?.declarations && importedModuleSymbol.declarations.some(d => ts.isAmbientModule(d))) return undefined; + if (importedModuleSymbol?.declarations && importedModuleSymbol.declarations.some(d => isAmbientModule(d))) return undefined; const toImport = oldFromNew !== undefined // If we're at the new location (file was already renamed), need to redo module resolution starting from the old location. // TODO:GH#18217 - ? getSourceFileToImportFromResolved(importLiteral, ts.resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host as ts.ModuleResolutionHost), + ? getSourceFileToImportFromResolved(importLiteral, resolveModuleName(importLiteral.text, oldImportFromPath, program.getCompilerOptions(), host as ModuleResolutionHost), oldToNew, allFiles) : getSourceFileToImport(importedModuleSymbol, importLiteral, sourceFile, program, host, oldToNew); // Need an update if the imported file moved, or the importing file moved and was using a relative path. - return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && ts.pathIsRelative(importLiteral.text))) - ? ts.moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), sourceFile, getCanonicalFileName(newImportFromPath) as ts.Path, toImport.newFileName, ts.createModuleSpecifierResolutionHost(program, host), importLiteral.text) + return toImport !== undefined && (toImport.updated || (importingSourceFileMoved && pathIsRelative(importLiteral.text))) + ? moduleSpecifiers.updateModuleSpecifier(program.getCompilerOptions(), sourceFile, getCanonicalFileName(newImportFromPath) as Path, toImport.newFileName, createModuleSpecifierResolutionHost(program, host), importLiteral.text) : undefined; }); } } function combineNormal(pathA: string, pathB: string): string { - return ts.normalizePath(ts.combinePaths(pathA, pathB)); + return normalizePath(combinePaths(pathA, pathB)); } function combinePathsSafe(pathA: string, pathB: string): string { - return ts.ensurePathIsNonModuleName(combineNormal(pathA, pathB)); + return ensurePathIsNonModuleName(combineNormal(pathA, pathB)); } interface ToImport { @@ -177,21 +187,21 @@ interface ToImport { readonly updated: boolean; } function getSourceFileToImport( - importedModuleSymbol: ts.Symbol | undefined, - importLiteral: ts.StringLiteralLike, - importingSourceFile: ts.SourceFile, - program: ts.Program, - host: ts.LanguageServiceHost, + importedModuleSymbol: Symbol | undefined, + importLiteral: StringLiteralLike, + importingSourceFile: SourceFile, + program: Program, + host: LanguageServiceHost, oldToNew: PathUpdater, ): ToImport | undefined { if (importedModuleSymbol) { // `find` should succeed because we checked for ambient modules before calling this function. - const oldFileName = ts.find(importedModuleSymbol.declarations, ts.isSourceFile)!.fileName; + const oldFileName = find(importedModuleSymbol.declarations, isSourceFile)!.fileName; const newFileName = oldToNew(oldFileName); return newFileName === undefined ? { newFileName: oldFileName, updated: false } : { newFileName, updated: true }; } else { - const mode = ts.getModeForUsageLocation(importingSourceFile, importLiteral); + const mode = getModeForUsageLocation(importingSourceFile, importLiteral); const resolved = host.resolveModuleNames ? host.getResolvedModuleWithFailedLookupLocationsFromCache && host.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName, mode) : program.getResolvedModuleWithFailedLookupLocationsFromCache(importLiteral.text, importingSourceFile.fileName, mode); @@ -199,7 +209,7 @@ function getSourceFileToImport( } } -function getSourceFileToImportFromResolved(importLiteral: ts.StringLiteralLike, resolved: ts.ResolvedModuleWithFailedLookupLocations | undefined, oldToNew: PathUpdater, sourceFiles: readonly ts.SourceFile[]): ToImport | undefined { +function getSourceFileToImportFromResolved(importLiteral: StringLiteralLike, resolved: ResolvedModuleWithFailedLookupLocations | undefined, oldToNew: PathUpdater, sourceFiles: readonly SourceFile[]): ToImport | undefined { // Search through all locations looking for a moved file, and only then test already existing files. // This is because if `a.ts` is compiled to `a.js` and `a.ts` is moved, we don't want to resolve anything to `a.js`, but to `a.ts`'s new location. if (!resolved) return undefined; @@ -211,10 +221,10 @@ function getSourceFileToImportFromResolved(importLiteral: ts.StringLiteralLike, } // Then failed lookups that are in the list of sources - const result = ts.forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJsonExisting) + const result = forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJsonExisting) // Then failed lookups except package.json since we dont want to touch them (only included ts/js files). // At this point, the confidence level of this fix being correct is too low to change bare specifiers or absolute paths. - || ts.pathIsRelative(importLiteral.text) && ts.forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJson); + || pathIsRelative(importLiteral.text) && forEach(resolved.failedLookupLocations, tryChangeWithIgnoringPackageJson); if (result) return result; // If nothing changed, then result is resolved module file thats not updated @@ -222,12 +232,12 @@ function getSourceFileToImportFromResolved(importLiteral: ts.StringLiteralLike, function tryChangeWithIgnoringPackageJsonExisting(oldFileName: string) { const newFileName = oldToNew(oldFileName); - return newFileName && ts.find(sourceFiles, src => src.fileName === newFileName) + return newFileName && find(sourceFiles, src => src.fileName === newFileName) ? tryChangeWithIgnoringPackageJson(oldFileName) : undefined; } function tryChangeWithIgnoringPackageJson(oldFileName: string) { - return !ts.endsWith(oldFileName, "/package.json") ? tryChange(oldFileName) : undefined; + return !endsWith(oldFileName, "/package.json") ? tryChange(oldFileName) : undefined; } function tryChange(oldFileName: string) { @@ -236,8 +246,8 @@ function getSourceFileToImportFromResolved(importLiteral: ts.StringLiteralLike, } } -function updateImportsWorker(sourceFile: ts.SourceFile, changeTracker: ts.textChanges.ChangeTracker, updateRef: (refText: string) => string | undefined, updateImport: (importLiteral: ts.StringLiteralLike) => string | undefined) { - for (const ref of sourceFile.referencedFiles || ts.emptyArray) { // TODO: GH#26162 +function updateImportsWorker(sourceFile: SourceFile, changeTracker: textChanges.ChangeTracker, updateRef: (refText: string) => string | undefined, updateImport: (importLiteral: StringLiteralLike) => string | undefined) { + for (const ref of sourceFile.referencedFiles || emptyArray) { // TODO: GH#26162 const updated = updateRef(ref.fileName); if (updated !== undefined && updated !== sourceFile.text.slice(ref.pos, ref.end)) changeTracker.replaceRangeWithText(sourceFile, ref, updated); } @@ -248,14 +258,14 @@ function updateImportsWorker(sourceFile: ts.SourceFile, changeTracker: ts.textCh } } -function createStringRange(node: ts.StringLiteralLike, sourceFile: ts.SourceFileLike): ts.TextRange { - return ts.createRange(node.getStart(sourceFile) + 1, node.end - 1); +function createStringRange(node: StringLiteralLike, sourceFile: SourceFileLike): TextRange { + return createRange(node.getStart(sourceFile) + 1, node.end - 1); } -function forEachProperty(objectLiteral: ts.Expression, cb: (property: ts.PropertyAssignment, propertyName: string) => void) { - if (!ts.isObjectLiteralExpression(objectLiteral)) return; +function forEachProperty(objectLiteral: Expression, cb: (property: PropertyAssignment, propertyName: string) => void) { + if (!isObjectLiteralExpression(objectLiteral)) return; for (const property of objectLiteral.properties) { - if (ts.isPropertyAssignment(property) && ts.isStringLiteral(property.name)) { + if (isPropertyAssignment(property) && isStringLiteral(property.name)) { cb(property, property.name.text); } } diff --git a/src/services/globalThisShim.ts b/src/services/globalThisShim.ts index 81e88c60ff62f..c7bc8a28e1f16 100644 --- a/src/services/globalThisShim.ts +++ b/src/services/globalThisShim.ts @@ -1,4 +1,4 @@ -import * as ts from "./_namespaces/ts"; +import { TypeScriptServicesFactory, versionMajorMinor } from "./_namespaces/ts"; // We polyfill `globalThis` here so re can reliably patch the global scope // in the contexts we want to in the same way across script and module formats @@ -55,11 +55,11 @@ if (typeof process === "undefined" || process.browser) { //@ts-ignore globalThis.TypeScript.Services = globalThis.TypeScript.Services || {}; //@ts-ignore - globalThis.TypeScript.Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory; + globalThis.TypeScript.Services.TypeScriptServicesFactory = TypeScriptServicesFactory; // 'toolsVersion' gets consumed by the managed side, so it's not unused. // TODO: it should be moved into a namespace though. //@ts-ignore - globalThis.toolsVersion = ts.versionMajorMinor; + globalThis.toolsVersion = versionMajorMinor; } \ No newline at end of file diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index a3fb1220e66bc..fe14c8cc23563 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -1,15 +1,34 @@ -import * as ts from "./_namespaces/ts"; +import { + AssignmentDeclarationKind, AssignmentExpression, AssignmentOperatorToken, CallLikeExpression, concatenate, + createTextSpan, createTextSpanFromBounds, createTextSpanFromNode, createTextSpanFromRange, Debug, Declaration, + DefinitionInfo, DefinitionInfoAndBoundSpan, emptyArray, every, FileReference, filter, find, FindAllReferences, + findAncestor, first, flatMap, forEach, FunctionLikeDeclaration, getAssignmentDeclarationKind, + getContainingObjectLiteralElement, getDirectoryPath, getEffectiveBaseTypeNode, getInvokedExpression, + getModeForUsageLocation, getNameFromPropertyName, getNameOfDeclaration, getPropertySymbolsFromContextualType, + getTargetLabel, getTextOfPropertyName, getTouchingPropertyName, getTouchingToken, hasEffectiveModifier, + hasInitializer, hasStaticModifier, isAnyImportOrBareOrAccessedRequire, isAssignmentDeclaration, + isAssignmentExpression, isBindingElement, isCallLikeExpression, isCallOrNewExpressionTarget, isClassElement, + isClassExpression, isClassLike, isClassStaticBlockDeclaration, isConstructorDeclaration, isDeclarationFileName, + isExternalModuleNameRelative, isFunctionLike, isFunctionLikeDeclaration, isFunctionTypeNode, isIdentifier, + isImportMeta, isJSDocOverrideTag, isJsxOpeningLikeElement, isJumpStatementTarget, isModuleSpecifierLike, + isNameOfFunctionDeclaration, isNewExpressionTarget, isObjectBindingPattern, isPropertyName, + isRightSideOfPropertyAccess, isStaticModifier, isVariableDeclaration, last, map, mapDefined, ModifierFlags, + moveRangePastModifiers, Node, NodeFlags, Program, resolvePath, ScriptElementKind, SignatureDeclaration, skipAlias, + skipParentheses, skipTrivia, some, SourceFile, Symbol, SymbolDisplay, SymbolFlags, SyntaxKind, + textRangeContainsPositionInclusive, TextSpan, tryCast, tryGetModuleSpecifierFromDeclaration, Type, TypeChecker, + TypeFlags, unescapeLeadingUnderscores, +} from "./_namespaces/ts"; /** @internal */ -export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.SourceFile, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly ts.DefinitionInfo[] | undefined { +export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { const resolvedRef = getReferenceAtPosition(sourceFile, position, program); - const fileReferenceDefinition = resolvedRef && [getDefinitionInfoForFileReference(resolvedRef.reference.fileName, resolvedRef.fileName, resolvedRef.unverified)] || ts.emptyArray; + const fileReferenceDefinition = resolvedRef && [getDefinitionInfoForFileReference(resolvedRef.reference.fileName, resolvedRef.fileName, resolvedRef.unverified)] || emptyArray; if (resolvedRef?.file) { // If `file` is missing, do a symbol-based lookup as well return fileReferenceDefinition; } - const node = ts.getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; } @@ -17,33 +36,33 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour const { parent } = node; const typeChecker = program.getTypeChecker(); - if (node.kind === ts.SyntaxKind.OverrideKeyword || (ts.isIdentifier(node) && ts.isJSDocOverrideTag(parent) && parent.tagName === node)) { - return getDefinitionFromOverriddenMember(typeChecker, node) || ts.emptyArray; + if (node.kind === SyntaxKind.OverrideKeyword || (isIdentifier(node) && isJSDocOverrideTag(parent) && parent.tagName === node)) { + return getDefinitionFromOverriddenMember(typeChecker, node) || emptyArray; } // Labels - if (ts.isJumpStatementTarget(node)) { - const label = ts.getTargetLabel(node.parent, node.text); - return label ? [createDefinitionInfoFromName(typeChecker, label, ts.ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 + if (isJumpStatementTarget(node)) { + const label = getTargetLabel(node.parent, node.text); + return label ? [createDefinitionInfoFromName(typeChecker, label, ScriptElementKind.label, node.text, /*containerName*/ undefined!)] : undefined; // TODO: GH#18217 } - if (node.kind === ts.SyntaxKind.ReturnKeyword) { - const functionDeclaration = ts.findAncestor(node.parent, n => - ts.isClassStaticBlockDeclaration(n) ? "quit" : ts.isFunctionLikeDeclaration(n)) as ts.FunctionLikeDeclaration | undefined; + if (node.kind === SyntaxKind.ReturnKeyword) { + const functionDeclaration = findAncestor(node.parent, n => + isClassStaticBlockDeclaration(n) ? "quit" : isFunctionLikeDeclaration(n)) as FunctionLikeDeclaration | undefined; return functionDeclaration ? [createDefinitionFromSignatureDeclaration(typeChecker, functionDeclaration)] : undefined; } - if (ts.isStaticModifier(node) && ts.isClassStaticBlockDeclaration(node.parent)) { + if (isStaticModifier(node) && isClassStaticBlockDeclaration(node.parent)) { const classDecl = node.parent.parent; const { symbol, failedAliasResolution } = getSymbol(classDecl, typeChecker, stopAtAlias); - const staticBlocks = ts.filter(classDecl.members, ts.isClassStaticBlockDeclaration); + const staticBlocks = filter(classDecl.members, isClassStaticBlockDeclaration); const containerName = symbol ? typeChecker.symbolToString(symbol, classDecl) : ""; const sourceFile = node.getSourceFile(); - return ts.map(staticBlocks, staticBlock => { - let { pos } = ts.moveRangePastModifiers(staticBlock); - pos = ts.skipTrivia(sourceFile.text, pos); - return createDefinitionInfoFromName(typeChecker, staticBlock, ts.ScriptElementKind.constructorImplementationElement, "static {}", containerName, /*unverified*/ false, failedAliasResolution, { start: pos, length: "static".length }); + return map(staticBlocks, staticBlock => { + let { pos } = moveRangePastModifiers(staticBlock); + pos = skipTrivia(sourceFile.text, pos); + return createDefinitionInfoFromName(typeChecker, staticBlock, ScriptElementKind.constructorImplementationElement, "static {}", containerName, /*unverified*/ false, failedAliasResolution, { start: pos, length: "static".length }); }); } @@ -52,28 +71,28 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour if (searchOtherFilesOnly && failedAliasResolution) { // We couldn't resolve the specific import, try on the module specifier. - const importDeclaration = ts.forEach([node, ...symbol?.declarations || ts.emptyArray], n => ts.findAncestor(n, ts.isAnyImportOrBareOrAccessedRequire)); - const moduleSpecifier = importDeclaration && ts.tryGetModuleSpecifierFromDeclaration(importDeclaration); + const importDeclaration = forEach([node, ...symbol?.declarations || emptyArray], n => findAncestor(n, isAnyImportOrBareOrAccessedRequire)); + const moduleSpecifier = importDeclaration && tryGetModuleSpecifierFromDeclaration(importDeclaration); if (moduleSpecifier) { ({ symbol, failedAliasResolution } = getSymbol(moduleSpecifier, typeChecker, stopAtAlias)); fallbackNode = moduleSpecifier; } } - if (!symbol && ts.isModuleSpecifierLike(fallbackNode)) { + if (!symbol && isModuleSpecifierLike(fallbackNode)) { // We couldn't resolve the module specifier as an external module, but it could // be that module resolution succeeded but the target was not a module. - const ref = sourceFile.resolvedModules?.get(fallbackNode.text, ts.getModeForUsageLocation(sourceFile, fallbackNode)); + const ref = sourceFile.resolvedModules?.get(fallbackNode.text, getModeForUsageLocation(sourceFile, fallbackNode)); if (ref) { return [{ name: fallbackNode.text, fileName: ref.resolvedFileName, containerName: undefined!, containerKind: undefined!, - kind: ts.ScriptElementKind.scriptElement, - textSpan: ts.createTextSpan(0, 0), + kind: ScriptElementKind.scriptElement, + textSpan: createTextSpan(0, 0), failedAliasResolution, - isAmbient: ts.isDeclarationFileName(ref.resolvedFileName), + isAmbient: isDeclarationFileName(ref.resolvedFileName), unverified: fallbackNode !== node, }]; } @@ -82,14 +101,14 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour // Could not find a symbol e.g. node is string or number keyword, // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol if (!symbol) { - return ts.concatenate(fileReferenceDefinition, getDefinitionInfoForIndexSignatures(node, typeChecker)); + return concatenate(fileReferenceDefinition, getDefinitionInfoForIndexSignatures(node, typeChecker)); } - if (searchOtherFilesOnly && ts.every(symbol.declarations, d => d.getSourceFile().fileName === sourceFile.fileName)) return undefined; + if (searchOtherFilesOnly && every(symbol.declarations, d => d.getSourceFile().fileName === sourceFile.fileName)) return undefined; const calledDeclaration = tryGetSignatureDeclaration(typeChecker, node); // Don't go to the component constructor definition for a JSX element, just go to the component definition. - if (calledDeclaration && !(ts.isJsxOpeningLikeElement(node.parent) && isConstructorLike(calledDeclaration))) { + if (calledDeclaration && !(isJsxOpeningLikeElement(node.parent) && isConstructorLike(calledDeclaration))) { const sigInfo = createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration, failedAliasResolution); // For a function, if this is the original function definition, return just sigInfo. // If this is the original constructor definition, parent is the class. @@ -97,9 +116,9 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour return [sigInfo]; } else { - const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) || ts.emptyArray; + const defs = getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution, calledDeclaration) || emptyArray; // For a 'super()' call, put the signature first, else put the variable first. - return node.kind === ts.SyntaxKind.SuperKeyword ? [sigInfo, ...defs] : [...defs, sigInfo]; + return node.kind === SyntaxKind.SuperKeyword ? [sigInfo, ...defs] : [...defs, sigInfo]; } } @@ -108,10 +127,10 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition // is performed at the location of property access, we would like to go to definition of the property in the short-hand // assignment. This case and others are handled by the following code. - if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) { + if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); - const definitions = shorthandSymbol?.declarations ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node, /*unverified*/ false, failedAliasResolution)) : ts.emptyArray; - return ts.concatenate(definitions, getDefinitionFromObjectLiteralElement(typeChecker, node) || ts.emptyArray); + const definitions = shorthandSymbol?.declarations ? shorthandSymbol.declarations.map(decl => createDefinitionInfo(decl, typeChecker, shorthandSymbol, node, /*unverified*/ false, failedAliasResolution)) : emptyArray; + return concatenate(definitions, getDefinitionFromObjectLiteralElement(typeChecker, node) || emptyArray); } // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the @@ -125,17 +144,17 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour // pr/*destination*/op1: number // } // bar(({pr/*goto*/op1})=>{}); - if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) && + if (isPropertyName(node) && isBindingElement(parent) && isObjectBindingPattern(parent.parent) && (node === (parent.propertyName || parent.name))) { - const name = ts.getNameFromPropertyName(node); + const name = getNameFromPropertyName(node); const type = typeChecker.getTypeAtLocation(parent.parent); - return name === undefined ? ts.emptyArray : ts.flatMap(type.isUnion() ? type.types : [type], t => { + return name === undefined ? emptyArray : flatMap(type.isUnion() ? type.types : [type], t => { const prop = t.getProperty(name); return prop && getDefinitionFromSymbol(typeChecker, prop, node); }); } - return ts.concatenate(fileReferenceDefinition, getDefinitionFromObjectLiteralElement(typeChecker, node) || getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution)); + return concatenate(fileReferenceDefinition, getDefinitionFromObjectLiteralElement(typeChecker, node) || getDefinitionFromSymbol(typeChecker, symbol, node, failedAliasResolution)); } /** @@ -143,11 +162,11 @@ export function getDefinitionAtPosition(program: ts.Program, sourceFile: ts.Sour * True for `const |f = |() => 0`, false for `function |f() {} const |g = f;`. * Also true for any assignment RHS. */ -function symbolMatchesSignature(s: ts.Symbol, calledDeclaration: ts.SignatureDeclaration) { +function symbolMatchesSignature(s: Symbol, calledDeclaration: SignatureDeclaration) { return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent - || ts.isAssignmentExpression(calledDeclaration.parent) - || (!ts.isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol); + || isAssignmentExpression(calledDeclaration.parent) + || (!isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol); } // If the current location we want to find its definition is in an object literal, try to get the contextual type for the @@ -159,32 +178,32 @@ function symbolMatchesSignature(s: ts.Symbol, calledDeclaration: ts.SignatureDec // } // function Foo(arg: Props) {} // Foo( { pr/*1*/op1: 10, prop2: true }) -function getDefinitionFromObjectLiteralElement(typeChecker: ts.TypeChecker, node: ts.Node) { - const element = ts.getContainingObjectLiteralElement(node); +function getDefinitionFromObjectLiteralElement(typeChecker: TypeChecker, node: Node) { + const element = getContainingObjectLiteralElement(node); if (element) { const contextualType = element && typeChecker.getContextualType(element.parent); if (contextualType) { - return ts.flatMap(ts.getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), propertySymbol => + return flatMap(getPropertySymbolsFromContextualType(element, typeChecker, contextualType, /*unionSymbolOk*/ false), propertySymbol => getDefinitionFromSymbol(typeChecker, propertySymbol, node)); } } } -function getDefinitionFromOverriddenMember(typeChecker: ts.TypeChecker, node: ts.Node) { - const classElement = ts.findAncestor(node, ts.isClassElement); +function getDefinitionFromOverriddenMember(typeChecker: TypeChecker, node: Node) { + const classElement = findAncestor(node, isClassElement); if (!(classElement && classElement.name)) return; - const baseDeclaration = ts.findAncestor(classElement, ts.isClassLike); + const baseDeclaration = findAncestor(classElement, isClassLike); if (!baseDeclaration) return; - const baseTypeNode = ts.getEffectiveBaseTypeNode(baseDeclaration); + const baseTypeNode = getEffectiveBaseTypeNode(baseDeclaration); if (!baseTypeNode) return; - const expression = ts.skipParentheses(baseTypeNode.expression); - const base = ts.isClassExpression(expression) ? expression.symbol : typeChecker.getSymbolAtLocation(expression); + const expression = skipParentheses(baseTypeNode.expression); + const base = isClassExpression(expression) ? expression.symbol : typeChecker.getSymbolAtLocation(expression); if (!base) return; - const name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(classElement.name)); - const symbol = ts.hasStaticModifier(classElement) + const name = unescapeLeadingUnderscores(getTextOfPropertyName(classElement.name)); + const symbol = hasStaticModifier(classElement) ? typeChecker.getPropertyOfType(typeChecker.getTypeOfSymbol(base), name) : typeChecker.getPropertyOfType(typeChecker.getDeclaredTypeOfSymbol(base), name); if (!symbol) return; @@ -193,7 +212,7 @@ function getDefinitionFromOverriddenMember(typeChecker: ts.TypeChecker, node: ts } /** @internal */ -export function getReferenceAtPosition(sourceFile: ts.SourceFile, position: number, program: ts.Program): { reference: ts.FileReference, fileName: string, unverified: boolean, file?: ts.SourceFile } | undefined { +export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { reference: FileReference, fileName: string, unverified: boolean, file?: SourceFile } | undefined { const referencePath = findReferenceInPosition(sourceFile.referencedFiles, position); if (referencePath) { const file = program.getSourceFileFromReference(sourceFile, referencePath); @@ -214,10 +233,10 @@ export function getReferenceAtPosition(sourceFile: ts.SourceFile, position: numb } if (sourceFile.resolvedModules?.size()) { - const node = ts.getTouchingToken(sourceFile, position); - if (ts.isModuleSpecifierLike(node) && ts.isExternalModuleNameRelative(node.text) && sourceFile.resolvedModules.has(node.text, ts.getModeForUsageLocation(sourceFile, node))) { - const verifiedFileName = sourceFile.resolvedModules.get(node.text, ts.getModeForUsageLocation(sourceFile, node))?.resolvedFileName; - const fileName = verifiedFileName || ts.resolvePath(ts.getDirectoryPath(sourceFile.fileName), node.text); + const node = getTouchingToken(sourceFile, position); + if (isModuleSpecifierLike(node) && isExternalModuleNameRelative(node.text) && sourceFile.resolvedModules.has(node.text, getModeForUsageLocation(sourceFile, node))) { + const verifiedFileName = sourceFile.resolvedModules.get(node.text, getModeForUsageLocation(sourceFile, node))?.resolvedFileName; + const fileName = verifiedFileName || resolvePath(getDirectoryPath(sourceFile.fileName), node.text); return { file: program.getSourceFile(fileName), fileName, @@ -236,13 +255,13 @@ export function getReferenceAtPosition(sourceFile: ts.SourceFile, position: numb /// Goto type /** @internal */ -export function getTypeDefinitionAtPosition(typeChecker: ts.TypeChecker, sourceFile: ts.SourceFile, position: number): readonly ts.DefinitionInfo[] | undefined { - const node = ts.getTouchingPropertyName(sourceFile, position); +export function getTypeDefinitionAtPosition(typeChecker: TypeChecker, sourceFile: SourceFile, position: number): readonly DefinitionInfo[] | undefined { + const node = getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { return undefined; } - if (ts.isImportMeta(node.parent) && node.parent.name === node) { + if (isImportMeta(node.parent) && node.parent.name === node) { return definitionFromType(typeChecker.getTypeAtLocation(node.parent), typeChecker, node.parent, /*failedAliasResolution*/ false); } @@ -255,29 +274,29 @@ export function getTypeDefinitionAtPosition(typeChecker: ts.TypeChecker, sourceF // If a function returns 'void' or some other type with no definition, just return the function definition. const typeDefinitions = fromReturnType && fromReturnType.length !== 0 ? fromReturnType : definitionFromType(typeAtLocation, typeChecker, node, failedAliasResolution); return typeDefinitions.length ? typeDefinitions - : !(symbol.flags & ts.SymbolFlags.Value) && symbol.flags & ts.SymbolFlags.Type ? getDefinitionFromSymbol(typeChecker, ts.skipAlias(symbol, typeChecker), node, failedAliasResolution) + : !(symbol.flags & SymbolFlags.Value) && symbol.flags & SymbolFlags.Type ? getDefinitionFromSymbol(typeChecker, skipAlias(symbol, typeChecker), node, failedAliasResolution) : undefined; } -function definitionFromType(type: ts.Type, checker: ts.TypeChecker, node: ts.Node, failedAliasResolution: boolean | undefined): readonly ts.DefinitionInfo[] { - return ts.flatMap(type.isUnion() && !(type.flags & ts.TypeFlags.Enum) ? type.types : [type], t => +function definitionFromType(type: Type, checker: TypeChecker, node: Node, failedAliasResolution: boolean | undefined): readonly DefinitionInfo[] { + return flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t => t.symbol && getDefinitionFromSymbol(checker, t.symbol, node, failedAliasResolution)); } -function tryGetReturnTypeOfFunction(symbol: ts.Symbol, type: ts.Type, checker: ts.TypeChecker): ts.Type | undefined { +function tryGetReturnTypeOfFunction(symbol: Symbol, type: Type, checker: TypeChecker): Type | undefined { // If the type is just a function's inferred type, // go-to-type should go to the return type instead, since go-to-definition takes you to the function anyway. if (type.symbol === symbol || // At `const f = () => {}`, the symbol is `f` and the type symbol is at `() => {}` - symbol.valueDeclaration && type.symbol && ts.isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration as ts.Node) { + symbol.valueDeclaration && type.symbol && isVariableDeclaration(symbol.valueDeclaration) && symbol.valueDeclaration.initializer === type.symbol.valueDeclaration as Node) { const sigs = type.getCallSignatures(); - if (sigs.length === 1) return checker.getReturnTypeOfSignature(ts.first(sigs)); + if (sigs.length === 1) return checker.getReturnTypeOfSignature(first(sigs)); } return undefined; } /** @internal */ -export function getDefinitionAndBoundSpan(program: ts.Program, sourceFile: ts.SourceFile, position: number): ts.DefinitionInfoAndBoundSpan | undefined { +export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined { const definitions = getDefinitionAtPosition(program, sourceFile, position); if (!definitions || definitions.length === 0) { @@ -290,28 +309,28 @@ export function getDefinitionAndBoundSpan(program: ts.Program, sourceFile: ts.So findReferenceInPosition(sourceFile.libReferenceDirectives, position); if (comment) { - return { definitions, textSpan: ts.createTextSpanFromRange(comment) }; + return { definitions, textSpan: createTextSpanFromRange(comment) }; } - const node = ts.getTouchingPropertyName(sourceFile, position); - const textSpan = ts.createTextSpan(node.getStart(), node.getWidth()); + const node = getTouchingPropertyName(sourceFile, position); + const textSpan = createTextSpan(node.getStart(), node.getWidth()); return { definitions, textSpan }; } // At 'x.foo', see if the type of 'x' has an index signature, and if so find its declarations. -function getDefinitionInfoForIndexSignatures(node: ts.Node, checker: ts.TypeChecker): ts.DefinitionInfo[] | undefined { - return ts.mapDefined(checker.getIndexInfosAtLocation(node), info => info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration)); +function getDefinitionInfoForIndexSignatures(node: Node, checker: TypeChecker): DefinitionInfo[] | undefined { + return mapDefined(checker.getIndexInfosAtLocation(node), info => info.declaration && createDefinitionFromSignatureDeclaration(checker, info.declaration)); } -function getSymbol(node: ts.Node, checker: ts.TypeChecker, stopAtAlias: boolean | undefined) { +function getSymbol(node: Node, checker: TypeChecker, stopAtAlias: boolean | undefined) { const symbol = checker.getSymbolAtLocation(node); // If this is an alias, and the request came at the declaration location // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; // to jump to the implementation directly. let failedAliasResolution = false; - if (symbol?.declarations && symbol.flags & ts.SymbolFlags.Alias && !stopAtAlias && shouldSkipAlias(node, symbol.declarations[0])) { + if (symbol?.declarations && symbol.flags & SymbolFlags.Alias && !stopAtAlias && shouldSkipAlias(node, symbol.declarations[0])) { const aliased = checker.getAliasedSymbol(symbol); if (aliased.declarations) { return { symbol: aliased }; @@ -328,14 +347,14 @@ function getSymbol(node: ts.Node, checker: ts.TypeChecker, stopAtAlias: boolean // (1) when the aliased symbol was declared in the location(parent). // (2) when the aliased symbol is originating from an import. // -function shouldSkipAlias(node: ts.Node, declaration: ts.Node): boolean { - if (node.kind !== ts.SyntaxKind.Identifier) { +function shouldSkipAlias(node: Node, declaration: Node): boolean { + if (node.kind !== SyntaxKind.Identifier) { return false; } if (node.parent === declaration) { return true; } - if (declaration.kind === ts.SyntaxKind.NamespaceImport) { + if (declaration.kind === SyntaxKind.NamespaceImport) { return false; } return true; @@ -358,68 +377,68 @@ function shouldSkipAlias(node: ts.Node, declaration: ts.Node): boolean { * calling) covers our tests but feels like a hack, and it would be great if someone could come * up with a more precise definition of what counts as a definition. */ -function isExpandoDeclaration(node: ts.Declaration): boolean { - if (!ts.isAssignmentDeclaration(node)) return false; - const containingAssignment = ts.findAncestor(node, p => { - if (ts.isAssignmentExpression(p)) return true; - if (!ts.isAssignmentDeclaration(p as ts.Declaration)) return "quit"; +function isExpandoDeclaration(node: Declaration): boolean { + if (!isAssignmentDeclaration(node)) return false; + const containingAssignment = findAncestor(node, p => { + if (isAssignmentExpression(p)) return true; + if (!isAssignmentDeclaration(p as Declaration)) return "quit"; return false; - }) as ts.AssignmentExpression | undefined; - return !!containingAssignment && ts.getAssignmentDeclarationKind(containingAssignment) === ts.AssignmentDeclarationKind.Property; + }) as AssignmentExpression | undefined; + return !!containingAssignment && getAssignmentDeclarationKind(containingAssignment) === AssignmentDeclarationKind.Property; } -function getDefinitionFromSymbol(typeChecker: ts.TypeChecker, symbol: ts.Symbol, node: ts.Node, failedAliasResolution?: boolean, excludeDeclaration?: ts.Node): ts.DefinitionInfo[] | undefined { - const filteredDeclarations = ts.filter(symbol.declarations, d => d !== excludeDeclaration); - const withoutExpandos = ts.filter(filteredDeclarations, d => !isExpandoDeclaration(d)); - const results = ts.some(withoutExpandos) ? withoutExpandos : filteredDeclarations; - return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)); +function getDefinitionFromSymbol(typeChecker: TypeChecker, symbol: Symbol, node: Node, failedAliasResolution?: boolean, excludeDeclaration?: Node): DefinitionInfo[] | undefined { + const filteredDeclarations = filter(symbol.declarations, d => d !== excludeDeclaration); + const withoutExpandos = filter(filteredDeclarations, d => !isExpandoDeclaration(d)); + const results = some(withoutExpandos) ? withoutExpandos : filteredDeclarations; + return getConstructSignatureDefinition() || getCallSignatureDefinition() || map(results, declaration => createDefinitionInfo(declaration, typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)); - function getConstructSignatureDefinition(): ts.DefinitionInfo[] | undefined { + function getConstructSignatureDefinition(): DefinitionInfo[] | undefined { // Applicable only if we are in a new expression, or we are on a constructor declaration // and in either case the symbol has a construct signature definition, i.e. class - if (symbol.flags & ts.SymbolFlags.Class && !(symbol.flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Variable)) && (ts.isNewExpressionTarget(node) || node.kind === ts.SyntaxKind.ConstructorKeyword)) { - const cls = ts.find(filteredDeclarations, ts.isClassLike) || ts.Debug.fail("Expected declaration to have at least one class-like declaration"); + if (symbol.flags & SymbolFlags.Class && !(symbol.flags & (SymbolFlags.Function | SymbolFlags.Variable)) && (isNewExpressionTarget(node) || node.kind === SyntaxKind.ConstructorKeyword)) { + const cls = find(filteredDeclarations, isClassLike) || Debug.fail("Expected declaration to have at least one class-like declaration"); return getSignatureDefinition(cls.members, /*selectConstructors*/ true); } } - function getCallSignatureDefinition(): ts.DefinitionInfo[] | undefined { - return ts.isCallOrNewExpressionTarget(node) || ts.isNameOfFunctionDeclaration(node) + function getCallSignatureDefinition(): DefinitionInfo[] | undefined { + return isCallOrNewExpressionTarget(node) || isNameOfFunctionDeclaration(node) ? getSignatureDefinition(filteredDeclarations, /*selectConstructors*/ false) : undefined; } - function getSignatureDefinition(signatureDeclarations: readonly ts.Declaration[] | undefined, selectConstructors: boolean): ts.DefinitionInfo[] | undefined { + function getSignatureDefinition(signatureDeclarations: readonly Declaration[] | undefined, selectConstructors: boolean): DefinitionInfo[] | undefined { if (!signatureDeclarations) { return undefined; } - const declarations = signatureDeclarations.filter(selectConstructors ? ts.isConstructorDeclaration : ts.isFunctionLike); - const declarationsWithBody = declarations.filter(d => !!(d as ts.FunctionLikeDeclaration).body); + const declarations = signatureDeclarations.filter(selectConstructors ? isConstructorDeclaration : isFunctionLike); + const declarationsWithBody = declarations.filter(d => !!(d as FunctionLikeDeclaration).body); // declarations defined on the global scope can be defined on multiple files. Get all of them. return declarations.length ? declarationsWithBody.length !== 0 ? declarationsWithBody.map(x => createDefinitionInfo(x, typeChecker, symbol, node)) - : [createDefinitionInfo(ts.last(declarations), typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)] + : [createDefinitionInfo(last(declarations), typeChecker, symbol, node, /*unverified*/ false, failedAliasResolution)] : undefined; } } /** @internal */ /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */ -export function createDefinitionInfo(declaration: ts.Declaration, checker: ts.TypeChecker, symbol: ts.Symbol, node: ts.Node, unverified?: boolean, failedAliasResolution?: boolean): ts.DefinitionInfo { +export function createDefinitionInfo(declaration: Declaration, checker: TypeChecker, symbol: Symbol, node: Node, unverified?: boolean, failedAliasResolution?: boolean): DefinitionInfo { const symbolName = checker.symbolToString(symbol); // Do not get scoped name, just the name of the symbol - const symbolKind = ts.SymbolDisplay.getSymbolKind(checker, symbol, node); + const symbolKind = SymbolDisplay.getSymbolKind(checker, symbol, node); const containerName = symbol.parent ? checker.symbolToString(symbol.parent, node) : ""; return createDefinitionInfoFromName(checker, declaration, symbolKind, symbolName, containerName, unverified, failedAliasResolution); } /** Creates a DefinitionInfo directly from the name of a declaration. */ -function createDefinitionInfoFromName(checker: ts.TypeChecker, declaration: ts.Declaration, symbolKind: ts.ScriptElementKind, symbolName: string, containerName: string, unverified?: boolean, failedAliasResolution?: boolean, textSpan?: ts.TextSpan): ts.DefinitionInfo { +function createDefinitionInfoFromName(checker: TypeChecker, declaration: Declaration, symbolKind: ScriptElementKind, symbolName: string, containerName: string, unverified?: boolean, failedAliasResolution?: boolean, textSpan?: TextSpan): DefinitionInfo { const sourceFile = declaration.getSourceFile(); if (!textSpan) { - const name = ts.getNameOfDeclaration(declaration) || declaration; - textSpan = ts.createTextSpanFromNode(name, sourceFile); + const name = getNameOfDeclaration(declaration) || declaration; + textSpan = createTextSpanFromNode(name, sourceFile); } return { fileName: sourceFile.fileName, @@ -428,63 +447,63 @@ function createDefinitionInfoFromName(checker: ts.TypeChecker, declaration: ts.D name: symbolName, containerKind: undefined!, // TODO: GH#18217 containerName, - ...ts.FindAllReferences.toContextSpan( + ...FindAllReferences.toContextSpan( textSpan, sourceFile, - ts.FindAllReferences.getContextNode(declaration) + FindAllReferences.getContextNode(declaration) ), isLocal: !isDefinitionVisible(checker, declaration), - isAmbient: !!(declaration.flags & ts.NodeFlags.Ambient), + isAmbient: !!(declaration.flags & NodeFlags.Ambient), unverified, failedAliasResolution, }; } -function isDefinitionVisible(checker: ts.TypeChecker, declaration: ts.Declaration): boolean { +function isDefinitionVisible(checker: TypeChecker, declaration: Declaration): boolean { if (checker.isDeclarationVisible(declaration)) return true; if (!declaration.parent) return false; // Variable initializers are visible if variable is visible - if (ts.hasInitializer(declaration.parent) && declaration.parent.initializer === declaration) return isDefinitionVisible(checker, declaration.parent as ts.Declaration); + if (hasInitializer(declaration.parent) && declaration.parent.initializer === declaration) return isDefinitionVisible(checker, declaration.parent as Declaration); // Handle some exceptions here like arrow function, members of class and object literal expression which are technically not visible but we want the definition to be determined by its parent switch (declaration.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: // Private/protected properties/methods are not visible - if (ts.hasEffectiveModifier(declaration, ts.ModifierFlags.Private)) return false; + if (hasEffectiveModifier(declaration, ModifierFlags.Private)) return false; // Public properties/methods are visible if its parents are visible, so: // falls through - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - return isDefinitionVisible(checker, declaration.parent as ts.Declaration); + case SyntaxKind.Constructor: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + return isDefinitionVisible(checker, declaration.parent as Declaration); default: return false; } } -function createDefinitionFromSignatureDeclaration(typeChecker: ts.TypeChecker, decl: ts.SignatureDeclaration, failedAliasResolution?: boolean): ts.DefinitionInfo { +function createDefinitionFromSignatureDeclaration(typeChecker: TypeChecker, decl: SignatureDeclaration, failedAliasResolution?: boolean): DefinitionInfo { return createDefinitionInfo(decl, typeChecker, decl.symbol, decl, /*unverified*/ false, failedAliasResolution); } /** @internal */ -export function findReferenceInPosition(refs: readonly ts.FileReference[], pos: number): ts.FileReference | undefined { - return ts.find(refs, ref => ts.textRangeContainsPositionInclusive(ref, pos)); +export function findReferenceInPosition(refs: readonly FileReference[], pos: number): FileReference | undefined { + return find(refs, ref => textRangeContainsPositionInclusive(ref, pos)); } -function getDefinitionInfoForFileReference(name: string, targetFileName: string, unverified: boolean): ts.DefinitionInfo { +function getDefinitionInfoForFileReference(name: string, targetFileName: string, unverified: boolean): DefinitionInfo { return { fileName: targetFileName, - textSpan: ts.createTextSpanFromBounds(0, 0), - kind: ts.ScriptElementKind.scriptElement, + textSpan: createTextSpanFromBounds(0, 0), + kind: ScriptElementKind.scriptElement, name, containerName: undefined!, containerKind: undefined!, // TODO: GH#18217 @@ -493,24 +512,24 @@ function getDefinitionInfoForFileReference(name: string, targetFileName: string, } /** Returns a CallLikeExpression where `node` is the target being invoked. */ -function getAncestorCallLikeExpression(node: ts.Node): ts.CallLikeExpression | undefined { - const target = ts.findAncestor(node, n => !ts.isRightSideOfPropertyAccess(n)); +function getAncestorCallLikeExpression(node: Node): CallLikeExpression | undefined { + const target = findAncestor(node, n => !isRightSideOfPropertyAccess(n)); const callLike = target?.parent; - return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target ? callLike : undefined; + return callLike && isCallLikeExpression(callLike) && getInvokedExpression(callLike) === target ? callLike : undefined; } -function tryGetSignatureDeclaration(typeChecker: ts.TypeChecker, node: ts.Node): ts.SignatureDeclaration | undefined { +function tryGetSignatureDeclaration(typeChecker: TypeChecker, node: Node): SignatureDeclaration | undefined { const callLike = getAncestorCallLikeExpression(node); const signature = callLike && typeChecker.getResolvedSignature(callLike); // Don't go to a function type, go to the value having that type. - return ts.tryCast(signature && signature.declaration, (d): d is ts.SignatureDeclaration => ts.isFunctionLike(d) && !ts.isFunctionTypeNode(d)); + return tryCast(signature && signature.declaration, (d): d is SignatureDeclaration => isFunctionLike(d) && !isFunctionTypeNode(d)); } -function isConstructorLike(node: ts.Node): boolean { +function isConstructorLike(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructorType: - case ts.SyntaxKind.ConstructSignature: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: return true; default: return false; diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 703e742e18695..21d318d2b54cb 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -1,22 +1,37 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, AnyImportOrReExport, AssignmentDeclarationKind, BinaryExpression, BindingElement, CallExpression, + CancellationToken, canHaveModifiers, cast, Debug, ESMap, ExportAssignment, ExportDeclaration, FileReference, + findAncestor, forEach, getAssignmentDeclarationKind, getFirstIdentifier, getNameOfAccessExpression, + getSourceFileOfNode, getSymbolId, hasSyntacticModifier, Identifier, ImportCall, ImportClause, ImportDeclaration, + ImportEqualsDeclaration, importFromModuleSpecifier, ImportSpecifier, InternalSymbolName, isAccessExpression, + isBinaryExpression, isBindingElement, isCatchClause, isDefaultImport, isExportAssignment, isExportDeclaration, + isExportModifier, isExportSpecifier, isExternalModuleAugmentation, isExternalModuleSymbol, isImportCall, + isImportEqualsDeclaration, isImportTypeNode, isInJSFile, isJSDocTypedefTag, isModuleExportsAccessExpression, + isNamedExports, isNamespaceExport, isPrivateIdentifier, isPropertyAccessExpression, isShorthandPropertyAssignment, + isSourceFile, isStringLiteral, isVariableDeclaration, isVariableDeclarationInitializedToBareOrAccessedRequire, + isVariableStatement, Map, ModifierFlags, ModuleBlock, ModuleDeclaration, NamedImportsOrExports, NamespaceImport, + Node, nodeSeenTracker, Program, ReadonlySet, some, SourceFile, Statement, StringLiteral, StringLiteralLike, Symbol, + symbolEscapedNameNoDefault, SymbolFlags, symbolName, SyntaxKind, TypeChecker, ValidImportTypeNode, + VariableDeclaration, walkUpBindingElementsAndPatterns, +} from "./_namespaces/ts"; /* Code for finding imports of an exported symbol. Used only by FindAllReferences. */ /** @internal */ export interface ImportsResult { /** For every import of the symbol, the location and local symbol for the import. */ - importSearches: readonly [ts.Identifier, ts.Symbol][]; + importSearches: readonly [Identifier, Symbol][]; /** For rename imports/exports `{ foo as bar }`, `foo` is not a local, so it may be added as a reference immediately without further searching. */ - singleReferences: readonly (ts.Identifier | ts.StringLiteral)[]; + singleReferences: readonly (Identifier | StringLiteral)[]; /** List of source files that may (or may not) use the symbol via a namespace. (For UMD modules this is every file.) */ - indirectUsers: readonly ts.SourceFile[]; + indirectUsers: readonly SourceFile[]; } /** @internal */ -export type ImportTracker = (exportSymbol: ts.Symbol, exportInfo: ExportInfo, isForRename: boolean) => ImportsResult; +export type ImportTracker = (exportSymbol: Symbol, exportInfo: ExportInfo, isForRename: boolean) => ImportsResult; /** @internal */ /** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */ -export function createImportTracker(sourceFiles: readonly ts.SourceFile[], sourceFilesSet: ts.ReadonlySet, checker: ts.TypeChecker, cancellationToken: ts.CancellationToken | undefined): ImportTracker { +export function createImportTracker(sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet, checker: TypeChecker, cancellationToken: CancellationToken | undefined): ImportTracker { const allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken); return (exportSymbol, exportInfo, isForRename) => { const { directImports, indirectUsers } = getImportersForExport(sourceFiles, sourceFilesSet, allDirectImports, exportInfo, checker, cancellationToken); @@ -27,7 +42,7 @@ export function createImportTracker(sourceFiles: readonly ts.SourceFile[], sourc /** @internal */ /** Info about an exported symbol to perform recursive search on. */ export interface ExportInfo { - exportingModuleSymbol: ts.Symbol; + exportingModuleSymbol: Symbol; exportKind: ExportKind; } @@ -37,23 +52,23 @@ export const enum ExportKind { Named, Default, ExportEquals } /** @internal */ export const enum ImportExport { Import, Export } -interface AmbientModuleDeclaration extends ts.ModuleDeclaration { body?: ts.ModuleBlock; } -type SourceFileLike = ts.SourceFile | AmbientModuleDeclaration; +interface AmbientModuleDeclaration extends ModuleDeclaration { body?: ModuleBlock; } +type SourceFileLike = SourceFile | AmbientModuleDeclaration; // Identifier for the case of `const x = require("y")`. -type Importer = ts.AnyImportOrReExport | ts.ValidImportTypeNode | ts.Identifier; -type ImporterOrCallExpression = Importer | ts.CallExpression; +type Importer = AnyImportOrReExport | ValidImportTypeNode | Identifier; +type ImporterOrCallExpression = Importer | CallExpression; /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */ function getImportersForExport( - sourceFiles: readonly ts.SourceFile[], - sourceFilesSet: ts.ReadonlySet, - allDirectImports: ts.ESMap, + sourceFiles: readonly SourceFile[], + sourceFilesSet: ReadonlySet, + allDirectImports: ESMap, { exportingModuleSymbol, exportKind }: ExportInfo, - checker: ts.TypeChecker, - cancellationToken: ts.CancellationToken | undefined, -): { directImports: Importer[], indirectUsers: readonly ts.SourceFile[] } { - const markSeenDirectImport = ts.nodeSeenTracker(); - const markSeenIndirectUser = ts.nodeSeenTracker(); + checker: TypeChecker, + cancellationToken: CancellationToken | undefined, +): { directImports: Importer[], indirectUsers: readonly SourceFile[] } { + const markSeenDirectImport = nodeSeenTracker(); + const markSeenIndirectUser = nodeSeenTracker(); const directImports: Importer[] = []; const isAvailableThroughGlobal = !!exportingModuleSymbol.globalExports; const indirectUserDeclarations: SourceFileLike[] | undefined = isAvailableThroughGlobal ? undefined : []; @@ -62,7 +77,7 @@ function getImportersForExport( return { directImports, indirectUsers: getIndirectUsers() }; - function getIndirectUsers(): readonly ts.SourceFile[] { + function getIndirectUsers(): readonly SourceFile[] { if (isAvailableThroughGlobal) { // It has `export as namespace`, so anything could potentially use it. return sourceFiles; @@ -71,17 +86,17 @@ function getImportersForExport( // Module augmentations may use this module's exports without importing it. if (exportingModuleSymbol.declarations) { for (const decl of exportingModuleSymbol.declarations) { - if (ts.isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) { + if (isExternalModuleAugmentation(decl) && sourceFilesSet.has(decl.getSourceFile().fileName)) { addIndirectUser(decl); } } } // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that. - return indirectUserDeclarations!.map(ts.getSourceFileOfNode); + return indirectUserDeclarations!.map(getSourceFileOfNode); } - function handleDirectImports(exportingModuleSymbol: ts.Symbol): void { + function handleDirectImports(exportingModuleSymbol: Symbol): void { const theseDirectImports = getDirectImports(exportingModuleSymbol); if (theseDirectImports) { for (const direct of theseDirectImports) { @@ -92,16 +107,16 @@ function getImportersForExport( if (cancellationToken) cancellationToken.throwIfCancellationRequested(); switch (direct.kind) { - case ts.SyntaxKind.CallExpression: - if (ts.isImportCall(direct)) { + case SyntaxKind.CallExpression: + if (isImportCall(direct)) { handleImportCall(direct); break; } if (!isAvailableThroughGlobal) { const parent = direct.parent; - if (exportKind === ExportKind.ExportEquals && parent.kind === ts.SyntaxKind.VariableDeclaration) { - const { name } = parent as ts.VariableDeclaration; - if (name.kind === ts.SyntaxKind.Identifier) { + if (exportKind === ExportKind.ExportEquals && parent.kind === SyntaxKind.VariableDeclaration) { + const { name } = parent as VariableDeclaration; + if (name.kind === SyntaxKind.Identifier) { directImports.push(name); break; } @@ -109,30 +124,30 @@ function getImportersForExport( } break; - case ts.SyntaxKind.Identifier: // for 'const x = require("y"); + case SyntaxKind.Identifier: // for 'const x = require("y"); break; // TODO: GH#23879 - case ts.SyntaxKind.ImportEqualsDeclaration: - handleNamespaceImport(direct, direct.name, ts.hasSyntacticModifier(direct, ts.ModifierFlags.Export), /*alreadyAddedDirect*/ false); + case SyntaxKind.ImportEqualsDeclaration: + handleNamespaceImport(direct, direct.name, hasSyntacticModifier(direct, ModifierFlags.Export), /*alreadyAddedDirect*/ false); break; - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportDeclaration: directImports.push(direct); const namedBindings = direct.importClause && direct.importClause.namedBindings; - if (namedBindings && namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + if (namedBindings && namedBindings.kind === SyntaxKind.NamespaceImport) { handleNamespaceImport(direct, namedBindings.name, /*isReExport*/ false, /*alreadyAddedDirect*/ true); } - else if (!isAvailableThroughGlobal && ts.isDefaultImport(direct)) { + else if (!isAvailableThroughGlobal && isDefaultImport(direct)) { addIndirectUser(getSourceFileLikeForImportDeclaration(direct)); // Add a check for indirect uses to handle synthetic default imports } break; - case ts.SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportDeclaration: if (!direct.exportClause) { // This is `export * from "foo"`, so imports of this module may import the export too. handleDirectImports(getContainingModuleSymbol(direct, checker)); } - else if (direct.exportClause.kind === ts.SyntaxKind.NamespaceExport) { + else if (direct.exportClause.kind === SyntaxKind.NamespaceExport) { // `export * as foo from "foo"` add to indirect uses addIndirectUser(getSourceFileLikeForImportDeclaration(direct), /** addTransitiveDependencies */ true); } @@ -142,7 +157,7 @@ function getImportersForExport( } break; - case ts.SyntaxKind.ImportType: + case SyntaxKind.ImportType: // Only check for typeof import('xyz') if (!isAvailableThroughGlobal && direct.isTypeOf && !direct.qualifier && isExported(direct)) { addIndirectUser(direct.getSourceFile(), /** addTransitiveDependencies */ true); @@ -151,32 +166,32 @@ function getImportersForExport( break; default: - ts.Debug.failBadSyntaxKind(direct, "Unexpected import kind."); + Debug.failBadSyntaxKind(direct, "Unexpected import kind."); } } } } - function handleImportCall(importCall: ts.ImportCall) { - const top = ts.findAncestor(importCall, isAmbientModuleDeclaration) || importCall.getSourceFile(); + function handleImportCall(importCall: ImportCall) { + const top = findAncestor(importCall, isAmbientModuleDeclaration) || importCall.getSourceFile(); addIndirectUser(top, /** addTransitiveDependencies */ !!isExported(importCall, /** stopAtAmbientModule */ true)); } - function isExported(node: ts.Node, stopAtAmbientModule = false) { - return ts.findAncestor(node, node => { + function isExported(node: Node, stopAtAmbientModule = false) { + return findAncestor(node, node => { if (stopAtAmbientModule && isAmbientModuleDeclaration(node)) return "quit"; - return ts.canHaveModifiers(node) && ts.some(node.modifiers, ts.isExportModifier); + return canHaveModifiers(node) && some(node.modifiers, isExportModifier); }); } - function handleNamespaceImport(importDeclaration: ts.ImportEqualsDeclaration | ts.ImportDeclaration, name: ts.Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void { + function handleNamespaceImport(importDeclaration: ImportEqualsDeclaration | ImportDeclaration, name: Identifier, isReExport: boolean, alreadyAddedDirect: boolean): void { if (exportKind === ExportKind.ExportEquals) { // This is a direct import, not import-as-namespace. if (!alreadyAddedDirect) directImports.push(importDeclaration); } else if (!isAvailableThroughGlobal) { const sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration); - ts.Debug.assert(sourceFileLike.kind === ts.SyntaxKind.SourceFile || sourceFileLike.kind === ts.SyntaxKind.ModuleDeclaration); + Debug.assert(sourceFileLike.kind === SyntaxKind.SourceFile || sourceFileLike.kind === SyntaxKind.ModuleDeclaration); if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) { addIndirectUser(sourceFileLike, /** addTransitiveDependencies */ true); } @@ -188,7 +203,7 @@ function getImportersForExport( /** Adds a module and all of its transitive dependencies as possible indirect users. */ function addIndirectUser(sourceFileLike: SourceFileLike, addTransitiveDependencies = false): void { - ts.Debug.assert(!isAvailableThroughGlobal); + Debug.assert(!isAvailableThroughGlobal); const isNew = markSeenIndirectUser(sourceFileLike); if (!isNew) return; indirectUserDeclarations!.push(sourceFileLike); // TODO: GH#18217 @@ -196,19 +211,19 @@ function getImportersForExport( if (!addTransitiveDependencies) return; const moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol); if (!moduleSymbol) return; - ts.Debug.assert(!!(moduleSymbol.flags & ts.SymbolFlags.Module)); + Debug.assert(!!(moduleSymbol.flags & SymbolFlags.Module)); const directImports = getDirectImports(moduleSymbol); if (directImports) { for (const directImport of directImports) { - if (!ts.isImportTypeNode(directImport)) { + if (!isImportTypeNode(directImport)) { addIndirectUser(getSourceFileLikeForImportDeclaration(directImport), /** addTransitiveDependencies */ true); } } } } - function getDirectImports(moduleSymbol: ts.Symbol): ImporterOrCallExpression[] | undefined { - return allDirectImports.get(ts.getSymbolId(moduleSymbol).toString()); + function getDirectImports(moduleSymbol: Symbol): ImporterOrCallExpression[] | undefined { + return allDirectImports.get(getSymbolId(moduleSymbol).toString()); } } @@ -217,10 +232,10 @@ function getImportersForExport( * The returned `importSearches` will result in the entire source file being searched. * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced. */ -function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: ts.Symbol, exportKind: ExportKind, checker: ts.TypeChecker, isForRename: boolean): Pick { - const importSearches: [ts.Identifier, ts.Symbol][] = []; - const singleReferences: (ts.Identifier | ts.StringLiteral)[] = []; - function addSearch(location: ts.Identifier, symbol: ts.Symbol): void { +function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker, isForRename: boolean): Pick { + const importSearches: [Identifier, Symbol][] = []; + const singleReferences: (Identifier | StringLiteral)[] = []; + function addSearch(location: Identifier, symbol: Symbol): void { importSearches.push([location, symbol]); } @@ -233,22 +248,22 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t return { importSearches, singleReferences }; function handleImport(decl: Importer): void { - if (decl.kind === ts.SyntaxKind.ImportEqualsDeclaration) { + if (decl.kind === SyntaxKind.ImportEqualsDeclaration) { if (isExternalModuleImportEquals(decl)) { handleNamespaceImportLike(decl.name); } return; } - if (decl.kind === ts.SyntaxKind.Identifier) { + if (decl.kind === SyntaxKind.Identifier) { handleNamespaceImportLike(decl); return; } - if (decl.kind === ts.SyntaxKind.ImportType) { + if (decl.kind === SyntaxKind.ImportType) { if (decl.qualifier) { - const firstIdentifier = ts.getFirstIdentifier(decl.qualifier); - if (firstIdentifier.escapedText === ts.symbolName(exportSymbol)) { + const firstIdentifier = getFirstIdentifier(decl.qualifier); + if (firstIdentifier.escapedText === symbolName(exportSymbol)) { singleReferences.push(firstIdentifier); } } @@ -259,12 +274,12 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t } // Ignore if there's a grammar error - if (decl.moduleSpecifier!.kind !== ts.SyntaxKind.StringLiteral) { + if (decl.moduleSpecifier!.kind !== SyntaxKind.StringLiteral) { return; } - if (decl.kind === ts.SyntaxKind.ExportDeclaration) { - if (decl.exportClause && ts.isNamedExports(decl.exportClause)) { + if (decl.kind === SyntaxKind.ExportDeclaration) { + if (decl.exportClause && isNamedExports(decl.exportClause)) { searchForNamedImport(decl.exportClause); } return; @@ -274,24 +289,24 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t if (namedBindings) { switch (namedBindings.kind) { - case ts.SyntaxKind.NamespaceImport: + case SyntaxKind.NamespaceImport: handleNamespaceImportLike(namedBindings.name); break; - case ts.SyntaxKind.NamedImports: + case SyntaxKind.NamedImports: // 'default' might be accessed as a named import `{ default as foo }`. if (exportKind === ExportKind.Named || exportKind === ExportKind.Default) { searchForNamedImport(namedBindings); } break; default: - ts.Debug.assertNever(namedBindings); + Debug.assertNever(namedBindings); } } // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals. // If a default import has the same name as the default export, allow to rename it. // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. - if (name && (exportKind === ExportKind.Default || exportKind === ExportKind.ExportEquals) && (!isForRename || name.escapedText === ts.symbolEscapedNameNoDefault(exportSymbol))) { + if (name && (exportKind === ExportKind.Default || exportKind === ExportKind.ExportEquals) && (!isForRename || name.escapedText === symbolEscapedNameNoDefault(exportSymbol))) { const defaultImportAlias = checker.getSymbolAtLocation(name)!; addSearch(name, defaultImportAlias); } @@ -302,14 +317,14 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t * An `export =` may be imported by this syntax, so it may be a direct import. * If it's not a direct import, it will be in `indirectUsers`, so we don't have to do anything here. */ - function handleNamespaceImportLike(importName: ts.Identifier): void { + function handleNamespaceImportLike(importName: Identifier): void { // Don't rename an import that already has a different name than the export. if (exportKind === ExportKind.ExportEquals && (!isForRename || isNameMatch(importName.escapedText))) { addSearch(importName, checker.getSymbolAtLocation(importName)!); } } - function searchForNamedImport(namedBindings: ts.NamedImportsOrExports | undefined): void { + function searchForNamedImport(namedBindings: NamedImportsOrExports | undefined): void { if (!namedBindings) { return; } @@ -331,7 +346,7 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t } } else { - const localSymbol = element.kind === ts.SyntaxKind.ExportSpecifier && element.propertyName + const localSymbol = element.kind === SyntaxKind.ExportSpecifier && element.propertyName ? checker.getExportSpecifierLocalTargetSymbol(element)! // For re-exporting under a different name, we want to get the re-exported symbol. : checker.getSymbolAtLocation(name)!; addSearch(name, localSymbol); @@ -339,20 +354,20 @@ function getSearchesFromDirectImports(directImports: Importer[], exportSymbol: t } } - function isNameMatch(name: ts.__String): boolean { + function isNameMatch(name: __String): boolean { // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports - return name === exportSymbol.escapedName || exportKind !== ExportKind.Named && name === ts.InternalSymbolName.Default; + return name === exportSymbol.escapedName || exportKind !== ExportKind.Named && name === InternalSymbolName.Default; } } /** Returns 'true' is the namespace 'name' is re-exported from this module, and 'false' if it is only used locally. */ -function findNamespaceReExports(sourceFileLike: SourceFileLike, name: ts.Identifier, checker: ts.TypeChecker): boolean { +function findNamespaceReExports(sourceFileLike: SourceFileLike, name: Identifier, checker: TypeChecker): boolean { const namespaceImportSymbol = checker.getSymbolAtLocation(name); return !!forEachPossibleImportOrExportStatement(sourceFileLike, statement => { - if (!ts.isExportDeclaration(statement)) return; + if (!isExportDeclaration(statement)) return; const { exportClause, moduleSpecifier } = statement; - return !moduleSpecifier && exportClause && ts.isNamedExports(exportClause) && + return !moduleSpecifier && exportClause && isNamedExports(exportClause) && exportClause.elements.some(element => checker.getExportSpecifierLocalTargetSymbol(element) === namespaceImportSymbol); }); } @@ -360,16 +375,16 @@ function findNamespaceReExports(sourceFileLike: SourceFileLike, name: ts.Identif /** @internal */ export type ModuleReference = /** "import" also includes require() calls. */ - | { kind: "import", literal: ts.StringLiteralLike } + | { kind: "import", literal: StringLiteralLike } /** or */ - | { kind: "reference", referencingFile: ts.SourceFile, ref: ts.FileReference }; + | { kind: "reference", referencingFile: SourceFile, ref: FileReference }; /** @internal */ -export function findModuleReferences(program: ts.Program, sourceFiles: readonly ts.SourceFile[], searchModuleSymbol: ts.Symbol): ModuleReference[] { +export function findModuleReferences(program: Program, sourceFiles: readonly SourceFile[], searchModuleSymbol: Symbol): ModuleReference[] { const refs: ModuleReference[] = []; const checker = program.getTypeChecker(); for (const referencingFile of sourceFiles) { const searchSourceFile = searchModuleSymbol.valueDeclaration; - if (searchSourceFile?.kind === ts.SyntaxKind.SourceFile) { + if (searchSourceFile?.kind === SyntaxKind.SourceFile) { for (const ref of referencingFile.referencedFiles) { if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) { refs.push({ kind: "reference", referencingFile, ref }); @@ -377,7 +392,7 @@ export function findModuleReferences(program: ts.Program, sourceFiles: readonly } for (const ref of referencingFile.typeReferenceDirectives) { const referenced = program.getResolvedTypeReferenceDirectives().get(ref.fileName, ref.resolutionMode || referencingFile.impliedNodeFormat); - if (referenced !== undefined && referenced.resolvedFileName === (searchSourceFile as ts.SourceFile).fileName) { + if (referenced !== undefined && referenced.resolvedFileName === (searchSourceFile as SourceFile).fileName) { refs.push({ kind: "reference", referencingFile, ref }); } } @@ -394,15 +409,15 @@ export function findModuleReferences(program: ts.Program, sourceFiles: readonly } /** Returns a map from a module symbol Id to all import statements that directly reference the module. */ -function getDirectImportsMap(sourceFiles: readonly ts.SourceFile[], checker: ts.TypeChecker, cancellationToken: ts.CancellationToken | undefined): ts.ESMap { - const map = new ts.Map(); +function getDirectImportsMap(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken | undefined): ESMap { + const map = new Map(); for (const sourceFile of sourceFiles) { if (cancellationToken) cancellationToken.throwIfCancellationRequested(); forEachImport(sourceFile, (importDecl, moduleSpecifier) => { const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); if (moduleSymbol) { - const id = ts.getSymbolId(moduleSymbol).toString(); + const id = getSymbolId(moduleSymbol).toString(); let imports = map.get(id); if (!imports) { map.set(id, imports = []); @@ -416,32 +431,32 @@ function getDirectImportsMap(sourceFiles: readonly ts.SourceFile[], checker: ts. } /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */ -function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: ts.Statement) => T) { - return ts.forEach(sourceFileLike.kind === ts.SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217 - action(statement) || (isAmbientModuleDeclaration(statement) && ts.forEach(statement.body && statement.body.statements, action))); +function forEachPossibleImportOrExportStatement(sourceFileLike: SourceFileLike, action: (statement: Statement) => T) { + return forEach(sourceFileLike.kind === SyntaxKind.SourceFile ? sourceFileLike.statements : sourceFileLike.body!.statements, statement => // TODO: GH#18217 + action(statement) || (isAmbientModuleDeclaration(statement) && forEach(statement.body && statement.body.statements, action))); } /** Calls `action` for each import, re-export, or require() in a file. */ -function forEachImport(sourceFile: ts.SourceFile, action: (importStatement: ImporterOrCallExpression, imported: ts.StringLiteralLike) => void): void { +function forEachImport(sourceFile: SourceFile, action: (importStatement: ImporterOrCallExpression, imported: StringLiteralLike) => void): void { if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) { for (const i of sourceFile.imports) { - action(ts.importFromModuleSpecifier(i), i); + action(importFromModuleSpecifier(i), i); } } else { forEachPossibleImportOrExportStatement(sourceFile, statement => { switch (statement.kind) { - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ImportDeclaration: { - const decl = statement as ts.ImportDeclaration | ts.ExportDeclaration; - if (decl.moduleSpecifier && ts.isStringLiteral(decl.moduleSpecifier)) { + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ImportDeclaration: { + const decl = statement as ImportDeclaration | ExportDeclaration; + if (decl.moduleSpecifier && isStringLiteral(decl.moduleSpecifier)) { action(decl, decl.moduleSpecifier); } break; } - case ts.SyntaxKind.ImportEqualsDeclaration: { - const decl = statement as ts.ImportEqualsDeclaration; + case SyntaxKind.ImportEqualsDeclaration: { + const decl = statement as ImportEqualsDeclaration; if (isExternalModuleImportEquals(decl)) { action(decl, decl.moduleReference.expression); } @@ -455,12 +470,12 @@ function forEachImport(sourceFile: ts.SourceFile, action: (importStatement: Impo /** @internal */ export interface ImportedSymbol { kind: ImportExport.Import; - symbol: ts.Symbol; + symbol: Symbol; } /** @internal */ export interface ExportedSymbol { kind: ImportExport.Export; - symbol: ts.Symbol; + symbol: Symbol; exportInfo: ExportInfo; } @@ -472,17 +487,17 @@ export interface ExportedSymbol { * This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`. * @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here. */ -export function getImportOrExportSymbol(node: ts.Node, symbol: ts.Symbol, checker: ts.TypeChecker, comingFromExport: boolean): ImportedSymbol | ExportedSymbol | undefined { +export function getImportOrExportSymbol(node: Node, symbol: Symbol, checker: TypeChecker, comingFromExport: boolean): ImportedSymbol | ExportedSymbol | undefined { return comingFromExport ? getExport() : getExport() || getImport(); function getExport(): ExportedSymbol | ImportedSymbol | undefined { const { parent } = node; const grandparent = parent.parent; if (symbol.exportSymbol) { - if (parent.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (parent.kind === SyntaxKind.PropertyAccessExpression) { // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use. // So check that we are at the declaration. - return symbol.declarations?.some(d => d === parent) && ts.isBinaryExpression(grandparent) + return symbol.declarations?.some(d => d === parent) && isBinaryExpression(grandparent) ? getSpecialPropertyExport(grandparent, /*useLhsSymbol*/ false) : undefined; } @@ -492,8 +507,8 @@ export function getImportOrExportSymbol(node: ts.Node, symbol: ts.Symbol, checke } else { const exportNode = getExportNode(parent, node); - if (exportNode && ts.hasSyntacticModifier(exportNode, ts.ModifierFlags.Export)) { - if (ts.isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { + if (exportNode && hasSyntacticModifier(exportNode, ModifierFlags.Export)) { + if (isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) { // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement. if (comingFromExport) { return undefined; @@ -506,50 +521,50 @@ export function getImportOrExportSymbol(node: ts.Node, symbol: ts.Symbol, checke return exportInfo(symbol, getExportKindForDeclaration(exportNode)); } } - else if (ts.isNamespaceExport(parent)) { + else if (isNamespaceExport(parent)) { return exportInfo(symbol, ExportKind.Named); } // If we are in `export = a;` or `export default a;`, `parent` is the export assignment. - else if (ts.isExportAssignment(parent)) { + else if (isExportAssignment(parent)) { return getExportAssignmentExport(parent); } // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment. - else if (ts.isExportAssignment(grandparent)) { + else if (isExportAssignment(grandparent)) { return getExportAssignmentExport(grandparent); } // Similar for `module.exports =` and `exports.A =`. - else if (ts.isBinaryExpression(parent)) { + else if (isBinaryExpression(parent)) { return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true); } - else if (ts.isBinaryExpression(grandparent)) { + else if (isBinaryExpression(grandparent)) { return getSpecialPropertyExport(grandparent, /*useLhsSymbol*/ true); } - else if (ts.isJSDocTypedefTag(parent)) { + else if (isJSDocTypedefTag(parent)) { return exportInfo(symbol, ExportKind.Named); } } - function getExportAssignmentExport(ex: ts.ExportAssignment): ExportedSymbol | undefined { + function getExportAssignmentExport(ex: ExportAssignment): ExportedSymbol | undefined { // Get the symbol for the `export =` node; its parent is the module it's the export of. if (!ex.symbol.parent) return undefined; const exportKind = ex.isExportEquals ? ExportKind.ExportEquals : ExportKind.Default; return { kind: ImportExport.Export, symbol, exportInfo: { exportingModuleSymbol: ex.symbol.parent, exportKind } }; } - function getSpecialPropertyExport(node: ts.BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined { + function getSpecialPropertyExport(node: BinaryExpression, useLhsSymbol: boolean): ExportedSymbol | undefined { let kind: ExportKind; - switch (ts.getAssignmentDeclarationKind(node)) { - case ts.AssignmentDeclarationKind.ExportsProperty: + switch (getAssignmentDeclarationKind(node)) { + case AssignmentDeclarationKind.ExportsProperty: kind = ExportKind.Named; break; - case ts.AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.ModuleExports: kind = ExportKind.ExportEquals; break; default: return undefined; } - const sym = useLhsSymbol ? checker.getSymbolAtLocation(ts.getNameOfAccessExpression(ts.cast(node.left, ts.isAccessExpression))) : symbol; + const sym = useLhsSymbol ? checker.getSymbolAtLocation(getNameOfAccessExpression(cast(node.left, isAccessExpression))) : symbol; return sym && exportInfo(sym, kind); } } @@ -573,36 +588,36 @@ export function getImportOrExportSymbol(node: ts.Node, symbol: ts.Symbol, checke // If the import has a different name than the export, do not continue searching. // If `importedName` is undefined, do continue searching as the export is anonymous. // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.) - const importedName = ts.symbolEscapedNameNoDefault(importedSymbol); - if (importedName === undefined || importedName === ts.InternalSymbolName.Default || importedName === symbol.escapedName) { + const importedName = symbolEscapedNameNoDefault(importedSymbol); + if (importedName === undefined || importedName === InternalSymbolName.Default || importedName === symbol.escapedName) { return { kind: ImportExport.Import, symbol: importedSymbol }; } } - function exportInfo(symbol: ts.Symbol, kind: ExportKind): ExportedSymbol | undefined { + function exportInfo(symbol: Symbol, kind: ExportKind): ExportedSymbol | undefined { const exportInfo = getExportInfo(symbol, kind, checker); return exportInfo && { kind: ImportExport.Export, symbol, exportInfo }; } // Not meant for use with export specifiers or export assignment. - function getExportKindForDeclaration(node: ts.Node): ExportKind { - return ts.hasSyntacticModifier(node, ts.ModifierFlags.Default) ? ExportKind.Default : ExportKind.Named; + function getExportKindForDeclaration(node: Node): ExportKind { + return hasSyntacticModifier(node, ModifierFlags.Default) ? ExportKind.Default : ExportKind.Named; } } -function getExportEqualsLocalSymbol(importedSymbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol | undefined { - if (importedSymbol.flags & ts.SymbolFlags.Alias) { +function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker): Symbol | undefined { + if (importedSymbol.flags & SymbolFlags.Alias) { return checker.getImmediateAliasedSymbol(importedSymbol); } - const decl = ts.Debug.checkDefined(importedSymbol.valueDeclaration); - if (ts.isExportAssignment(decl)) { // `export = class {}` + const decl = Debug.checkDefined(importedSymbol.valueDeclaration); + if (isExportAssignment(decl)) { // `export = class {}` return decl.expression.symbol; } - else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}` + else if (isBinaryExpression(decl)) { // `module.exports = class {}` return decl.right.symbol; } - else if (ts.isSourceFile(decl)) { // json module + else if (isSourceFile(decl)) { // json module return decl.symbol; } return undefined; @@ -610,60 +625,60 @@ function getExportEqualsLocalSymbol(importedSymbol: ts.Symbol, checker: ts.TypeC // If a reference is a class expression, the exported node would be its parent. // If a reference is a variable declaration, the exported node would be the variable statement. -function getExportNode(parent: ts.Node, node: ts.Node): ts.Node | undefined { - const declaration = ts.isVariableDeclaration(parent) ? parent : ts.isBindingElement(parent) ? ts.walkUpBindingElementsAndPatterns(parent) : undefined; +function getExportNode(parent: Node, node: Node): Node | undefined { + const declaration = isVariableDeclaration(parent) ? parent : isBindingElement(parent) ? walkUpBindingElementsAndPatterns(parent) : undefined; if (declaration) { - return (parent as ts.VariableDeclaration | ts.BindingElement).name !== node ? undefined : - ts.isCatchClause(declaration.parent) ? undefined : ts.isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined; + return (parent as VariableDeclaration | BindingElement).name !== node ? undefined : + isCatchClause(declaration.parent) ? undefined : isVariableStatement(declaration.parent.parent) ? declaration.parent.parent : undefined; } else { return parent; } } -function isNodeImport(node: ts.Node): boolean { +function isNodeImport(node: Node): boolean { const { parent } = node; switch (parent.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: - return (parent as ts.ImportEqualsDeclaration).name === node && isExternalModuleImportEquals(parent as ts.ImportEqualsDeclaration); - case ts.SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + return (parent as ImportEqualsDeclaration).name === node && isExternalModuleImportEquals(parent as ImportEqualsDeclaration); + case SyntaxKind.ImportSpecifier: // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`. - return !(parent as ts.ImportSpecifier).propertyName; - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceImport: - ts.Debug.assert((parent as ts.ImportClause | ts.NamespaceImport).name === node); + return !(parent as ImportSpecifier).propertyName; + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + Debug.assert((parent as ImportClause | NamespaceImport).name === node); return true; - case ts.SyntaxKind.BindingElement: - return ts.isInJSFile(node) && ts.isVariableDeclarationInitializedToBareOrAccessedRequire(parent.parent.parent); + case SyntaxKind.BindingElement: + return isInJSFile(node) && isVariableDeclarationInitializedToBareOrAccessedRequire(parent.parent.parent); default: return false; } } /** @internal */ -export function getExportInfo(exportSymbol: ts.Symbol, exportKind: ExportKind, checker: ts.TypeChecker): ExportInfo | undefined { +export function getExportInfo(exportSymbol: Symbol, exportKind: ExportKind, checker: TypeChecker): ExportInfo | undefined { const moduleSymbol = exportSymbol.parent; if (!moduleSymbol) return undefined; // This can happen if an `export` is not at the top-level (which is a compile error). const exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation. // `export` may appear in a namespace. In that case, just rely on global search. - return ts.isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; + return isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol, exportKind } : undefined; } /** If at an export specifier, go to the symbol it refers to. */ -function skipExportSpecifierSymbol(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol { +function skipExportSpecifierSymbol(symbol: Symbol, checker: TypeChecker): Symbol { // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does. if (symbol.declarations) { for (const declaration of symbol.declarations) { - if (ts.isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) { + if (isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) { return checker.getExportSpecifierLocalTargetSymbol(declaration)!; } - else if (ts.isPropertyAccessExpression(declaration) && ts.isModuleExportsAccessExpression(declaration.expression) && !ts.isPrivateIdentifier(declaration.name)) { + else if (isPropertyAccessExpression(declaration) && isModuleExportsAccessExpression(declaration.expression) && !isPrivateIdentifier(declaration.name)) { // Export of form 'module.exports.propName = expr'; return checker.getSymbolAtLocation(declaration)!; } - else if (ts.isShorthandPropertyAssignment(declaration) - && ts.isBinaryExpression(declaration.parent.parent) - && ts.getAssignmentDeclarationKind(declaration.parent.parent) === ts.AssignmentDeclarationKind.ModuleExports) { + else if (isShorthandPropertyAssignment(declaration) + && isBinaryExpression(declaration.parent.parent) + && getAssignmentDeclarationKind(declaration.parent.parent) === AssignmentDeclarationKind.ModuleExports) { return checker.getExportSpecifierLocalTargetSymbol(declaration.name)!; } } @@ -671,27 +686,27 @@ function skipExportSpecifierSymbol(symbol: ts.Symbol, checker: ts.TypeChecker): return symbol; } -function getContainingModuleSymbol(importer: Importer, checker: ts.TypeChecker): ts.Symbol { +function getContainingModuleSymbol(importer: Importer, checker: TypeChecker): Symbol { return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol); } function getSourceFileLikeForImportDeclaration(node: ImporterOrCallExpression): SourceFileLike { - if (node.kind === ts.SyntaxKind.CallExpression) { + if (node.kind === SyntaxKind.CallExpression) { return node.getSourceFile(); } const { parent } = node; - if (parent.kind === ts.SyntaxKind.SourceFile) { - return parent as ts.SourceFile; + if (parent.kind === SyntaxKind.SourceFile) { + return parent as SourceFile; } - ts.Debug.assert(parent.kind === ts.SyntaxKind.ModuleBlock); - return ts.cast(parent.parent, isAmbientModuleDeclaration); + Debug.assert(parent.kind === SyntaxKind.ModuleBlock); + return cast(parent.parent, isAmbientModuleDeclaration); } -function isAmbientModuleDeclaration(node: ts.Node): node is AmbientModuleDeclaration { - return node.kind === ts.SyntaxKind.ModuleDeclaration && (node as ts.ModuleDeclaration).name.kind === ts.SyntaxKind.StringLiteral; +function isAmbientModuleDeclaration(node: Node): node is AmbientModuleDeclaration { + return node.kind === SyntaxKind.ModuleDeclaration && (node as ModuleDeclaration).name.kind === SyntaxKind.StringLiteral; } -function isExternalModuleImportEquals(eq: ts.ImportEqualsDeclaration): eq is ts.ImportEqualsDeclaration & { moduleReference: { expression: ts.StringLiteral } } { - return eq.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference && eq.moduleReference.expression.kind === ts.SyntaxKind.StringLiteral; +function isExternalModuleImportEquals(eq: ImportEqualsDeclaration): eq is ImportEqualsDeclaration & { moduleReference: { expression: StringLiteral } } { + return eq.moduleReference.kind === SyntaxKind.ExternalModuleReference && eq.moduleReference.expression.kind === SyntaxKind.StringLiteral; } diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index b04dbec126022..2d890d7f31cfc 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -1,4 +1,18 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, ArrowFunction, CallExpression, createPrinter, Debug, EmitHint, EnumMember, equateStringsCaseInsensitive, + Expression, findChildOfKind, forEachChild, FunctionDeclaration, FunctionExpression, FunctionLikeDeclaration, + GetAccessorDeclaration, getEffectiveReturnTypeNode, getEffectiveTypeAnnotationNode, getLanguageVariant, + getLeadingCommentRanges, hasContextSensitiveParameters, Identifier, InlayHint, InlayHintKind, InlayHintsContext, + isArrowFunction, isAssertionExpression, isBindingPattern, isCallExpression, isEnumMember, + isExpressionWithTypeArguments, isFunctionDeclaration, isFunctionExpression, isFunctionLikeDeclaration, + isGetAccessorDeclaration, isIdentifier, isIdentifierText, isInfinityOrNaNString, isLiteralExpression, + isMethodDeclaration, isNewExpression, isObjectLiteralExpression, isParameter, isParameterDeclaration, + isPropertyAccessExpression, isPropertyDeclaration, isTypeNode, isVarConst, isVariableDeclaration, MethodDeclaration, + NewExpression, Node, NodeBuilderFlags, ParameterDeclaration, PrefixUnaryExpression, PrinterOptions, + PropertyDeclaration, Signature, skipParentheses, some, Symbol, SymbolFlags, SyntaxKind, textSpanIntersectsWith, + Type, TypeFormatFlags, unescapeLeadingUnderscores, UserPreferences, usingSingleLineStringWriter, + VariableDeclaration, +} from "./_namespaces/ts"; const maxHintsLength = 30; @@ -6,83 +20,83 @@ const leadingParameterNameCommentRegexFactory = (name: string) => { return new RegExp(`^\\s?/\\*\\*?\\s?${name}\\s?\\*\\/\\s?$`); }; -function shouldShowParameterNameHints(preferences: ts.UserPreferences) { +function shouldShowParameterNameHints(preferences: UserPreferences) { return preferences.includeInlayParameterNameHints === "literals" || preferences.includeInlayParameterNameHints === "all"; } -function shouldShowLiteralParameterNameHintsOnly(preferences: ts.UserPreferences) { +function shouldShowLiteralParameterNameHintsOnly(preferences: UserPreferences) { return preferences.includeInlayParameterNameHints === "literals"; } /** @internal */ -export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] { +export function provideInlayHints(context: InlayHintsContext): InlayHint[] { const { file, program, span, cancellationToken, preferences } = context; const sourceFileText = file.text; const compilerOptions = program.getCompilerOptions(); const checker = program.getTypeChecker(); - const result: ts.InlayHint[] = []; + const result: InlayHint[] = []; visitor(file); return result; - function visitor(node: ts.Node): true | undefined { + function visitor(node: Node): true | undefined { if (!node || node.getFullWidth() === 0) { return; } switch (node.kind) { - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ArrowFunction: cancellationToken.throwIfCancellationRequested(); } - if (!ts.textSpanIntersectsWith(span, node.pos, node.getFullWidth())) { + if (!textSpanIntersectsWith(span, node.pos, node.getFullWidth())) { return; } - if (ts.isTypeNode(node) && !ts.isExpressionWithTypeArguments(node)) { + if (isTypeNode(node) && !isExpressionWithTypeArguments(node)) { return; } - if (preferences.includeInlayVariableTypeHints && ts.isVariableDeclaration(node)) { + if (preferences.includeInlayVariableTypeHints && isVariableDeclaration(node)) { visitVariableLikeDeclaration(node); } - else if (preferences.includeInlayPropertyDeclarationTypeHints && ts.isPropertyDeclaration(node)) { + else if (preferences.includeInlayPropertyDeclarationTypeHints && isPropertyDeclaration(node)) { visitVariableLikeDeclaration(node); } - else if (preferences.includeInlayEnumMemberValueHints && ts.isEnumMember(node)) { + else if (preferences.includeInlayEnumMemberValueHints && isEnumMember(node)) { visitEnumMember(node); } - else if (shouldShowParameterNameHints(preferences) && (ts.isCallExpression(node) || ts.isNewExpression(node))) { + else if (shouldShowParameterNameHints(preferences) && (isCallExpression(node) || isNewExpression(node))) { visitCallOrNewExpression(node); } else { - if (preferences.includeInlayFunctionParameterTypeHints && ts.isFunctionLikeDeclaration(node) && ts.hasContextSensitiveParameters(node)) { + if (preferences.includeInlayFunctionParameterTypeHints && isFunctionLikeDeclaration(node) && hasContextSensitiveParameters(node)) { visitFunctionLikeForParameterType(node); } if (preferences.includeInlayFunctionLikeReturnTypeHints && isSignatureSupportingReturnAnnotation(node)) { visitFunctionDeclarationLikeForReturnType(node); } } - return ts.forEachChild(node, visitor); + return forEachChild(node, visitor); } - function isSignatureSupportingReturnAnnotation(node: ts.Node): node is ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration | ts.GetAccessorDeclaration { - return ts.isArrowFunction(node) || ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isGetAccessorDeclaration(node); + function isSignatureSupportingReturnAnnotation(node: Node): node is FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration { + return isArrowFunction(node) || isFunctionExpression(node) || isFunctionDeclaration(node) || isMethodDeclaration(node) || isGetAccessorDeclaration(node); } function addParameterHints(text: string, position: number, isFirstVariadicArgument: boolean) { result.push({ text: `${isFirstVariadicArgument ? "..." : ""}${truncation(text, maxHintsLength)}:`, position, - kind: ts.InlayHintKind.Parameter, + kind: InlayHintKind.Parameter, whitespaceAfter: true, }); } @@ -91,7 +105,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] result.push({ text: `: ${truncation(text, maxHintsLength)}`, position, - kind: ts.InlayHintKind.Type, + kind: InlayHintKind.Type, whitespaceBefore: true, }); } @@ -100,12 +114,12 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] result.push({ text: `= ${truncation(text, maxHintsLength)}`, position, - kind: ts.InlayHintKind.Enum, + kind: InlayHintKind.Enum, whitespaceBefore: true, }); } - function visitEnumMember(member: ts.EnumMember) { + function visitEnumMember(member: EnumMember) { if (member.initializer) { return; } @@ -116,16 +130,16 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] } } - function isModuleReferenceType(type: ts.Type) { - return type.symbol && (type.symbol.flags & ts.SymbolFlags.Module); + function isModuleReferenceType(type: Type) { + return type.symbol && (type.symbol.flags & SymbolFlags.Module); } - function visitVariableLikeDeclaration(decl: ts.VariableDeclaration | ts.PropertyDeclaration) { - if (!decl.initializer || ts.isBindingPattern(decl.name) || ts.isVariableDeclaration(decl) && !isHintableDeclaration(decl)) { + function visitVariableLikeDeclaration(decl: VariableDeclaration | PropertyDeclaration) { + if (!decl.initializer || isBindingPattern(decl.name) || isVariableDeclaration(decl) && !isHintableDeclaration(decl)) { return; } - const effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(decl); + const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(decl); if (effectiveTypeAnnotation) { return; } @@ -137,7 +151,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] const typeDisplayString = printTypeInSingleLine(declarationType); if (typeDisplayString) { - const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false && ts.equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString); + const isVariableNameMatchesType = preferences.includeInlayVariableTypeHintsWhenTypeMatchesName === false && equateStringsCaseInsensitive(decl.name.getText(), typeDisplayString); if (isVariableNameMatchesType) { return; } @@ -145,13 +159,13 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] } } - function visitCallOrNewExpression(expr: ts.CallExpression | ts.NewExpression) { + function visitCallOrNewExpression(expr: CallExpression | NewExpression) { const args = expr.arguments; if (!args || !args.length) { return; } - const candidates: ts.Signature[] = []; + const candidates: Signature[] = []; const signature = checker.getResolvedSignatureForSignatureHelp(expr, candidates); if (!signature || !candidates.length) { return; @@ -159,7 +173,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] for (let i = 0; i < args.length; ++i) { const originalArg = args[i]; - const arg = ts.skipParentheses(originalArg); + const arg = skipParentheses(originalArg); if (shouldShowLiteralParameterNameHintsOnly(preferences) && !isHintableLiteral(arg)) { continue; } @@ -172,7 +186,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] continue; } - const name = ts.unescapeLeadingUnderscores(parameterName); + const name = unescapeLeadingUnderscores(parameterName); if (leadingCommentsContainsParameterName(arg, name)) { continue; } @@ -182,58 +196,58 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] } } - function identifierOrAccessExpressionPostfixMatchesParameterName(expr: ts.Expression, parameterName: ts.__String) { - if (ts.isIdentifier(expr)) { + function identifierOrAccessExpressionPostfixMatchesParameterName(expr: Expression, parameterName: __String) { + if (isIdentifier(expr)) { return expr.text === parameterName; } - if (ts.isPropertyAccessExpression(expr)) { + if (isPropertyAccessExpression(expr)) { return expr.name.text === parameterName; } return false; } - function leadingCommentsContainsParameterName(node: ts.Node, name: string) { - if (!ts.isIdentifierText(name, compilerOptions.target, ts.getLanguageVariant(file.scriptKind))) { + function leadingCommentsContainsParameterName(node: Node, name: string) { + if (!isIdentifierText(name, compilerOptions.target, getLanguageVariant(file.scriptKind))) { return false; } - const ranges = ts.getLeadingCommentRanges(sourceFileText, node.pos); + const ranges = getLeadingCommentRanges(sourceFileText, node.pos); if (!ranges?.length) { return false; } const regex = leadingParameterNameCommentRegexFactory(name); - return ts.some(ranges, range => regex.test(sourceFileText.substring(range.pos, range.end))); + return some(ranges, range => regex.test(sourceFileText.substring(range.pos, range.end))); } - function isHintableLiteral(node: ts.Node) { + function isHintableLiteral(node: Node) { switch (node.kind) { - case ts.SyntaxKind.PrefixUnaryExpression: { - const operand = (node as ts.PrefixUnaryExpression).operand; - return ts.isLiteralExpression(operand) || ts.isIdentifier(operand) && ts.isInfinityOrNaNString(operand.escapedText); + case SyntaxKind.PrefixUnaryExpression: { + const operand = (node as PrefixUnaryExpression).operand; + return isLiteralExpression(operand) || isIdentifier(operand) && isInfinityOrNaNString(operand.escapedText); } - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TemplateExpression: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateExpression: return true; - case ts.SyntaxKind.Identifier: { - const name = (node as ts.Identifier).escapedText; - return isUndefined(name) || ts.isInfinityOrNaNString(name); + case SyntaxKind.Identifier: { + const name = (node as Identifier).escapedText; + return isUndefined(name) || isInfinityOrNaNString(name); } } - return ts.isLiteralExpression(node); + return isLiteralExpression(node); } - function visitFunctionDeclarationLikeForReturnType(decl: ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration | ts.GetAccessorDeclaration) { - if (ts.isArrowFunction(decl)) { - if (!ts.findChildOfKind(decl, ts.SyntaxKind.OpenParenToken, file)) { + function visitFunctionDeclarationLikeForReturnType(decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration) { + if (isArrowFunction(decl)) { + if (!findChildOfKind(decl, SyntaxKind.OpenParenToken, file)) { return; } } - const effectiveTypeAnnotation = ts.getEffectiveReturnTypeNode(decl); + const effectiveTypeAnnotation = getEffectiveReturnTypeNode(decl); if (effectiveTypeAnnotation || !decl.body) { return; } @@ -256,15 +270,15 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] addTypeHints(typeDisplayString, getTypeAnnotationPosition(decl)); } - function getTypeAnnotationPosition(decl: ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression | ts.MethodDeclaration | ts.GetAccessorDeclaration) { - const closeParenToken = ts.findChildOfKind(decl, ts.SyntaxKind.CloseParenToken, file); + function getTypeAnnotationPosition(decl: FunctionDeclaration | ArrowFunction | FunctionExpression | MethodDeclaration | GetAccessorDeclaration) { + const closeParenToken = findChildOfKind(decl, SyntaxKind.CloseParenToken, file); if (closeParenToken) { return closeParenToken.end; } return decl.parameters.end; } - function visitFunctionLikeForParameterType(node: ts.FunctionLikeDeclaration) { + function visitFunctionLikeForParameterType(node: FunctionLikeDeclaration) { const signature = checker.getSignatureFromDeclaration(node); if (!signature) { return; @@ -276,7 +290,7 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] continue; } - const effectiveTypeAnnotation = ts.getEffectiveTypeAnnotationNode(param); + const effectiveTypeAnnotation = getEffectiveTypeAnnotationNode(param); if (effectiveTypeAnnotation) { continue; } @@ -290,9 +304,9 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] } } - function getParameterDeclarationTypeDisplayString(symbol: ts.Symbol) { + function getParameterDeclarationTypeDisplayString(symbol: Symbol) { const valueDeclaration = symbol.valueDeclaration; - if (!valueDeclaration || !ts.isParameter(valueDeclaration)) { + if (!valueDeclaration || !isParameter(valueDeclaration)) { return undefined; } @@ -311,26 +325,26 @@ export function provideInlayHints(context: ts.InlayHintsContext): ts.InlayHint[] return text; } - function printTypeInSingleLine(type: ts.Type) { - const flags = ts.NodeBuilderFlags.IgnoreErrors | ts.TypeFormatFlags.AllowUniqueESSymbolType | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope; - const options: ts.PrinterOptions = { removeComments: true }; - const printer = ts.createPrinter(options); + function printTypeInSingleLine(type: Type) { + const flags = NodeBuilderFlags.IgnoreErrors | TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope; + const options: PrinterOptions = { removeComments: true }; + const printer = createPrinter(options); - return ts.usingSingleLineStringWriter(writer => { + return usingSingleLineStringWriter(writer => { const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); - ts.Debug.assertIsDefined(typeNode, "should always get typenode"); - printer.writeNode(ts.EmitHint.Unspecified, typeNode, /*sourceFile*/ file, writer); + Debug.assertIsDefined(typeNode, "should always get typenode"); + printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ file, writer); }); } - function isUndefined(name: ts.__String) { + function isUndefined(name: __String) { return name === "undefined"; } - function isHintableDeclaration(node: ts.VariableDeclaration | ts.ParameterDeclaration) { - if ((ts.isParameterDeclaration(node) || ts.isVariableDeclaration(node) && ts.isVarConst(node)) && node.initializer) { - const initializer = ts.skipParentheses(node.initializer); - return !(isHintableLiteral(initializer) || ts.isNewExpression(initializer) || ts.isObjectLiteralExpression(initializer) || ts.isAssertionExpression(initializer)); + function isHintableDeclaration(node: VariableDeclaration | ParameterDeclaration) { + if ((isParameterDeclaration(node) || isVariableDeclaration(node) && isVarConst(node)) && node.initializer) { + const initializer = skipParentheses(node.initializer); + return !(isHintableLiteral(initializer) || isNewExpression(initializer) || isObjectLiteralExpression(initializer) || isAssertionExpression(initializer)); } return true; } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 8e5cf8c6309e7..a8335e8e77589 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -1,4 +1,19 @@ -import * as ts from "./_namespaces/ts"; +import { + arraysEqual, ArrowFunction, AssignmentDeclarationKind, BinaryExpression, buildLinkParts, ClassExpression, + CompletionEntry, CompletionEntryDetails, Completions, ConstructorDeclaration, contains, Declaration, + DocCommentTemplateOptions, emptyArray, Expression, ExpressionStatement, find, findAncestor, flatMap, flatten, + forEach, forEachAncestor, forEachReturnStatement, forEachUnique, FunctionDeclaration, FunctionExpression, + getAssignmentDeclarationKind, getJSDocCommentsAndTags, getJSDocTags, getLineStartPositionForPosition, + getTokenAtPosition, hasJSDocNodes, hasJSFileExtension, intersperse, isArrowFunction, isBlock, + isConstructorDeclaration, isExpression, isFunctionExpression, isFunctionLike, isFunctionLikeDeclaration, + isFunctionTypeNode, isIdentifier, isJSDoc, isJSDocParameterTag, isWhiteSpaceSingleLine, JSDoc, JSDocAugmentsTag, + JSDocCallbackTag, JSDocComment, JSDocImplementsTag, JSDocParameterTag, JSDocPropertyTag, JSDocSeeTag, JSDocTag, + JSDocTagInfo, JSDocTemplateTag, JSDocTypedefTag, JSDocTypeTag, lastOrUndefined, length, lineBreakPart, map, + mapDefined, MethodDeclaration, MethodSignature, Node, ParameterDeclaration, parameterNamePart, + ParenthesizedExpression, PropertyAssignment, PropertyDeclaration, propertyNamePart, PropertySignature, + punctuationPart, ScriptElementKind, SourceFile, spacePart, startsWith, SymbolDisplayPart, SyntaxKind, TextInsertion, + textPart, typeAliasNamePart, TypeChecker, typeParameterNamePart, VariableStatement, +} from "./_namespaces/ts"; const jsDocTagNames = [ "abstract", @@ -80,73 +95,73 @@ const jsDocTagNames = [ "virtual", "yields" ]; -let jsDocTagNameCompletionEntries: ts.CompletionEntry[]; -let jsDocTagCompletionEntries: ts.CompletionEntry[]; +let jsDocTagNameCompletionEntries: CompletionEntry[]; +let jsDocTagCompletionEntries: CompletionEntry[]; /** @internal */ -export function getJsDocCommentsFromDeclarations(declarations: readonly ts.Declaration[], checker?: ts.TypeChecker): ts.SymbolDisplayPart[] { +export function getJsDocCommentsFromDeclarations(declarations: readonly Declaration[], checker?: TypeChecker): SymbolDisplayPart[] { // Only collect doc comments from duplicate declarations once: // In case of a union property there might be same declaration multiple times // which only varies in type parameter // Eg. const a: Array | Array; a.length // The property length will have two declarations of property length coming // from Array - Array and Array - const parts: ts.SymbolDisplayPart[][] = []; - ts.forEachUnique(declarations, declaration => { + const parts: SymbolDisplayPart[][] = []; + forEachUnique(declarations, declaration => { for (const jsdoc of getCommentHavingNodes(declaration)) { - const inheritDoc = ts.isJSDoc(jsdoc) && jsdoc.tags && ts.find(jsdoc.tags, t => t.kind === ts.SyntaxKind.JSDocTag && (t.tagName.escapedText === "inheritDoc" || t.tagName.escapedText === "inheritdoc")); + const inheritDoc = isJSDoc(jsdoc) && jsdoc.tags && find(jsdoc.tags, t => t.kind === SyntaxKind.JSDocTag && (t.tagName.escapedText === "inheritDoc" || t.tagName.escapedText === "inheritdoc")); // skip comments containing @typedefs since they're not associated with particular declarations // Exceptions: // - @typedefs are themselves declarations with associated comments // - @param or @return indicate that the author thinks of it as a 'local' @typedef that's part of the function documentation if (jsdoc.comment === undefined && !inheritDoc - || ts.isJSDoc(jsdoc) - && declaration.kind !== ts.SyntaxKind.JSDocTypedefTag && declaration.kind !== ts.SyntaxKind.JSDocCallbackTag + || isJSDoc(jsdoc) + && declaration.kind !== SyntaxKind.JSDocTypedefTag && declaration.kind !== SyntaxKind.JSDocCallbackTag && jsdoc.tags - && jsdoc.tags.some(t => t.kind === ts.SyntaxKind.JSDocTypedefTag || t.kind === ts.SyntaxKind.JSDocCallbackTag) - && !jsdoc.tags.some(t => t.kind === ts.SyntaxKind.JSDocParameterTag || t.kind === ts.SyntaxKind.JSDocReturnTag)) { + && jsdoc.tags.some(t => t.kind === SyntaxKind.JSDocTypedefTag || t.kind === SyntaxKind.JSDocCallbackTag) + && !jsdoc.tags.some(t => t.kind === SyntaxKind.JSDocParameterTag || t.kind === SyntaxKind.JSDocReturnTag)) { continue; } let newparts = jsdoc.comment ? getDisplayPartsFromComment(jsdoc.comment, checker) : []; if (inheritDoc && inheritDoc.comment) { newparts = newparts.concat(getDisplayPartsFromComment(inheritDoc.comment, checker)); } - if (!ts.contains(parts, newparts, isIdenticalListOfDisplayParts)) { + if (!contains(parts, newparts, isIdenticalListOfDisplayParts)) { parts.push(newparts); } } }); - return ts.flatten(ts.intersperse(parts, [ts.lineBreakPart()])); + return flatten(intersperse(parts, [lineBreakPart()])); } -function isIdenticalListOfDisplayParts(parts1: ts.SymbolDisplayPart[], parts2: ts.SymbolDisplayPart[]) { - return ts.arraysEqual(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text); +function isIdenticalListOfDisplayParts(parts1: SymbolDisplayPart[], parts2: SymbolDisplayPart[]) { + return arraysEqual(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text); } -function getCommentHavingNodes(declaration: ts.Declaration): readonly (ts.JSDoc | ts.JSDocTag)[] { +function getCommentHavingNodes(declaration: Declaration): readonly (JSDoc | JSDocTag)[] { switch (declaration.kind) { - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocPropertyTag: - return [declaration as ts.JSDocPropertyTag]; - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocTypedefTag: - return [(declaration as ts.JSDocTypedefTag), (declaration as ts.JSDocTypedefTag).parent]; + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + return [declaration as JSDocPropertyTag]; + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocTypedefTag: + return [(declaration as JSDocTypedefTag), (declaration as JSDocTypedefTag).parent]; default: - return ts.getJSDocCommentsAndTags(declaration); + return getJSDocCommentsAndTags(declaration); } } /** @internal */ -export function getJsDocTagsFromDeclarations(declarations?: ts.Declaration[], checker?: ts.TypeChecker): ts.JSDocTagInfo[] { +export function getJsDocTagsFromDeclarations(declarations?: Declaration[], checker?: TypeChecker): JSDocTagInfo[] { // Only collect doc comments from duplicate declarations once. - const infos: ts.JSDocTagInfo[] = []; - ts.forEachUnique(declarations, declaration => { - const tags = ts.getJSDocTags(declaration); + const infos: JSDocTagInfo[] = []; + forEachUnique(declarations, declaration => { + const tags = getJSDocTags(declaration); // skip comments containing @typedefs since they're not associated with particular declarations // Exceptions: // - @param or @return indicate that the author thinks of it as a 'local' @typedef that's part of the function documentation - if (tags.some(t => t.kind === ts.SyntaxKind.JSDocTypedefTag || t.kind === ts.SyntaxKind.JSDocCallbackTag) - && !tags.some(t => t.kind === ts.SyntaxKind.JSDocParameterTag || t.kind === ts.SyntaxKind.JSDocReturnTag)) { + if (tags.some(t => t.kind === SyntaxKind.JSDocTypedefTag || t.kind === SyntaxKind.JSDocCallbackTag) + && !tags.some(t => t.kind === SyntaxKind.JSDocParameterTag || t.kind === SyntaxKind.JSDocReturnTag)) { return; } for (const tag of tags) { @@ -156,54 +171,54 @@ export function getJsDocTagsFromDeclarations(declarations?: ts.Declaration[], ch return infos; } -function getDisplayPartsFromComment(comment: string | readonly ts.JSDocComment[], checker: ts.TypeChecker | undefined): ts.SymbolDisplayPart[] { +function getDisplayPartsFromComment(comment: string | readonly JSDocComment[], checker: TypeChecker | undefined): SymbolDisplayPart[] { if (typeof comment === "string") { - return [ts.textPart(comment)]; + return [textPart(comment)]; } - return ts.flatMap( + return flatMap( comment, - node => node.kind === ts.SyntaxKind.JSDocText ? [ts.textPart(node.text)] : ts.buildLinkParts(node, checker) - ) as ts.SymbolDisplayPart[]; + node => node.kind === SyntaxKind.JSDocText ? [textPart(node.text)] : buildLinkParts(node, checker) + ) as SymbolDisplayPart[]; } -function getCommentDisplayParts(tag: ts.JSDocTag, checker?: ts.TypeChecker): ts.SymbolDisplayPart[] | undefined { +function getCommentDisplayParts(tag: JSDocTag, checker?: TypeChecker): SymbolDisplayPart[] | undefined { const { comment, kind } = tag; const namePart = getTagNameDisplayPart(kind); switch (kind) { - case ts.SyntaxKind.JSDocImplementsTag: - return withNode((tag as ts.JSDocImplementsTag).class); - case ts.SyntaxKind.JSDocAugmentsTag: - return withNode((tag as ts.JSDocAugmentsTag).class); - case ts.SyntaxKind.JSDocTemplateTag: - const templateTag = tag as ts.JSDocTemplateTag; - const displayParts: ts.SymbolDisplayPart[] = []; + case SyntaxKind.JSDocImplementsTag: + return withNode((tag as JSDocImplementsTag).class); + case SyntaxKind.JSDocAugmentsTag: + return withNode((tag as JSDocAugmentsTag).class); + case SyntaxKind.JSDocTemplateTag: + const templateTag = tag as JSDocTemplateTag; + const displayParts: SymbolDisplayPart[] = []; if (templateTag.constraint) { - displayParts.push(ts.textPart(templateTag.constraint.getText())); + displayParts.push(textPart(templateTag.constraint.getText())); } - if (ts.length(templateTag.typeParameters)) { - if (ts.length(displayParts)) { - displayParts.push(ts.spacePart()); + if (length(templateTag.typeParameters)) { + if (length(displayParts)) { + displayParts.push(spacePart()); } const lastTypeParameter = templateTag.typeParameters[templateTag.typeParameters.length - 1]; - ts.forEach(templateTag.typeParameters, tp => { + forEach(templateTag.typeParameters, tp => { displayParts.push(namePart(tp.getText())); if (lastTypeParameter !== tp) { - displayParts.push(...[ts.punctuationPart(ts.SyntaxKind.CommaToken), ts.spacePart()]); + displayParts.push(...[punctuationPart(SyntaxKind.CommaToken), spacePart()]); } }); } if (comment) { - displayParts.push(...[ts.spacePart(), ...getDisplayPartsFromComment(comment, checker)]); + displayParts.push(...[spacePart(), ...getDisplayPartsFromComment(comment, checker)]); } return displayParts; - case ts.SyntaxKind.JSDocTypeTag: - return withNode((tag as ts.JSDocTypeTag).typeExpression); - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocPropertyTag: - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocSeeTag: - const { name } = tag as ts.JSDocTypedefTag | ts.JSDocCallbackTag | ts.JSDocPropertyTag | ts.JSDocParameterTag | ts.JSDocSeeTag; + case SyntaxKind.JSDocTypeTag: + return withNode((tag as JSDocTypeTag).typeExpression); + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocSeeTag: + const { name } = tag as JSDocTypedefTag | JSDocCallbackTag | JSDocPropertyTag | JSDocParameterTag | JSDocSeeTag; return name ? withNode(name) : comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); @@ -211,49 +226,49 @@ function getCommentDisplayParts(tag: ts.JSDocTag, checker?: ts.TypeChecker): ts. return comment === undefined ? undefined : getDisplayPartsFromComment(comment, checker); } - function withNode(node: ts.Node) { + function withNode(node: Node) { return addComment(node.getText()); } function addComment(s: string) { if (comment) { if (s.match(/^https?$/)) { - return [ts.textPart(s), ...getDisplayPartsFromComment(comment, checker)]; + return [textPart(s), ...getDisplayPartsFromComment(comment, checker)]; } else { - return [namePart(s), ts.spacePart(), ...getDisplayPartsFromComment(comment, checker)]; + return [namePart(s), spacePart(), ...getDisplayPartsFromComment(comment, checker)]; } } else { - return [ts.textPart(s)]; + return [textPart(s)]; } } } -function getTagNameDisplayPart(kind: ts.SyntaxKind): (text: string) => ts.SymbolDisplayPart { +function getTagNameDisplayPart(kind: SyntaxKind): (text: string) => SymbolDisplayPart { switch (kind) { - case ts.SyntaxKind.JSDocParameterTag: - return ts.parameterNamePart; - case ts.SyntaxKind.JSDocPropertyTag: - return ts.propertyNamePart; - case ts.SyntaxKind.JSDocTemplateTag: - return ts.typeParameterNamePart; - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: - return ts.typeAliasNamePart; + case SyntaxKind.JSDocParameterTag: + return parameterNamePart; + case SyntaxKind.JSDocPropertyTag: + return propertyNamePart; + case SyntaxKind.JSDocTemplateTag: + return typeParameterNamePart; + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: + return typeAliasNamePart; default: - return ts.textPart; + return textPart; } } /** @internal */ -export function getJSDocTagNameCompletions(): ts.CompletionEntry[] { - return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, tagName => { +export function getJSDocTagNameCompletions(): CompletionEntry[] { + return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = map(jsDocTagNames, tagName => { return { name: tagName, - kind: ts.ScriptElementKind.keyword, + kind: ScriptElementKind.keyword, kindModifiers: "", - sortText: ts.Completions.SortText.LocationPriority, + sortText: Completions.SortText.LocationPriority, }; })); } @@ -262,61 +277,61 @@ export function getJSDocTagNameCompletions(): ts.CompletionEntry[] { export const getJSDocTagNameCompletionDetails = getJSDocTagCompletionDetails; /** @internal */ -export function getJSDocTagCompletions(): ts.CompletionEntry[] { - return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, tagName => { +export function getJSDocTagCompletions(): CompletionEntry[] { + return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = map(jsDocTagNames, tagName => { return { name: `@${tagName}`, - kind: ts.ScriptElementKind.keyword, + kind: ScriptElementKind.keyword, kindModifiers: "", - sortText: ts.Completions.SortText.LocationPriority + sortText: Completions.SortText.LocationPriority }; })); } /** @internal */ -export function getJSDocTagCompletionDetails(name: string): ts.CompletionEntryDetails { +export function getJSDocTagCompletionDetails(name: string): CompletionEntryDetails { return { name, - kind: ts.ScriptElementKind.unknown, // TODO: should have its own kind? + kind: ScriptElementKind.unknown, // TODO: should have its own kind? kindModifiers: "", - displayParts: [ts.textPart(name)], - documentation: ts.emptyArray, + displayParts: [textPart(name)], + documentation: emptyArray, tags: undefined, codeActions: undefined, }; } /** @internal */ -export function getJSDocParameterNameCompletions(tag: ts.JSDocParameterTag): ts.CompletionEntry[] { - if (!ts.isIdentifier(tag.name)) { - return ts.emptyArray; +export function getJSDocParameterNameCompletions(tag: JSDocParameterTag): CompletionEntry[] { + if (!isIdentifier(tag.name)) { + return emptyArray; } const nameThusFar = tag.name.text; const jsdoc = tag.parent; const fn = jsdoc.parent; - if (!ts.isFunctionLike(fn)) return []; + if (!isFunctionLike(fn)) return []; - return ts.mapDefined(fn.parameters, param => { - if (!ts.isIdentifier(param.name)) return undefined; + return mapDefined(fn.parameters, param => { + if (!isIdentifier(param.name)) return undefined; const name = param.name.text; - if (jsdoc.tags!.some(t => t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name) // TODO: GH#18217 - || nameThusFar !== undefined && !ts.startsWith(name, nameThusFar)) { + if (jsdoc.tags!.some(t => t !== tag && isJSDocParameterTag(t) && isIdentifier(t.name) && t.name.escapedText === name) // TODO: GH#18217 + || nameThusFar !== undefined && !startsWith(name, nameThusFar)) { return undefined; } - return { name, kind: ts.ScriptElementKind.parameterElement, kindModifiers: "", sortText: ts.Completions.SortText.LocationPriority }; + return { name, kind: ScriptElementKind.parameterElement, kindModifiers: "", sortText: Completions.SortText.LocationPriority }; }); } /** @internal */ -export function getJSDocParameterNameCompletionDetails(name: string): ts.CompletionEntryDetails { +export function getJSDocParameterNameCompletionDetails(name: string): CompletionEntryDetails { return { name, - kind: ts.ScriptElementKind.parameterElement, + kind: ScriptElementKind.parameterElement, kindModifiers: "", - displayParts: [ts.textPart(name)], - documentation: ts.emptyArray, + displayParts: [textPart(name)], + documentation: emptyArray, tags: undefined, codeActions: undefined, }; @@ -346,10 +361,10 @@ export function getJSDocParameterNameCompletionDetails(name: string): ts.Complet * @param position The (character-indexed) position in the file where the check should * be performed. */ -export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: ts.SourceFile, position: number, options?: ts.DocCommentTemplateOptions): ts.TextInsertion | undefined { - const tokenAtPos = ts.getTokenAtPosition(sourceFile, position); - const existingDocComment = ts.findAncestor(tokenAtPos, ts.isJSDoc); - if (existingDocComment && (existingDocComment.comment !== undefined || ts.length(existingDocComment.tags))) { +export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: SourceFile, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined { + const tokenAtPos = getTokenAtPosition(sourceFile, position); + const existingDocComment = findAncestor(tokenAtPos, isJSDoc); + if (existingDocComment && (existingDocComment.comment !== undefined || length(existingDocComment.tags))) { // Non-empty comment already exists. return undefined; } @@ -366,8 +381,8 @@ export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: ts. } const { commentOwner, parameters, hasReturn } = commentOwnerInfo; - const commentOwnerJsDoc = ts.hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? commentOwner.jsDoc : undefined; - const lastJsDoc = ts.lastOrUndefined(commentOwnerJsDoc); + const commentOwnerJsDoc = hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? commentOwner.jsDoc : undefined; + const lastJsDoc = lastOrUndefined(commentOwnerJsDoc); if (commentOwner.getStart(sourceFile) < position || lastJsDoc && existingDocComment @@ -376,7 +391,7 @@ export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: ts. } const indentationStr = getIndentationStringAtPosition(sourceFile, position); - const isJavaScriptFile = ts.hasJSFileExtension(sourceFile.fileName); + const isJavaScriptFile = hasJSFileExtension(sourceFile.fileName); const tags = (parameters ? parameterDocComments(parameters || [], isJavaScriptFile, indentationStr, newLine) : "") + (hasReturn ? returnsDocComment(indentationStr, newLine) : ""); @@ -404,17 +419,17 @@ export function getDocCommentTemplateAtPosition(newLine: string, sourceFile: ts. return { newText: openComment + closeComment, caretOffset: 3 }; } -function getIndentationStringAtPosition(sourceFile: ts.SourceFile, position: number): string { +function getIndentationStringAtPosition(sourceFile: SourceFile, position: number): string { const { text } = sourceFile; - const lineStart = ts.getLineStartPositionForPosition(position, sourceFile); + const lineStart = getLineStartPositionForPosition(position, sourceFile); let pos = lineStart; - for (; pos <= position && ts.isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++); + for (; pos <= position && isWhiteSpaceSingleLine(text.charCodeAt(pos)); pos++); return text.slice(lineStart, pos); } -function parameterDocComments(parameters: readonly ts.ParameterDeclaration[], isJavaScriptFile: boolean, indentationStr: string, newLine: string): string { +function parameterDocComments(parameters: readonly ParameterDeclaration[], isJavaScriptFile: boolean, indentationStr: string, newLine: string): string { return parameters.map(({ name, dotDotDotToken }, i) => { - const paramName = name.kind === ts.SyntaxKind.Identifier ? name.text : "param" + i; + const paramName = name.kind === SyntaxKind.Identifier ? name.text : "param" + i; const type = isJavaScriptFile ? (dotDotDotToken ? "{...any} " : "{any} ") : ""; return `${indentationStr} * @param ${type}${paramName}${newLine}`; }).join(""); @@ -425,43 +440,43 @@ function returnsDocComment(indentationStr: string, newLine: string) { } interface CommentOwnerInfo { - readonly commentOwner: ts.Node; - readonly parameters?: readonly ts.ParameterDeclaration[]; + readonly commentOwner: Node; + readonly parameters?: readonly ParameterDeclaration[]; readonly hasReturn?: boolean; } -function getCommentOwnerInfo(tokenAtPos: ts.Node, options: ts.DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined { - return ts.forEachAncestor(tokenAtPos, n => getCommentOwnerInfoWorker(n, options)); +function getCommentOwnerInfo(tokenAtPos: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined { + return forEachAncestor(tokenAtPos, n => getCommentOwnerInfoWorker(n, options)); } -function getCommentOwnerInfoWorker(commentOwner: ts.Node, options: ts.DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined | "quit" { +function getCommentOwnerInfoWorker(commentOwner: Node, options: DocCommentTemplateOptions | undefined): CommentOwnerInfo | undefined | "quit" { switch (commentOwner.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.ArrowFunction: - const host = commentOwner as ts.ArrowFunction | ts.FunctionDeclaration | ts.MethodDeclaration | ts.ConstructorDeclaration | ts.MethodSignature; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.MethodSignature: + case SyntaxKind.ArrowFunction: + const host = commentOwner as ArrowFunction | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature; return { commentOwner, parameters: host.parameters, hasReturn: hasReturn(host, options) }; - case ts.SyntaxKind.PropertyAssignment: - return getCommentOwnerInfoWorker((commentOwner as ts.PropertyAssignment).initializer, options); + case SyntaxKind.PropertyAssignment: + return getCommentOwnerInfoWorker((commentOwner as PropertyAssignment).initializer, options); - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.TypeAliasDeclaration: return { commentOwner }; - case ts.SyntaxKind.PropertySignature: { - const host = commentOwner as ts.PropertySignature; - return host.type && ts.isFunctionTypeNode(host.type) + case SyntaxKind.PropertySignature: { + const host = commentOwner as PropertySignature; + return host.type && isFunctionTypeNode(host.type) ? { commentOwner, parameters: host.type.parameters, hasReturn: hasReturn(host.type, options) } : { commentOwner }; } - case ts.SyntaxKind.VariableStatement: { - const varStatement = commentOwner as ts.VariableStatement; + case SyntaxKind.VariableStatement: { + const varStatement = commentOwner as VariableStatement; const varDeclarations = varStatement.declarationList.declarations; const host = varDeclarations.length === 1 && varDeclarations[0].initializer ? getRightHandSideOfAssignment(varDeclarations[0].initializer) @@ -471,50 +486,50 @@ function getCommentOwnerInfoWorker(commentOwner: ts.Node, options: ts.DocComment : { commentOwner }; } - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: return "quit"; - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.ModuleDeclaration: // If in walking up the tree, we hit a a nested namespace declaration, // then we must be somewhere within a dotted namespace name; however we don't // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'. - return commentOwner.parent.kind === ts.SyntaxKind.ModuleDeclaration ? undefined : { commentOwner }; + return commentOwner.parent.kind === SyntaxKind.ModuleDeclaration ? undefined : { commentOwner }; - case ts.SyntaxKind.ExpressionStatement: - return getCommentOwnerInfoWorker((commentOwner as ts.ExpressionStatement).expression, options); - case ts.SyntaxKind.BinaryExpression: { - const be = commentOwner as ts.BinaryExpression; - if (ts.getAssignmentDeclarationKind(be) === ts.AssignmentDeclarationKind.None) { + case SyntaxKind.ExpressionStatement: + return getCommentOwnerInfoWorker((commentOwner as ExpressionStatement).expression, options); + case SyntaxKind.BinaryExpression: { + const be = commentOwner as BinaryExpression; + if (getAssignmentDeclarationKind(be) === AssignmentDeclarationKind.None) { return "quit"; } - return ts.isFunctionLike(be.right) + return isFunctionLike(be.right) ? { commentOwner, parameters: be.right.parameters, hasReturn: hasReturn(be.right, options) } : { commentOwner }; } - case ts.SyntaxKind.PropertyDeclaration: - const init = (commentOwner as ts.PropertyDeclaration).initializer; - if (init && (ts.isFunctionExpression(init) || ts.isArrowFunction(init))) { + case SyntaxKind.PropertyDeclaration: + const init = (commentOwner as PropertyDeclaration).initializer; + if (init && (isFunctionExpression(init) || isArrowFunction(init))) { return { commentOwner, parameters: init.parameters, hasReturn: hasReturn(init, options) }; } } } -function hasReturn(node: ts.Node, options: ts.DocCommentTemplateOptions | undefined) { +function hasReturn(node: Node, options: DocCommentTemplateOptions | undefined) { return !!options?.generateReturnInDocTemplate && - (ts.isFunctionTypeNode(node) || ts.isArrowFunction(node) && ts.isExpression(node.body) - || ts.isFunctionLikeDeclaration(node) && node.body && ts.isBlock(node.body) && !!ts.forEachReturnStatement(node.body, n => n)); + (isFunctionTypeNode(node) || isArrowFunction(node) && isExpression(node.body) + || isFunctionLikeDeclaration(node) && node.body && isBlock(node.body) && !!forEachReturnStatement(node.body, n => n)); } -function getRightHandSideOfAssignment(rightHandSide: ts.Expression): ts.FunctionExpression | ts.ArrowFunction | ts.ConstructorDeclaration | undefined { - while (rightHandSide.kind === ts.SyntaxKind.ParenthesizedExpression) { - rightHandSide = (rightHandSide as ts.ParenthesizedExpression).expression; +function getRightHandSideOfAssignment(rightHandSide: Expression): FunctionExpression | ArrowFunction | ConstructorDeclaration | undefined { + while (rightHandSide.kind === SyntaxKind.ParenthesizedExpression) { + rightHandSide = (rightHandSide as ParenthesizedExpression).expression; } switch (rightHandSide.kind) { - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - return (rightHandSide as ts.FunctionExpression); - case ts.SyntaxKind.ClassExpression: - return ts.find((rightHandSide as ts.ClassExpression).members, ts.isConstructorDeclaration); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return (rightHandSide as FunctionExpression); + case SyntaxKind.ClassExpression: + return find((rightHandSide as ClassExpression).members, isConstructorDeclaration); } } diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 91389e873c790..0d0f78140556d 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -1,17 +1,23 @@ -import * as ts from "./_namespaces/ts"; +import { + CancellationToken, compareStringsCaseSensitiveUI, compareValues, createPatternMatcher, createTextSpanFromNode, + Declaration, emptyArray, Expression, getContainerNode, getNameOfDeclaration, getNodeKind, getNodeModifiers, + getTextOfIdentifierOrLiteral, Identifier, ImportClause, ImportEqualsDeclaration, ImportSpecifier, + isPropertyAccessExpression, isPropertyNameLiteral, NavigateToItem, Node, PatternMatcher, PatternMatchKind, Push, + ScriptElementKind, SourceFile, SyntaxKind, TypeChecker, +} from "./_namespaces/ts"; interface RawNavigateToItem { readonly name: string; readonly fileName: string; - readonly matchKind: ts.PatternMatchKind; + readonly matchKind: PatternMatchKind; readonly isCaseSensitive: boolean; - readonly declaration: ts.Declaration; + readonly declaration: Declaration; } /** @internal */ -export function getNavigateToItems(sourceFiles: readonly ts.SourceFile[], checker: ts.TypeChecker, cancellationToken: ts.CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): ts.NavigateToItem[] { - const patternMatcher = ts.createPatternMatcher(searchValue); - if (!patternMatcher) return ts.emptyArray; +export function getNavigateToItems(sourceFiles: readonly SourceFile[], checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number | undefined, excludeDtsFiles: boolean): NavigateToItem[] { + const patternMatcher = createPatternMatcher(searchValue); + if (!patternMatcher) return emptyArray; const rawItems: RawNavigateToItem[] = []; // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] @@ -31,7 +37,7 @@ export function getNavigateToItems(sourceFiles: readonly ts.SourceFile[], checke return (maxResultCount === undefined ? rawItems : rawItems.slice(0, maxResultCount)).map(createNavigateToItem); } -function getItemsFromNamedDeclaration(patternMatcher: ts.PatternMatcher, name: string, declarations: readonly ts.Declaration[], checker: ts.TypeChecker, fileName: string, rawItems: ts.Push): void { +function getItemsFromNamedDeclaration(patternMatcher: PatternMatcher, name: string, declarations: readonly Declaration[], checker: TypeChecker, fileName: string, rawItems: Push): void { // First do a quick check to see if the name of the declaration matches the // last portion of the (possibly) dotted name they're searching for. const match = patternMatcher.getMatchForLastSegmentOfPattern(name); @@ -55,12 +61,12 @@ function getItemsFromNamedDeclaration(patternMatcher: ts.PatternMatcher, name: s } } -function shouldKeepItem(declaration: ts.Declaration, checker: ts.TypeChecker): boolean { +function shouldKeepItem(declaration: Declaration, checker: TypeChecker): boolean { switch (declaration.kind) { - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ImportEqualsDeclaration: - const importer = checker.getSymbolAtLocation((declaration as ts.ImportClause | ts.ImportSpecifier | ts.ImportEqualsDeclaration).name!)!; // TODO: GH#18217 + case SyntaxKind.ImportClause: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + const importer = checker.getSymbolAtLocation((declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration).name!)!; // TODO: GH#18217 const imported = checker.getAliasedSymbol(importer); return importer.escapedName !== imported.escapedName; default: @@ -68,44 +74,44 @@ function shouldKeepItem(declaration: ts.Declaration, checker: ts.TypeChecker): b } } -function tryAddSingleDeclarationName(declaration: ts.Declaration, containers: ts.Push): boolean { - const name = ts.getNameOfDeclaration(declaration); - return !!name && (pushLiteral(name, containers) || name.kind === ts.SyntaxKind.ComputedPropertyName && tryAddComputedPropertyName(name.expression, containers)); +function tryAddSingleDeclarationName(declaration: Declaration, containers: Push): boolean { + const name = getNameOfDeclaration(declaration); + return !!name && (pushLiteral(name, containers) || name.kind === SyntaxKind.ComputedPropertyName && tryAddComputedPropertyName(name.expression, containers)); } // Only added the names of computed properties if they're simple dotted expressions, like: // // [X.Y.Z]() { } -function tryAddComputedPropertyName(expression: ts.Expression, containers: ts.Push): boolean { +function tryAddComputedPropertyName(expression: Expression, containers: Push): boolean { return pushLiteral(expression, containers) - || ts.isPropertyAccessExpression(expression) && (containers.push(expression.name.text), true) && tryAddComputedPropertyName(expression.expression, containers); + || isPropertyAccessExpression(expression) && (containers.push(expression.name.text), true) && tryAddComputedPropertyName(expression.expression, containers); } -function pushLiteral(node: ts.Node, containers: ts.Push): boolean { - return ts.isPropertyNameLiteral(node) && (containers.push(ts.getTextOfIdentifierOrLiteral(node)), true); +function pushLiteral(node: Node, containers: Push): boolean { + return isPropertyNameLiteral(node) && (containers.push(getTextOfIdentifierOrLiteral(node)), true); } -function getContainers(declaration: ts.Declaration): readonly string[] { +function getContainers(declaration: Declaration): readonly string[] { const containers: string[] = []; // First, if we started with a computed property name, then add all but the last // portion into the container array. - const name = ts.getNameOfDeclaration(declaration); - if (name && name.kind === ts.SyntaxKind.ComputedPropertyName && !tryAddComputedPropertyName(name.expression, containers)) { - return ts.emptyArray; + const name = getNameOfDeclaration(declaration); + if (name && name.kind === SyntaxKind.ComputedPropertyName && !tryAddComputedPropertyName(name.expression, containers)) { + return emptyArray; } // Don't include the last portion. containers.shift(); // Now, walk up our containers, adding all their names to the container array. - let container = ts.getContainerNode(declaration); + let container = getContainerNode(declaration); while (container) { if (!tryAddSingleDeclarationName(container, containers)) { - return ts.emptyArray; + return emptyArray; } - container = ts.getContainerNode(container); + container = getContainerNode(container); } return containers.reverse(); @@ -113,24 +119,24 @@ function getContainers(declaration: ts.Declaration): readonly string[] { function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem) { // TODO(cyrusn): get the gamut of comparisons that VS already uses here. - return ts.compareValues(i1.matchKind, i2.matchKind) - || ts.compareStringsCaseSensitiveUI(i1.name, i2.name); + return compareValues(i1.matchKind, i2.matchKind) + || compareStringsCaseSensitiveUI(i1.name, i2.name); } -function createNavigateToItem(rawItem: RawNavigateToItem): ts.NavigateToItem { +function createNavigateToItem(rawItem: RawNavigateToItem): NavigateToItem { const declaration = rawItem.declaration; - const container = ts.getContainerNode(declaration); - const containerName = container && ts.getNameOfDeclaration(container); + const container = getContainerNode(declaration); + const containerName = container && getNameOfDeclaration(container); return { name: rawItem.name, - kind: ts.getNodeKind(declaration), - kindModifiers: ts.getNodeModifiers(declaration), - matchKind: ts.PatternMatchKind[rawItem.matchKind] as keyof typeof ts.PatternMatchKind, + kind: getNodeKind(declaration), + kindModifiers: getNodeModifiers(declaration), + matchKind: PatternMatchKind[rawItem.matchKind] as keyof typeof PatternMatchKind, isCaseSensitive: rawItem.isCaseSensitive, fileName: rawItem.fileName, - textSpan: ts.createTextSpanFromNode(declaration), + textSpan: createTextSpanFromNode(declaration), // TODO(jfreeman): What should be the containerName when the container has a computed name? - containerName: containerName ? (containerName as ts.Identifier).text : "", - containerKind: containerName ? ts.getNodeKind(container) : ts.ScriptElementKind.unknown, + containerName: containerName ? (containerName as Identifier).text : "", + containerKind: containerName ? getNodeKind(container) : ScriptElementKind.unknown, }; } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 8554bd1d1fa98..dda82911fba14 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -1,4 +1,25 @@ -import * as ts from "./_namespaces/ts"; +import { + ArrowFunction, AssignmentDeclarationKind, BinaryExpression, BindableElementAccessExpression, + BindableObjectDefinePropertyCall, BindableStaticNameExpression, BindingElement, CallExpression, CancellationToken, + ClassElement, ClassExpression, ClassLikeDeclaration, compareStringsCaseSensitiveUI, compareValues, concatenate, + ConstructorDeclaration, contains, createTextSpanFromNode, createTextSpanFromRange, Debug, Declaration, + DeclarationName, declarationNameToString, EntityNameExpression, EnumDeclaration, EnumMember, escapeString, ESMap, + ExportAssignment, Expression, factory, filterMutate, forEach, forEachChild, FunctionDeclaration, FunctionExpression, + FunctionLikeDeclaration, getAssignmentDeclarationKind, getBaseFileName, getElementOrPropertyAccessName, + getFullWidth, getNameOfDeclaration, getNameOrArgument, getNodeKind, getNodeModifiers, + getPropertyNameForPropertyNameNode, getSyntacticModifierFlags, getTextOfIdentifierOrLiteral, getTextOfNode, + hasDynamicName, hasJSDocNodes, Identifier, idText, ImportClause, InterfaceDeclaration, InternalSymbolName, + isAmbientModule, isArrowFunction, isBinaryExpression, isBindableStaticAccessExpression, isBindingPattern, + isCallExpression, isClassDeclaration, isClassLike, isDeclaration, isElementAccessExpression, isExportAssignment, + isExpression, isExternalModule, isFunctionDeclaration, isFunctionExpression, isIdentifier, isJSDocTypeAlias, + isModuleBlock, isModuleDeclaration, isObjectLiteralExpression, isParameterPropertyDeclaration, isPrivateIdentifier, + isPropertyAccessExpression, isPropertyAssignment, isPropertyName, isPropertyNameLiteral, isStatic, + isStringLiteralLike, isToken, isVariableDeclaration, lastOrUndefined, map, Map, mapDefined, ModifierFlags, + ModuleDeclaration, NavigationBarItem, NavigationTree, Node, NodeFlags, normalizePath, PropertyAccessExpression, + PropertyAssignment, PropertyDeclaration, PropertyNameLiteral, removeFileExtension, setTextRange, + ShorthandPropertyAssignment, SourceFile, SpreadAssignment, SyntaxKind, TextSpan, TypeElement, + unescapeLeadingUnderscores, VariableDeclaration, +} from "./_namespaces/ts"; /** * Matches all whitespace characters in a string. Eg: @@ -22,8 +43,8 @@ const whiteSpaceRegex = /\s+/g; const maxLength = 150; // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`. -let curCancellationToken: ts.CancellationToken; -let curSourceFile: ts.SourceFile; +let curCancellationToken: CancellationToken; +let curSourceFile: SourceFile; /** * For performance, we keep navigation bar parents on a stack rather than passing them through each recursion. @@ -33,31 +54,31 @@ let curSourceFile: ts.SourceFile; let parentsStack: NavigationBarNode[] = []; let parent: NavigationBarNode; -const trackedEs5ClassesStack: (ts.ESMap | undefined)[] = []; -let trackedEs5Classes: ts.ESMap | undefined; +const trackedEs5ClassesStack: (ESMap | undefined)[] = []; +let trackedEs5Classes: ESMap | undefined; // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance. -let emptyChildItemArray: ts.NavigationBarItem[] = []; +let emptyChildItemArray: NavigationBarItem[] = []; /** * Represents a navigation bar item and its children. * The returned NavigationBarItem is more complicated and doesn't include 'parent', so we use these to do work before converting. */ interface NavigationBarNode { - node: ts.Node; - name: ts.DeclarationName | undefined; - additionalNodes: ts.Node[] | undefined; + node: Node; + name: DeclarationName | undefined; + additionalNodes: Node[] | undefined; parent: NavigationBarNode | undefined; // Present for all but root node children: NavigationBarNode[] | undefined; indent: number; // # of parents } /** @internal */ -export function getNavigationBarItems(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken): ts.NavigationBarItem[] { +export function getNavigationBarItems(sourceFile: SourceFile, cancellationToken: CancellationToken): NavigationBarItem[] { curCancellationToken = cancellationToken; curSourceFile = sourceFile; try { - return ts.map(primaryNavBarMenuItems(rootNavigationBarNode(sourceFile)), convertToPrimaryNavBarMenuItem); + return map(primaryNavBarMenuItems(rootNavigationBarNode(sourceFile)), convertToPrimaryNavBarMenuItem); } finally { reset(); @@ -65,7 +86,7 @@ export function getNavigationBarItems(sourceFile: ts.SourceFile, cancellationTok } /** @internal */ -export function getNavigationTree(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken): ts.NavigationTree { +export function getNavigationTree(sourceFile: SourceFile, cancellationToken: CancellationToken): NavigationTree { curCancellationToken = cancellationToken; curSourceFile = sourceFile; try { @@ -84,11 +105,11 @@ function reset() { emptyChildItemArray = []; } -function nodeText(node: ts.Node): string { +function nodeText(node: Node): string { return cleanText(node.getText(curSourceFile)); } -function navigationBarNodeKind(n: NavigationBarNode): ts.SyntaxKind { +function navigationBarNodeKind(n: NavigationBarNode): SyntaxKind { return n.node.kind; } @@ -101,26 +122,26 @@ function pushChild(parent: NavigationBarNode, child: NavigationBarNode): void { } } -function rootNavigationBarNode(sourceFile: ts.SourceFile): NavigationBarNode { - ts.Debug.assert(!parentsStack.length); +function rootNavigationBarNode(sourceFile: SourceFile): NavigationBarNode { + Debug.assert(!parentsStack.length); const root: NavigationBarNode = { node: sourceFile, name: undefined, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 }; parent = root; for (const statement of sourceFile.statements) { addChildrenRecursively(statement); } endNode(); - ts.Debug.assert(!parent && !parentsStack.length); + Debug.assert(!parent && !parentsStack.length); return root; } -function addLeafNode(node: ts.Node, name?: ts.DeclarationName): void { +function addLeafNode(node: Node, name?: DeclarationName): void { pushChild(parent, emptyNavigationBarNode(node, name)); } -function emptyNavigationBarNode(node: ts.Node, name?: ts.DeclarationName): NavigationBarNode { +function emptyNavigationBarNode(node: Node, name?: DeclarationName): NavigationBarNode { return { node, - name: name || (ts.isDeclaration(node) || ts.isExpression(node) ? ts.getNameOfDeclaration(node) : undefined), + name: name || (isDeclaration(node) || isExpression(node) ? getNameOfDeclaration(node) : undefined), additionalNodes: undefined, parent, children: undefined, @@ -130,20 +151,20 @@ function emptyNavigationBarNode(node: ts.Node, name?: ts.DeclarationName): Navig function addTrackedEs5Class(name: string) { if (!trackedEs5Classes) { - trackedEs5Classes = new ts.Map(); + trackedEs5Classes = new Map(); } trackedEs5Classes.set(name, true); } function endNestedNodes(depth: number): void { for (let i = 0; i < depth; i++) endNode(); } -function startNestedNodes(targetNode: ts.Node, entityName: ts.BindableStaticNameExpression) { - const names: ts.PropertyNameLiteral[] = []; - while (!ts.isPropertyNameLiteral(entityName)) { - const name = ts.getNameOrArgument(entityName); - const nameText = ts.getElementOrPropertyAccessName(entityName); +function startNestedNodes(targetNode: Node, entityName: BindableStaticNameExpression) { + const names: PropertyNameLiteral[] = []; + while (!isPropertyNameLiteral(entityName)) { + const name = getNameOrArgument(entityName); + const nameText = getElementOrPropertyAccessName(entityName); entityName = entityName.expression; - if (nameText === "prototype" || ts.isPrivateIdentifier(name)) continue; + if (nameText === "prototype" || isPrivateIdentifier(name)) continue; names.push(name); } names.push(entityName); @@ -158,7 +179,7 @@ function startNestedNodes(targetNode: ts.Node, entityName: ts.BindableStaticName * Add a new level of NavigationBarNodes. * This pushes to the stack, so you must call `endNode` when you are done adding to this node. */ -function startNode(node: ts.Node, name?: ts.DeclarationName): void { +function startNode(node: Node, name?: DeclarationName): void { const navNode: NavigationBarNode = emptyNavigationBarNode(node, name); pushChild(parent, navNode); @@ -179,16 +200,16 @@ function endNode(): void { trackedEs5Classes = trackedEs5ClassesStack.pop(); } -function addNodeWithRecursiveChild(node: ts.Node, child: ts.Node | undefined, name?: ts.DeclarationName): void { +function addNodeWithRecursiveChild(node: Node, child: Node | undefined, name?: DeclarationName): void { startNode(node, name); addChildrenRecursively(child); endNode(); } -function addNodeWithRecursiveInitializer(node: ts.VariableDeclaration | ts.PropertyAssignment | ts.BindingElement | ts.PropertyDeclaration): void { +function addNodeWithRecursiveInitializer(node: VariableDeclaration | PropertyAssignment | BindingElement | PropertyDeclaration): void { if (node.initializer && isFunctionOrClassExpression(node.initializer)) { startNode(node); - ts.forEachChild(node.initializer, addChildrenRecursively); + forEachChild(node.initializer, addChildrenRecursively); endNode(); } else { @@ -201,60 +222,60 @@ function addNodeWithRecursiveInitializer(node: ts.VariableDeclaration | ts.Prope * but included certain "well known" symbol names. While we no longer distinguish those well-known * symbols from other unique symbols, we do the below to retain those members in the nav tree. */ -function hasNavigationBarName(node: ts.Declaration) { - return !ts.hasDynamicName(node) || +function hasNavigationBarName(node: Declaration) { + return !hasDynamicName(node) || ( - node.kind !== ts.SyntaxKind.BinaryExpression && - ts.isPropertyAccessExpression(node.name.expression) && - ts.isIdentifier(node.name.expression.expression) && - ts.idText(node.name.expression.expression) === "Symbol" + node.kind !== SyntaxKind.BinaryExpression && + isPropertyAccessExpression(node.name.expression) && + isIdentifier(node.name.expression.expression) && + idText(node.name.expression.expression) === "Symbol" ); } /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */ -function addChildrenRecursively(node: ts.Node | undefined): void { +function addChildrenRecursively(node: Node | undefined): void { curCancellationToken.throwIfCancellationRequested(); - if (!node || ts.isToken(node)) { + if (!node || isToken(node)) { return; } switch (node.kind) { - case ts.SyntaxKind.Constructor: + case SyntaxKind.Constructor: // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it. - const ctr = node as ts.ConstructorDeclaration; + const ctr = node as ConstructorDeclaration; addNodeWithRecursiveChild(ctr, ctr.body); // Parameter properties are children of the class, not the constructor. for (const param of ctr.parameters) { - if (ts.isParameterPropertyDeclaration(param, ctr)) { + if (isParameterPropertyDeclaration(param, ctr)) { addLeafNode(param); } } break; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.MethodSignature: - if (hasNavigationBarName(node as ts.ClassElement | ts.TypeElement)) { - addNodeWithRecursiveChild(node, (node as ts.FunctionLikeDeclaration).body); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodSignature: + if (hasNavigationBarName(node as ClassElement | TypeElement)) { + addNodeWithRecursiveChild(node, (node as FunctionLikeDeclaration).body); } break; - case ts.SyntaxKind.PropertyDeclaration: - if (hasNavigationBarName(node as ts.ClassElement)) { - addNodeWithRecursiveInitializer(node as ts.PropertyDeclaration); + case SyntaxKind.PropertyDeclaration: + if (hasNavigationBarName(node as ClassElement)) { + addNodeWithRecursiveInitializer(node as PropertyDeclaration); } break; - case ts.SyntaxKind.PropertySignature: - if (hasNavigationBarName(node as ts.TypeElement)) { + case SyntaxKind.PropertySignature: + if (hasNavigationBarName(node as TypeElement)) { addLeafNode(node); } break; - case ts.SyntaxKind.ImportClause: - const importClause = node as ts.ImportClause; + case SyntaxKind.ImportClause: + const importClause = node as ImportClause; // Handle default import case e.g.: // import d from "mod"; if (importClause.name) { @@ -266,7 +287,7 @@ function addChildrenRecursively(node: ts.Node | undefined): void { // import {a, b as B} from "mod"; const { namedBindings } = importClause; if (namedBindings) { - if (namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + if (namedBindings.kind === SyntaxKind.NamespaceImport) { addLeafNode(namedBindings); } else { @@ -277,19 +298,19 @@ function addChildrenRecursively(node: ts.Node | undefined): void { } break; - case ts.SyntaxKind.ShorthandPropertyAssignment: - addNodeWithRecursiveChild(node, (node as ts.ShorthandPropertyAssignment).name); + case SyntaxKind.ShorthandPropertyAssignment: + addNodeWithRecursiveChild(node, (node as ShorthandPropertyAssignment).name); break; - case ts.SyntaxKind.SpreadAssignment: - const { expression } = node as ts.SpreadAssignment; + case SyntaxKind.SpreadAssignment: + const { expression } = node as SpreadAssignment; // Use the expression as the name of the SpreadAssignment, otherwise show as . - ts.isIdentifier(expression) ? addLeafNode(node, expression) : addLeafNode(node); + isIdentifier(expression) ? addLeafNode(node, expression) : addLeafNode(node); break; - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.VariableDeclaration: { - const child = node as ts.VariableDeclaration | ts.PropertyAssignment | ts.BindingElement; - if (ts.isBindingPattern(child.name)) { + case SyntaxKind.BindingElement: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.VariableDeclaration: { + const child = node as VariableDeclaration | PropertyAssignment | BindingElement; + if (isBindingPattern(child.name)) { addChildrenRecursively(child.name); } else { @@ -297,22 +318,22 @@ function addChildrenRecursively(node: ts.Node | undefined): void { } break; } - case ts.SyntaxKind.FunctionDeclaration: - const nameNode = (node as ts.FunctionLikeDeclaration).name; + case SyntaxKind.FunctionDeclaration: + const nameNode = (node as FunctionLikeDeclaration).name; // If we see a function declaration track as a possible ES5 class - if (nameNode && ts.isIdentifier(nameNode)) { + if (nameNode && isIdentifier(nameNode)) { addTrackedEs5Class(nameNode.text); } - addNodeWithRecursiveChild(node, (node as ts.FunctionLikeDeclaration).body); + addNodeWithRecursiveChild(node, (node as FunctionLikeDeclaration).body); break; - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - addNodeWithRecursiveChild(node, (node as ts.FunctionLikeDeclaration).body); + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + addNodeWithRecursiveChild(node, (node as FunctionLikeDeclaration).body); break; - case ts.SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumDeclaration: startNode(node); - for (const member of (node as ts.EnumDeclaration).members) { + for (const member of (node as EnumDeclaration).members) { if (!isComputedProperty(member)) { addLeafNode(member); } @@ -320,24 +341,24 @@ function addChildrenRecursively(node: ts.Node | undefined): void { endNode(); break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: startNode(node); - for (const member of (node as ts.InterfaceDeclaration).members) { + for (const member of (node as InterfaceDeclaration).members) { addChildrenRecursively(member); } endNode(); break; - case ts.SyntaxKind.ModuleDeclaration: - addNodeWithRecursiveChild(node, getInteriorModule(node as ts.ModuleDeclaration).body); + case SyntaxKind.ModuleDeclaration: + addNodeWithRecursiveChild(node, getInteriorModule(node as ModuleDeclaration).body); break; - case ts.SyntaxKind.ExportAssignment: { - const expression = (node as ts.ExportAssignment).expression; - const child = ts.isObjectLiteralExpression(expression) || ts.isCallExpression(expression) ? expression : - ts.isArrowFunction(expression) || ts.isFunctionExpression(expression) ? expression.body : undefined; + case SyntaxKind.ExportAssignment: { + const expression = (node as ExportAssignment).expression; + const child = isObjectLiteralExpression(expression) || isCallExpression(expression) ? expression : + isArrowFunction(expression) || isFunctionExpression(expression) ? expression.body : undefined; if (child) { startNode(node); addChildrenRecursively(child); @@ -348,53 +369,53 @@ function addChildrenRecursively(node: ts.Node | undefined): void { } break; } - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.IndexSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.IndexSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.TypeAliasDeclaration: addLeafNode(node); break; - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.BinaryExpression: { - const special = ts.getAssignmentDeclarationKind(node as ts.BinaryExpression); + case SyntaxKind.CallExpression: + case SyntaxKind.BinaryExpression: { + const special = getAssignmentDeclarationKind(node as BinaryExpression); switch (special) { - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.ModuleExports: - addNodeWithRecursiveChild(node, (node as ts.BinaryExpression).right); + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ModuleExports: + addNodeWithRecursiveChild(node, (node as BinaryExpression).right); return; - case ts.AssignmentDeclarationKind.Prototype: - case ts.AssignmentDeclarationKind.PrototypeProperty: { - const binaryExpression = (node as ts.BinaryExpression); - const assignmentTarget = binaryExpression.left as ts.PropertyAccessExpression; + case AssignmentDeclarationKind.Prototype: + case AssignmentDeclarationKind.PrototypeProperty: { + const binaryExpression = (node as BinaryExpression); + const assignmentTarget = binaryExpression.left as PropertyAccessExpression; - const prototypeAccess = special === ts.AssignmentDeclarationKind.PrototypeProperty ? - assignmentTarget.expression as ts.PropertyAccessExpression : + const prototypeAccess = special === AssignmentDeclarationKind.PrototypeProperty ? + assignmentTarget.expression as PropertyAccessExpression : assignmentTarget; let depth = 0; - let className: ts.PropertyNameLiteral; + let className: PropertyNameLiteral; // If we see a prototype assignment, start tracking the target as a class // This is only done for simple classes not nested assignments. - if (ts.isIdentifier(prototypeAccess.expression)) { + if (isIdentifier(prototypeAccess.expression)) { addTrackedEs5Class(prototypeAccess.expression.text); className = prototypeAccess.expression; } else { - [depth, className] = startNestedNodes(binaryExpression, prototypeAccess.expression as ts.EntityNameExpression); + [depth, className] = startNestedNodes(binaryExpression, prototypeAccess.expression as EntityNameExpression); } - if (special === ts.AssignmentDeclarationKind.Prototype) { - if (ts.isObjectLiteralExpression(binaryExpression.right)) { + if (special === AssignmentDeclarationKind.Prototype) { + if (isObjectLiteralExpression(binaryExpression.right)) { if (binaryExpression.right.properties.length > 0) { startNode(binaryExpression, className); - ts.forEachChild(binaryExpression.right, addChildrenRecursively); + forEachChild(binaryExpression.right, addChildrenRecursively); endNode(); } } } - else if (ts.isFunctionExpression(binaryExpression.right) || ts.isArrowFunction(binaryExpression.right)) { + else if (isFunctionExpression(binaryExpression.right) || isArrowFunction(binaryExpression.right)) { addNodeWithRecursiveChild(node, binaryExpression.right, className); @@ -407,71 +428,71 @@ function addChildrenRecursively(node: ts.Node | undefined): void { endNestedNodes(depth); return; } - case ts.AssignmentDeclarationKind.ObjectDefinePropertyValue: - case ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty: { - const defineCall = node as ts.BindableObjectDefinePropertyCall; - const className = special === ts.AssignmentDeclarationKind.ObjectDefinePropertyValue ? + case AssignmentDeclarationKind.ObjectDefinePropertyValue: + case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: { + const defineCall = node as BindableObjectDefinePropertyCall; + const className = special === AssignmentDeclarationKind.ObjectDefinePropertyValue ? defineCall.arguments[0] : - (defineCall.arguments[0] as ts.PropertyAccessExpression).expression as ts.EntityNameExpression; + (defineCall.arguments[0] as PropertyAccessExpression).expression as EntityNameExpression; const memberName = defineCall.arguments[1]; const [depth, classNameIdentifier] = startNestedNodes(node, className); startNode(node, classNameIdentifier); - startNode(node, ts.setTextRange(ts.factory.createIdentifier(memberName.text), memberName)); - addChildrenRecursively((node as ts.CallExpression).arguments[2]); + startNode(node, setTextRange(factory.createIdentifier(memberName.text), memberName)); + addChildrenRecursively((node as CallExpression).arguments[2]); endNode(); endNode(); endNestedNodes(depth); return; } - case ts.AssignmentDeclarationKind.Property: { - const binaryExpression = (node as ts.BinaryExpression); - const assignmentTarget = binaryExpression.left as ts.PropertyAccessExpression | ts.BindableElementAccessExpression; + case AssignmentDeclarationKind.Property: { + const binaryExpression = (node as BinaryExpression); + const assignmentTarget = binaryExpression.left as PropertyAccessExpression | BindableElementAccessExpression; const targetFunction = assignmentTarget.expression; - if (ts.isIdentifier(targetFunction) && ts.getElementOrPropertyAccessName(assignmentTarget) !== "prototype" && + if (isIdentifier(targetFunction) && getElementOrPropertyAccessName(assignmentTarget) !== "prototype" && trackedEs5Classes && trackedEs5Classes.has(targetFunction.text)) { - if (ts.isFunctionExpression(binaryExpression.right) || ts.isArrowFunction(binaryExpression.right)) { + if (isFunctionExpression(binaryExpression.right) || isArrowFunction(binaryExpression.right)) { addNodeWithRecursiveChild(node, binaryExpression.right, targetFunction); } - else if (ts.isBindableStaticAccessExpression(assignmentTarget)) { + else if (isBindableStaticAccessExpression(assignmentTarget)) { startNode(binaryExpression, targetFunction); - addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, ts.getNameOrArgument(assignmentTarget)); + addNodeWithRecursiveChild(binaryExpression.left, binaryExpression.right, getNameOrArgument(assignmentTarget)); endNode(); } return; } break; } - case ts.AssignmentDeclarationKind.ThisProperty: - case ts.AssignmentDeclarationKind.None: - case ts.AssignmentDeclarationKind.ObjectDefinePropertyExports: + case AssignmentDeclarationKind.ThisProperty: + case AssignmentDeclarationKind.None: + case AssignmentDeclarationKind.ObjectDefinePropertyExports: break; default: - ts.Debug.assertNever(special); + Debug.assertNever(special); } } // falls through default: - if (ts.hasJSDocNodes(node)) { - ts.forEach(node.jsDoc, jsDoc => { - ts.forEach(jsDoc.tags, tag => { - if (ts.isJSDocTypeAlias(tag)) { + if (hasJSDocNodes(node)) { + forEach(node.jsDoc, jsDoc => { + forEach(jsDoc.tags, tag => { + if (isJSDocTypeAlias(tag)) { addLeafNode(tag); } }); }); } - ts.forEachChild(node, addChildrenRecursively); + forEachChild(node, addChildrenRecursively); } } /** Merge declarations of the same kind. */ function mergeChildren(children: NavigationBarNode[], node: NavigationBarNode): void { - const nameToItems = new ts.Map(); - ts.filterMutate(children, (child, index) => { - const declName = child.name || ts.getNameOfDeclaration(child.node as ts.Declaration); + const nameToItems = new Map(); + filterMutate(children, (child, index) => { + const declName = child.name || getNameOfDeclaration(child.node as Declaration); const name = declName && nodeText(declName); if (!name) { // Anonymous items are never merged. @@ -503,43 +524,43 @@ function mergeChildren(children: NavigationBarNode[], node: NavigationBarNode): } }); } -const isEs5ClassMember: Record = { - [ts.AssignmentDeclarationKind.Property]: true, - [ts.AssignmentDeclarationKind.PrototypeProperty]: true, - [ts.AssignmentDeclarationKind.ObjectDefinePropertyValue]: true, - [ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty]: true, - [ts.AssignmentDeclarationKind.None]: false, - [ts.AssignmentDeclarationKind.ExportsProperty]: false, - [ts.AssignmentDeclarationKind.ModuleExports]: false, - [ts.AssignmentDeclarationKind.ObjectDefinePropertyExports]: false, - [ts.AssignmentDeclarationKind.Prototype]: true, - [ts.AssignmentDeclarationKind.ThisProperty]: false, +const isEs5ClassMember: Record = { + [AssignmentDeclarationKind.Property]: true, + [AssignmentDeclarationKind.PrototypeProperty]: true, + [AssignmentDeclarationKind.ObjectDefinePropertyValue]: true, + [AssignmentDeclarationKind.ObjectDefinePrototypeProperty]: true, + [AssignmentDeclarationKind.None]: false, + [AssignmentDeclarationKind.ExportsProperty]: false, + [AssignmentDeclarationKind.ModuleExports]: false, + [AssignmentDeclarationKind.ObjectDefinePropertyExports]: false, + [AssignmentDeclarationKind.Prototype]: true, + [AssignmentDeclarationKind.ThisProperty]: false, }; function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, parent: NavigationBarNode): boolean | undefined { - function isPossibleConstructor(node: ts.Node) { - return ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node) || ts.isVariableDeclaration(node); + function isPossibleConstructor(node: Node) { + return isFunctionExpression(node) || isFunctionDeclaration(node) || isVariableDeclaration(node); } - const bAssignmentDeclarationKind = ts.isBinaryExpression(b.node) || ts.isCallExpression(b.node) ? - ts.getAssignmentDeclarationKind(b.node) : - ts.AssignmentDeclarationKind.None; + const bAssignmentDeclarationKind = isBinaryExpression(b.node) || isCallExpression(b.node) ? + getAssignmentDeclarationKind(b.node) : + AssignmentDeclarationKind.None; - const aAssignmentDeclarationKind = ts.isBinaryExpression(a.node) || ts.isCallExpression(a.node) ? - ts.getAssignmentDeclarationKind(a.node) : - ts.AssignmentDeclarationKind.None; + const aAssignmentDeclarationKind = isBinaryExpression(a.node) || isCallExpression(a.node) ? + getAssignmentDeclarationKind(a.node) : + AssignmentDeclarationKind.None; // We treat this as an es5 class and merge the nodes in in one of several cases if ((isEs5ClassMember[bAssignmentDeclarationKind] && isEs5ClassMember[aAssignmentDeclarationKind]) // merge two class elements || (isPossibleConstructor(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // ctor function & member || (isPossibleConstructor(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & ctor function - || (ts.isClassDeclaration(a.node) && isSynthesized(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member - || (ts.isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated) - || (ts.isClassDeclaration(a.node) && isSynthesized(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor - || (ts.isClassDeclaration(b.node) && isPossibleConstructor(a.node) && isSynthesized(a.node)) // ctor & class (generated) + || (isClassDeclaration(a.node) && isSynthesized(a.node) && isEs5ClassMember[bAssignmentDeclarationKind]) // class (generated) & member + || (isClassDeclaration(b.node) && isEs5ClassMember[aAssignmentDeclarationKind]) // member & class (generated) + || (isClassDeclaration(a.node) && isSynthesized(a.node) && isPossibleConstructor(b.node)) // class (generated) & ctor + || (isClassDeclaration(b.node) && isPossibleConstructor(a.node) && isSynthesized(a.node)) // ctor & class (generated) ) { - let lastANode = a.additionalNodes && ts.lastOrUndefined(a.additionalNodes) || a.node; + let lastANode = a.additionalNodes && lastOrUndefined(a.additionalNodes) || a.node; - if ((!ts.isClassDeclaration(a.node) && !ts.isClassDeclaration(b.node)) // If neither outline node is a class + if ((!isClassDeclaration(a.node) && !isClassDeclaration(b.node)) // If neither outline node is a class || isPossibleConstructor(a.node) || isPossibleConstructor(b.node) // If either function is a constructor function ) { const ctorFunction = isPossibleConstructor(a.node) ? a.node : @@ -547,17 +568,17 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu undefined; if (ctorFunction !== undefined) { - const ctorNode = ts.setTextRange( - ts.factory.createConstructorDeclaration(/* modifiers */ undefined, [], /* body */ undefined), + const ctorNode = setTextRange( + factory.createConstructorDeclaration(/* modifiers */ undefined, [], /* body */ undefined), ctorFunction); const ctor = emptyNavigationBarNode(ctorNode); ctor.indent = a.indent + 1; ctor.children = a.node === ctorFunction ? a.children : b.children; - a.children = a.node === ctorFunction ? ts.concatenate([ctor], b.children || [b]) : ts.concatenate(a.children || [{ ...a }], [ctor]); + a.children = a.node === ctorFunction ? concatenate([ctor], b.children || [b]) : concatenate(a.children || [{ ...a }], [ctor]); } else { if (a.children || b.children) { - a.children = ts.concatenate(a.children || [{ ...a }], b.children || [b]); + a.children = concatenate(a.children || [{ ...a }], b.children || [b]); if (a.children) { mergeChildren(a.children, a); sortChildren(a.children); @@ -565,16 +586,16 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu } } - lastANode = a.node = ts.setTextRange(ts.factory.createClassDeclaration( + lastANode = a.node = setTextRange(factory.createClassDeclaration( /* modifiers */ undefined, - a.name as ts.Identifier || ts.factory.createIdentifier("__class__"), + a.name as Identifier || factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, [] ), a.node); } else { - a.children = ts.concatenate(a.children, b.children); + a.children = concatenate(a.children, b.children); if (a.children) { mergeChildren(a.children, a); } @@ -588,13 +609,13 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu // Ex This will produce 3 outline nodes: C, a, C // function C() {}; let a = 1; C.prototype.m = function () {} if (parent.children![bIndex - 1].node.end === lastANode.end) { - ts.setTextRange(lastANode, { pos: lastANode.pos, end: bNode.end }); + setTextRange(lastANode, { pos: lastANode.pos, end: bNode.end }); } else { if (!a.additionalNodes) a.additionalNodes = []; - a.additionalNodes.push(ts.setTextRange(ts.factory.createClassDeclaration( + a.additionalNodes.push(setTextRange(factory.createClassDeclaration( /* modifiers */ undefined, - a.name as ts.Identifier || ts.factory.createIdentifier("__class__"), + a.name as Identifier || factory.createIdentifier("__class__"), /* typeParameters */ undefined, /* heritageClauses */ undefined, [] @@ -602,7 +623,7 @@ function tryMergeEs5Class(a: NavigationBarNode, b: NavigationBarNode, bIndex: nu } return true; } - return bAssignmentDeclarationKind === ts.AssignmentDeclarationKind.None ? false : true; + return bAssignmentDeclarationKind === AssignmentDeclarationKind.None ? false : true; } function tryMerge(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, parent: NavigationBarNode): boolean { @@ -618,42 +639,42 @@ function tryMerge(a: NavigationBarNode, b: NavigationBarNode, bIndex: number, pa } /** a and b have the same name, but they may not be mergeable. */ -function shouldReallyMerge(a: ts.Node, b: ts.Node, parent: NavigationBarNode): boolean { +function shouldReallyMerge(a: Node, b: Node, parent: NavigationBarNode): boolean { if (a.kind !== b.kind || a.parent !== b.parent && !(isOwnChild(a, parent) && isOwnChild(b, parent))) { return false; } switch (a.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - return ts.isStatic(a) === ts.isStatic(b); - case ts.SyntaxKind.ModuleDeclaration: - return areSameModule(a as ts.ModuleDeclaration, b as ts.ModuleDeclaration) - && getFullyQualifiedModuleName(a as ts.ModuleDeclaration) === getFullyQualifiedModuleName(b as ts.ModuleDeclaration); + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return isStatic(a) === isStatic(b); + case SyntaxKind.ModuleDeclaration: + return areSameModule(a as ModuleDeclaration, b as ModuleDeclaration) + && getFullyQualifiedModuleName(a as ModuleDeclaration) === getFullyQualifiedModuleName(b as ModuleDeclaration); default: return true; } } -function isSynthesized(node: ts.Node) { - return !!(node.flags & ts.NodeFlags.Synthesized); +function isSynthesized(node: Node) { + return !!(node.flags & NodeFlags.Synthesized); } // We want to merge own children like `I` in in `module A { interface I {} } module A { interface I {} }` // We don't want to merge unrelated children like `m` in `const o = { a: { m() {} }, b: { m() {} } };` -function isOwnChild(n: ts.Node, parent: NavigationBarNode): boolean { - const par = ts.isModuleBlock(n.parent) ? n.parent.parent : n.parent; - return par === parent.node || ts.contains(parent.additionalNodes, par); +function isOwnChild(n: Node, parent: NavigationBarNode): boolean { + const par = isModuleBlock(n.parent) ? n.parent.parent : n.parent; + return par === parent.node || contains(parent.additionalNodes, par); } // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes. // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'! -function areSameModule(a: ts.ModuleDeclaration, b: ts.ModuleDeclaration): boolean { +function areSameModule(a: ModuleDeclaration, b: ModuleDeclaration): boolean { if (!a.body || !b.body) { return a.body === b.body; } - return a.body.kind === b.body.kind && (a.body.kind !== ts.SyntaxKind.ModuleDeclaration || areSameModule(a.body as ts.ModuleDeclaration, b.body as ts.ModuleDeclaration)); + return a.body.kind === b.body.kind && (a.body.kind !== SyntaxKind.ModuleDeclaration || areSameModule(a.body as ModuleDeclaration, b.body as ModuleDeclaration)); } /** Merge source into target. Source should be thrown away after this is called. */ @@ -664,7 +685,7 @@ function merge(target: NavigationBarNode, source: NavigationBarNode): void { target.additionalNodes.push(...source.additionalNodes); } - target.children = ts.concatenate(target.children, source.children); + target.children = concatenate(target.children, source.children); if (target.children) { mergeChildren(target.children, target); sortChildren(target.children); @@ -677,8 +698,8 @@ function sortChildren(children: NavigationBarNode[]): void { } function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) { - return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node)!, tryGetName(child2.node)!) // TODO: GH#18217 - || ts.compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); + return compareStringsCaseSensitiveUI(tryGetName(child1.node)!, tryGetName(child2.node)!) // TODO: GH#18217 + || compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2)); } /** @@ -686,34 +707,34 @@ function compareChildren(child1: NavigationBarNode, child2: NavigationBarNode) { * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like. * So `new()` can still come before an `aardvark` method. */ -function tryGetName(node: ts.Node): string | undefined { - if (node.kind === ts.SyntaxKind.ModuleDeclaration) { - return getModuleName(node as ts.ModuleDeclaration); +function tryGetName(node: Node): string | undefined { + if (node.kind === SyntaxKind.ModuleDeclaration) { + return getModuleName(node as ModuleDeclaration); } - const declName = ts.getNameOfDeclaration(node as ts.Declaration); - if (declName && ts.isPropertyName(declName)) { - const propertyName = ts.getPropertyNameForPropertyNameNode(declName); - return propertyName && ts.unescapeLeadingUnderscores(propertyName); + const declName = getNameOfDeclaration(node as Declaration); + if (declName && isPropertyName(declName)) { + const propertyName = getPropertyNameForPropertyNameNode(declName); + return propertyName && unescapeLeadingUnderscores(propertyName); } switch (node.kind) { - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.ClassExpression: - return getFunctionOrClassName(node as ts.FunctionExpression | ts.ArrowFunction | ts.ClassExpression); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + return getFunctionOrClassName(node as FunctionExpression | ArrowFunction | ClassExpression); default: return undefined; } } -function getItemName(node: ts.Node, name: ts.Node | undefined): string { - if (node.kind === ts.SyntaxKind.ModuleDeclaration) { - return cleanText(getModuleName(node as ts.ModuleDeclaration)); +function getItemName(node: Node, name: Node | undefined): string { + if (node.kind === SyntaxKind.ModuleDeclaration) { + return cleanText(getModuleName(node as ModuleDeclaration)); } if (name) { - const text = ts.isIdentifier(name) ? name.text - : ts.isElementAccessExpression(name) ? `[${nodeText(name.argumentExpression)}]` + const text = isIdentifier(name) ? name.text + : isElementAccessExpression(name) ? `[${nodeText(name.argumentExpression)}]` : nodeText(name); if (text.length > 0) { return cleanText(text); @@ -721,33 +742,33 @@ function getItemName(node: ts.Node, name: ts.Node | undefined): string { } switch (node.kind) { - case ts.SyntaxKind.SourceFile: - const sourceFile = node as ts.SourceFile; - return ts.isExternalModule(sourceFile) - ? `"${ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName))))}"` + case SyntaxKind.SourceFile: + const sourceFile = node as SourceFile; + return isExternalModule(sourceFile) + ? `"${escapeString(getBaseFileName(removeFileExtension(normalizePath(sourceFile.fileName))))}"` : ""; - case ts.SyntaxKind.ExportAssignment: - return ts.isExportAssignment(node) && node.isExportEquals ? ts.InternalSymbolName.ExportEquals : ts.InternalSymbolName.Default; - - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - if (ts.getSyntacticModifierFlags(node) & ts.ModifierFlags.Default) { + case SyntaxKind.ExportAssignment: + return isExportAssignment(node) && node.isExportEquals ? InternalSymbolName.ExportEquals : InternalSymbolName.Default; + + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + if (getSyntacticModifierFlags(node) & ModifierFlags.Default) { return "default"; } // We may get a string with newlines or other whitespace in the case of an object dereference // (eg: "app\n.onactivated"), so we should remove the whitespace for readability in the // navigation bar. - return getFunctionOrClassName(node as ts.ArrowFunction | ts.FunctionExpression | ts.ClassExpression); - case ts.SyntaxKind.Constructor: + return getFunctionOrClassName(node as ArrowFunction | FunctionExpression | ClassExpression); + case SyntaxKind.Constructor: return "constructor"; - case ts.SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructSignature: return "new()"; - case ts.SyntaxKind.CallSignature: + case SyntaxKind.CallSignature: return "()"; - case ts.SyntaxKind.IndexSignature: + case SyntaxKind.IndexSignature: return "[]"; default: return ""; @@ -782,35 +803,35 @@ function primaryNavBarMenuItems(root: NavigationBarNode): NavigationBarNode[] { // Some nodes are otherwise important enough to always include in the primary navigation menu. switch (navigationBarNodeKind(item)) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocCallbackTag: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.SourceFile: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocCallbackTag: return true; - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: return isTopLevelFunctionDeclaration(item); default: return false; } function isTopLevelFunctionDeclaration(item: NavigationBarNode): boolean { - if (!(item.node as ts.FunctionDeclaration).body) { + if (!(item.node as FunctionDeclaration).body) { return false; } switch (navigationBarNodeKind(item.parent!)) { - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: + case SyntaxKind.ModuleBlock: + case SyntaxKind.SourceFile: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: return true; default: return false; @@ -819,34 +840,34 @@ function primaryNavBarMenuItems(root: NavigationBarNode): NavigationBarNode[] { } } -function convertToTree(n: NavigationBarNode): ts.NavigationTree { +function convertToTree(n: NavigationBarNode): NavigationTree { return { text: getItemName(n.node, n.name), - kind: ts.getNodeKind(n.node), + kind: getNodeKind(n.node), kindModifiers: getModifiers(n.node), spans: getSpans(n), nameSpan: n.name && getNodeSpan(n.name), - childItems: ts.map(n.children, convertToTree) + childItems: map(n.children, convertToTree) }; } -function convertToPrimaryNavBarMenuItem(n: NavigationBarNode): ts.NavigationBarItem { +function convertToPrimaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem { return { text: getItemName(n.node, n.name), - kind: ts.getNodeKind(n.node), + kind: getNodeKind(n.node), kindModifiers: getModifiers(n.node), spans: getSpans(n), - childItems: ts.map(n.children, convertToSecondaryNavBarMenuItem) || emptyChildItemArray, + childItems: map(n.children, convertToSecondaryNavBarMenuItem) || emptyChildItemArray, indent: n.indent, bolded: false, grayed: false }; - function convertToSecondaryNavBarMenuItem(n: NavigationBarNode): ts.NavigationBarItem { + function convertToSecondaryNavBarMenuItem(n: NavigationBarNode): NavigationBarItem { return { text: getItemName(n.node, n.name), - kind: ts.getNodeKind(n.node), - kindModifiers: ts.getNodeModifiers(n.node), + kind: getNodeKind(n.node), + kindModifiers: getNodeModifiers(n.node), spans: getSpans(n), childItems: emptyChildItemArray, indent: 0, @@ -856,7 +877,7 @@ function convertToPrimaryNavBarMenuItem(n: NavigationBarNode): ts.NavigationBarI } } -function getSpans(n: NavigationBarNode): ts.TextSpan[] { +function getSpans(n: NavigationBarNode): TextSpan[] { const spans = [getNodeSpan(n.node)]; if (n.additionalNodes) { for (const node of n.additionalNodes) { @@ -866,21 +887,21 @@ function getSpans(n: NavigationBarNode): ts.TextSpan[] { return spans; } -function getModuleName(moduleDeclaration: ts.ModuleDeclaration): string { +function getModuleName(moduleDeclaration: ModuleDeclaration): string { // We want to maintain quotation marks. - if (ts.isAmbientModule(moduleDeclaration)) { - return ts.getTextOfNode(moduleDeclaration.name); + if (isAmbientModule(moduleDeclaration)) { + return getTextOfNode(moduleDeclaration.name); } return getFullyQualifiedModuleName(moduleDeclaration); } -function getFullyQualifiedModuleName(moduleDeclaration: ts.ModuleDeclaration): string { +function getFullyQualifiedModuleName(moduleDeclaration: ModuleDeclaration): string { // Otherwise, we need to aggregate each identifier to build up the qualified name. - const result = [ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)]; - while (moduleDeclaration.body && moduleDeclaration.body.kind === ts.SyntaxKind.ModuleDeclaration) { + const result = [getTextOfIdentifierOrLiteral(moduleDeclaration.name)]; + while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { moduleDeclaration = moduleDeclaration.body; - result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name)); + result.push(getTextOfIdentifierOrLiteral(moduleDeclaration.name)); } return result.join("."); } @@ -889,50 +910,50 @@ function getFullyQualifiedModuleName(moduleDeclaration: ts.ModuleDeclaration): s * For 'module A.B.C', we want to get the node for 'C'. * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again. */ -function getInteriorModule(decl: ts.ModuleDeclaration): ts.ModuleDeclaration { - return decl.body && ts.isModuleDeclaration(decl.body) ? getInteriorModule(decl.body) : decl; +function getInteriorModule(decl: ModuleDeclaration): ModuleDeclaration { + return decl.body && isModuleDeclaration(decl.body) ? getInteriorModule(decl.body) : decl; } -function isComputedProperty(member: ts.EnumMember): boolean { - return !member.name || member.name.kind === ts.SyntaxKind.ComputedPropertyName; +function isComputedProperty(member: EnumMember): boolean { + return !member.name || member.name.kind === SyntaxKind.ComputedPropertyName; } -function getNodeSpan(node: ts.Node): ts.TextSpan { - return node.kind === ts.SyntaxKind.SourceFile ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile); +function getNodeSpan(node: Node): TextSpan { + return node.kind === SyntaxKind.SourceFile ? createTextSpanFromRange(node) : createTextSpanFromNode(node, curSourceFile); } -function getModifiers(node: ts.Node): string { - if (node.parent && node.parent.kind === ts.SyntaxKind.VariableDeclaration) { +function getModifiers(node: Node): string { + if (node.parent && node.parent.kind === SyntaxKind.VariableDeclaration) { node = node.parent; } - return ts.getNodeModifiers(node); + return getNodeModifiers(node); } -function getFunctionOrClassName(node: ts.FunctionExpression | ts.FunctionDeclaration | ts.ArrowFunction | ts.ClassLikeDeclaration): string { +function getFunctionOrClassName(node: FunctionExpression | FunctionDeclaration | ArrowFunction | ClassLikeDeclaration): string { const { parent } = node; - if (node.name && ts.getFullWidth(node.name) > 0) { - return cleanText(ts.declarationNameToString(node.name)); + if (node.name && getFullWidth(node.name) > 0) { + return cleanText(declarationNameToString(node.name)); } // See if it is a var initializer. If so, use the var name. - else if (ts.isVariableDeclaration(parent)) { - return cleanText(ts.declarationNameToString(parent.name)); + else if (isVariableDeclaration(parent)) { + return cleanText(declarationNameToString(parent.name)); } // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. - else if (ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { + else if (isBinaryExpression(parent) && parent.operatorToken.kind === SyntaxKind.EqualsToken) { return nodeText(parent.left).replace(whiteSpaceRegex, ""); } // See if it is a property assignment, and if so use the property name - else if (ts.isPropertyAssignment(parent)) { + else if (isPropertyAssignment(parent)) { return nodeText(parent.name); } // Default exports are named "default" - else if (ts.getSyntacticModifierFlags(node) & ts.ModifierFlags.Default) { + else if (getSyntacticModifierFlags(node) & ModifierFlags.Default) { return "default"; } - else if (ts.isClassLike(node)) { + else if (isClassLike(node)) { return ""; } - else if (ts.isCallExpression(parent)) { + else if (isCallExpression(parent)) { let name = getCalledExpressionName(parent.expression); if (name !== undefined) { name = cleanText(name); @@ -941,7 +962,7 @@ function getFunctionOrClassName(node: ts.FunctionExpression | ts.FunctionDeclara return `${name} callback`; } - const args = cleanText(ts.mapDefined(parent.arguments, a => ts.isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined).join(", ")); + const args = cleanText(mapDefined(parent.arguments, a => isStringLiteralLike(a) ? a.getText(curSourceFile) : undefined).join(", ")); return `${name}(${args}) callback`; } } @@ -949,11 +970,11 @@ function getFunctionOrClassName(node: ts.FunctionExpression | ts.FunctionDeclara } // See also 'tryGetPropertyAccessOrIdentifierToString' -function getCalledExpressionName(expr: ts.Expression): string | undefined { - if (ts.isIdentifier(expr)) { +function getCalledExpressionName(expr: Expression): string | undefined { + if (isIdentifier(expr)) { return expr.text; } - else if (ts.isPropertyAccessExpression(expr)) { + else if (isPropertyAccessExpression(expr)) { const left = getCalledExpressionName(expr.expression); const right = expr.name.text; return left === undefined ? right : `${left}.${right}`; @@ -963,11 +984,11 @@ function getCalledExpressionName(expr: ts.Expression): string | undefined { } } -function isFunctionOrClassExpression(node: ts.Node): node is ts.ArrowFunction | ts.FunctionExpression | ts.ClassExpression { +function isFunctionOrClassExpression(node: Node): node is ArrowFunction | FunctionExpression | ClassExpression { switch (node.kind) { - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ClassExpression: return true; default: return false; diff --git a/src/services/organizeImports.ts b/src/services/organizeImports.ts index 469b608585def..d5cf85d076cfe 100644 --- a/src/services/organizeImports.ts +++ b/src/services/organizeImports.ts @@ -1,4 +1,14 @@ -import * as ts from "./_namespaces/ts"; +import { + AnyImportOrRequireStatement, arrayIsSorted, binarySearch, compareBooleans, compareStringsCaseInsensitive, + compareValues, createScanner, emptyArray, ExportDeclaration, ExportSpecifier, Expression, factory, + FindAllReferences, flatMap, formatting, getNewLineOrDefaultFromHost, group, Identifier, identity, ImportDeclaration, + ImportOrExportSpecifier, ImportSpecifier, isAmbientModule, isExportDeclaration, isExternalModuleNameRelative, + isExternalModuleReference, isImportDeclaration, isNamedExports, isNamedImports, isNamespaceImport, isString, + isStringLiteral, isStringLiteralLike, jsxModeNeedsExplicitImport, LanguageServiceHost, length, map, + NamedImportBindings, NamedImports, NamespaceImport, OrganizeImportsMode, Program, Scanner, some, + SortedReadonlyArray, SourceFile, stableSort, suppressLeadingTrivia, SyntaxKind, textChanges, TransformFlags, + tryCast, UserPreferences, +} from "./_namespaces/ts"; /** @internal */ /** @@ -8,57 +18,57 @@ import * as ts from "./_namespaces/ts"; * 3) Sorting imports */ export function organizeImports( - sourceFile: ts.SourceFile, - formatContext: ts.formatting.FormatContext, - host: ts.LanguageServiceHost, - program: ts.Program, - preferences: ts.UserPreferences, - mode: ts.OrganizeImportsMode, + sourceFile: SourceFile, + formatContext: formatting.FormatContext, + host: LanguageServiceHost, + program: Program, + preferences: UserPreferences, + mode: OrganizeImportsMode, ) { - const changeTracker = ts.textChanges.ChangeTracker.fromContext({ host, formatContext, preferences }); - const shouldSort = mode === ts.OrganizeImportsMode.SortAndCombine || mode === ts.OrganizeImportsMode.All; + const changeTracker = textChanges.ChangeTracker.fromContext({ host, formatContext, preferences }); + const shouldSort = mode === OrganizeImportsMode.SortAndCombine || mode === OrganizeImportsMode.All; const shouldCombine = shouldSort; // These are currently inseparable, but I draw a distinction for clarity and in case we add modes in the future. - const shouldRemove = mode === ts.OrganizeImportsMode.RemoveUnused || mode === ts.OrganizeImportsMode.All; - const maybeRemove = shouldRemove ? removeUnusedImports : ts.identity; - const maybeCoalesce = shouldCombine ? coalesceImports : ts.identity; - const processImportsOfSameModuleSpecifier = (importGroup: readonly ts.ImportDeclaration[]) => { + const shouldRemove = mode === OrganizeImportsMode.RemoveUnused || mode === OrganizeImportsMode.All; + const maybeRemove = shouldRemove ? removeUnusedImports : identity; + const maybeCoalesce = shouldCombine ? coalesceImports : identity; + const processImportsOfSameModuleSpecifier = (importGroup: readonly ImportDeclaration[]) => { const processedDeclarations = maybeCoalesce(maybeRemove(importGroup, sourceFile, program)); return shouldSort - ? ts.stableSort(processedDeclarations, (s1, s2) => compareImportsOrRequireStatements(s1, s2)) + ? stableSort(processedDeclarations, (s1, s2) => compareImportsOrRequireStatements(s1, s2)) : processedDeclarations; }; // All of the old ImportDeclarations in the file, in syntactic order. - const topLevelImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, sourceFile.statements.filter(ts.isImportDeclaration)); + const topLevelImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, sourceFile.statements.filter(isImportDeclaration)); topLevelImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier)); // Exports are always used - if (mode !== ts.OrganizeImportsMode.RemoveUnused) { + if (mode !== OrganizeImportsMode.RemoveUnused) { // All of the old ExportDeclarations in the file, in syntactic order. - const topLevelExportDecls = sourceFile.statements.filter(ts.isExportDeclaration); + const topLevelExportDecls = sourceFile.statements.filter(isExportDeclaration); organizeImportsWorker(topLevelExportDecls, coalesceExports); } - for (const ambientModule of sourceFile.statements.filter(ts.isAmbientModule)) { + for (const ambientModule of sourceFile.statements.filter(isAmbientModule)) { if (!ambientModule.body) continue; - const ambientModuleImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(ts.isImportDeclaration)); + const ambientModuleImportGroupDecls = groupImportsByNewlineContiguous(sourceFile, ambientModule.body.statements.filter(isImportDeclaration)); ambientModuleImportGroupDecls.forEach(importGroupDecl => organizeImportsWorker(importGroupDecl, processImportsOfSameModuleSpecifier)); // Exports are always used - if (mode !== ts.OrganizeImportsMode.RemoveUnused) { - const ambientModuleExportDecls = ambientModule.body.statements.filter(ts.isExportDeclaration); + if (mode !== OrganizeImportsMode.RemoveUnused) { + const ambientModuleExportDecls = ambientModule.body.statements.filter(isExportDeclaration); organizeImportsWorker(ambientModuleExportDecls, coalesceExports); } } return changeTracker.getChanges(); - function organizeImportsWorker( + function organizeImportsWorker( oldImportDecls: readonly T[], coalesce: (group: readonly T[]) => readonly T[], ) { - if (ts.length(oldImportDecls) === 0) { + if (length(oldImportDecls) === 0) { return; } @@ -67,15 +77,15 @@ export function organizeImports( // on the first import because it is probably the header comment for the file. // Consider: we could do a more careful check that this trivia is actually a header, // but the consequences of being wrong are very minor. - ts.suppressLeadingTrivia(oldImportDecls[0]); + suppressLeadingTrivia(oldImportDecls[0]); const oldImportGroups = shouldCombine - ? ts.group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!) + ? group(oldImportDecls, importDecl => getExternalModuleName(importDecl.moduleSpecifier!)!) : [oldImportDecls]; const sortedImportGroups = shouldSort - ? ts.stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)) + ? stableSort(oldImportGroups, (group1, group2) => compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier)) : oldImportGroups; - const newImportDecls = ts.flatMap(sortedImportGroups, importGroup => + const newImportDecls = flatMap(sortedImportGroups, importGroup => getExternalModuleName(importGroup[0].moduleSpecifier!) ? coalesce(importGroup) : importGroup); @@ -85,28 +95,28 @@ export function organizeImports( // Consider the first node to have trailingTrivia as we want to exclude the // "header" comment. changeTracker.deleteNodes(sourceFile, oldImportDecls, { - trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, + trailingTriviaOption: textChanges.TrailingTriviaOption.Include, }, /*hasTrailingComment*/ true); } else { // Note: Delete the surrounding trivia because it will have been retained in newImportDecls. const replaceOptions = { - leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, // Leave header comment in place - trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, - suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options), + leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, // Leave header comment in place + trailingTriviaOption: textChanges.TrailingTriviaOption.Include, + suffix: getNewLineOrDefaultFromHost(host, formatContext.options), }; changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, replaceOptions); const hasTrailingComment = changeTracker.nodeHasTrailingComment(sourceFile, oldImportDecls[0], replaceOptions); changeTracker.deleteNodes(sourceFile, oldImportDecls.slice(1), { - trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include, + trailingTriviaOption: textChanges.TrailingTriviaOption.Include, }, hasTrailingComment); } } } -function groupImportsByNewlineContiguous(sourceFile: ts.SourceFile, importDecls: ts.ImportDeclaration[]): ts.ImportDeclaration[][] { - const scanner = ts.createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant); - const groupImports: ts.ImportDeclaration[][] = []; +function groupImportsByNewlineContiguous(sourceFile: SourceFile, importDecls: ImportDeclaration[]): ImportDeclaration[][] { + const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ false, sourceFile.languageVariant); + const groupImports: ImportDeclaration[][] = []; let groupIndex = 0; for (const topLevelImportDecl of importDecls) { if (isNewGroup(sourceFile, topLevelImportDecl, scanner)) { @@ -125,7 +135,7 @@ function groupImportsByNewlineContiguous(sourceFile: ts.SourceFile, importDecls: // a new group is created if an import includes at least two new line // new line from multi-line comment doesn't count -function isNewGroup(sourceFile: ts.SourceFile, topLevelImportDecl: ts.ImportDeclaration, scanner: ts.Scanner) { +function isNewGroup(sourceFile: SourceFile, topLevelImportDecl: ImportDeclaration, scanner: Scanner) { const startPos = topLevelImportDecl.getFullStart(); const endPos = topLevelImportDecl.getStart(); scanner.setText(sourceFile.text, startPos, endPos - startPos); @@ -134,7 +144,7 @@ function isNewGroup(sourceFile: ts.SourceFile, topLevelImportDecl: ts.ImportDecl while (scanner.getTokenPos() < endPos) { const tokenKind = scanner.scan(); - if (tokenKind === ts.SyntaxKind.NewLineTrivia) { + if (tokenKind === SyntaxKind.NewLineTrivia) { numberOfNewLines++; if (numberOfNewLines >= 2) { @@ -146,14 +156,14 @@ function isNewGroup(sourceFile: ts.SourceFile, topLevelImportDecl: ts.ImportDecl return false; } -function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], sourceFile: ts.SourceFile, program: ts.Program) { +function removeUnusedImports(oldImports: readonly ImportDeclaration[], sourceFile: SourceFile, program: Program) { const typeChecker = program.getTypeChecker(); const compilerOptions = program.getCompilerOptions(); const jsxNamespace = typeChecker.getJsxNamespace(sourceFile); const jsxFragmentFactory = typeChecker.getJsxFragmentFactory(sourceFile); - const jsxElementsPresent = !!(sourceFile.transformFlags & ts.TransformFlags.ContainsJsx); + const jsxElementsPresent = !!(sourceFile.transformFlags & TransformFlags.ContainsJsx); - const usedImports: ts.ImportDeclaration[] = []; + const usedImports: ImportDeclaration[] = []; for (const importDecl of oldImports) { const { importClause, moduleSpecifier } = importDecl; @@ -172,7 +182,7 @@ function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], source } if (namedBindings) { - if (ts.isNamespaceImport(namedBindings)) { + if (isNamespaceImport(namedBindings)) { // Namespace import if (!isDeclarationUsed(namedBindings.name)) { namedBindings = undefined; @@ -183,7 +193,7 @@ function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], source const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.name)); if (newElements.length < namedBindings.elements.length) { namedBindings = newElements.length - ? ts.factory.updateNamedImports(namedBindings, newElements) + ? factory.updateNamedImports(namedBindings, newElements) : undefined; } } @@ -196,7 +206,7 @@ function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], source else if (hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier)) { // If we’re in a declaration file, it’s safe to remove the import clause from it if (sourceFile.isDeclarationFile) { - usedImports.push(ts.factory.createImportDeclaration( + usedImports.push(factory.createImportDeclaration( importDecl.modifiers, /*importClause*/ undefined, moduleSpecifier, @@ -213,22 +223,22 @@ function removeUnusedImports(oldImports: readonly ts.ImportDeclaration[], source return usedImports; - function isDeclarationUsed(identifier: ts.Identifier) { + function isDeclarationUsed(identifier: Identifier) { // The JSX factory symbol is always used if JSX elements are present - even if they are not allowed. - return jsxElementsPresent && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) && ts.jsxModeNeedsExplicitImport(compilerOptions.jsx) || - ts.FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); + return jsxElementsPresent && (identifier.text === jsxNamespace || jsxFragmentFactory && identifier.text === jsxFragmentFactory) && jsxModeNeedsExplicitImport(compilerOptions.jsx) || + FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile); } } -function hasModuleDeclarationMatchingSpecifier(sourceFile: ts.SourceFile, moduleSpecifier: ts.Expression) { - const moduleSpecifierText = ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text; - return ts.isString(moduleSpecifierText) && ts.some(sourceFile.moduleAugmentations, moduleName => - ts.isStringLiteral(moduleName) +function hasModuleDeclarationMatchingSpecifier(sourceFile: SourceFile, moduleSpecifier: Expression) { + const moduleSpecifierText = isStringLiteral(moduleSpecifier) && moduleSpecifier.text; + return isString(moduleSpecifierText) && some(sourceFile.moduleAugmentations, moduleName => + isStringLiteral(moduleName) && moduleName.text === moduleSpecifierText); } -function getExternalModuleName(specifier: ts.Expression) { - return specifier !== undefined && ts.isStringLiteralLike(specifier) +function getExternalModuleName(specifier: Expression) { + return specifier !== undefined && isStringLiteralLike(specifier) ? specifier.text : undefined; } @@ -238,14 +248,14 @@ function getExternalModuleName(specifier: ts.Expression) { /** * @param importGroup a list of ImportDeclarations, all with the same module name. */ -export function coalesceImports(importGroup: readonly ts.ImportDeclaration[]) { +export function coalesceImports(importGroup: readonly ImportDeclaration[]) { if (importGroup.length === 0) { return importGroup; } const { importWithoutClause, typeOnlyImports, regularImports } = getCategorizedImports(importGroup); - const coalescedImports: ts.ImportDeclaration[] = []; + const coalescedImports: ImportDeclaration[] = []; if (importWithoutClause) { coalescedImports.push(importWithoutClause); @@ -265,8 +275,8 @@ export function coalesceImports(importGroup: readonly ts.ImportDeclaration[]) { continue; } - const sortedNamespaceImports = ts.stableSort(namespaceImports, (i1, i2) => - compareIdentifiers((i1.importClause!.namedBindings as ts.NamespaceImport).name, (i2.importClause!.namedBindings as ts.NamespaceImport).name)); // TODO: GH#18217 + const sortedNamespaceImports = stableSort(namespaceImports, (i1, i2) => + compareIdentifiers((i1.importClause!.namedBindings as NamespaceImport).name, (i2.importClause!.namedBindings as NamespaceImport).name)); // TODO: GH#18217 for (const namespaceImport of sortedNamespaceImports) { // Drop the name, if any @@ -278,15 +288,15 @@ export function coalesceImports(importGroup: readonly ts.ImportDeclaration[]) { continue; } - let newDefaultImport: ts.Identifier | undefined; - const newImportSpecifiers: ts.ImportSpecifier[] = []; + let newDefaultImport: Identifier | undefined; + const newImportSpecifiers: ImportSpecifier[] = []; if (defaultImports.length === 1) { newDefaultImport = defaultImports[0].importClause!.name; } else { for (const defaultImport of defaultImports) { newImportSpecifiers.push( - ts.factory.createImportSpecifier(/*isTypeOnly*/ false, ts.factory.createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217 + factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217 } } @@ -300,10 +310,10 @@ export function coalesceImports(importGroup: readonly ts.ImportDeclaration[]) { const newNamedImports = sortedImportSpecifiers.length === 0 ? newDefaultImport ? undefined - : ts.factory.createNamedImports(ts.emptyArray) + : factory.createNamedImports(emptyArray) : namedImports.length === 0 - ? ts.factory.createNamedImports(sortedImportSpecifiers) - : ts.factory.updateNamedImports(namedImports[0].importClause!.namedBindings as ts.NamedImports, sortedImportSpecifiers); // TODO: GH#18217 + ? factory.createNamedImports(sortedImportSpecifiers) + : factory.updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217 // Type-only imports are not allowed to mix default, namespace, and named imports in any combination. // We could rewrite a default import as a named import (`import { default as name }`), but we currently @@ -325,9 +335,9 @@ export function coalesceImports(importGroup: readonly ts.ImportDeclaration[]) { } interface ImportGroup { - defaultImports: ts.ImportDeclaration[]; - namespaceImports: ts.ImportDeclaration[]; - namedImports: ts.ImportDeclaration[]; + defaultImports: ImportDeclaration[]; + namespaceImports: ImportDeclaration[]; + namedImports: ImportDeclaration[]; } /* @@ -337,8 +347,8 @@ interface ImportGroup { * * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`. */ -function getCategorizedImports(importGroup: readonly ts.ImportDeclaration[]) { - let importWithoutClause: ts.ImportDeclaration | undefined; +function getCategorizedImports(importGroup: readonly ImportDeclaration[]) { + let importWithoutClause: ImportDeclaration | undefined; const typeOnlyImports: ImportGroup = { defaultImports: [], namespaceImports: [], namedImports: [] }; const regularImports: ImportGroup = { defaultImports: [], namespaceImports: [], namedImports: [] }; @@ -358,7 +368,7 @@ function getCategorizedImports(importGroup: readonly ts.ImportDeclaration[]) { } if (namedBindings) { - if (ts.isNamespaceImport(namedBindings)) { + if (isNamespaceImport(namedBindings)) { group.namespaceImports.push(importDeclaration); } else { @@ -379,14 +389,14 @@ function getCategorizedImports(importGroup: readonly ts.ImportDeclaration[]) { /** * @param exportGroup a list of ExportDeclarations, all with the same module name. */ -export function coalesceExports(exportGroup: readonly ts.ExportDeclaration[]) { +export function coalesceExports(exportGroup: readonly ExportDeclaration[]) { if (exportGroup.length === 0) { return exportGroup; } const { exportWithoutClause, namedExports, typeOnlyExports } = getCategorizedExports(exportGroup); - const coalescedExports: ts.ExportDeclaration[] = []; + const coalescedExports: ExportDeclaration[] = []; if (exportWithoutClause) { coalescedExports.push(exportWithoutClause); @@ -396,21 +406,21 @@ export function coalesceExports(exportGroup: readonly ts.ExportDeclaration[]) { if (exportGroup.length === 0) { continue; } - const newExportSpecifiers: ts.ExportSpecifier[] = []; - newExportSpecifiers.push(...ts.flatMap(exportGroup, i => i.exportClause && ts.isNamedExports(i.exportClause) ? i.exportClause.elements : ts.emptyArray)); + const newExportSpecifiers: ExportSpecifier[] = []; + newExportSpecifiers.push(...flatMap(exportGroup, i => i.exportClause && isNamedExports(i.exportClause) ? i.exportClause.elements : emptyArray)); const sortedExportSpecifiers = sortSpecifiers(newExportSpecifiers); const exportDecl = exportGroup[0]; coalescedExports.push( - ts.factory.updateExportDeclaration( + factory.updateExportDeclaration( exportDecl, exportDecl.modifiers, exportDecl.isTypeOnly, exportDecl.exportClause && ( - ts.isNamedExports(exportDecl.exportClause) ? - ts.factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) : - ts.factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name) + isNamedExports(exportDecl.exportClause) ? + factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) : + factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name) ), exportDecl.moduleSpecifier, exportDecl.assertClause)); @@ -423,10 +433,10 @@ export function coalesceExports(exportGroup: readonly ts.ExportDeclaration[]) { * may lack parent pointers. The desired parts can easily be recovered based on the * categorization. */ - function getCategorizedExports(exportGroup: readonly ts.ExportDeclaration[]) { - let exportWithoutClause: ts.ExportDeclaration | undefined; - const namedExports: ts.ExportDeclaration[] = []; - const typeOnlyExports: ts.ExportDeclaration[] = []; + function getCategorizedExports(exportGroup: readonly ExportDeclaration[]) { + let exportWithoutClause: ExportDeclaration | undefined; + const namedExports: ExportDeclaration[] = []; + const typeOnlyExports: ExportDeclaration[] = []; for (const exportDeclaration of exportGroup) { if (exportDeclaration.exportClause === undefined) { @@ -451,83 +461,83 @@ export function coalesceExports(exportGroup: readonly ts.ExportDeclaration[]) { } function updateImportDeclarationAndClause( - importDeclaration: ts.ImportDeclaration, - name: ts.Identifier | undefined, - namedBindings: ts.NamedImportBindings | undefined) { + importDeclaration: ImportDeclaration, + name: Identifier | undefined, + namedBindings: NamedImportBindings | undefined) { - return ts.factory.updateImportDeclaration( + return factory.updateImportDeclaration( importDeclaration, importDeclaration.modifiers, - ts.factory.updateImportClause(importDeclaration.importClause!, importDeclaration.importClause!.isTypeOnly, name, namedBindings), // TODO: GH#18217 + factory.updateImportClause(importDeclaration.importClause!, importDeclaration.importClause!.isTypeOnly, name, namedBindings), // TODO: GH#18217 importDeclaration.moduleSpecifier, importDeclaration.assertClause); } -function sortSpecifiers(specifiers: readonly T[]) { - return ts.stableSort(specifiers, compareImportOrExportSpecifiers); +function sortSpecifiers(specifiers: readonly T[]) { + return stableSort(specifiers, compareImportOrExportSpecifiers); } /** @internal */ -export function compareImportOrExportSpecifiers(s1: T, s2: T) { - return ts.compareBooleans(s1.isTypeOnly, s2.isTypeOnly) +export function compareImportOrExportSpecifiers(s1: T, s2: T) { + return compareBooleans(s1.isTypeOnly, s2.isTypeOnly) || compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) || compareIdentifiers(s1.name, s2.name); } /* internal */ // Exported for testing /** @internal */ -export function compareModuleSpecifiers(m1: ts.Expression | undefined, m2: ts.Expression | undefined) { +export function compareModuleSpecifiers(m1: Expression | undefined, m2: Expression | undefined) { const name1 = m1 === undefined ? undefined : getExternalModuleName(m1); const name2 = m2 === undefined ? undefined : getExternalModuleName(m2); - return ts.compareBooleans(name1 === undefined, name2 === undefined) || - ts.compareBooleans(ts.isExternalModuleNameRelative(name1!), ts.isExternalModuleNameRelative(name2!)) || - ts.compareStringsCaseInsensitive(name1!, name2!); + return compareBooleans(name1 === undefined, name2 === undefined) || + compareBooleans(isExternalModuleNameRelative(name1!), isExternalModuleNameRelative(name2!)) || + compareStringsCaseInsensitive(name1!, name2!); } -function compareIdentifiers(s1: ts.Identifier, s2: ts.Identifier) { - return ts.compareStringsCaseInsensitive(s1.text, s2.text); +function compareIdentifiers(s1: Identifier, s2: Identifier) { + return compareStringsCaseInsensitive(s1.text, s2.text); } -function getModuleSpecifierExpression(declaration: ts.AnyImportOrRequireStatement): ts.Expression | undefined { +function getModuleSpecifierExpression(declaration: AnyImportOrRequireStatement): Expression | undefined { switch (declaration.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: - return ts.tryCast(declaration.moduleReference, ts.isExternalModuleReference)?.expression; - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + return tryCast(declaration.moduleReference, isExternalModuleReference)?.expression; + case SyntaxKind.ImportDeclaration: return declaration.moduleSpecifier; - case ts.SyntaxKind.VariableStatement: + case SyntaxKind.VariableStatement: return declaration.declarationList.declarations[0].initializer.arguments[0]; } } /** @internal */ -export function importsAreSorted(imports: readonly ts.AnyImportOrRequireStatement[]): imports is ts.SortedReadonlyArray { - return ts.arrayIsSorted(imports, compareImportsOrRequireStatements); +export function importsAreSorted(imports: readonly AnyImportOrRequireStatement[]): imports is SortedReadonlyArray { + return arrayIsSorted(imports, compareImportsOrRequireStatements); } /** @internal */ -export function importSpecifiersAreSorted(imports: readonly ts.ImportSpecifier[]): imports is ts.SortedReadonlyArray { - return ts.arrayIsSorted(imports, compareImportOrExportSpecifiers); +export function importSpecifiersAreSorted(imports: readonly ImportSpecifier[]): imports is SortedReadonlyArray { + return arrayIsSorted(imports, compareImportOrExportSpecifiers); } /** @internal */ -export function getImportDeclarationInsertionIndex(sortedImports: ts.SortedReadonlyArray, newImport: ts.AnyImportOrRequireStatement) { - const index = ts.binarySearch(sortedImports, newImport, ts.identity, compareImportsOrRequireStatements); +export function getImportDeclarationInsertionIndex(sortedImports: SortedReadonlyArray, newImport: AnyImportOrRequireStatement) { + const index = binarySearch(sortedImports, newImport, identity, compareImportsOrRequireStatements); return index < 0 ? ~index : index; } /** @internal */ -export function getImportSpecifierInsertionIndex(sortedImports: ts.SortedReadonlyArray, newImport: ts.ImportSpecifier) { - const index = ts.binarySearch(sortedImports, newImport, ts.identity, compareImportOrExportSpecifiers); +export function getImportSpecifierInsertionIndex(sortedImports: SortedReadonlyArray, newImport: ImportSpecifier) { + const index = binarySearch(sortedImports, newImport, identity, compareImportOrExportSpecifiers); return index < 0 ? ~index : index; } /** @internal */ -export function compareImportsOrRequireStatements(s1: ts.AnyImportOrRequireStatement, s2: ts.AnyImportOrRequireStatement) { +export function compareImportsOrRequireStatements(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement) { return compareModuleSpecifiers(getModuleSpecifierExpression(s1), getModuleSpecifierExpression(s2)) || compareImportKind(s1, s2); } -function compareImportKind(s1: ts.AnyImportOrRequireStatement, s2: ts.AnyImportOrRequireStatement) { - return ts.compareValues(getImportKindOrder(s1), getImportKindOrder(s2)); +function compareImportKind(s1: AnyImportOrRequireStatement, s2: AnyImportOrRequireStatement) { + return compareValues(getImportKindOrder(s1), getImportKindOrder(s2)); } // 1. Side-effect imports @@ -537,33 +547,33 @@ function compareImportKind(s1: ts.AnyImportOrRequireStatement, s2: ts.AnyImportO // 5. Named imports // 6. ImportEqualsDeclarations // 7. Require variable statements -function getImportKindOrder(s1: ts.AnyImportOrRequireStatement) { +function getImportKindOrder(s1: AnyImportOrRequireStatement) { switch (s1.kind) { - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportDeclaration: if (!s1.importClause) return 0; if (s1.importClause.isTypeOnly) return 1; - if (s1.importClause.namedBindings?.kind === ts.SyntaxKind.NamespaceImport) return 2; + if (s1.importClause.namedBindings?.kind === SyntaxKind.NamespaceImport) return 2; if (s1.importClause.name) return 3; return 4; - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return 5; - case ts.SyntaxKind.VariableStatement: + case SyntaxKind.VariableStatement: return 6; } } -function getNewImportSpecifiers(namedImports: ts.ImportDeclaration[]) { - return ts.flatMap(namedImports, namedImport => - ts.map(tryGetNamedBindingElements(namedImport), importSpecifier => +function getNewImportSpecifiers(namedImports: ImportDeclaration[]) { + return flatMap(namedImports, namedImport => + map(tryGetNamedBindingElements(namedImport), importSpecifier => importSpecifier.name && importSpecifier.propertyName && importSpecifier.name.escapedText === importSpecifier.propertyName.escapedText - ? ts.factory.updateImportSpecifier(importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ undefined, importSpecifier.name) + ? factory.updateImportSpecifier(importSpecifier, importSpecifier.isTypeOnly, /*propertyName*/ undefined, importSpecifier.name) : importSpecifier ) ); } -function tryGetNamedBindingElements(namedImport: ts.ImportDeclaration) { - return namedImport.importClause?.namedBindings && ts.isNamedImports(namedImport.importClause.namedBindings) +function tryGetNamedBindingElements(namedImport: ImportDeclaration) { + return namedImport.importClause?.namedBindings && isNamedImports(namedImport.importClause.namedBindings) ? namedImport.importClause.namedBindings.elements : undefined; } diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index 406bd6e747562..5a80301e00055 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -1,53 +1,63 @@ -import * as ts from "./_namespaces/ts"; +import { + ArrowFunction, Block, CallExpression, CancellationToken, CaseClause, createTextSpanFromBounds, + createTextSpanFromNode, createTextSpanFromRange, Debug, DefaultClause, findChildOfKind, getLeadingCommentRanges, + isAnyImportSyntax, isArrayLiteralExpression, isBinaryExpression, isBindingElement, isBlock, isCallExpression, + isCallOrNewExpression, isClassLike, isDeclaration, isFunctionLike, isIfStatement, isInComment, + isInterfaceDeclaration, isJsxText, isModuleBlock, isNodeArrayMultiLine, isParenthesizedExpression, + isPropertyAccessExpression, isReturnStatement, isTupleTypeNode, isVariableStatement, JsxAttributes, JsxElement, + JsxFragment, JsxOpeningLikeElement, Node, NodeArray, NoSubstitutionTemplateLiteral, OutliningSpan, + OutliningSpanKind, ParenthesizedExpression, positionsAreOnSameLine, Push, SignatureDeclaration, SourceFile, + startsWith, SyntaxKind, TemplateExpression, TextSpan, trimString, trimStringStart, TryStatement, +} from "./_namespaces/ts"; /** @internal */ -export function collectElements(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken): ts.OutliningSpan[] { - const res: ts.OutliningSpan[] = []; +export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] { + const res: OutliningSpan[] = []; addNodeOutliningSpans(sourceFile, cancellationToken, res); addRegionOutliningSpans(sourceFile, res); return res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); } -function addNodeOutliningSpans(sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken, out: ts.Push): void { +function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { let depthRemaining = 40; let current = 0; // Includes the EOF Token so that comments which aren't attached to statements are included const statements = [...sourceFile.statements, sourceFile.endOfFileToken]; const n = statements.length; while (current < n) { - while (current < n && !ts.isAnyImportSyntax(statements[current])) { + while (current < n && !isAnyImportSyntax(statements[current])) { visitNonImportNode(statements[current]); current++; } if (current === n) break; const firstImport = current; - while (current < n && ts.isAnyImportSyntax(statements[current])) { + while (current < n && isAnyImportSyntax(statements[current])) { addOutliningForLeadingCommentsForNode(statements[current], sourceFile, cancellationToken, out); current++; } const lastImport = current - 1; if (lastImport !== firstImport) { - out.push(createOutliningSpanFromBounds(ts.findChildOfKind(statements[firstImport], ts.SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), statements[lastImport].getEnd(), ts.OutliningSpanKind.Imports)); + out.push(createOutliningSpanFromBounds(findChildOfKind(statements[firstImport], SyntaxKind.ImportKeyword, sourceFile)!.getStart(sourceFile), statements[lastImport].getEnd(), OutliningSpanKind.Imports)); } } - function visitNonImportNode(n: ts.Node) { + function visitNonImportNode(n: Node) { if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); - if (ts.isDeclaration(n) || ts.isVariableStatement(n) || ts.isReturnStatement(n) || ts.isCallOrNewExpression(n) || n.kind === ts.SyntaxKind.EndOfFileToken) { + if (isDeclaration(n) || isVariableStatement(n) || isReturnStatement(n) || isCallOrNewExpression(n) || n.kind === SyntaxKind.EndOfFileToken) { addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out); } - if (ts.isFunctionLike(n) && ts.isBinaryExpression(n.parent) && ts.isPropertyAccessExpression(n.parent.left)) { + if (isFunctionLike(n) && isBinaryExpression(n.parent) && isPropertyAccessExpression(n.parent.left)) { addOutliningForLeadingCommentsForNode(n.parent.left, sourceFile, cancellationToken, out); } - if (ts.isBlock(n) || ts.isModuleBlock(n)) { + if (isBlock(n) || isModuleBlock(n)) { addOutliningForLeadingCommentsForPos(n.statements.end, sourceFile, cancellationToken, out); } - if (ts.isClassLike(n) || ts.isInterfaceDeclaration(n)) { + if (isClassLike(n) || isInterfaceDeclaration(n)) { addOutliningForLeadingCommentsForPos(n.members.end, sourceFile, cancellationToken, out); } @@ -55,14 +65,14 @@ function addNodeOutliningSpans(sourceFile: ts.SourceFile, cancellationToken: ts. if (span) out.push(span); depthRemaining--; - if (ts.isCallExpression(n)) { + if (isCallExpression(n)) { depthRemaining++; visitNonImportNode(n.expression); depthRemaining--; n.arguments.forEach(visitNonImportNode); n.typeArguments?.forEach(visitNonImportNode); } - else if (ts.isIfStatement(n) && n.elseStatement && ts.isIfStatement(n.elseStatement)) { + else if (isIfStatement(n) && n.elseStatement && isIfStatement(n.elseStatement)) { // Consider an 'else if' to be on the same depth as the 'if'. visitNonImportNode(n.expression); visitNonImportNode(n.thenStatement); @@ -77,20 +87,20 @@ function addNodeOutliningSpans(sourceFile: ts.SourceFile, cancellationToken: ts. } } -function addRegionOutliningSpans(sourceFile: ts.SourceFile, out: ts.Push): void { - const regions: ts.OutliningSpan[] = []; +function addRegionOutliningSpans(sourceFile: SourceFile, out: Push): void { + const regions: OutliningSpan[] = []; const lineStarts = sourceFile.getLineStarts(); for (const currentLineStart of lineStarts) { const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart); const lineText = sourceFile.text.substring(currentLineStart, lineEnd); const result = isRegionDelimiter(lineText); - if (!result || ts.isInComment(sourceFile, currentLineStart)) { + if (!result || isInComment(sourceFile, currentLineStart)) { continue; } if (!result[1]) { - const span = ts.createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); - regions.push(createOutliningSpan(span, ts.OutliningSpanKind.Region, span, /*autoCollapse*/ false, result[2] || "#region")); + const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); + regions.push(createOutliningSpan(span, OutliningSpanKind.Region, span, /*autoCollapse*/ false, result[2] || "#region")); } else { const region = regions.pop(); @@ -107,16 +117,16 @@ const regionDelimiterRegExp = /^#(end)?region(?:\s+(.*))?(?:\r)?$/; function isRegionDelimiter(lineText: string) { // We trim the leading whitespace and // without the regex since the // multiple potential whitespace matches can make for some gnarly backtracking behavior - lineText = ts.trimStringStart(lineText); - if (!ts.startsWith(lineText, "\/\/")) { + lineText = trimStringStart(lineText); + if (!startsWith(lineText, "\/\/")) { return null; // eslint-disable-line no-null/no-null } - lineText = ts.trimString(lineText.slice(2)); + lineText = trimString(lineText.slice(2)); return regionDelimiterRegExp.exec(lineText); } -function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken, out: ts.Push): void { - const comments = ts.getLeadingCommentRanges(sourceFile.text, pos); +function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { + const comments = getLeadingCommentRanges(sourceFile.text, pos); if (!comments) return; let firstSingleLineCommentStart = -1; @@ -126,7 +136,7 @@ function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: ts.Source for (const { kind, pos, end } of comments) { cancellationToken.throwIfCancellationRequested(); switch (kind) { - case ts.SyntaxKind.SingleLineCommentTrivia: + case SyntaxKind.SingleLineCommentTrivia: // never fold region delimiters into single-line comment regions const commentText = sourceText.slice(pos, end); if (isRegionDelimiter(commentText)) { @@ -143,13 +153,13 @@ function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: ts.Source lastSingleLineCommentEnd = end; singleLineCommentCount++; break; - case ts.SyntaxKind.MultiLineCommentTrivia: + case SyntaxKind.MultiLineCommentTrivia: combineAndAddMultipleSingleLineComments(); - out.push(createOutliningSpanFromBounds(pos, end, ts.OutliningSpanKind.Comment)); + out.push(createOutliningSpanFromBounds(pos, end, OutliningSpanKind.Comment)); singleLineCommentCount = 0; break; default: - ts.Debug.assertNever(kind); + Debug.assertNever(kind); } } combineAndAddMultipleSingleLineComments(); @@ -157,188 +167,188 @@ function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: ts.Source function combineAndAddMultipleSingleLineComments(): void { // Only outline spans of two or more consecutive single line comments if (singleLineCommentCount > 1) { - out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, ts.OutliningSpanKind.Comment)); + out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd, OutliningSpanKind.Comment)); } } } -function addOutliningForLeadingCommentsForNode(n: ts.Node, sourceFile: ts.SourceFile, cancellationToken: ts.CancellationToken, out: ts.Push): void { - if (ts.isJsxText(n)) return; +function addOutliningForLeadingCommentsForNode(n: Node, sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { + if (isJsxText(n)) return; addOutliningForLeadingCommentsForPos(n.pos, sourceFile, cancellationToken, out); } -function createOutliningSpanFromBounds(pos: number, end: number, kind: ts.OutliningSpanKind): ts.OutliningSpan { - return createOutliningSpan(ts.createTextSpanFromBounds(pos, end), kind); +function createOutliningSpanFromBounds(pos: number, end: number, kind: OutliningSpanKind): OutliningSpan { + return createOutliningSpan(createTextSpanFromBounds(pos, end), kind); } -function getOutliningSpanForNode(n: ts.Node, sourceFile: ts.SourceFile): ts.OutliningSpan | undefined { +function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan | undefined { switch (n.kind) { - case ts.SyntaxKind.Block: - if (ts.isFunctionLike(n.parent)) { - return functionSpan(n.parent, n as ts.Block, sourceFile); + case SyntaxKind.Block: + if (isFunctionLike(n.parent)) { + return functionSpan(n.parent, n as Block, sourceFile); } // Check if the block is standalone, or 'attached' to some parent statement. // If the latter, we want to collapse the block, but consider its hint span // to be the entire span of the parent. switch (n.parent.kind) { - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.WithStatement: - case ts.SyntaxKind.CatchClause: + case SyntaxKind.DoStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.CatchClause: return spanForNode(n.parent); - case ts.SyntaxKind.TryStatement: + case SyntaxKind.TryStatement: // Could be the try-block, or the finally-block. - const tryStatement = n.parent as ts.TryStatement; + const tryStatement = n.parent as TryStatement; if (tryStatement.tryBlock === n) { return spanForNode(n.parent); } else if (tryStatement.finallyBlock === n) { - const node = ts.findChildOfKind(tryStatement, ts.SyntaxKind.FinallyKeyword, sourceFile); + const node = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); if (node) return spanForNode(node); } // falls through default: // Block was a standalone block. In this case we want to only collapse // the span of the block, independent of any parent span. - return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile), ts.OutliningSpanKind.Code); + return createOutliningSpan(createTextSpanFromNode(n, sourceFile), OutliningSpanKind.Code); } - case ts.SyntaxKind.ModuleBlock: + case SyntaxKind.ModuleBlock: return spanForNode(n.parent); - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.CaseBlock: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.CaseBlock: + case SyntaxKind.TypeLiteral: + case SyntaxKind.ObjectBindingPattern: return spanForNode(n); - case ts.SyntaxKind.TupleType: - return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !ts.isTupleTypeNode(n.parent), ts.SyntaxKind.OpenBracketToken); - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: - return spanForNodeArray((n as ts.CaseClause | ts.DefaultClause).statements); - case ts.SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TupleType: + return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !isTupleTypeNode(n.parent), SyntaxKind.OpenBracketToken); + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + return spanForNodeArray((n as CaseClause | DefaultClause).statements); + case SyntaxKind.ObjectLiteralExpression: return spanForObjectOrArrayLiteral(n); - case ts.SyntaxKind.ArrayLiteralExpression: - return spanForObjectOrArrayLiteral(n, ts.SyntaxKind.OpenBracketToken); - case ts.SyntaxKind.JsxElement: - return spanForJSXElement(n as ts.JsxElement); - case ts.SyntaxKind.JsxFragment: - return spanForJSXFragment(n as ts.JsxFragment); - case ts.SyntaxKind.JsxSelfClosingElement: - case ts.SyntaxKind.JsxOpeningElement: - return spanForJSXAttributes((n as ts.JsxOpeningLikeElement).attributes); - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - return spanForTemplateLiteral(n as ts.TemplateExpression | ts.NoSubstitutionTemplateLiteral); - case ts.SyntaxKind.ArrayBindingPattern: - return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !ts.isBindingElement(n.parent), ts.SyntaxKind.OpenBracketToken); - case ts.SyntaxKind.ArrowFunction: - return spanForArrowFunction(n as ts.ArrowFunction); - case ts.SyntaxKind.CallExpression: - return spanForCallExpression(n as ts.CallExpression); - case ts.SyntaxKind.ParenthesizedExpression: - return spanForParenthesizedExpression(n as ts.ParenthesizedExpression); + case SyntaxKind.ArrayLiteralExpression: + return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken); + case SyntaxKind.JsxElement: + return spanForJSXElement(n as JsxElement); + case SyntaxKind.JsxFragment: + return spanForJSXFragment(n as JsxFragment); + case SyntaxKind.JsxSelfClosingElement: + case SyntaxKind.JsxOpeningElement: + return spanForJSXAttributes((n as JsxOpeningLikeElement).attributes); + case SyntaxKind.TemplateExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return spanForTemplateLiteral(n as TemplateExpression | NoSubstitutionTemplateLiteral); + case SyntaxKind.ArrayBindingPattern: + return spanForNode(n, /*autoCollapse*/ false, /*useFullStart*/ !isBindingElement(n.parent), SyntaxKind.OpenBracketToken); + case SyntaxKind.ArrowFunction: + return spanForArrowFunction(n as ArrowFunction); + case SyntaxKind.CallExpression: + return spanForCallExpression(n as CallExpression); + case SyntaxKind.ParenthesizedExpression: + return spanForParenthesizedExpression(n as ParenthesizedExpression); } - function spanForCallExpression(node: ts.CallExpression): ts.OutliningSpan | undefined { + function spanForCallExpression(node: CallExpression): OutliningSpan | undefined { if (!node.arguments.length) { return undefined; } - const openToken = ts.findChildOfKind(node, ts.SyntaxKind.OpenParenToken, sourceFile); - const closeToken = ts.findChildOfKind(node, ts.SyntaxKind.CloseParenToken, sourceFile); - if (!openToken || !closeToken || ts.positionsAreOnSameLine(openToken.pos, closeToken.pos, sourceFile)) { + const openToken = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); + const closeToken = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile); + if (!openToken || !closeToken || positionsAreOnSameLine(openToken.pos, closeToken.pos, sourceFile)) { return undefined; } return spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ false, /*useFullStart*/ true); } - function spanForArrowFunction(node: ts.ArrowFunction): ts.OutliningSpan | undefined { - if (ts.isBlock(node.body) || ts.isParenthesizedExpression(node.body) || ts.positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile)) { + function spanForArrowFunction(node: ArrowFunction): OutliningSpan | undefined { + if (isBlock(node.body) || isParenthesizedExpression(node.body) || positionsAreOnSameLine(node.body.getFullStart(), node.body.getEnd(), sourceFile)) { return undefined; } - const textSpan = ts.createTextSpanFromBounds(node.body.getFullStart(), node.body.getEnd()); - return createOutliningSpan(textSpan, ts.OutliningSpanKind.Code, ts.createTextSpanFromNode(node)); + const textSpan = createTextSpanFromBounds(node.body.getFullStart(), node.body.getEnd()); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(node)); } - function spanForJSXElement(node: ts.JsxElement): ts.OutliningSpan | undefined { - const textSpan = ts.createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd()); + function spanForJSXElement(node: JsxElement): OutliningSpan | undefined { + const textSpan = createTextSpanFromBounds(node.openingElement.getStart(sourceFile), node.closingElement.getEnd()); const tagName = node.openingElement.tagName.getText(sourceFile); const bannerText = "<" + tagName + ">..."; - return createOutliningSpan(textSpan, ts.OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); } - function spanForJSXFragment(node: ts.JsxFragment): ts.OutliningSpan | undefined { - const textSpan = ts.createTextSpanFromBounds(node.openingFragment.getStart(sourceFile), node.closingFragment.getEnd()); + function spanForJSXFragment(node: JsxFragment): OutliningSpan | undefined { + const textSpan = createTextSpanFromBounds(node.openingFragment.getStart(sourceFile), node.closingFragment.getEnd()); const bannerText = "<>..."; - return createOutliningSpan(textSpan, ts.OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, textSpan, /*autoCollapse*/ false, bannerText); } - function spanForJSXAttributes(node: ts.JsxAttributes): ts.OutliningSpan | undefined { + function spanForJSXAttributes(node: JsxAttributes): OutliningSpan | undefined { if (node.properties.length === 0) { return undefined; } - return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), ts.OutliningSpanKind.Code); + return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), OutliningSpanKind.Code); } - function spanForTemplateLiteral(node: ts.TemplateExpression | ts.NoSubstitutionTemplateLiteral) { - if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral && node.text.length === 0) { + function spanForTemplateLiteral(node: TemplateExpression | NoSubstitutionTemplateLiteral) { + if (node.kind === SyntaxKind.NoSubstitutionTemplateLiteral && node.text.length === 0) { return undefined; } - return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), ts.OutliningSpanKind.Code); + return createOutliningSpanFromBounds(node.getStart(sourceFile), node.getEnd(), OutliningSpanKind.Code); } - function spanForObjectOrArrayLiteral(node: ts.Node, open: ts.SyntaxKind.OpenBraceToken | ts.SyntaxKind.OpenBracketToken = ts.SyntaxKind.OpenBraceToken): ts.OutliningSpan | undefined { + function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { // If the block has no leading keywords and is inside an array literal or call expression, // we only want to collapse the span of the block. // Otherwise, the collapsed section will include the end of the previous line. - return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !ts.isArrayLiteralExpression(node.parent) && !ts.isCallExpression(node.parent), open); + return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent) && !isCallExpression(node.parent), open); } - function spanForNode(hintSpanNode: ts.Node, autoCollapse = false, useFullStart = true, open: ts.SyntaxKind.OpenBraceToken | ts.SyntaxKind.OpenBracketToken = ts.SyntaxKind.OpenBraceToken, close: ts.SyntaxKind = open === ts.SyntaxKind.OpenBraceToken ? ts.SyntaxKind.CloseBraceToken : ts.SyntaxKind.CloseBracketToken): ts.OutliningSpan | undefined { - const openToken = ts.findChildOfKind(n, open, sourceFile); - const closeToken = ts.findChildOfKind(n, close, sourceFile); + function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken, close: SyntaxKind = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken): OutliningSpan | undefined { + const openToken = findChildOfKind(n, open, sourceFile); + const closeToken = findChildOfKind(n, close, sourceFile); return openToken && closeToken && spanBetweenTokens(openToken, closeToken, hintSpanNode, sourceFile, autoCollapse, useFullStart); } - function spanForNodeArray(nodeArray: ts.NodeArray): ts.OutliningSpan | undefined { - return nodeArray.length ? createOutliningSpan(ts.createTextSpanFromRange(nodeArray), ts.OutliningSpanKind.Code) : undefined; + function spanForNodeArray(nodeArray: NodeArray): OutliningSpan | undefined { + return nodeArray.length ? createOutliningSpan(createTextSpanFromRange(nodeArray), OutliningSpanKind.Code) : undefined; } - function spanForParenthesizedExpression(node: ts.ParenthesizedExpression): ts.OutliningSpan | undefined { - if (ts.positionsAreOnSameLine(node.getStart(), node.getEnd(), sourceFile)) return undefined; - const textSpan = ts.createTextSpanFromBounds(node.getStart(), node.getEnd()); - return createOutliningSpan(textSpan, ts.OutliningSpanKind.Code, ts.createTextSpanFromNode(node)); + function spanForParenthesizedExpression(node: ParenthesizedExpression): OutliningSpan | undefined { + if (positionsAreOnSameLine(node.getStart(), node.getEnd(), sourceFile)) return undefined; + const textSpan = createTextSpanFromBounds(node.getStart(), node.getEnd()); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(node)); } } -function functionSpan(node: ts.SignatureDeclaration, body: ts.Block, sourceFile: ts.SourceFile): ts.OutliningSpan | undefined { +function functionSpan(node: SignatureDeclaration, body: Block, sourceFile: SourceFile): OutliningSpan | undefined { const openToken = tryGetFunctionOpenToken(node, body, sourceFile); - const closeToken = ts.findChildOfKind(body, ts.SyntaxKind.CloseBraceToken, sourceFile); - return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== ts.SyntaxKind.ArrowFunction); + const closeToken = findChildOfKind(body, SyntaxKind.CloseBraceToken, sourceFile); + return openToken && closeToken && spanBetweenTokens(openToken, closeToken, node, sourceFile, /*autoCollapse*/ node.kind !== SyntaxKind.ArrowFunction); } -function spanBetweenTokens(openToken: ts.Node, closeToken: ts.Node, hintSpanNode: ts.Node, sourceFile: ts.SourceFile, autoCollapse = false, useFullStart = true): ts.OutliningSpan { - const textSpan = ts.createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); - return createOutliningSpan(textSpan, ts.OutliningSpanKind.Code, ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); +function spanBetweenTokens(openToken: Node, closeToken: Node, hintSpanNode: Node, sourceFile: SourceFile, autoCollapse = false, useFullStart = true): OutliningSpan { + const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); + return createOutliningSpan(textSpan, OutliningSpanKind.Code, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); } -function createOutliningSpan(textSpan: ts.TextSpan, kind: ts.OutliningSpanKind, hintSpan: ts.TextSpan = textSpan, autoCollapse = false, bannerText = "..."): ts.OutliningSpan { +function createOutliningSpan(textSpan: TextSpan, kind: OutliningSpanKind, hintSpan: TextSpan = textSpan, autoCollapse = false, bannerText = "..."): OutliningSpan { return { textSpan, kind, hintSpan, bannerText, autoCollapse }; } -function tryGetFunctionOpenToken(node: ts.SignatureDeclaration, body: ts.Block, sourceFile: ts.SourceFile): ts.Node | undefined { - if (ts.isNodeArrayMultiLine(node.parameters, sourceFile)) { - const openParenToken = ts.findChildOfKind(node, ts.SyntaxKind.OpenParenToken, sourceFile); +function tryGetFunctionOpenToken(node: SignatureDeclaration, body: Block, sourceFile: SourceFile): Node | undefined { + if (isNodeArrayMultiLine(node.parameters, sourceFile)) { + const openParenToken = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); if (openParenToken) { return openParenToken; } } - return ts.findChildOfKind(body, ts.SyntaxKind.OpenBraceToken, sourceFile); + return findChildOfKind(body, SyntaxKind.OpenBraceToken, sourceFile); } diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index 179826818136c..abb19c785f9ba 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -1,4 +1,7 @@ -import * as ts from "./_namespaces/ts"; +import { + CharacterCodes, compareBooleans, compareValues, Comparison, createTextSpan, ESMap, isUnicodeIdentifierStart, last, + Map, min, ScriptTarget, startsWith, TextSpan, +} from "./_namespaces/ts"; // Note(cyrusn): this enum is ordered from strongest match type to weakest match type. /** @internal */ @@ -90,7 +93,7 @@ interface TextChunk { // independently. For example, if the chunk is for "UIElement" the the spans of interest // correspond to "U", "I" and "Element". If "UIElement" isn't found as an exact, prefix. // or substring match, then the character spans will be used to attempt a camel case match. - characterSpans: ts.TextSpan[]; + characterSpans: TextSpan[]; } function createPatternMatch(kind: PatternMatchKind, isCaseSensitive: boolean): PatternMatch { @@ -106,7 +109,7 @@ export function createPatternMatcher(pattern: string): PatternMatcher | undefine // we see the name of a module that is used everywhere, or the name of an overload). As // such, we cache the information we compute about the candidate for the life of this // pattern matcher so we don't have to compute it multiple times. - const stringToWordSpans = new ts.Map(); + const stringToWordSpans = new Map(); const dotSeparatedSegments = pattern.trim().split(".").map(p => createSegment(p.trim())); // A segment is considered invalid if we couldn't find any words in it. @@ -114,16 +117,16 @@ export function createPatternMatcher(pattern: string): PatternMatcher | undefine return { getFullMatch: (containers, candidate) => getFullMatch(containers, candidate, dotSeparatedSegments, stringToWordSpans), - getMatchForLastSegmentOfPattern: candidate => matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans), + getMatchForLastSegmentOfPattern: candidate => matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans), patternContainsDots: dotSeparatedSegments.length > 1 }; } -function getFullMatch(candidateContainers: readonly string[], candidate: string, dotSeparatedSegments: readonly Segment[], stringToWordSpans: ts.ESMap): PatternMatch | undefined { +function getFullMatch(candidateContainers: readonly string[], candidate: string, dotSeparatedSegments: readonly Segment[], stringToWordSpans: ESMap): PatternMatch | undefined { // First, check that the last part of the dot separated pattern matches the name of the // candidate. If not, then there's no point in proceeding and doing the more // expensive work. - const candidateMatch = matchSegment(candidate, ts.last(dotSeparatedSegments), stringToWordSpans); + const candidateMatch = matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans); if (!candidateMatch) { return undefined; } @@ -145,7 +148,7 @@ function getFullMatch(candidateContainers: readonly string[], candidate: string, return bestMatch; } -function getWordSpans(word: string, stringToWordSpans: ts.ESMap): ts.TextSpan[] { +function getWordSpans(word: string, stringToWordSpans: ESMap): TextSpan[] { let spans = stringToWordSpans.get(word); if (!spans) { stringToWordSpans.set(word, spans = breakIntoWordSpans(word)); @@ -153,12 +156,12 @@ function getWordSpans(word: string, stringToWordSpans: ts.ESMap): PatternMatch | undefined { +function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: ESMap): PatternMatch | undefined { const index = indexOfIgnoringCase(candidate, chunk.textLowerCase); if (index === 0) { // a) Check if the word is a prefix of the candidate, in a case insensitive or // sensitive manner. If it does, return that there was an exact match if the word and candidate are the same length, else a prefix match. - return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text)); + return createPatternMatch(chunk.text.length === candidate.length ? PatternMatchKind.exact : PatternMatchKind.prefix, /*isCaseSensitive:*/ startsWith(candidate, chunk.text)); } if (chunk.isLowerCase) { @@ -205,7 +208,7 @@ function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: } } -function matchSegment(candidate: string, segment: Segment, stringToWordSpans: ts.ESMap): PatternMatch | undefined { +function matchSegment(candidate: string, segment: Segment, stringToWordSpans: ESMap): PatternMatch | undefined { // First check if the segment matches as is. This is also useful if the segment contains // characters we would normally strip when splitting into parts that we also may want to // match in the candidate. For example if the segment is "@int" and the candidate is @@ -213,7 +216,7 @@ function matchSegment(candidate: string, segment: Segment, stringToWordSpans: ts // // Note: if the segment contains a space or an asterisk then we must assume that it's a // multi-word segment. - if (every(segment.totalTextChunk.text, ch => ch !== ts.CharacterCodes.space && ch !== ts.CharacterCodes.asterisk)) { + if (every(segment.totalTextChunk.text, ch => ch !== CharacterCodes.space && ch !== CharacterCodes.asterisk)) { const match = matchTextChunk(candidate, segment.totalTextChunk, stringToWordSpans); if (match) return match; } @@ -263,14 +266,14 @@ function matchSegment(candidate: string, segment: Segment, stringToWordSpans: ts } function betterMatch(a: PatternMatch | undefined, b: PatternMatch | undefined): PatternMatch | undefined { - return ts.min([a, b], compareMatches); + return min([a, b], compareMatches); } -function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined): ts.Comparison { - return a === undefined ? ts.Comparison.GreaterThan : b === undefined ? ts.Comparison.LessThan - : ts.compareValues(a.kind, b.kind) || ts.compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive); +function compareMatches(a: PatternMatch | undefined, b: PatternMatch | undefined): Comparison { + return a === undefined ? Comparison.GreaterThan : b === undefined ? Comparison.LessThan + : compareValues(a.kind, b.kind) || compareBooleans(!a.isCaseSensitive, !b.isCaseSensitive); } -function partStartsWith(candidate: string, candidateSpan: ts.TextSpan, pattern: string, ignoreCase: boolean, patternSpan: ts.TextSpan = { start: 0, length: pattern.length }): boolean { +function partStartsWith(candidate: string, candidateSpan: TextSpan, pattern: string, ignoreCase: boolean, patternSpan: TextSpan = { start: 0, length: pattern.length }): boolean { return patternSpan.length <= candidateSpan.length // If pattern part is longer than the candidate part there can never be a match. && everyInRange(0, patternSpan.length, i => equalChars(pattern.charCodeAt(patternSpan.start + i), candidate.charCodeAt(candidateSpan.start + i), ignoreCase)); } @@ -279,7 +282,7 @@ function equalChars(ch1: number, ch2: number, ignoreCase: boolean): boolean { return ignoreCase ? toLowerCase(ch1) === toLowerCase(ch2) : ch1 === ch2; } -function tryCamelCaseMatch(candidate: string, candidateParts: ts.TextSpan[], chunk: TextChunk, ignoreCase: boolean): boolean { +function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): boolean { const chunkCharacterSpans = chunk.characterSpans; // Note: we may have more pattern parts than candidate parts. This is because multiple @@ -335,7 +338,7 @@ function tryCamelCaseMatch(candidate: string, candidateParts: ts.TextSpan[], chu // obviously contiguous. contiguous = contiguous === undefined ? true : contiguous; - candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); + candidatePart = createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length); } // Check if we matched anything at all. If we didn't, then we need to unset the @@ -360,11 +363,11 @@ function createSegment(text: string): Segment { function isUpperCaseLetter(ch: number) { // Fast check for the ascii range. - if (ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.Z) { + if (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) { return true; } - if (ch < ts.CharacterCodes.maxAsciiCharacter || !ts.isUnicodeIdentifierStart(ch, ts.ScriptTarget.Latest)) { + if (ch < CharacterCodes.maxAsciiCharacter || !isUnicodeIdentifierStart(ch, ScriptTarget.Latest)) { return false; } @@ -376,11 +379,11 @@ function isUpperCaseLetter(ch: number) { function isLowerCaseLetter(ch: number) { // Fast check for the ascii range. - if (ch >= ts.CharacterCodes.a && ch <= ts.CharacterCodes.z) { + if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) { return true; } - if (ch < ts.CharacterCodes.maxAsciiCharacter || !ts.isUnicodeIdentifierStart(ch, ts.ScriptTarget.Latest)) { + if (ch < CharacterCodes.maxAsciiCharacter || !isUnicodeIdentifierStart(ch, ScriptTarget.Latest)) { return false; } @@ -405,11 +408,11 @@ function indexOfIgnoringCase(str: string, value: string): number { function toLowerCase(ch: number): number { // Fast convert for the ascii range. - if (ch >= ts.CharacterCodes.A && ch <= ts.CharacterCodes.Z) { - return ts.CharacterCodes.a + (ch - ts.CharacterCodes.A); + if (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) { + return CharacterCodes.a + (ch - CharacterCodes.A); } - if (ch < ts.CharacterCodes.maxAsciiCharacter) { + if (ch < CharacterCodes.maxAsciiCharacter) { return ch; } @@ -420,11 +423,11 @@ function toLowerCase(ch: number): number { function isDigit(ch: number) { // TODO(cyrusn): Find a way to support this for unicode digits. - return ch >= ts.CharacterCodes._0 && ch <= ts.CharacterCodes._9; + return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } function isWordChar(ch: number) { - return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === ts.CharacterCodes._ || ch === ts.CharacterCodes.$; + return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === CharacterCodes._ || ch === CharacterCodes.$; } function breakPatternIntoTextChunks(pattern: string): TextChunk[] { @@ -466,17 +469,17 @@ function createTextChunk(text: string): TextChunk { } /** @internal */ -export function breakIntoCharacterSpans(identifier: string): ts.TextSpan[] { +export function breakIntoCharacterSpans(identifier: string): TextSpan[] { return breakIntoSpans(identifier, /*word:*/ false); } /** @internal */ -export function breakIntoWordSpans(identifier: string): ts.TextSpan[] { +export function breakIntoWordSpans(identifier: string): TextSpan[] { return breakIntoSpans(identifier, /*word:*/ true); } -function breakIntoSpans(identifier: string, word: boolean): ts.TextSpan[] { - const result: ts.TextSpan[] = []; +function breakIntoSpans(identifier: string, word: boolean): TextSpan[] { + const result: TextSpan[] = []; let wordStart = 0; for (let i = 1; i < identifier.length; i++) { @@ -493,7 +496,7 @@ function breakIntoSpans(identifier: string, word: boolean): ts.TextSpan[] { hasTransitionFromUpperToLower) { if (!isAllPunctuation(identifier, wordStart, i)) { - result.push(ts.createTextSpan(wordStart, i - wordStart)); + result.push(createTextSpan(wordStart, i - wordStart)); } wordStart = i; @@ -501,7 +504,7 @@ function breakIntoSpans(identifier: string, word: boolean): ts.TextSpan[] { } if (!isAllPunctuation(identifier, wordStart, identifier.length)) { - result.push(ts.createTextSpan(wordStart, identifier.length - wordStart)); + result.push(createTextSpan(wordStart, identifier.length - wordStart)); } return result; @@ -509,29 +512,29 @@ function breakIntoSpans(identifier: string, word: boolean): ts.TextSpan[] { function charIsPunctuation(ch: number) { switch (ch) { - case ts.CharacterCodes.exclamation: - case ts.CharacterCodes.doubleQuote: - case ts.CharacterCodes.hash: - case ts.CharacterCodes.percent: - case ts.CharacterCodes.ampersand: - case ts.CharacterCodes.singleQuote: - case ts.CharacterCodes.openParen: - case ts.CharacterCodes.closeParen: - case ts.CharacterCodes.asterisk: - case ts.CharacterCodes.comma: - case ts.CharacterCodes.minus: - case ts.CharacterCodes.dot: - case ts.CharacterCodes.slash: - case ts.CharacterCodes.colon: - case ts.CharacterCodes.semicolon: - case ts.CharacterCodes.question: - case ts.CharacterCodes.at: - case ts.CharacterCodes.openBracket: - case ts.CharacterCodes.backslash: - case ts.CharacterCodes.closeBracket: - case ts.CharacterCodes._: - case ts.CharacterCodes.openBrace: - case ts.CharacterCodes.closeBrace: + case CharacterCodes.exclamation: + case CharacterCodes.doubleQuote: + case CharacterCodes.hash: + case CharacterCodes.percent: + case CharacterCodes.ampersand: + case CharacterCodes.singleQuote: + case CharacterCodes.openParen: + case CharacterCodes.closeParen: + case CharacterCodes.asterisk: + case CharacterCodes.comma: + case CharacterCodes.minus: + case CharacterCodes.dot: + case CharacterCodes.slash: + case CharacterCodes.colon: + case CharacterCodes.semicolon: + case CharacterCodes.question: + case CharacterCodes.at: + case CharacterCodes.openBracket: + case CharacterCodes.backslash: + case CharacterCodes.closeBracket: + case CharacterCodes._: + case CharacterCodes.openBrace: + case CharacterCodes.closeBrace: return true; } @@ -539,7 +542,7 @@ function charIsPunctuation(ch: number) { } function isAllPunctuation(identifier: string, start: number, end: number): boolean { - return every(identifier, ch => charIsPunctuation(ch) && ch !== ts.CharacterCodes._, start, end); + return every(identifier, ch => charIsPunctuation(ch) && ch !== CharacterCodes._, start, end); } function transitionFromUpperToLower(identifier: string, index: number, wordStart: number): boolean { diff --git a/src/services/preProcess.ts b/src/services/preProcess.ts index 960375d3f1d1c..be3823693ea75 100644 --- a/src/services/preProcess.ts +++ b/src/services/preProcess.ts @@ -1,8 +1,11 @@ -import * as ts from "./_namespaces/ts"; - -export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): ts.PreProcessedFileInfo { - const pragmaContext: ts.PragmaContext = { - languageVersion: ts.ScriptTarget.ES5, // controls whether the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia +import { + FileReference, isKeyword, lastOrUndefined, length, noop, PragmaContext, PreProcessedFileInfo, processCommentPragmas, + processPragmasIntoFields, scanner, ScriptTarget, SyntaxKind, +} from "./_namespaces/ts"; + +export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { + const pragmaContext: PragmaContext = { + languageVersion: ScriptTarget.ES5, // controls whether the token scanner considers unicode identifiers or not - shouldn't matter, since we're only using it for trivia pragmas: undefined, checkJsDirective: undefined, referencedFiles: [], @@ -12,10 +15,10 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec hasNoDefaultLib: undefined, moduleName: undefined }; - const importedFiles: ts.FileReference[] = []; - let ambientExternalModules: { ref: ts.FileReference, depth: number }[] | undefined; - let lastToken: ts.SyntaxKind; - let currentToken: ts.SyntaxKind; + const importedFiles: FileReference[] = []; + let ambientExternalModules: { ref: FileReference, depth: number }[] | undefined; + let lastToken: SyntaxKind; + let currentToken: SyntaxKind; let braceNesting = 0; // assume that text represent an external module if it contains at least one top level import/export // ambient modules that are found inside external modules are interpreted as module augmentations @@ -23,19 +26,19 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec function nextToken() { lastToken = currentToken; - currentToken = ts.scanner.scan(); - if (currentToken === ts.SyntaxKind.OpenBraceToken) { + currentToken = scanner.scan(); + if (currentToken === SyntaxKind.OpenBraceToken) { braceNesting++; } - else if (currentToken === ts.SyntaxKind.CloseBraceToken) { + else if (currentToken === SyntaxKind.CloseBraceToken) { braceNesting--; } return currentToken; } function getFileReference() { - const fileName = ts.scanner.getTokenValue(); - const pos = ts.scanner.getTokenPos(); + const fileName = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); return { fileName, pos, end: pos + fileName.length }; } @@ -62,13 +65,13 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec * Returns true if at least one token was consumed from the stream */ function tryConsumeDeclare(): boolean { - let token = ts.scanner.getToken(); - if (token === ts.SyntaxKind.DeclareKeyword) { + let token = scanner.getToken(); + if (token === SyntaxKind.DeclareKeyword) { // declare module "mod" token = nextToken(); - if (token === ts.SyntaxKind.ModuleKeyword) { + if (token === SyntaxKind.ModuleKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { recordAmbientExternalModule(); } } @@ -82,34 +85,34 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec * Returns true if at least one token was consumed from the stream */ function tryConsumeImport(): boolean { - if (lastToken === ts.SyntaxKind.DotToken) { + if (lastToken === SyntaxKind.DotToken) { return false; } - let token = ts.scanner.getToken(); - if (token === ts.SyntaxKind.ImportKeyword) { + let token = scanner.getToken(); + if (token === SyntaxKind.ImportKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.OpenParenToken) { + if (token === SyntaxKind.OpenParenToken) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral || token === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { + if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NoSubstitutionTemplateLiteral) { // import("mod"); recordModuleName(); return true; } } - else if (token === ts.SyntaxKind.StringLiteral) { + else if (token === SyntaxKind.StringLiteral) { // import "mod"; recordModuleName(); return true; } else { - if (token === ts.SyntaxKind.TypeKeyword) { - const skipTypeKeyword = ts.scanner.lookAhead(() => { - const token = ts.scanner.scan(); - return token !== ts.SyntaxKind.FromKeyword && ( - token === ts.SyntaxKind.AsteriskToken || - token === ts.SyntaxKind.OpenBraceToken || - token === ts.SyntaxKind.Identifier || - ts.isKeyword(token) + if (token === SyntaxKind.TypeKeyword) { + const skipTypeKeyword = scanner.lookAhead(() => { + const token = scanner.scan(); + return token !== SyntaxKind.FromKeyword && ( + token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBraceToken || + token === SyntaxKind.Identifier || + isKeyword(token) ); }); if (skipTypeKeyword) { @@ -117,22 +120,22 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } - if (token === ts.SyntaxKind.Identifier || ts.isKeyword(token)) { + if (token === SyntaxKind.Identifier || isKeyword(token)) { token = nextToken(); - if (token === ts.SyntaxKind.FromKeyword) { + if (token === SyntaxKind.FromKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { // import d from "mod"; recordModuleName(); return true; } } - else if (token === ts.SyntaxKind.EqualsToken) { + else if (token === SyntaxKind.EqualsToken) { if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } } - else if (token === ts.SyntaxKind.CommaToken) { + else if (token === SyntaxKind.CommaToken) { // consume comma and keep going token = nextToken(); } @@ -142,19 +145,19 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } - if (token === ts.SyntaxKind.OpenBraceToken) { + if (token === SyntaxKind.OpenBraceToken) { token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure that it stops on EOF - while (token !== ts.SyntaxKind.CloseBraceToken && token !== ts.SyntaxKind.EndOfFileToken) { + while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken) { token = nextToken(); } - if (token === ts.SyntaxKind.CloseBraceToken) { + if (token === SyntaxKind.CloseBraceToken) { token = nextToken(); - if (token === ts.SyntaxKind.FromKeyword) { + if (token === SyntaxKind.FromKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { // import {a as A} from "mod"; // import d, {a, b as B} from "mod" recordModuleName(); @@ -162,15 +165,15 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } } - else if (token === ts.SyntaxKind.AsteriskToken) { + else if (token === SyntaxKind.AsteriskToken) { token = nextToken(); - if (token === ts.SyntaxKind.AsKeyword) { + if (token === SyntaxKind.AsKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.Identifier || ts.isKeyword(token)) { + if (token === SyntaxKind.Identifier || isKeyword(token)) { token = nextToken(); - if (token === ts.SyntaxKind.FromKeyword) { + if (token === SyntaxKind.FromKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { // import * as NS from "mod" // import d, * as NS from "mod" recordModuleName(); @@ -188,33 +191,33 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } function tryConsumeExport(): boolean { - let token = ts.scanner.getToken(); - if (token === ts.SyntaxKind.ExportKeyword) { + let token = scanner.getToken(); + if (token === SyntaxKind.ExportKeyword) { markAsExternalModuleIfTopLevel(); token = nextToken(); - if (token === ts.SyntaxKind.TypeKeyword) { - const skipTypeKeyword = ts.scanner.lookAhead(() => { - const token = ts.scanner.scan(); - return token === ts.SyntaxKind.AsteriskToken || - token === ts.SyntaxKind.OpenBraceToken; + if (token === SyntaxKind.TypeKeyword) { + const skipTypeKeyword = scanner.lookAhead(() => { + const token = scanner.scan(); + return token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBraceToken; }); if (skipTypeKeyword) { token = nextToken(); } } - if (token === ts.SyntaxKind.OpenBraceToken) { + if (token === SyntaxKind.OpenBraceToken) { token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure it stops on EOF - while (token !== ts.SyntaxKind.CloseBraceToken && token !== ts.SyntaxKind.EndOfFileToken) { + while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken) { token = nextToken(); } - if (token === ts.SyntaxKind.CloseBraceToken) { + if (token === SyntaxKind.CloseBraceToken) { token = nextToken(); - if (token === ts.SyntaxKind.FromKeyword) { + if (token === SyntaxKind.FromKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { // export {a as A} from "mod"; // export {a, b as B} from "mod" recordModuleName(); @@ -222,31 +225,31 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } } - else if (token === ts.SyntaxKind.AsteriskToken) { + else if (token === SyntaxKind.AsteriskToken) { token = nextToken(); - if (token === ts.SyntaxKind.FromKeyword) { + if (token === SyntaxKind.FromKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral) { + if (token === SyntaxKind.StringLiteral) { // export * from "mod" recordModuleName(); } } } - else if (token === ts.SyntaxKind.ImportKeyword) { + else if (token === SyntaxKind.ImportKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.TypeKeyword) { - const skipTypeKeyword = ts.scanner.lookAhead(() => { - const token = ts.scanner.scan(); - return token === ts.SyntaxKind.Identifier || - ts.isKeyword(token); + if (token === SyntaxKind.TypeKeyword) { + const skipTypeKeyword = scanner.lookAhead(() => { + const token = scanner.scan(); + return token === SyntaxKind.Identifier || + isKeyword(token); }); if (skipTypeKeyword) { token = nextToken(); } } - if (token === ts.SyntaxKind.Identifier || ts.isKeyword(token)) { + if (token === SyntaxKind.Identifier || isKeyword(token)) { token = nextToken(); - if (token === ts.SyntaxKind.EqualsToken) { + if (token === SyntaxKind.EqualsToken) { if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; } @@ -261,13 +264,13 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } function tryConsumeRequireCall(skipCurrentToken: boolean, allowTemplateLiterals = false): boolean { - let token = skipCurrentToken ? nextToken() : ts.scanner.getToken(); - if (token === ts.SyntaxKind.RequireKeyword) { + let token = skipCurrentToken ? nextToken() : scanner.getToken(); + if (token === SyntaxKind.RequireKeyword) { token = nextToken(); - if (token === ts.SyntaxKind.OpenParenToken) { + if (token === SyntaxKind.OpenParenToken) { token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral || - allowTemplateLiterals && token === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { + if (token === SyntaxKind.StringLiteral || + allowTemplateLiterals && token === SyntaxKind.NoSubstitutionTemplateLiteral) { // require("mod"); recordModuleName(); } @@ -278,18 +281,18 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } function tryConsumeDefine(): boolean { - let token = ts.scanner.getToken(); - if (token === ts.SyntaxKind.Identifier && ts.scanner.getTokenValue() === "define") { + let token = scanner.getToken(); + if (token === SyntaxKind.Identifier && scanner.getTokenValue() === "define") { token = nextToken(); - if (token !== ts.SyntaxKind.OpenParenToken) { + if (token !== SyntaxKind.OpenParenToken) { return true; } token = nextToken(); - if (token === ts.SyntaxKind.StringLiteral || token === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { + if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NoSubstitutionTemplateLiteral) { // looks like define ("modname", ... - skip string literal and comma token = nextToken(); - if (token === ts.SyntaxKind.CommaToken) { + if (token === SyntaxKind.CommaToken) { token = nextToken(); } else { @@ -299,16 +302,16 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } // should be start of dependency list - if (token !== ts.SyntaxKind.OpenBracketToken) { + if (token !== SyntaxKind.OpenBracketToken) { return true; } // skip open bracket token = nextToken(); // scan until ']' or EOF - while (token !== ts.SyntaxKind.CloseBracketToken && token !== ts.SyntaxKind.EndOfFileToken) { + while (token !== SyntaxKind.CloseBracketToken && token !== SyntaxKind.EndOfFileToken) { // record string literals as module names - if (token === ts.SyntaxKind.StringLiteral || token === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { + if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NoSubstitutionTemplateLiteral) { recordModuleName(); } @@ -321,7 +324,7 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } function processImports(): void { - ts.scanner.setText(sourceText); + scanner.setText(sourceText); nextToken(); // Look for: // import "mod"; @@ -342,32 +345,32 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec // AnySymbol.nested.import("mod") while (true) { - if (ts.scanner.getToken() === ts.SyntaxKind.EndOfFileToken) { + if (scanner.getToken() === SyntaxKind.EndOfFileToken) { break; } - if (ts.scanner.getToken() === ts.SyntaxKind.TemplateHead) { - const stack = [ts.scanner.getToken()]; - loop: while (ts.length(stack)) { - const token = ts.scanner.scan(); + if (scanner.getToken() === SyntaxKind.TemplateHead) { + const stack = [scanner.getToken()]; + loop: while (length(stack)) { + const token = scanner.scan(); switch (token) { - case ts.SyntaxKind.EndOfFileToken: + case SyntaxKind.EndOfFileToken: break loop; - case ts.SyntaxKind.ImportKeyword: + case SyntaxKind.ImportKeyword: tryConsumeImport(); break; - case ts.SyntaxKind.TemplateHead: + case SyntaxKind.TemplateHead: stack.push(token); break; - case ts.SyntaxKind.OpenBraceToken: - if (ts.length(stack)) { + case SyntaxKind.OpenBraceToken: + if (length(stack)) { stack.push(token); } break; - case ts.SyntaxKind.CloseBraceToken: - if (ts.length(stack)) { - if (ts.lastOrUndefined(stack) === ts.SyntaxKind.TemplateHead) { - if (ts.scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === ts.SyntaxKind.TemplateTail) { + case SyntaxKind.CloseBraceToken: + if (length(stack)) { + if (lastOrUndefined(stack) === SyntaxKind.TemplateHead) { + if (scanner.reScanTemplateToken(/* isTaggedTemplate */ false) === SyntaxKind.TemplateTail) { stack.pop(); } } @@ -396,14 +399,14 @@ export function preProcessFile(sourceText: string, readImportFiles = true, detec } } - ts.scanner.setText(undefined); + scanner.setText(undefined); } if (readImportFiles) { processImports(); } - ts.processCommentPragmas(pragmaContext, sourceText); - ts.processPragmasIntoFields(pragmaContext, ts.noop); + processCommentPragmas(pragmaContext, sourceText); + processPragmasIntoFields(pragmaContext, noop); if (externalModule) { // for external modules module all nested ambient modules are augmentations if (ambientExternalModules) { diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index c8045abf28b59..41f9b72547919 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -1,25 +1,28 @@ -import * as ts from "./_namespaces/ts"; +import { + ApplicableRefactorInfo, arrayFrom, flatMapIterator, Map, Refactor, RefactorContext, RefactorEditInfo, +} from "./_namespaces/ts"; +import { refactorKindBeginsWith } from "./_namespaces/ts.refactor"; // A map with the refactor code as key, the refactor itself as value // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want -const refactors = new ts.Map(); +const refactors = new Map(); /** @internal */ /** @param name An unique code associated with each refactor. Does not have to be human-readable. */ -export function registerRefactor(name: string, refactor: ts.Refactor) { +export function registerRefactor(name: string, refactor: Refactor) { refactors.set(name, refactor); } /** @internal */ -export function getApplicableRefactors(context: ts.RefactorContext): ts.ApplicableRefactorInfo[] { - return ts.arrayFrom(ts.flatMapIterator(refactors.values(), refactor => +export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] { + return arrayFrom(flatMapIterator(refactors.values(), refactor => context.cancellationToken && context.cancellationToken.isCancellationRequested() || - !refactor.kinds?.some(kind => ts.refactor.refactorKindBeginsWith(kind, context.kind)) ? undefined : + !refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined : refactor.getAvailableActions(context))); } /** @internal */ -export function getEditsForRefactor(context: ts.RefactorContext, refactorName: string, actionName: string): ts.RefactorEditInfo | undefined { +export function getEditsForRefactor(context: RefactorContext, refactorName: string, actionName: string): RefactorEditInfo | undefined { const refactor = refactors.get(refactorName); return refactor && refactor.getEditsForAction(context, actionName); } diff --git a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts index 63edc5a6c75c4..d0548b1d785ab 100644 --- a/src/services/refactors/addOrRemoveBracesToArrowFunction.ts +++ b/src/services/refactors/addOrRemoveBracesToArrowFunction.ts @@ -1,37 +1,46 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, ArrowFunction, ConciseBody, copyLeadingComments, copyTrailingAsLeadingComments, + copyTrailingComments, Debug, Diagnostics, emptyArray, Expression, factory, first, getContainingFunction, + getLocaleSpecificMessage, getTokenAtPosition, isArrowFunction, isBlock, isExpression, isReturnStatement, + needsParentheses, rangeContainsRange, RefactorContext, RefactorEditInfo, ReturnStatement, SourceFile, SyntaxKind, + textChanges, +} from "../_namespaces/ts"; +import { + isRefactorErrorInfo, RefactorErrorInfo, refactorKindBeginsWith, registerRefactor, +} from "../_namespaces/ts.refactor"; const refactorName = "Add or remove braces in an arrow function"; -const refactorDescription = ts.Diagnostics.Add_or_remove_braces_in_an_arrow_function.message; +const refactorDescription = Diagnostics.Add_or_remove_braces_in_an_arrow_function.message; const addBracesAction = { name: "Add braces to arrow function", - description: ts.Diagnostics.Add_braces_to_arrow_function.message, + description: Diagnostics.Add_braces_to_arrow_function.message, kind: "refactor.rewrite.arrow.braces.add", }; const removeBracesAction = { name: "Remove braces from arrow function", - description: ts.Diagnostics.Remove_braces_from_arrow_function.message, + description: Diagnostics.Remove_braces_from_arrow_function.message, kind: "refactor.rewrite.arrow.braces.remove" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [removeBracesAction.kind], getEditsForAction: getRefactorEditsToRemoveFunctionBraces, getAvailableActions: getRefactorActionsToRemoveFunctionBraces }); interface FunctionBracesInfo { - func: ts.ArrowFunction; - expression: ts.Expression | undefined; - returnStatement?: ts.ReturnStatement; + func: ArrowFunction; + expression: Expression | undefined; + returnStatement?: ReturnStatement; addBraces: boolean; } -function getRefactorActionsToRemoveFunctionBraces(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToRemoveFunctionBraces(context: RefactorContext): readonly ApplicableRefactorInfo[] { const { file, startPosition, triggerReason } = context; const info = getConvertibleArrowFunctionAtPosition(file, startPosition, triggerReason === "invoked"); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { return [{ name: refactorName, description: refactorDescription, @@ -52,67 +61,67 @@ function getRefactorActionsToRemoveFunctionBraces(context: ts.RefactorContext): }]; } - return ts.emptyArray; + return emptyArray; } -function getRefactorEditsToRemoveFunctionBraces(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { +function getRefactorEditsToRemoveFunctionBraces(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const { file, startPosition } = context; const info = getConvertibleArrowFunctionAtPosition(file, startPosition); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); const { expression, returnStatement, func } = info; - let body: ts.ConciseBody; + let body: ConciseBody; if (actionName === addBracesAction.name) { - const returnStatement = ts.factory.createReturnStatement(expression); - body = ts.factory.createBlock([returnStatement], /* multiLine */ true); - ts.copyLeadingComments(expression!, returnStatement, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true); + const returnStatement = factory.createReturnStatement(expression); + body = factory.createBlock([returnStatement], /* multiLine */ true); + copyLeadingComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true); } else if (actionName === removeBracesAction.name && returnStatement) { - const actualExpression = expression || ts.factory.createVoidZero(); - body = ts.needsParentheses(actualExpression) ? ts.factory.createParenthesizedExpression(actualExpression) : actualExpression; - ts.copyTrailingAsLeadingComments(returnStatement, body, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); - ts.copyLeadingComments(returnStatement, body, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); - ts.copyTrailingComments(returnStatement, body, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + const actualExpression = expression || factory.createVoidZero(); + body = needsParentheses(actualExpression) ? factory.createParenthesizedExpression(actualExpression) : actualExpression; + copyTrailingAsLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyTrailingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); } else { - ts.Debug.fail("invalid action"); + Debug.fail("invalid action"); } - const edits = ts.textChanges.ChangeTracker.with(context, t => { + const edits = textChanges.ChangeTracker.with(context, t => { t.replaceNode(file, func.body, body); }); return { renameFilename: undefined, renameLocation: undefined, edits }; } -function getConvertibleArrowFunctionAtPosition(file: ts.SourceFile, startPosition: number, considerFunctionBodies = true, kind?: string): FunctionBracesInfo | ts.refactor.RefactorErrorInfo | undefined { - const node = ts.getTokenAtPosition(file, startPosition); - const func = ts.getContainingFunction(node); +function getConvertibleArrowFunctionAtPosition(file: SourceFile, startPosition: number, considerFunctionBodies = true, kind?: string): FunctionBracesInfo | RefactorErrorInfo | undefined { + const node = getTokenAtPosition(file, startPosition); + const func = getContainingFunction(node); if (!func) { return { - error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_a_containing_arrow_function) + error: getLocaleSpecificMessage(Diagnostics.Could_not_find_a_containing_arrow_function) }; } - if (!ts.isArrowFunction(func)) { + if (!isArrowFunction(func)) { return { - error: ts.getLocaleSpecificMessage(ts.Diagnostics.Containing_function_is_not_an_arrow_function) + error: getLocaleSpecificMessage(Diagnostics.Containing_function_is_not_an_arrow_function) }; } - if ((!ts.rangeContainsRange(func, node) || ts.rangeContainsRange(func.body, node) && !considerFunctionBodies)) { + if ((!rangeContainsRange(func, node) || rangeContainsRange(func.body, node) && !considerFunctionBodies)) { return undefined; } - if (ts.refactor.refactorKindBeginsWith(addBracesAction.kind, kind) && ts.isExpression(func.body)) { + if (refactorKindBeginsWith(addBracesAction.kind, kind) && isExpression(func.body)) { return { func, addBraces: true, expression: func.body }; } - else if (ts.refactor.refactorKindBeginsWith(removeBracesAction.kind, kind) && ts.isBlock(func.body) && func.body.statements.length === 1) { - const firstStatement = ts.first(func.body.statements); - if (ts.isReturnStatement(firstStatement)) { + else if (refactorKindBeginsWith(removeBracesAction.kind, kind) && isBlock(func.body) && func.body.statements.length === 1) { + const firstStatement = first(func.body.statements); + if (isReturnStatement(firstStatement)) { return { func, addBraces: false, expression: firstStatement.expression, returnStatement: firstStatement }; } } diff --git a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts index 1a17f45015675..416f7caf3c1b1 100644 --- a/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts +++ b/src/services/refactors/convertArrowFunctionOrFunctionExpression.ts @@ -1,24 +1,35 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, ArrowFunction, Block, ConciseBody, copyComments, copyTrailingAsLeadingComments, Debug, + Diagnostics, emptyArray, factory, FileTextChanges, FindAllReferences, first, forEachChild, FunctionExpression, + getCombinedModifierFlags, getContainingFunction, getEffectiveModifierFlags, getLocaleSpecificMessage, + getTokenAtPosition, Identifier, isArrowFunction, isClassLike, isExpression, isFunctionDeclaration, + isFunctionExpression, isIdentifier, isReturnStatement, isThis, isVariableDeclaration, + isVariableDeclarationInVariableStatement, isVariableDeclarationList, isVariableStatement, length, ModifierFlags, + Node, Program, rangeContainsRange, RefactorActionInfo, RefactorContext, RefactorEditInfo, ReturnStatement, + SourceFile, Statement, suppressLeadingAndTrailingTrivia, suppressLeadingTrivia, SyntaxKind, textChanges, + TypeChecker, VariableDeclaration, VariableDeclarationList, VariableStatement, +} from "../_namespaces/ts"; +import { refactorKindBeginsWith, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert arrow function or function expression"; -const refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_arrow_function_or_function_expression); +const refactorDescription = getLocaleSpecificMessage(Diagnostics.Convert_arrow_function_or_function_expression); const toAnonymousFunctionAction = { name: "Convert to anonymous function", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_anonymous_function), + description: getLocaleSpecificMessage(Diagnostics.Convert_to_anonymous_function), kind: "refactor.rewrite.function.anonymous", }; const toNamedFunctionAction = { name: "Convert to named function", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_named_function), + description: getLocaleSpecificMessage(Diagnostics.Convert_to_named_function), kind: "refactor.rewrite.function.named", }; const toArrowFunctionAction = { name: "Convert to arrow function", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_arrow_function), + description: getLocaleSpecificMessage(Diagnostics.Convert_to_arrow_function), kind: "refactor.rewrite.function.arrow", }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [ toAnonymousFunctionAction.kind, toNamedFunctionAction.kind, @@ -30,27 +41,27 @@ ts.refactor.registerRefactor(refactorName, { interface FunctionInfo { readonly selectedVariableDeclaration: boolean; - readonly func: ts.FunctionExpression | ts.ArrowFunction; + readonly func: FunctionExpression | ArrowFunction; } interface VariableInfo { - readonly variableDeclaration: ts.VariableDeclaration; - readonly variableDeclarationList: ts.VariableDeclarationList; - readonly statement: ts.VariableStatement; - readonly name: ts.Identifier; + readonly variableDeclaration: VariableDeclaration; + readonly variableDeclarationList: VariableDeclarationList; + readonly statement: VariableStatement; + readonly name: Identifier; } -function getRefactorActionsToConvertFunctionExpressions(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToConvertFunctionExpressions(context: RefactorContext): readonly ApplicableRefactorInfo[] { const { file, startPosition, program, kind } = context; const info = getFunctionInfo(file, startPosition, program); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; const { selectedVariableDeclaration, func } = info; - const possibleActions: ts.RefactorActionInfo[] = []; - const errors: ts.RefactorActionInfo[] = []; - if (ts.refactor.refactorKindBeginsWith(toNamedFunctionAction.kind, kind)) { - const error = selectedVariableDeclaration || (ts.isArrowFunction(func) && ts.isVariableDeclaration(func.parent)) ? - undefined : ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_named_function); + const possibleActions: RefactorActionInfo[] = []; + const errors: RefactorActionInfo[] = []; + if (refactorKindBeginsWith(toNamedFunctionAction.kind, kind)) { + const error = selectedVariableDeclaration || (isArrowFunction(func) && isVariableDeclaration(func.parent)) ? + undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_named_function); if (error) { errors.push({ ...toNamedFunctionAction, notApplicableReason: error }); } @@ -59,9 +70,9 @@ function getRefactorActionsToConvertFunctionExpressions(context: ts.RefactorCont } } - if (ts.refactor.refactorKindBeginsWith(toAnonymousFunctionAction.kind, kind)) { - const error = !selectedVariableDeclaration && ts.isArrowFunction(func) ? - undefined: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_anonymous_function); + if (refactorKindBeginsWith(toAnonymousFunctionAction.kind, kind)) { + const error = !selectedVariableDeclaration && isArrowFunction(func) ? + undefined: getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_anonymous_function); if (error) { errors.push({ ...toAnonymousFunctionAction, notApplicableReason: error }); } @@ -70,8 +81,8 @@ function getRefactorActionsToConvertFunctionExpressions(context: ts.RefactorCont } } - if (ts.refactor.refactorKindBeginsWith(toArrowFunctionAction.kind, kind)) { - const error = ts.isFunctionExpression(func) ? undefined : ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_convert_to_arrow_function); + if (refactorKindBeginsWith(toArrowFunctionAction.kind, kind)) { + const error = isFunctionExpression(func) ? undefined : getLocaleSpecificMessage(Diagnostics.Could_not_convert_to_arrow_function); if (error) { errors.push({ ...toArrowFunctionAction, notApplicableReason: error }); } @@ -88,13 +99,13 @@ function getRefactorActionsToConvertFunctionExpressions(context: ts.RefactorCont }]; } -function getRefactorEditsToConvertFunctionExpressions(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { +function getRefactorEditsToConvertFunctionExpressions(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const { file, startPosition, program } = context; const info = getFunctionInfo(file, startPosition, program); if (!info) return undefined; const { func } = info; - const edits: ts.FileTextChanges[] = []; + const edits: FileTextChanges[] = []; switch (actionName) { case toAnonymousFunctionAction.name: @@ -109,149 +120,149 @@ function getRefactorEditsToConvertFunctionExpressions(context: ts.RefactorContex break; case toArrowFunctionAction.name: - if (!ts.isFunctionExpression(func)) return undefined; + if (!isFunctionExpression(func)) return undefined; edits.push(...getEditInfoForConvertToArrowFunction(context, func)); break; default: - return ts.Debug.fail("invalid action"); + return Debug.fail("invalid action"); } return { renameFilename: undefined, renameLocation: undefined, edits }; } -function containingThis(node: ts.Node): boolean { +function containingThis(node: Node): boolean { let containsThis = false; node.forEachChild(function checkThis(child) { - if (ts.isThis(child)) { + if (isThis(child)) { containsThis = true; return; } - if (!ts.isClassLike(child) && !ts.isFunctionDeclaration(child) && !ts.isFunctionExpression(child)) { - ts.forEachChild(child, checkThis); + if (!isClassLike(child) && !isFunctionDeclaration(child) && !isFunctionExpression(child)) { + forEachChild(child, checkThis); } }); return containsThis; } -function getFunctionInfo(file: ts.SourceFile, startPosition: number, program: ts.Program): FunctionInfo | undefined { - const token = ts.getTokenAtPosition(file, startPosition); +function getFunctionInfo(file: SourceFile, startPosition: number, program: Program): FunctionInfo | undefined { + const token = getTokenAtPosition(file, startPosition); const typeChecker = program.getTypeChecker(); const func = tryGetFunctionFromVariableDeclaration(file, typeChecker, token.parent); if (func && !containingThis(func.body) && !typeChecker.containsArgumentsReference(func)) { return { selectedVariableDeclaration: true, func }; } - const maybeFunc = ts.getContainingFunction(token); + const maybeFunc = getContainingFunction(token); if ( maybeFunc && - (ts.isFunctionExpression(maybeFunc) || ts.isArrowFunction(maybeFunc)) && - !ts.rangeContainsRange(maybeFunc.body, token) && + (isFunctionExpression(maybeFunc) || isArrowFunction(maybeFunc)) && + !rangeContainsRange(maybeFunc.body, token) && !containingThis(maybeFunc.body) && !typeChecker.containsArgumentsReference(maybeFunc) ) { - if (ts.isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined; + if (isFunctionExpression(maybeFunc) && isFunctionReferencedInFile(file, typeChecker, maybeFunc)) return undefined; return { selectedVariableDeclaration: false, func: maybeFunc }; } return undefined; } -function isSingleVariableDeclaration(parent: ts.Node): parent is ts.VariableDeclarationList { - return ts.isVariableDeclaration(parent) || (ts.isVariableDeclarationList(parent) && parent.declarations.length === 1); +function isSingleVariableDeclaration(parent: Node): parent is VariableDeclarationList { + return isVariableDeclaration(parent) || (isVariableDeclarationList(parent) && parent.declarations.length === 1); } -function tryGetFunctionFromVariableDeclaration(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker, parent: ts.Node): ts.ArrowFunction | ts.FunctionExpression | undefined { +function tryGetFunctionFromVariableDeclaration(sourceFile: SourceFile, typeChecker: TypeChecker, parent: Node): ArrowFunction | FunctionExpression | undefined { if (!isSingleVariableDeclaration(parent)) { return undefined; } - const variableDeclaration = ts.isVariableDeclaration(parent) ? parent : ts.first(parent.declarations); + const variableDeclaration = isVariableDeclaration(parent) ? parent : first(parent.declarations); const initializer = variableDeclaration.initializer; - if (initializer && (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer))) { + if (initializer && (isArrowFunction(initializer) || isFunctionExpression(initializer) && !isFunctionReferencedInFile(sourceFile, typeChecker, initializer))) { return initializer; } return undefined; } -function convertToBlock(body: ts.ConciseBody): ts.Block { - if (ts.isExpression(body)) { - const returnStatement = ts.factory.createReturnStatement(body); +function convertToBlock(body: ConciseBody): Block { + if (isExpression(body)) { + const returnStatement = factory.createReturnStatement(body); const file = body.getSourceFile(); - ts.suppressLeadingAndTrailingTrivia(returnStatement); - ts.copyTrailingAsLeadingComments(body, returnStatement, file, /* commentKind */ undefined, /* hasTrailingNewLine */ true); - return ts.factory.createBlock([returnStatement], /* multiLine */ true); + suppressLeadingAndTrailingTrivia(returnStatement); + copyTrailingAsLeadingComments(body, returnStatement, file, /* commentKind */ undefined, /* hasTrailingNewLine */ true); + return factory.createBlock([returnStatement], /* multiLine */ true); } else { return body; } } -function getVariableInfo(func: ts.FunctionExpression | ts.ArrowFunction): VariableInfo | undefined { +function getVariableInfo(func: FunctionExpression | ArrowFunction): VariableInfo | undefined { const variableDeclaration = func.parent; - if (!ts.isVariableDeclaration(variableDeclaration) || !ts.isVariableDeclarationInVariableStatement(variableDeclaration)) return undefined; + if (!isVariableDeclaration(variableDeclaration) || !isVariableDeclarationInVariableStatement(variableDeclaration)) return undefined; const variableDeclarationList = variableDeclaration.parent; const statement = variableDeclarationList.parent; - if (!ts.isVariableDeclarationList(variableDeclarationList) || !ts.isVariableStatement(statement) || !ts.isIdentifier(variableDeclaration.name)) return undefined; + if (!isVariableDeclarationList(variableDeclarationList) || !isVariableStatement(statement) || !isIdentifier(variableDeclaration.name)) return undefined; return { variableDeclaration, variableDeclarationList, statement, name: variableDeclaration.name }; } -function getEditInfoForConvertToAnonymousFunction(context: ts.RefactorContext, func: ts.FunctionExpression | ts.ArrowFunction): ts.FileTextChanges[] { +function getEditInfoForConvertToAnonymousFunction(context: RefactorContext, func: FunctionExpression | ArrowFunction): FileTextChanges[] { const { file } = context; const body = convertToBlock(func.body); - const newNode = ts.factory.createFunctionExpression(func.modifiers, func.asteriskToken, /* name */ undefined, func.typeParameters, func.parameters, func.type, body); - return ts.textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); + const newNode = factory.createFunctionExpression(func.modifiers, func.asteriskToken, /* name */ undefined, func.typeParameters, func.parameters, func.type, body); + return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); } -function getEditInfoForConvertToNamedFunction(context: ts.RefactorContext, func: ts.FunctionExpression | ts.ArrowFunction, variableInfo: VariableInfo): ts.FileTextChanges[] { +function getEditInfoForConvertToNamedFunction(context: RefactorContext, func: FunctionExpression | ArrowFunction, variableInfo: VariableInfo): FileTextChanges[] { const { file } = context; const body = convertToBlock(func.body); const { variableDeclaration, variableDeclarationList, statement, name } = variableInfo; - ts.suppressLeadingTrivia(statement); + suppressLeadingTrivia(statement); - const modifiersFlags = (ts.getCombinedModifierFlags(variableDeclaration) & ts.ModifierFlags.Export) | ts.getEffectiveModifierFlags(func); - const modifiers = ts.factory.createModifiersFromModifierFlags(modifiersFlags); - const newNode = ts.factory.createFunctionDeclaration(ts.length(modifiers) ? modifiers : undefined, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body); + const modifiersFlags = (getCombinedModifierFlags(variableDeclaration) & ModifierFlags.Export) | getEffectiveModifierFlags(func); + const modifiers = factory.createModifiersFromModifierFlags(modifiersFlags); + const newNode = factory.createFunctionDeclaration(length(modifiers) ? modifiers : undefined, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body); if (variableDeclarationList.declarations.length === 1) { - return ts.textChanges.ChangeTracker.with(context, t => t.replaceNode(file, statement, newNode)); + return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, statement, newNode)); } else { - return ts.textChanges.ChangeTracker.with(context, t => { + return textChanges.ChangeTracker.with(context, t => { t.delete(file, variableDeclaration); t.insertNodeAfter(file, statement, newNode); }); } } -function getEditInfoForConvertToArrowFunction(context: ts.RefactorContext, func: ts.FunctionExpression): ts.FileTextChanges[] { +function getEditInfoForConvertToArrowFunction(context: RefactorContext, func: FunctionExpression): FileTextChanges[] { const { file } = context; const statements = func.body.statements; const head = statements[0]; - let body: ts.ConciseBody; + let body: ConciseBody; if (canBeConvertedToExpression(func.body, head)) { body = head.expression!; - ts.suppressLeadingAndTrailingTrivia(body); - ts.copyComments(head, body); + suppressLeadingAndTrailingTrivia(body); + copyComments(head, body); } else { body = func.body; } - const newNode = ts.factory.createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), body); - return ts.textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); + const newNode = factory.createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, factory.createToken(SyntaxKind.EqualsGreaterThanToken), body); + return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode)); } -function canBeConvertedToExpression(body: ts.Block, head: ts.Statement): head is ts.ReturnStatement { - return body.statements.length === 1 && ((ts.isReturnStatement(head) && !!head.expression)); +function canBeConvertedToExpression(body: Block, head: Statement): head is ReturnStatement { + return body.statements.length === 1 && ((isReturnStatement(head) && !!head.expression)); } -function isFunctionReferencedInFile(sourceFile: ts.SourceFile, typeChecker: ts.TypeChecker, node: ts.FunctionExpression): boolean { - return !!node.name && ts.FindAllReferences.Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile); +function isFunctionReferencedInFile(sourceFile: SourceFile, typeChecker: TypeChecker, node: FunctionExpression): boolean { + return !!node.name && FindAllReferences.Core.isSymbolReferencedInFile(node.name, typeChecker, sourceFile); } diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index 87fb81b59820a..d759fdfbffce0 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -1,169 +1,179 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, CancellationToken, ClassDeclaration, Debug, Diagnostics, emptyArray, EnumDeclaration, + ExportAssignment, ExportSpecifier, factory, FindAllReferences, findModifier, first, FunctionDeclaration, + getLocaleSpecificMessage, getParentNodeInSpan, getRefactorContextSpan, getSyntacticModifierFlags, + getTokenAtPosition, Identifier, ImportClause, ImportSpecifier, ImportTypeNode, InterfaceDeclaration, + InternalSymbolName, isAmbientModule, isExportAssignment, isExternalModuleAugmentation, isIdentifier, isModuleBlock, + isSourceFile, isStringLiteral, makeImport, ModifierFlags, NamespaceDeclaration, Node, NodeFlags, Program, + PropertyAccessExpression, QuotePreference, quotePreferenceFromString, RefactorContext, RefactorEditInfo, SourceFile, + Symbol, SyntaxKind, textChanges, TypeAliasDeclaration, TypeChecker, VariableStatement, +} from "../_namespaces/ts"; +import { isRefactorErrorInfo, RefactorErrorInfo, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert export"; const defaultToNamedAction = { name: "Convert default export to named export", - description: ts.Diagnostics.Convert_default_export_to_named_export.message, + description: Diagnostics.Convert_default_export_to_named_export.message, kind: "refactor.rewrite.export.named" }; const namedToDefaultAction = { name: "Convert named export to default export", - description: ts.Diagnostics.Convert_named_export_to_default_export.message, + description: Diagnostics.Convert_named_export_to_default_export.message, kind: "refactor.rewrite.export.default" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [ defaultToNamedAction.kind, namedToDefaultAction.kind ], - getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndDefaultExports(context): readonly ts.ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndDefaultExports(context): readonly ApplicableRefactorInfo[] { const info = getInfo(context, context.triggerReason === "invoked"); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { const action = info.wasDefault ? defaultToNamedAction : namedToDefaultAction; return [{ name: refactorName, description: action.description, actions: [action] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [ - { name: refactorName, description: ts.Diagnostics.Convert_default_export_to_named_export.message, actions: [ + { name: refactorName, description: Diagnostics.Convert_default_export_to_named_export.message, actions: [ { ...defaultToNamedAction, notApplicableReason: info.error }, { ...namedToDefaultAction, notApplicableReason: info.error }, ]} ]; } - return ts.emptyArray; + return emptyArray; }, - getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndDefaultExports(context, actionName): ts.RefactorEditInfo { - ts.Debug.assert(actionName === defaultToNamedAction.name || actionName === namedToDefaultAction.name, "Unexpected action name"); + getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndDefaultExports(context, actionName): RefactorEditInfo { + Debug.assert(actionName === defaultToNamedAction.name || actionName === namedToDefaultAction.name, "Unexpected action name"); const info = getInfo(context); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = ts.textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, info, t, context.cancellationToken)); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); + const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, info, t, context.cancellationToken)); return { edits, renameFilename: undefined, renameLocation: undefined }; }, }); // If a VariableStatement, will have exactly one VariableDeclaration, with an Identifier for a name. -type ExportToConvert = ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration | ts.EnumDeclaration | ts.NamespaceDeclaration | ts.TypeAliasDeclaration | ts.VariableStatement | ts.ExportAssignment; +type ExportToConvert = FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | NamespaceDeclaration | TypeAliasDeclaration | VariableStatement | ExportAssignment; interface ExportInfo { readonly exportNode: ExportToConvert; - readonly exportName: ts.Identifier; // This is exportNode.name except for VariableStatement_s. + readonly exportName: Identifier; // This is exportNode.name except for VariableStatement_s. readonly wasDefault: boolean; - readonly exportingModuleSymbol: ts.Symbol; + readonly exportingModuleSymbol: Symbol; } -function getInfo(context: ts.RefactorContext, considerPartialSpans = true): ExportInfo | ts.refactor.RefactorErrorInfo | undefined { +function getInfo(context: RefactorContext, considerPartialSpans = true): ExportInfo | RefactorErrorInfo | undefined { const { file, program } = context; - const span = ts.getRefactorContextSpan(context); - const token = ts.getTokenAtPosition(file, span.start); - const exportNode = !!(token.parent && ts.getSyntacticModifierFlags(token.parent) & ts.ModifierFlags.Export) && considerPartialSpans ? token.parent : ts.getParentNodeInSpan(token, file, span); - if (!exportNode || (!ts.isSourceFile(exportNode.parent) && !(ts.isModuleBlock(exportNode.parent) && ts.isAmbientModule(exportNode.parent.parent)))) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_export_statement) }; + const span = getRefactorContextSpan(context); + const token = getTokenAtPosition(file, span.start); + const exportNode = !!(token.parent && getSyntacticModifierFlags(token.parent) & ModifierFlags.Export) && considerPartialSpans ? token.parent : getParentNodeInSpan(token, file, span); + if (!exportNode || (!isSourceFile(exportNode.parent) && !(isModuleBlock(exportNode.parent) && isAmbientModule(exportNode.parent.parent)))) { + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_export_statement) }; } const checker = program.getTypeChecker(); const exportingModuleSymbol = getExportingModuleSymbol(exportNode, checker); - const flags = ts.getSyntacticModifierFlags(exportNode) || ((ts.isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ts.ModifierFlags.ExportDefault : ts.ModifierFlags.None); + const flags = getSyntacticModifierFlags(exportNode) || ((isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ModifierFlags.ExportDefault : ModifierFlags.None); - const wasDefault = !!(flags & ts.ModifierFlags.Default); + const wasDefault = !!(flags & ModifierFlags.Default); // If source file already has a default export, don't offer refactor. - if (!(flags & ts.ModifierFlags.Export) || !wasDefault && exportingModuleSymbol.exports!.has(ts.InternalSymbolName.Default)) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.This_file_already_has_a_default_export) }; + if (!(flags & ModifierFlags.Export) || !wasDefault && exportingModuleSymbol.exports!.has(InternalSymbolName.Default)) { + return { error: getLocaleSpecificMessage(Diagnostics.This_file_already_has_a_default_export) }; } - const noSymbolError = (id: ts.Node) => - (ts.isIdentifier(id) && checker.getSymbolAtLocation(id)) ? undefined - : { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_named_export) }; + const noSymbolError = (id: Node) => + (isIdentifier(id) && checker.getSymbolAtLocation(id)) ? undefined + : { error: getLocaleSpecificMessage(Diagnostics.Can_only_convert_named_export) }; switch (exportNode.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ModuleDeclaration: { - const node = exportNode as ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration | ts.EnumDeclaration | ts.TypeAliasDeclaration | ts.NamespaceDeclaration; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ModuleDeclaration: { + const node = exportNode as FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | EnumDeclaration | TypeAliasDeclaration | NamespaceDeclaration; if (!node.name) return undefined; return noSymbolError(node.name) || { exportNode: node, exportName: node.name, wasDefault, exportingModuleSymbol }; } - case ts.SyntaxKind.VariableStatement: { - const vs = exportNode as ts.VariableStatement; + case SyntaxKind.VariableStatement: { + const vs = exportNode as VariableStatement; // Must be `export const x = something;`. - if (!(vs.declarationList.flags & ts.NodeFlags.Const) || vs.declarationList.declarations.length !== 1) { + if (!(vs.declarationList.flags & NodeFlags.Const) || vs.declarationList.declarations.length !== 1) { return undefined; } - const decl = ts.first(vs.declarationList.declarations); + const decl = first(vs.declarationList.declarations); if (!decl.initializer) return undefined; - ts.Debug.assert(!wasDefault, "Can't have a default flag here"); + Debug.assert(!wasDefault, "Can't have a default flag here"); return noSymbolError(decl.name) - || { exportNode: vs, exportName: decl.name as ts.Identifier, wasDefault, exportingModuleSymbol }; + || { exportNode: vs, exportName: decl.name as Identifier, wasDefault, exportingModuleSymbol }; } - case ts.SyntaxKind.ExportAssignment: { - const node = exportNode as ts.ExportAssignment; + case SyntaxKind.ExportAssignment: { + const node = exportNode as ExportAssignment; if (node.isExportEquals) return undefined; return noSymbolError(node.expression) - || { exportNode: node, exportName: node.expression as ts.Identifier, wasDefault, exportingModuleSymbol }; + || { exportNode: node, exportName: node.expression as Identifier, wasDefault, exportingModuleSymbol }; } default: return undefined; } } -function doChange(exportingSourceFile: ts.SourceFile, program: ts.Program, info: ExportInfo, changes: ts.textChanges.ChangeTracker, cancellationToken: ts.CancellationToken | undefined): void { +function doChange(exportingSourceFile: SourceFile, program: Program, info: ExportInfo, changes: textChanges.ChangeTracker, cancellationToken: CancellationToken | undefined): void { changeExport(exportingSourceFile, info, changes, program.getTypeChecker()); changeImports(program, info, changes, cancellationToken); } -function changeExport(exportingSourceFile: ts.SourceFile, { wasDefault, exportNode, exportName }: ExportInfo, changes: ts.textChanges.ChangeTracker, checker: ts.TypeChecker): void { +function changeExport(exportingSourceFile: SourceFile, { wasDefault, exportNode, exportName }: ExportInfo, changes: textChanges.ChangeTracker, checker: TypeChecker): void { if (wasDefault) { - if (ts.isExportAssignment(exportNode) && !exportNode.isExportEquals) { - const exp = exportNode.expression as ts.Identifier; + if (isExportAssignment(exportNode) && !exportNode.isExportEquals) { + const exp = exportNode.expression as Identifier; const spec = makeExportSpecifier(exp.text, exp.text); - changes.replaceNode(exportingSourceFile, exportNode, ts.factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, ts.factory.createNamedExports([spec]))); + changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([spec]))); } else { - changes.delete(exportingSourceFile, ts.Debug.checkDefined(ts.findModifier(exportNode, ts.SyntaxKind.DefaultKeyword), "Should find a default keyword in modifier list")); + changes.delete(exportingSourceFile, Debug.checkDefined(findModifier(exportNode, SyntaxKind.DefaultKeyword), "Should find a default keyword in modifier list")); } } else { - const exportKeyword = ts.Debug.checkDefined(ts.findModifier(exportNode, ts.SyntaxKind.ExportKeyword), "Should find an export keyword in modifier list"); + const exportKeyword = Debug.checkDefined(findModifier(exportNode, SyntaxKind.ExportKeyword), "Should find an export keyword in modifier list"); switch (exportNode.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - changes.insertNodeAfter(exportingSourceFile, exportKeyword, ts.factory.createToken(ts.SyntaxKind.DefaultKeyword)); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + changes.insertNodeAfter(exportingSourceFile, exportKeyword, factory.createToken(SyntaxKind.DefaultKeyword)); break; - case ts.SyntaxKind.VariableStatement: + case SyntaxKind.VariableStatement: // If 'x' isn't used in this file and doesn't have type definition, `export const x = 0;` --> `export default 0;` - const decl = ts.first(exportNode.declarationList.declarations); - if (!ts.FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile) && !decl.type) { + const decl = first(exportNode.declarationList.declarations); + if (!FindAllReferences.Core.isSymbolReferencedInFile(exportName, checker, exportingSourceFile) && !decl.type) { // We checked in `getInfo` that an initializer exists. - changes.replaceNode(exportingSourceFile, exportNode, ts.factory.createExportDefault(ts.Debug.checkDefined(decl.initializer, "Initializer was previously known to be present"))); + changes.replaceNode(exportingSourceFile, exportNode, factory.createExportDefault(Debug.checkDefined(decl.initializer, "Initializer was previously known to be present"))); break; } // falls through - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.ModuleDeclaration: // `export type T = number;` -> `type T = number; export default T;` changes.deleteModifier(exportingSourceFile, exportKeyword); - changes.insertNodeAfter(exportingSourceFile, exportNode, ts.factory.createExportDefault(ts.factory.createIdentifier(exportName.text))); + changes.insertNodeAfter(exportingSourceFile, exportNode, factory.createExportDefault(factory.createIdentifier(exportName.text))); break; default: - ts.Debug.fail(`Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`); + Debug.fail(`Unexpected exportNode kind ${(exportNode as ExportToConvert).kind}`); } } } -function changeImports(program: ts.Program, { wasDefault, exportName, exportingModuleSymbol }: ExportInfo, changes: ts.textChanges.ChangeTracker, cancellationToken: ts.CancellationToken | undefined): void { +function changeImports(program: Program, { wasDefault, exportName, exportingModuleSymbol }: ExportInfo, changes: textChanges.ChangeTracker, cancellationToken: CancellationToken | undefined): void { const checker = program.getTypeChecker(); - const exportSymbol = ts.Debug.checkDefined(checker.getSymbolAtLocation(exportName), "Export name should resolve to a symbol"); - ts.FindAllReferences.Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, ref => { + const exportSymbol = Debug.checkDefined(checker.getSymbolAtLocation(exportName), "Export name should resolve to a symbol"); + FindAllReferences.Core.eachExportReference(program.getSourceFiles(), checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName.text, wasDefault, ref => { if (exportName === ref) return; const importingSourceFile = ref.getSourceFile(); if (wasDefault) { @@ -175,34 +185,34 @@ function changeImports(program: ts.Program, { wasDefault, exportName, exportingM }); } -function changeDefaultToNamedImport(importingSourceFile: ts.SourceFile, ref: ts.Identifier, changes: ts.textChanges.ChangeTracker, exportName: string): void { +function changeDefaultToNamedImport(importingSourceFile: SourceFile, ref: Identifier, changes: textChanges.ChangeTracker, exportName: string): void { const { parent } = ref; switch (parent.kind) { - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAccessExpression: // `a.default` --> `a.foo` - changes.replaceNode(importingSourceFile, ref, ts.factory.createIdentifier(exportName)); + changes.replaceNode(importingSourceFile, ref, factory.createIdentifier(exportName)); break; - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: { - const spec = parent as ts.ImportSpecifier | ts.ExportSpecifier; + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: { + const spec = parent as ImportSpecifier | ExportSpecifier; // `default as foo` --> `foo`, `default as bar` --> `foo as bar` changes.replaceNode(importingSourceFile, spec, makeImportSpecifier(exportName, spec.name.text)); break; } - case ts.SyntaxKind.ImportClause: { - const clause = parent as ts.ImportClause; - ts.Debug.assert(clause.name === ref, "Import clause name should match provided ref"); + case SyntaxKind.ImportClause: { + const clause = parent as ImportClause; + Debug.assert(clause.name === ref, "Import clause name should match provided ref"); const spec = makeImportSpecifier(exportName, ref.text); const { namedBindings } = clause; if (!namedBindings) { // `import foo from "./a";` --> `import { foo } from "./a";` - changes.replaceNode(importingSourceFile, ref, ts.factory.createNamedImports([spec])); + changes.replaceNode(importingSourceFile, ref, factory.createNamedImports([spec])); } - else if (namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + else if (namedBindings.kind === SyntaxKind.NamespaceImport) { // `import foo, * as a from "./a";` --> `import * as a from ".a/"; import { foo } from "./a";` changes.deleteRange(importingSourceFile, { pos: ref.getStart(importingSourceFile), end: namedBindings.getStart(importingSourceFile) }); - const quotePreference = ts.isStringLiteral(clause.parent.moduleSpecifier) ? ts.quotePreferenceFromString(clause.parent.moduleSpecifier, importingSourceFile) : ts.QuotePreference.Double; - const newImport = ts.makeImport(/*default*/ undefined, [makeImportSpecifier(exportName, ref.text)], clause.parent.moduleSpecifier, quotePreference); + const quotePreference = isStringLiteral(clause.parent.moduleSpecifier) ? quotePreferenceFromString(clause.parent.moduleSpecifier, importingSourceFile) : QuotePreference.Double; + const newImport = makeImport(/*default*/ undefined, [makeImportSpecifier(exportName, ref.text)], clause.parent.moduleSpecifier, quotePreference); changes.insertNodeAfter(importingSourceFile, clause.parent, newImport); } else { @@ -212,26 +222,26 @@ function changeDefaultToNamedImport(importingSourceFile: ts.SourceFile, ref: ts. } break; } - case ts.SyntaxKind.ImportType: - const importTypeNode = parent as ts.ImportTypeNode; - changes.replaceNode(importingSourceFile, parent, ts.factory.createImportTypeNode(importTypeNode.argument, importTypeNode.assertions, ts.factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf)); + case SyntaxKind.ImportType: + const importTypeNode = parent as ImportTypeNode; + changes.replaceNode(importingSourceFile, parent, factory.createImportTypeNode(importTypeNode.argument, importTypeNode.assertions, factory.createIdentifier(exportName), importTypeNode.typeArguments, importTypeNode.isTypeOf)); break; default: - ts.Debug.failBadSyntaxKind(parent); + Debug.failBadSyntaxKind(parent); } } -function changeNamedToDefaultImport(importingSourceFile: ts.SourceFile, ref: ts.Identifier, changes: ts.textChanges.ChangeTracker): void { - const parent = ref.parent as ts.PropertyAccessExpression | ts.ImportSpecifier | ts.ExportSpecifier; +function changeNamedToDefaultImport(importingSourceFile: SourceFile, ref: Identifier, changes: textChanges.ChangeTracker): void { + const parent = ref.parent as PropertyAccessExpression | ImportSpecifier | ExportSpecifier; switch (parent.kind) { - case ts.SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAccessExpression: // `a.foo` --> `a.default` - changes.replaceNode(importingSourceFile, ref, ts.factory.createIdentifier("default")); + changes.replaceNode(importingSourceFile, ref, factory.createIdentifier("default")); break; - case ts.SyntaxKind.ImportSpecifier: { + case SyntaxKind.ImportSpecifier: { // `import { foo } from "./a";` --> `import foo from "./a";` // `import { foo as bar } from "./a";` --> `import bar from "./a";` - const defaultImport = ts.factory.createIdentifier(parent.name.text); + const defaultImport = factory.createIdentifier(parent.name.text); if (parent.parent.elements.length === 1) { changes.replaceNode(importingSourceFile, parent.parent, defaultImport); } @@ -241,7 +251,7 @@ function changeNamedToDefaultImport(importingSourceFile: ts.SourceFile, ref: ts. } break; } - case ts.SyntaxKind.ExportSpecifier: { + case SyntaxKind.ExportSpecifier: { // `export { foo } from "./a";` --> `export { default as foo } from "./a";` // `export { foo as bar } from "./a";` --> `export { default as bar } from "./a";` // `export { foo as default } from "./a";` --> `export { default } from "./a";` @@ -250,26 +260,26 @@ function changeNamedToDefaultImport(importingSourceFile: ts.SourceFile, ref: ts. break; } default: - ts.Debug.assertNever(parent, `Unexpected parent kind ${(parent as ts.Node).kind}`); + Debug.assertNever(parent, `Unexpected parent kind ${(parent as Node).kind}`); } } -function makeImportSpecifier(propertyName: string, name: string): ts.ImportSpecifier { - return ts.factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(name)); +function makeImportSpecifier(propertyName: string, name: string): ImportSpecifier { + return factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); } -function makeExportSpecifier(propertyName: string, name: string): ts.ExportSpecifier { - return ts.factory.createExportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(name)); +function makeExportSpecifier(propertyName: string, name: string): ExportSpecifier { + return factory.createExportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); } -function getExportingModuleSymbol(node: ts.Node, checker: ts.TypeChecker) { +function getExportingModuleSymbol(node: Node, checker: TypeChecker) { const parent = node.parent; - if (ts.isSourceFile(parent)) { + if (isSourceFile(parent)) { return parent.symbol; } const symbol = parent.parent.symbol; - if (symbol.valueDeclaration && ts.isExternalModuleAugmentation(symbol.valueDeclaration)) { + if (symbol.valueDeclaration && isExternalModuleAugmentation(symbol.valueDeclaration)) { return checker.getMergedSymbol(symbol); } return symbol; diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index 1f744eb721532..40fa29ea4bb52 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -1,141 +1,150 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, arrayFrom, codefix, Debug, Diagnostics, emptyArray, Expression, factory, FindAllReferences, + findAncestor, findNextToken, getAllowSyntheticDefaultImports, getLocaleSpecificMessage, getOwnValues, + getParentNodeInSpan, getRefactorContextSpan, getTokenAtPosition, getUniqueName, Identifier, ImportClause, + ImportDeclaration, ImportKind, ImportSpecifier, isExportSpecifier, isImportDeclaration, isPropertyAccessExpression, + isPropertyAccessOrQualifiedName, isShorthandPropertyAssignment, isStringLiteral, Map, NamedImports, NamespaceImport, + Program, PropertyAccessExpression, QualifiedName, RefactorContext, RefactorEditInfo, ScriptTarget, Set, some, + SourceFile, Symbol, SymbolFlags, SyntaxKind, textChanges, TypeChecker, +} from "../_namespaces/ts"; +import { isRefactorErrorInfo, RefactorErrorInfo, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert import"; const actions = { - [ts.ImportKind.Named]: { + [ImportKind.Named]: { name: "Convert namespace import to named imports", - description: ts.Diagnostics.Convert_namespace_import_to_named_imports.message, + description: Diagnostics.Convert_namespace_import_to_named_imports.message, kind: "refactor.rewrite.import.named", }, - [ts.ImportKind.Namespace]: { + [ImportKind.Namespace]: { name: "Convert named imports to namespace import", - description: ts.Diagnostics.Convert_named_imports_to_namespace_import.message, + description: Diagnostics.Convert_named_imports_to_namespace_import.message, kind: "refactor.rewrite.import.namespace", }, - [ts.ImportKind.Default]: { + [ImportKind.Default]: { name: "Convert named imports to default import", - description: ts.Diagnostics.Convert_named_imports_to_default_import.message, + description: Diagnostics.Convert_named_imports_to_default_import.message, kind: "refactor.rewrite.import.default", }, }; -ts.refactor.registerRefactor(refactorName, { - kinds: ts.getOwnValues(actions).map(a => a.kind), - getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports(context): readonly ts.ApplicableRefactorInfo[] { +registerRefactor(refactorName, { + kinds: getOwnValues(actions).map(a => a.kind), + getAvailableActions: function getRefactorActionsToConvertBetweenNamedAndNamespacedImports(context): readonly ApplicableRefactorInfo[] { const info = getImportConversionInfo(context, context.triggerReason === "invoked"); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { const action = actions[info.convertTo]; return [{ name: refactorName, description: action.description, actions: [action] }]; } if (context.preferences.provideRefactorNotApplicableReason) { - return ts.getOwnValues(actions).map(action => ({ + return getOwnValues(actions).map(action => ({ name: refactorName, description: action.description, actions: [{ ...action, notApplicableReason: info.error }] })); } - return ts.emptyArray; + return emptyArray; }, - getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports(context, actionName): ts.RefactorEditInfo { - ts.Debug.assert(ts.some(ts.getOwnValues(actions), action => action.name === actionName), "Unexpected action name"); + getEditsForAction: function getRefactorEditsToConvertBetweenNamedAndNamespacedImports(context, actionName): RefactorEditInfo { + Debug.assert(some(getOwnValues(actions), action => action.name === actionName), "Unexpected action name"); const info = getImportConversionInfo(context); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = ts.textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, t, info)); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); + const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, t, info)); return { edits, renameFilename: undefined, renameLocation: undefined }; } }); // Can convert imports of the form `import * as m from "m";` or `import d, { x, y } from "m";`. type ImportConversionInfo = - | { convertTo: ts.ImportKind.Default, import: ts.NamedImports } - | { convertTo: ts.ImportKind.Namespace, import: ts.NamedImports } - | { convertTo: ts.ImportKind.Named, import: ts.NamespaceImport }; + | { convertTo: ImportKind.Default, import: NamedImports } + | { convertTo: ImportKind.Namespace, import: NamedImports } + | { convertTo: ImportKind.Named, import: NamespaceImport }; -function getImportConversionInfo(context: ts.RefactorContext, considerPartialSpans = true): ImportConversionInfo | ts.refactor.RefactorErrorInfo | undefined { +function getImportConversionInfo(context: RefactorContext, considerPartialSpans = true): ImportConversionInfo | RefactorErrorInfo | undefined { const { file } = context; - const span = ts.getRefactorContextSpan(context); - const token = ts.getTokenAtPosition(file, span.start); - const importDecl = considerPartialSpans ? ts.findAncestor(token, ts.isImportDeclaration) : ts.getParentNodeInSpan(token, file, span); - if (!importDecl || !ts.isImportDeclaration(importDecl)) return { error: "Selection is not an import declaration." }; + const span = getRefactorContextSpan(context); + const token = getTokenAtPosition(file, span.start); + const importDecl = considerPartialSpans ? findAncestor(token, isImportDeclaration) : getParentNodeInSpan(token, file, span); + if (!importDecl || !isImportDeclaration(importDecl)) return { error: "Selection is not an import declaration." }; const end = span.start + span.length; - const nextToken = ts.findNextToken(importDecl, importDecl.parent, file); + const nextToken = findNextToken(importDecl, importDecl.parent, file); if (nextToken && end > nextToken.getStart()) return undefined; const { importClause } = importDecl; if (!importClause) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_import_clause) }; + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_import_clause) }; } if (!importClause.namedBindings) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_namespace_import_or_named_imports) }; + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_namespace_import_or_named_imports) }; } - if (importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) { - return { convertTo: ts.ImportKind.Named, import: importClause.namedBindings }; + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { + return { convertTo: ImportKind.Named, import: importClause.namedBindings }; } const shouldUseDefault = getShouldUseDefault(context.program, importClause); return shouldUseDefault - ? { convertTo: ts.ImportKind.Default, import: importClause.namedBindings } - : { convertTo: ts.ImportKind.Namespace, import: importClause.namedBindings }; + ? { convertTo: ImportKind.Default, import: importClause.namedBindings } + : { convertTo: ImportKind.Namespace, import: importClause.namedBindings }; } -function getShouldUseDefault(program: ts.Program, importClause: ts.ImportClause) { - return ts.getAllowSyntheticDefaultImports(program.getCompilerOptions()) +function getShouldUseDefault(program: Program, importClause: ImportClause) { + return getAllowSyntheticDefaultImports(program.getCompilerOptions()) && isExportEqualsModule(importClause.parent.moduleSpecifier, program.getTypeChecker()); } -function doChange(sourceFile: ts.SourceFile, program: ts.Program, changes: ts.textChanges.ChangeTracker, info: ImportConversionInfo): void { +function doChange(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, info: ImportConversionInfo): void { const checker = program.getTypeChecker(); - if (info.convertTo === ts.ImportKind.Named) { - doChangeNamespaceToNamed(sourceFile, checker, changes, info.import, ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())); + if (info.convertTo === ImportKind.Named) { + doChangeNamespaceToNamed(sourceFile, checker, changes, info.import, getAllowSyntheticDefaultImports(program.getCompilerOptions())); } else { - doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, info.import, info.convertTo === ts.ImportKind.Default); + doChangeNamedToNamespaceOrDefault(sourceFile, program, changes, info.import, info.convertTo === ImportKind.Default); } } -function doChangeNamespaceToNamed(sourceFile: ts.SourceFile, checker: ts.TypeChecker, changes: ts.textChanges.ChangeTracker, toConvert: ts.NamespaceImport, allowSyntheticDefaultImports: boolean): void { +function doChangeNamespaceToNamed(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, toConvert: NamespaceImport, allowSyntheticDefaultImports: boolean): void { let usedAsNamespaceOrDefault = false; - const nodesToReplace: (ts.PropertyAccessExpression | ts.QualifiedName)[] = []; - const conflictingNames = new ts.Map(); + const nodesToReplace: (PropertyAccessExpression | QualifiedName)[] = []; + const conflictingNames = new Map(); - ts.FindAllReferences.Core.eachSymbolReferenceInFile(toConvert.name, checker, sourceFile, id => { - if (!ts.isPropertyAccessOrQualifiedName(id.parent)) { + FindAllReferences.Core.eachSymbolReferenceInFile(toConvert.name, checker, sourceFile, id => { + if (!isPropertyAccessOrQualifiedName(id.parent)) { usedAsNamespaceOrDefault = true; } else { const exportName = getRightOfPropertyAccessOrQualifiedName(id.parent).text; - if (checker.resolveName(exportName, id, ts.SymbolFlags.All, /*excludeGlobals*/ true)) { + if (checker.resolveName(exportName, id, SymbolFlags.All, /*excludeGlobals*/ true)) { conflictingNames.set(exportName, true); } - ts.Debug.assert(getLeftOfPropertyAccessOrQualifiedName(id.parent) === id, "Parent expression should match id"); + Debug.assert(getLeftOfPropertyAccessOrQualifiedName(id.parent) === id, "Parent expression should match id"); nodesToReplace.push(id.parent); } }); // We may need to change `mod.x` to `_x` to avoid a name conflict. - const exportNameToImportName = new ts.Map(); + const exportNameToImportName = new Map(); for (const propertyAccessOrQualifiedName of nodesToReplace) { const exportName = getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName).text; let importName = exportNameToImportName.get(exportName); if (importName === undefined) { - exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? ts.getUniqueName(exportName, sourceFile) : exportName); + exportNameToImportName.set(exportName, importName = conflictingNames.has(exportName) ? getUniqueName(exportName, sourceFile) : exportName); } - changes.replaceNode(sourceFile, propertyAccessOrQualifiedName, ts.factory.createIdentifier(importName)); + changes.replaceNode(sourceFile, propertyAccessOrQualifiedName, factory.createIdentifier(importName)); } - const importSpecifiers: ts.ImportSpecifier[] = []; + const importSpecifiers: ImportSpecifier[] = []; exportNameToImportName.forEach((name, propertyName) => { - importSpecifiers.push(ts.factory.createImportSpecifier(/*isTypeOnly*/ false, name === propertyName ? undefined : ts.factory.createIdentifier(propertyName), ts.factory.createIdentifier(name))); + importSpecifiers.push(factory.createImportSpecifier(/*isTypeOnly*/ false, name === propertyName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name))); }); const importDecl = toConvert.parent.parent; @@ -144,42 +153,42 @@ function doChangeNamespaceToNamed(sourceFile: ts.SourceFile, checker: ts.TypeChe changes.insertNodeAfter(sourceFile, importDecl, updateImport(importDecl, /*defaultImportName*/ undefined, importSpecifiers)); } else { - changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? ts.factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); + changes.replaceNode(sourceFile, importDecl, updateImport(importDecl, usedAsNamespaceOrDefault ? factory.createIdentifier(toConvert.name.text) : undefined, importSpecifiers)); } } -function getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: ts.PropertyAccessExpression | ts.QualifiedName) { - return ts.isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name : propertyAccessOrQualifiedName.right; +function getRightOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) { + return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.name : propertyAccessOrQualifiedName.right; } -function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: ts.PropertyAccessExpression | ts.QualifiedName) { - return ts.isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left; +function getLeftOfPropertyAccessOrQualifiedName(propertyAccessOrQualifiedName: PropertyAccessExpression | QualifiedName) { + return isPropertyAccessExpression(propertyAccessOrQualifiedName) ? propertyAccessOrQualifiedName.expression : propertyAccessOrQualifiedName.left; } /** @internal */ -export function doChangeNamedToNamespaceOrDefault(sourceFile: ts.SourceFile, program: ts.Program, changes: ts.textChanges.ChangeTracker, toConvert: ts.NamedImports, shouldUseDefault = getShouldUseDefault(program, toConvert.parent)): void { +export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, program: Program, changes: textChanges.ChangeTracker, toConvert: NamedImports, shouldUseDefault = getShouldUseDefault(program, toConvert.parent)): void { const checker = program.getTypeChecker(); const importDecl = toConvert.parent.parent; const { moduleSpecifier } = importDecl; - const toConvertSymbols: ts.Set = new ts.Set(); + const toConvertSymbols: Set = new Set(); toConvert.elements.forEach(namedImport => { const symbol = checker.getSymbolAtLocation(namedImport.name); if (symbol) { toConvertSymbols.add(symbol); } }); - const preferredName = moduleSpecifier && ts.isStringLiteral(moduleSpecifier) ? ts.codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, ts.ScriptTarget.ESNext) : "module"; - function hasNamespaceNameConflict(namedImport: ts.ImportSpecifier): boolean { + const preferredName = moduleSpecifier && isStringLiteral(moduleSpecifier) ? codefix.moduleSpecifierToValidIdentifier(moduleSpecifier.text, ScriptTarget.ESNext) : "module"; + function hasNamespaceNameConflict(namedImport: ImportSpecifier): boolean { // We need to check if the preferred namespace name (`preferredName`) we'd like to use in the refactored code will present a name conflict. // A name conflict means that, in a scope where we would like to use the preferred namespace name, there already exists a symbol with that name in that scope. // We are going to use the namespace name in the scopes the named imports being refactored are referenced, // so we look for conflicts by looking at every reference to those named imports. - return !!ts.FindAllReferences.Core.eachSymbolReferenceInFile(namedImport.name, checker, sourceFile, id => { - const symbol = checker.resolveName(preferredName, id, ts.SymbolFlags.All, /*excludeGlobals*/ true); + return !!FindAllReferences.Core.eachSymbolReferenceInFile(namedImport.name, checker, sourceFile, id => { + const symbol = checker.resolveName(preferredName, id, SymbolFlags.All, /*excludeGlobals*/ true); if (symbol) { // There already is a symbol with the same name as the preferred namespace name. if (toConvertSymbols.has(symbol)) { // `preferredName` resolves to a symbol for one of the named import references we are going to transform into namespace import references... - return ts.isExportSpecifier(id.parent); // ...but if this reference is an export specifier, it will not be transformed, so it is a conflict; otherwise, it will be renamed and is not a conflict. + return isExportSpecifier(id.parent); // ...but if this reference is an export specifier, it will not be transformed, so it is a conflict; otherwise, it will be renamed and is not a conflict. } return true; // `preferredName` resolves to any other symbol, which will be present in the refactored code and so poses a name conflict. } @@ -187,20 +196,20 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: ts.SourceFile, pro }); } const namespaceNameConflicts = toConvert.elements.some(hasNamespaceNameConflict); - const namespaceImportName = namespaceNameConflicts ? ts.getUniqueName(preferredName, sourceFile) : preferredName; + const namespaceImportName = namespaceNameConflicts ? getUniqueName(preferredName, sourceFile) : preferredName; // Imports that need to be kept as named imports in the refactored code, to avoid changing the semantics. // More specifically, those are named imports that appear in named exports in the original code, e.g. `a` in `import { a } from "m"; export { a }`. - const neededNamedImports: ts.Set = new ts.Set(); + const neededNamedImports: Set = new Set(); for (const element of toConvert.elements) { const propertyName = (element.propertyName || element.name).text; - ts.FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, id => { - const access = ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(namespaceImportName), propertyName); - if (ts.isShorthandPropertyAssignment(id.parent)) { - changes.replaceNode(sourceFile, id.parent, ts.factory.createPropertyAssignment(id.text, access)); + FindAllReferences.Core.eachSymbolReferenceInFile(element.name, checker, sourceFile, id => { + const access = factory.createPropertyAccessExpression(factory.createIdentifier(namespaceImportName), propertyName); + if (isShorthandPropertyAssignment(id.parent)) { + changes.replaceNode(sourceFile, id.parent, factory.createPropertyAssignment(id.text, access)); } - else if (ts.isExportSpecifier(id.parent)) { + else if (isExportSpecifier(id.parent)) { neededNamedImports.add(element); } else { @@ -210,23 +219,23 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: ts.SourceFile, pro } changes.replaceNode(sourceFile, toConvert, shouldUseDefault - ? ts.factory.createIdentifier(namespaceImportName) - : ts.factory.createNamespaceImport(ts.factory.createIdentifier(namespaceImportName))); + ? factory.createIdentifier(namespaceImportName) + : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); if (neededNamedImports.size) { - const newNamedImports: ts.ImportSpecifier[] = ts.arrayFrom(neededNamedImports.values()).map(element => - ts.factory.createImportSpecifier(element.isTypeOnly, element.propertyName && ts.factory.createIdentifier(element.propertyName.text), ts.factory.createIdentifier(element.name.text))); + const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values()).map(element => + factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports)); } } -function isExportEqualsModule(moduleSpecifier: ts.Expression, checker: ts.TypeChecker) { +function isExportEqualsModule(moduleSpecifier: Expression, checker: TypeChecker) { const externalModule = checker.resolveExternalModuleName(moduleSpecifier); if (!externalModule) return false; const exportEquals = checker.resolveExternalModuleSymbol(externalModule); return externalModule !== exportEquals; } -function updateImport(old: ts.ImportDeclaration, defaultImportName: ts.Identifier | undefined, elements: readonly ts.ImportSpecifier[] | undefined): ts.ImportDeclaration { - return ts.factory.createImportDeclaration(/*modifiers*/ undefined, - ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? ts.factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*assertClause*/ undefined); +function updateImport(old: ImportDeclaration, defaultImportName: Identifier | undefined, elements: readonly ImportSpecifier[] | undefined): ImportDeclaration { + return factory.createImportDeclaration(/*modifiers*/ undefined, + factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, elements && elements.length ? factory.createNamedImports(elements) : undefined), old.moduleSpecifier, /*assertClause*/ undefined); } diff --git a/src/services/refactors/convertOverloadListToSingleSignature.ts b/src/services/refactors/convertOverloadListToSingleSignature.ts index 76617e69222f8..ebe0535e0098e 100644 --- a/src/services/refactors/convertOverloadListToSingleSignature.ts +++ b/src/services/refactors/convertOverloadListToSingleSignature.ts @@ -1,23 +1,31 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, CallSignatureDeclaration, ConstructorDeclaration, ConstructSignatureDeclaration, Debug, + Diagnostics, displayPartsToString, EmitFlags, emptyArray, every, factory, findAncestor, FunctionDeclaration, + getSourceFileOfNode, getSyntheticLeadingComments, getTokenAtPosition, isFunctionLikeDeclaration, isIdentifier, + length, map, mapDefined, MethodDeclaration, MethodSignature, NamedTupleMember, Node, NodeArray, + ParameterDeclaration, Program, rangeContainsPosition, RefactorContext, RefactorEditInfo, setEmitFlags, + setSyntheticLeadingComments, setTextRange, some, SourceFile, SyntaxKind, textChanges, TupleTypeNode, +} from "../_namespaces/ts"; +import { registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert overload list to single signature"; -const refactorDescription = ts.Diagnostics.Convert_overload_list_to_single_signature.message; +const refactorDescription = Diagnostics.Convert_overload_list_to_single_signature.message; const functionOverloadAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.function.overloadList", }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [functionOverloadAction.kind], getEditsForAction: getRefactorEditsToConvertOverloadsToOneSignature, getAvailableActions: getRefactorActionsToConvertOverloadsToOneSignature }); -function getRefactorActionsToConvertOverloadsToOneSignature(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToConvertOverloadsToOneSignature(context: RefactorContext): readonly ApplicableRefactorInfo[] { const { file, startPosition, program } = context; const info = getConvertableOverloadListAtPosition(file, startPosition, program); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; return [{ name: refactorName, @@ -26,7 +34,7 @@ function getRefactorActionsToConvertOverloadsToOneSignature(context: ts.Refactor }]; } -function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorContext): ts.RefactorEditInfo | undefined { +function getRefactorEditsToConvertOverloadsToOneSignature(context: RefactorContext): RefactorEditInfo | undefined { const { file, startPosition, program } = context; const signatureDecls = getConvertableOverloadListAtPosition(file, startPosition, program); if (!signatureDecls) return undefined; @@ -36,8 +44,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo const lastDeclaration = signatureDecls[signatureDecls.length - 1]; let updated = lastDeclaration; switch (lastDeclaration.kind) { - case ts.SyntaxKind.MethodSignature: { - updated = ts.factory.updateMethodSignature( + case SyntaxKind.MethodSignature: { + updated = factory.updateMethodSignature( lastDeclaration, lastDeclaration.modifiers, lastDeclaration.name, @@ -48,8 +56,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.MethodDeclaration: { - updated = ts.factory.updateMethodDeclaration( + case SyntaxKind.MethodDeclaration: { + updated = factory.updateMethodDeclaration( lastDeclaration, lastDeclaration.modifiers, lastDeclaration.asteriskToken, @@ -62,8 +70,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.CallSignature: { - updated = ts.factory.updateCallSignature( + case SyntaxKind.CallSignature: { + updated = factory.updateCallSignature( lastDeclaration, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), @@ -71,8 +79,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.Constructor: { - updated = ts.factory.updateConstructorDeclaration( + case SyntaxKind.Constructor: { + updated = factory.updateConstructorDeclaration( lastDeclaration, lastDeclaration.modifiers, getNewParametersForCombinedSignature(signatureDecls), @@ -80,8 +88,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.ConstructSignature: { - updated = ts.factory.updateConstructSignature( + case SyntaxKind.ConstructSignature: { + updated = factory.updateConstructSignature( lastDeclaration, lastDeclaration.typeParameters, getNewParametersForCombinedSignature(signatureDecls), @@ -89,8 +97,8 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - case ts.SyntaxKind.FunctionDeclaration: { - updated = ts.factory.updateFunctionDeclaration( + case SyntaxKind.FunctionDeclaration: { + updated = factory.updateFunctionDeclaration( lastDeclaration, lastDeclaration.modifiers, lastDeclaration.asteriskToken, @@ -102,58 +110,58 @@ function getRefactorEditsToConvertOverloadsToOneSignature(context: ts.RefactorCo ); break; } - default: return ts.Debug.failBadSyntaxKind(lastDeclaration, "Unhandled signature kind in overload list conversion refactoring"); + default: return Debug.failBadSyntaxKind(lastDeclaration, "Unhandled signature kind in overload list conversion refactoring"); } if (updated === lastDeclaration) { return; // No edits to apply, do nothing } - const edits = ts.textChanges.ChangeTracker.with(context, t => { + const edits = textChanges.ChangeTracker.with(context, t => { t.replaceNodeRange(file, signatureDecls[0], signatureDecls[signatureDecls.length - 1], updated); }); return { renameFilename: undefined, renameLocation: undefined, edits }; - function getNewParametersForCombinedSignature(signatureDeclarations: (ts.MethodSignature | ts.MethodDeclaration | ts.CallSignatureDeclaration | ts.ConstructorDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionDeclaration)[]): ts.NodeArray { + function getNewParametersForCombinedSignature(signatureDeclarations: (MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration)[]): NodeArray { const lastSig = signatureDeclarations[signatureDeclarations.length - 1]; - if (ts.isFunctionLikeDeclaration(lastSig) && lastSig.body) { + if (isFunctionLikeDeclaration(lastSig) && lastSig.body) { // Trim away implementation signature arguments (they should already be compatible with overloads, but are likely less precise to guarantee compatability with the overloads) signatureDeclarations = signatureDeclarations.slice(0, signatureDeclarations.length - 1); } - return ts.factory.createNodeArray([ - ts.factory.createParameterDeclaration( + return factory.createNodeArray([ + factory.createParameterDeclaration( /*modifiers*/ undefined, - ts.factory.createToken(ts.SyntaxKind.DotDotDotToken), + factory.createToken(SyntaxKind.DotDotDotToken), "args", /*questionToken*/ undefined, - ts.factory.createUnionTypeNode(ts.map(signatureDeclarations, convertSignatureParametersToTuple)) + factory.createUnionTypeNode(map(signatureDeclarations, convertSignatureParametersToTuple)) ) ]); } - function convertSignatureParametersToTuple(decl: ts.MethodSignature | ts.MethodDeclaration | ts.CallSignatureDeclaration | ts.ConstructorDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionDeclaration): ts.TupleTypeNode { - const members = ts.map(decl.parameters, convertParameterToNamedTupleMember); - return ts.setEmitFlags(ts.factory.createTupleTypeNode(members), ts.some(members, m => !!ts.length(ts.getSyntheticLeadingComments(m))) ? ts.EmitFlags.None : ts.EmitFlags.SingleLine); + function convertSignatureParametersToTuple(decl: MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration): TupleTypeNode { + const members = map(decl.parameters, convertParameterToNamedTupleMember); + return setEmitFlags(factory.createTupleTypeNode(members), some(members, m => !!length(getSyntheticLeadingComments(m))) ? EmitFlags.None : EmitFlags.SingleLine); } - function convertParameterToNamedTupleMember(p: ts.ParameterDeclaration): ts.NamedTupleMember { - ts.Debug.assert(ts.isIdentifier(p.name)); // This is checked during refactoring applicability checking - const result = ts.setTextRange(ts.factory.createNamedTupleMember( + function convertParameterToNamedTupleMember(p: ParameterDeclaration): NamedTupleMember { + Debug.assert(isIdentifier(p.name)); // This is checked during refactoring applicability checking + const result = setTextRange(factory.createNamedTupleMember( p.dotDotDotToken, p.name, p.questionToken, - p.type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword) + p.type || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) ), p); const parameterDocComment = p.symbol && p.symbol.getDocumentationComment(checker); if (parameterDocComment) { - const newComment = ts.displayPartsToString(parameterDocComment); + const newComment = displayPartsToString(parameterDocComment); if (newComment.length) { - ts.setSyntheticLeadingComments(result, [{ + setSyntheticLeadingComments(result, [{ text: `* ${newComment.split("\n").map(c => ` * ${c}`).join("\n")} `, - kind: ts.SyntaxKind.MultiLineCommentTrivia, + kind: SyntaxKind.MultiLineCommentTrivia, pos: -1, end: -1, hasTrailingNewLine: true, @@ -166,26 +174,26 @@ ${newComment.split("\n").map(c => ` * ${c}`).join("\n")} } -function isConvertableSignatureDeclaration(d: ts.Node): d is ts.MethodSignature | ts.MethodDeclaration | ts.CallSignatureDeclaration | ts.ConstructorDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionDeclaration { +function isConvertableSignatureDeclaration(d: Node): d is MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration { switch (d.kind) { - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.CallSignature: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructSignature: + case SyntaxKind.FunctionDeclaration: return true; } return false; } -function getConvertableOverloadListAtPosition(file: ts.SourceFile, startPosition: number, program: ts.Program) { - const node = ts.getTokenAtPosition(file, startPosition); - const containingDecl = ts.findAncestor(node, isConvertableSignatureDeclaration); +function getConvertableOverloadListAtPosition(file: SourceFile, startPosition: number, program: Program) { + const node = getTokenAtPosition(file, startPosition); + const containingDecl = findAncestor(node, isConvertableSignatureDeclaration); if (!containingDecl) { return; } - if (ts.isFunctionLikeDeclaration(containingDecl) && containingDecl.body && ts.rangeContainsPosition(containingDecl.body, startPosition)) { + if (isFunctionLikeDeclaration(containingDecl) && containingDecl.body && rangeContainsPosition(containingDecl.body, startPosition)) { return; } @@ -195,29 +203,29 @@ function getConvertableOverloadListAtPosition(file: ts.SourceFile, startPosition return; } const decls = signatureSymbol.declarations; - if (ts.length(decls) <= 1) { + if (length(decls) <= 1) { return; } - if (!ts.every(decls, d => ts.getSourceFileOfNode(d) === file)) { + if (!every(decls, d => getSourceFileOfNode(d) === file)) { return; } if (!isConvertableSignatureDeclaration(decls![0])) { return; } const kindOne = decls![0].kind; - if (!ts.every(decls, d => d.kind === kindOne)) { + if (!every(decls, d => d.kind === kindOne)) { return; } - const signatureDecls = decls as (ts.MethodSignature | ts.MethodDeclaration | ts.CallSignatureDeclaration | ts.ConstructorDeclaration | ts.ConstructSignatureDeclaration | ts.FunctionDeclaration)[]; - if (ts.some(signatureDecls, d => !!d.typeParameters || ts.some(d.parameters, p => !!p.modifiers || !ts.isIdentifier(p.name)))) { + const signatureDecls = decls as (MethodSignature | MethodDeclaration | CallSignatureDeclaration | ConstructorDeclaration | ConstructSignatureDeclaration | FunctionDeclaration)[]; + if (some(signatureDecls, d => !!d.typeParameters || some(d.parameters, p => !!p.modifiers || !isIdentifier(p.name)))) { return; } - const signatures = ts.mapDefined(signatureDecls, d => checker.getSignatureFromDeclaration(d)); - if (ts.length(signatures) !== ts.length(decls)) { + const signatures = mapDefined(signatureDecls, d => checker.getSignatureFromDeclaration(d)); + if (length(signatures) !== length(decls)) { return; } const returnOne = checker.getReturnTypeOfSignature(signatures[0]); - if (!ts.every(signatures, s => checker.getReturnTypeOfSignature(s) === returnOne)) { + if (!every(signatures, s => checker.getReturnTypeOfSignature(s) === returnOne)) { return; } diff --git a/src/services/refactors/convertParamsToDestructuredObject.ts b/src/services/refactors/convertParamsToDestructuredObject.ts index ef50dda564c10..a4072a335b8b7 100644 --- a/src/services/refactors/convertParamsToDestructuredObject.ts +++ b/src/services/refactors/convertParamsToDestructuredObject.ts @@ -1,26 +1,46 @@ -import * as ts from "../_namespaces/ts"; +import { + addEmitFlags, ApplicableRefactorInfo, ArrowFunction, BindingElement, CallExpression, CancellationToken, CheckFlags, + ClassDeclaration, ClassExpression, compareValues, ConstructorDeclaration, contains, copyComments, Debug, + deduplicate, Diagnostics, ElementAccessExpression, EmitFlags, emptyArray, equateValues, every, Expression, factory, + FindAllReferences, findAncestor, findChildOfKind, findModifier, first, flatMap, FunctionBody, FunctionDeclaration, + FunctionExpression, FunctionLikeDeclaration, getCheckFlags, getContainingFunctionDeclaration, + getContainingObjectLiteralElement, getLocaleSpecificMessage, getMeaningFromLocation, getSourceFileOfNode, + getSymbolTarget, getSynthesizedDeepClone, getTextOfIdentifierOrLiteral, getTouchingToken, getTypeNodeIfAccessible, + Identifier, isCallOrNewExpression, isClassDeclaration, isConstructorDeclaration, isDeclaration, + isElementAccessExpression, isExportAssignment, isExportSpecifier, isExpressionWithTypeArgumentsInClassExtendsClause, + isFunctionLikeDeclaration, isIdentifier, isImportClause, isImportEqualsDeclaration, isImportSpecifier, + isInterfaceDeclaration, isJSDocNode, isMethodSignature, isNamespaceImport, isNewExpressionTarget, + isObjectLiteralExpression, isPropertyAccessExpression, isPropertyAssignment, isRestParameter, isSourceFileJS, + isThis, isTypeLiteralNode, isVarConst, isVariableDeclaration, LanguageServiceHost, last, map, MethodDeclaration, + MethodSignature, Modifier, NewExpression, Node, NodeArray, ObjectLiteralElementLike, ObjectLiteralExpression, + ParameterDeclaration, Program, PropertyAccessExpression, PropertyAssignment, PropertySignature, rangeContainsRange, + RefactorContext, RefactorEditInfo, SemanticMeaning, ShorthandPropertyAssignment, sortAndDeduplicate, SourceFile, + suppressLeadingAndTrailingTrivia, Symbol, SyntaxKind, textChanges, tryCast, TypeChecker, TypeLiteralNode, TypeNode, + VariableDeclaration, +} from "../_namespaces/ts"; +import { registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert parameters to destructured object"; const minimumParameterLength = 1; -const refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_parameters_to_destructured_object); +const refactorDescription = getLocaleSpecificMessage(Diagnostics.Convert_parameters_to_destructured_object); const toDestructuredAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.parameters.toDestructured" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [toDestructuredAction.kind], getEditsForAction: getRefactorEditsToConvertParametersToDestructuredObject, getAvailableActions: getRefactorActionsToConvertParametersToDestructuredObject }); -function getRefactorActionsToConvertParametersToDestructuredObject(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToConvertParametersToDestructuredObject(context: RefactorContext): readonly ApplicableRefactorInfo[] { const { file, startPosition } = context; - const isJSFile = ts.isSourceFileJS(file); - if (isJSFile) return ts.emptyArray; // TODO: GH#30113 + const isJSFile = isSourceFileJS(file); + if (isJSFile) return emptyArray; // TODO: GH#30113 const functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, context.program.getTypeChecker()); - if (!functionDeclaration) return ts.emptyArray; + if (!functionDeclaration) return emptyArray; return [{ name: refactorName, @@ -29,15 +49,15 @@ function getRefactorActionsToConvertParametersToDestructuredObject(context: ts.R }]; } -function getRefactorEditsToConvertParametersToDestructuredObject(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { - ts.Debug.assert(actionName === refactorName, "Unexpected action name"); +function getRefactorEditsToConvertParametersToDestructuredObject(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { + Debug.assert(actionName === refactorName, "Unexpected action name"); const { file, startPosition, program, cancellationToken, host } = context; const functionDeclaration = getFunctionDeclarationAtPosition(file, startPosition, program.getTypeChecker()); if (!functionDeclaration || !cancellationToken) return undefined; const groupedReferences = getGroupedReferences(functionDeclaration, program, cancellationToken); if (groupedReferences.valid) { - const edits = ts.textChanges.ChangeTracker.with(context, t => doChange(file, program, host, t, functionDeclaration, groupedReferences)); + const edits = textChanges.ChangeTracker.with(context, t => doChange(file, program, host, t, functionDeclaration, groupedReferences)); return { renameFilename: undefined, renameLocation: undefined, edits }; } @@ -45,75 +65,75 @@ function getRefactorEditsToConvertParametersToDestructuredObject(context: ts.Ref } function doChange( - sourceFile: ts.SourceFile, - program: ts.Program, - host: ts.LanguageServiceHost, - changes: ts.textChanges.ChangeTracker, + sourceFile: SourceFile, + program: Program, + host: LanguageServiceHost, + changes: textChanges.ChangeTracker, functionDeclaration: ValidFunctionDeclaration, groupedReferences: GroupedReferences): void { const signature = groupedReferences.signature; - const newFunctionDeclarationParams = ts.map(createNewParameters(functionDeclaration, program, host), param => ts.getSynthesizedDeepClone(param)); + const newFunctionDeclarationParams = map(createNewParameters(functionDeclaration, program, host), param => getSynthesizedDeepClone(param)); if (signature) { - const newSignatureParams = ts.map(createNewParameters(signature, program, host), param => ts.getSynthesizedDeepClone(param)); + const newSignatureParams = map(createNewParameters(signature, program, host), param => getSynthesizedDeepClone(param)); replaceParameters(signature, newSignatureParams); } replaceParameters(functionDeclaration, newFunctionDeclarationParams); - const functionCalls = ts.sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ (a, b) => ts.compareValues(a.pos, b.pos)); + const functionCalls = sortAndDeduplicate(groupedReferences.functionCalls, /*comparer*/ (a, b) => compareValues(a.pos, b.pos)); for (const call of functionCalls) { if (call.arguments && call.arguments.length) { - const newArgument = ts.getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); + const newArgument = getSynthesizedDeepClone(createNewArgument(functionDeclaration, call.arguments), /*includeTrivia*/ true); changes.replaceNodeRange( - ts.getSourceFileOfNode(call), - ts.first(call.arguments), - ts.last(call.arguments), + getSourceFileOfNode(call), + first(call.arguments), + last(call.arguments), newArgument, - { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include }); + { leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll, trailingTriviaOption: textChanges.TrailingTriviaOption.Include }); } } - function replaceParameters(declarationOrSignature: ValidFunctionDeclaration | ValidMethodSignature, parameterDeclarations: ts.ParameterDeclaration[]) { + function replaceParameters(declarationOrSignature: ValidFunctionDeclaration | ValidMethodSignature, parameterDeclarations: ParameterDeclaration[]) { changes.replaceNodeRangeWithNodes( sourceFile, - ts.first(declarationOrSignature.parameters), - ts.last(declarationOrSignature.parameters), + first(declarationOrSignature.parameters), + last(declarationOrSignature.parameters), parameterDeclarations, { joiner: ", ", // indentation is set to 0 because otherwise the object parameter will be indented if there is a `this` parameter indentation: 0, - leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll, - trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Include + leadingTriviaOption: textChanges.LeadingTriviaOption.IncludeAll, + trailingTriviaOption: textChanges.TrailingTriviaOption.Include }); } } -function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, program: ts.Program, cancellationToken: ts.CancellationToken): GroupedReferences { +function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, program: Program, cancellationToken: CancellationToken): GroupedReferences { const functionNames = getFunctionNames(functionDeclaration); - const classNames = ts.isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; - const names = ts.deduplicate([...functionNames, ...classNames], ts.equateValues); + const classNames = isConstructorDeclaration(functionDeclaration) ? getClassNames(functionDeclaration) : []; + const names = deduplicate([...functionNames, ...classNames], equateValues); const checker = program.getTypeChecker(); - const references = ts.flatMap(names, /*mapfn*/ name => ts.FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken)); + const references = flatMap(names, /*mapfn*/ name => FindAllReferences.getReferenceEntriesForNode(-1, name, program, program.getSourceFiles(), cancellationToken)); const groupedReferences = groupReferences(references); - if (!ts.every(groupedReferences.declarations, /*callback*/ decl => ts.contains(names, decl))) { + if (!every(groupedReferences.declarations, /*callback*/ decl => contains(names, decl))) { groupedReferences.valid = false; } return groupedReferences; - function groupReferences(referenceEntries: readonly ts.FindAllReferences.Entry[]): GroupedReferences { + function groupReferences(referenceEntries: readonly FindAllReferences.Entry[]): GroupedReferences { const classReferences: ClassReferences = { accessExpressions: [], typeUsages: [] }; const groupedReferences: GroupedReferences = { functionCalls: [], declarations: [], classReferences, valid: true }; - const functionSymbols = ts.map(functionNames, getSymbolTargetAtLocation); - const classSymbols = ts.map(classNames, getSymbolTargetAtLocation); - const isConstructor = ts.isConstructorDeclaration(functionDeclaration); - const contextualSymbols = ts.map(functionNames, name => getSymbolForContextualType(name, checker)); + const functionSymbols = map(functionNames, getSymbolTargetAtLocation); + const classSymbols = map(classNames, getSymbolTargetAtLocation); + const isConstructor = isConstructorDeclaration(functionDeclaration); + const contextualSymbols = map(functionNames, name => getSymbolForContextualType(name, checker)); for (const entry of referenceEntries) { - if (entry.kind === ts.FindAllReferences.EntryKind.Span) { + if (entry.kind === FindAllReferences.EntryKind.Span) { groupedReferences.valid = false; continue; } @@ -124,7 +144,7 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro const foo: IFoo = { m(a: number): void {} } In these cases we get the symbol for the signature from the contextual type. */ - if (ts.contains(contextualSymbols, getSymbolTargetAtLocation(entry.node))) { + if (contains(contextualSymbols, getSymbolTargetAtLocation(entry.node))) { if (isValidMethodSignature(entry.node.parent)) { groupedReferences.signature = entry.node.parent; continue; @@ -137,7 +157,7 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro } const contextualSymbol = getSymbolForContextualType(entry.node, checker); - if (contextualSymbol && ts.contains(contextualSymbols, contextualSymbol)) { + if (contextualSymbol && contains(contextualSymbols, contextualSymbol)) { const decl = entryToDeclaration(entry); if (decl) { groupedReferences.declarations.push(decl); @@ -156,7 +176,7 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro So we need to add a special case for this because when calling a constructor of a class through one of its subclasses, the symbols are going to be different. */ - if (ts.contains(functionSymbols, getSymbolTargetAtLocation(entry.node)) || ts.isNewExpressionTarget(entry.node)) { + if (contains(functionSymbols, getSymbolTargetAtLocation(entry.node)) || isNewExpressionTarget(entry.node)) { const importOrExportReference = entryToImportOrExport(entry); if (importOrExportReference) { continue; @@ -174,7 +194,7 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro } } // if the refactored function is a constructor, we must also check if the references to its class are valid - if (isConstructor && ts.contains(classSymbols, getSymbolTargetAtLocation(entry.node))) { + if (isConstructor && contains(classSymbols, getSymbolTargetAtLocation(entry.node))) { const importOrExportReference = entryToImportOrExport(entry); if (importOrExportReference) { continue; @@ -194,7 +214,7 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro // Only class declarations are allowed to be used as a type (in a heritage clause), // otherwise `findAllReferences` might not be able to track constructor calls. - if (ts.isClassDeclaration(functionDeclaration.parent)) { + if (isClassDeclaration(functionDeclaration.parent)) { const type = entryToType(entry); if (type) { classReferences.typeUsages.push(type); @@ -208,77 +228,77 @@ function getGroupedReferences(functionDeclaration: ValidFunctionDeclaration, pro return groupedReferences; } - function getSymbolTargetAtLocation(node: ts.Node) { + function getSymbolTargetAtLocation(node: Node) { const symbol = checker.getSymbolAtLocation(node); - return symbol && ts.getSymbolTarget(symbol, checker); + return symbol && getSymbolTarget(symbol, checker); } } /** * Gets the symbol for the contextual type of the node if it is not a union or intersection. */ -function getSymbolForContextualType(node: ts.Node, checker: ts.TypeChecker): ts.Symbol | undefined { - const element = ts.getContainingObjectLiteralElement(node); +function getSymbolForContextualType(node: Node, checker: TypeChecker): Symbol | undefined { + const element = getContainingObjectLiteralElement(node); if (element) { - const contextualType = checker.getContextualTypeForObjectLiteralElement(element as ts.ObjectLiteralElementLike); + const contextualType = checker.getContextualTypeForObjectLiteralElement(element as ObjectLiteralElementLike); const symbol = contextualType?.getSymbol(); - if (symbol && !(ts.getCheckFlags(symbol) & ts.CheckFlags.Synthetic)) { + if (symbol && !(getCheckFlags(symbol) & CheckFlags.Synthetic)) { return symbol; } } } -function entryToImportOrExport(entry: ts.FindAllReferences.NodeEntry): ts.Node | undefined { +function entryToImportOrExport(entry: FindAllReferences.NodeEntry): Node | undefined { const node = entry.node; - if (ts.isImportSpecifier(node.parent) - || ts.isImportClause(node.parent) - || ts.isImportEqualsDeclaration(node.parent) - || ts.isNamespaceImport(node.parent)) { + if (isImportSpecifier(node.parent) + || isImportClause(node.parent) + || isImportEqualsDeclaration(node.parent) + || isNamespaceImport(node.parent)) { return node; } - if (ts.isExportSpecifier(node.parent) || ts.isExportAssignment(node.parent)) { + if (isExportSpecifier(node.parent) || isExportAssignment(node.parent)) { return node; } return undefined; } -function entryToDeclaration(entry: ts.FindAllReferences.NodeEntry): ts.Node | undefined { - if (ts.isDeclaration(entry.node.parent)) { +function entryToDeclaration(entry: FindAllReferences.NodeEntry): Node | undefined { + if (isDeclaration(entry.node.parent)) { return entry.node; } return undefined; } -function entryToFunctionCall(entry: ts.FindAllReferences.NodeEntry): ts.CallExpression | ts.NewExpression | undefined { +function entryToFunctionCall(entry: FindAllReferences.NodeEntry): CallExpression | NewExpression | undefined { if (entry.node.parent) { const functionReference = entry.node; const parent = functionReference.parent; switch (parent.kind) { // foo(...) or super(...) or new Foo(...) - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - const callOrNewExpression = ts.tryCast(parent, ts.isCallOrNewExpression); + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + const callOrNewExpression = tryCast(parent, isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === functionReference) { return callOrNewExpression; } break; // x.foo(...) - case ts.SyntaxKind.PropertyAccessExpression: - const propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + case SyntaxKind.PropertyAccessExpression: + const propertyAccessExpression = tryCast(parent, isPropertyAccessExpression); if (propertyAccessExpression && propertyAccessExpression.parent && propertyAccessExpression.name === functionReference) { - const callOrNewExpression = ts.tryCast(propertyAccessExpression.parent, ts.isCallOrNewExpression); + const callOrNewExpression = tryCast(propertyAccessExpression.parent, isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === propertyAccessExpression) { return callOrNewExpression; } } break; // x["foo"](...) - case ts.SyntaxKind.ElementAccessExpression: - const elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + case SyntaxKind.ElementAccessExpression: + const elementAccessExpression = tryCast(parent, isElementAccessExpression); if (elementAccessExpression && elementAccessExpression.parent && elementAccessExpression.argumentExpression === functionReference) { - const callOrNewExpression = ts.tryCast(elementAccessExpression.parent, ts.isCallOrNewExpression); + const callOrNewExpression = tryCast(elementAccessExpression.parent, isCallOrNewExpression); if (callOrNewExpression && callOrNewExpression.expression === elementAccessExpression) { return callOrNewExpression; } @@ -289,21 +309,21 @@ function entryToFunctionCall(entry: ts.FindAllReferences.NodeEntry): ts.CallExpr return undefined; } -function entryToAccessExpression(entry: ts.FindAllReferences.NodeEntry): ts.ElementAccessExpression | ts.PropertyAccessExpression | undefined { +function entryToAccessExpression(entry: FindAllReferences.NodeEntry): ElementAccessExpression | PropertyAccessExpression | undefined { if (entry.node.parent) { const reference = entry.node; const parent = reference.parent; switch (parent.kind) { // `C.foo` - case ts.SyntaxKind.PropertyAccessExpression: - const propertyAccessExpression = ts.tryCast(parent, ts.isPropertyAccessExpression); + case SyntaxKind.PropertyAccessExpression: + const propertyAccessExpression = tryCast(parent, isPropertyAccessExpression); if (propertyAccessExpression && propertyAccessExpression.expression === reference) { return propertyAccessExpression; } break; // `C["foo"]` - case ts.SyntaxKind.ElementAccessExpression: - const elementAccessExpression = ts.tryCast(parent, ts.isElementAccessExpression); + case SyntaxKind.ElementAccessExpression: + const elementAccessExpression = tryCast(parent, isElementAccessExpression); if (elementAccessExpression && elementAccessExpression.expression === reference) { return elementAccessExpression; } @@ -313,167 +333,167 @@ function entryToAccessExpression(entry: ts.FindAllReferences.NodeEntry): ts.Elem return undefined; } -function entryToType(entry: ts.FindAllReferences.NodeEntry): ts.Node | undefined { +function entryToType(entry: FindAllReferences.NodeEntry): Node | undefined { const reference = entry.node; - if (ts.getMeaningFromLocation(reference) === ts.SemanticMeaning.Type || ts.isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { + if (getMeaningFromLocation(reference) === SemanticMeaning.Type || isExpressionWithTypeArgumentsInClassExtendsClause(reference.parent)) { return reference; } return undefined; } -function getFunctionDeclarationAtPosition(file: ts.SourceFile, startPosition: number, checker: ts.TypeChecker): ValidFunctionDeclaration | undefined { - const node = ts.getTouchingToken(file, startPosition); - const functionDeclaration = ts.getContainingFunctionDeclaration(node); +function getFunctionDeclarationAtPosition(file: SourceFile, startPosition: number, checker: TypeChecker): ValidFunctionDeclaration | undefined { + const node = getTouchingToken(file, startPosition); + const functionDeclaration = getContainingFunctionDeclaration(node); // don't offer refactor on top-level JSDoc if (isTopLevelJSDoc(node)) return undefined; if (functionDeclaration && isValidFunctionDeclaration(functionDeclaration, checker) - && ts.rangeContainsRange(functionDeclaration, node) - && !(functionDeclaration.body && ts.rangeContainsRange(functionDeclaration.body, node))) return functionDeclaration; + && rangeContainsRange(functionDeclaration, node) + && !(functionDeclaration.body && rangeContainsRange(functionDeclaration.body, node))) return functionDeclaration; return undefined; } -function isTopLevelJSDoc(node: ts.Node): boolean { - const containingJSDoc = ts.findAncestor(node, ts.isJSDocNode); +function isTopLevelJSDoc(node: Node): boolean { + const containingJSDoc = findAncestor(node, isJSDocNode); if (containingJSDoc) { - const containingNonJSDoc = ts.findAncestor(containingJSDoc, n => !ts.isJSDocNode(n)); - return !!containingNonJSDoc && ts.isFunctionLikeDeclaration(containingNonJSDoc); + const containingNonJSDoc = findAncestor(containingJSDoc, n => !isJSDocNode(n)); + return !!containingNonJSDoc && isFunctionLikeDeclaration(containingNonJSDoc); } return false; } -function isValidMethodSignature(node: ts.Node): node is ValidMethodSignature { - return ts.isMethodSignature(node) && (ts.isInterfaceDeclaration(node.parent) || ts.isTypeLiteralNode(node.parent)); +function isValidMethodSignature(node: Node): node is ValidMethodSignature { + return isMethodSignature(node) && (isInterfaceDeclaration(node.parent) || isTypeLiteralNode(node.parent)); } function isValidFunctionDeclaration( - functionDeclaration: ts.FunctionLikeDeclaration, - checker: ts.TypeChecker): functionDeclaration is ValidFunctionDeclaration { + functionDeclaration: FunctionLikeDeclaration, + checker: TypeChecker): functionDeclaration is ValidFunctionDeclaration { if (!isValidParameterNodeArray(functionDeclaration.parameters, checker)) return false; switch (functionDeclaration.kind) { - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionDeclaration: return hasNameOrDefault(functionDeclaration) && isSingleImplementation(functionDeclaration, checker); - case ts.SyntaxKind.MethodDeclaration: - if (ts.isObjectLiteralExpression(functionDeclaration.parent)) { + case SyntaxKind.MethodDeclaration: + if (isObjectLiteralExpression(functionDeclaration.parent)) { const contextualSymbol = getSymbolForContextualType(functionDeclaration.name, checker); // don't offer the refactor when there are multiple signatures since we won't know which ones the user wants to change return contextualSymbol?.declarations?.length === 1 && isSingleImplementation(functionDeclaration, checker); } return isSingleImplementation(functionDeclaration, checker); - case ts.SyntaxKind.Constructor: - if (ts.isClassDeclaration(functionDeclaration.parent)) { + case SyntaxKind.Constructor: + if (isClassDeclaration(functionDeclaration.parent)) { return hasNameOrDefault(functionDeclaration.parent) && isSingleImplementation(functionDeclaration, checker); } else { return isValidVariableDeclaration(functionDeclaration.parent.parent) && isSingleImplementation(functionDeclaration, checker); } - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: return isValidVariableDeclaration(functionDeclaration.parent); } return false; } -function isSingleImplementation(functionDeclaration: ts.FunctionLikeDeclaration, checker: ts.TypeChecker): boolean { +function isSingleImplementation(functionDeclaration: FunctionLikeDeclaration, checker: TypeChecker): boolean { return !!functionDeclaration.body && !checker.isImplementationOfOverload(functionDeclaration); } -function hasNameOrDefault(functionOrClassDeclaration: ts.FunctionDeclaration | ts.ClassDeclaration): boolean { +function hasNameOrDefault(functionOrClassDeclaration: FunctionDeclaration | ClassDeclaration): boolean { if (!functionOrClassDeclaration.name) { - const defaultKeyword = ts.findModifier(functionOrClassDeclaration, ts.SyntaxKind.DefaultKeyword); + const defaultKeyword = findModifier(functionOrClassDeclaration, SyntaxKind.DefaultKeyword); return !!defaultKeyword; } return true; } function isValidParameterNodeArray( - parameters: ts.NodeArray, - checker: ts.TypeChecker): parameters is ValidParameterNodeArray { + parameters: NodeArray, + checker: TypeChecker): parameters is ValidParameterNodeArray { return getRefactorableParametersLength(parameters) >= minimumParameterLength - && ts.every(parameters, /*callback*/ paramDecl => isValidParameterDeclaration(paramDecl, checker)); + && every(parameters, /*callback*/ paramDecl => isValidParameterDeclaration(paramDecl, checker)); } function isValidParameterDeclaration( - parameterDeclaration: ts.ParameterDeclaration, - checker: ts.TypeChecker): parameterDeclaration is ValidParameterDeclaration { - if (ts.isRestParameter(parameterDeclaration)) { + parameterDeclaration: ParameterDeclaration, + checker: TypeChecker): parameterDeclaration is ValidParameterDeclaration { + if (isRestParameter(parameterDeclaration)) { const type = checker.getTypeAtLocation(parameterDeclaration); if (!checker.isArrayType(type) && !checker.isTupleType(type)) return false; } - return !parameterDeclaration.modifiers && ts.isIdentifier(parameterDeclaration.name); + return !parameterDeclaration.modifiers && isIdentifier(parameterDeclaration.name); } -function isValidVariableDeclaration(node: ts.Node): node is ValidVariableDeclaration { - return ts.isVariableDeclaration(node) && ts.isVarConst(node) && ts.isIdentifier(node.name) && !node.type; // TODO: GH#30113 +function isValidVariableDeclaration(node: Node): node is ValidVariableDeclaration { + return isVariableDeclaration(node) && isVarConst(node) && isIdentifier(node.name) && !node.type; // TODO: GH#30113 } -function hasThisParameter(parameters: ts.NodeArray): boolean { - return parameters.length > 0 && ts.isThis(parameters[0].name); +function hasThisParameter(parameters: NodeArray): boolean { + return parameters.length > 0 && isThis(parameters[0].name); } -function getRefactorableParametersLength(parameters: ts.NodeArray): number { +function getRefactorableParametersLength(parameters: NodeArray): number { if (hasThisParameter(parameters)) { return parameters.length - 1; } return parameters.length; } -function getRefactorableParameters(parameters: ts.NodeArray): ts.NodeArray { +function getRefactorableParameters(parameters: NodeArray): NodeArray { if (hasThisParameter(parameters)) { - parameters = ts.factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); + parameters = factory.createNodeArray(parameters.slice(1), parameters.hasTrailingComma); } return parameters; } -function createPropertyOrShorthandAssignment(name: string, initializer: ts.Expression): ts.PropertyAssignment | ts.ShorthandPropertyAssignment { - if (ts.isIdentifier(initializer) && ts.getTextOfIdentifierOrLiteral(initializer) === name) { - return ts.factory.createShorthandPropertyAssignment(name); +function createPropertyOrShorthandAssignment(name: string, initializer: Expression): PropertyAssignment | ShorthandPropertyAssignment { + if (isIdentifier(initializer) && getTextOfIdentifierOrLiteral(initializer) === name) { + return factory.createShorthandPropertyAssignment(name); } - return ts.factory.createPropertyAssignment(name, initializer); + return factory.createPropertyAssignment(name, initializer); } -function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: ts.NodeArray): ts.ObjectLiteralExpression { +function createNewArgument(functionDeclaration: ValidFunctionDeclaration, functionArguments: NodeArray): ObjectLiteralExpression { const parameters = getRefactorableParameters(functionDeclaration.parameters); - const hasRestParameter = ts.isRestParameter(ts.last(parameters)); + const hasRestParameter = isRestParameter(last(parameters)); const nonRestArguments = hasRestParameter ? functionArguments.slice(0, parameters.length - 1) : functionArguments; - const properties = ts.map(nonRestArguments, (arg, i) => { + const properties = map(nonRestArguments, (arg, i) => { const parameterName = getParameterName(parameters[i]); const property = createPropertyOrShorthandAssignment(parameterName, arg); - ts.suppressLeadingAndTrailingTrivia(property.name); - if (ts.isPropertyAssignment(property)) ts.suppressLeadingAndTrailingTrivia(property.initializer); - ts.copyComments(arg, property); + suppressLeadingAndTrailingTrivia(property.name); + if (isPropertyAssignment(property)) suppressLeadingAndTrailingTrivia(property.initializer); + copyComments(arg, property); return property; }); if (hasRestParameter && functionArguments.length >= parameters.length) { const restArguments = functionArguments.slice(parameters.length - 1); - const restProperty = ts.factory.createPropertyAssignment(getParameterName(ts.last(parameters)), ts.factory.createArrayLiteralExpression(restArguments)); + const restProperty = factory.createPropertyAssignment(getParameterName(last(parameters)), factory.createArrayLiteralExpression(restArguments)); properties.push(restProperty); } - const objectLiteral = ts.factory.createObjectLiteralExpression(properties, /*multiLine*/ false); + const objectLiteral = factory.createObjectLiteralExpression(properties, /*multiLine*/ false); return objectLiteral; } -function createNewParameters(functionDeclaration: ValidFunctionDeclaration | ValidMethodSignature, program: ts.Program, host: ts.LanguageServiceHost): ts.NodeArray { +function createNewParameters(functionDeclaration: ValidFunctionDeclaration | ValidMethodSignature, program: Program, host: LanguageServiceHost): NodeArray { const checker = program.getTypeChecker(); const refactorableParameters = getRefactorableParameters(functionDeclaration.parameters); - const bindingElements = ts.map(refactorableParameters, createBindingElementFromParameterDeclaration); - const objectParameterName = ts.factory.createObjectBindingPattern(bindingElements); + const bindingElements = map(refactorableParameters, createBindingElementFromParameterDeclaration); + const objectParameterName = factory.createObjectBindingPattern(bindingElements); const objectParameterType = createParameterTypeNode(refactorableParameters); - let objectInitializer: ts.Expression | undefined; + let objectInitializer: Expression | undefined; // If every parameter in the original function was optional, add an empty object initializer to the new object parameter - if (ts.every(refactorableParameters, isOptionalParameter)) { - objectInitializer = ts.factory.createObjectLiteralExpression(); + if (every(refactorableParameters, isOptionalParameter)) { + objectInitializer = factory.createObjectLiteralExpression(); } - const objectParameter = ts.factory.createParameterDeclaration( + const objectParameter = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, objectParameterName, @@ -483,72 +503,72 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val if (hasThisParameter(functionDeclaration.parameters)) { const thisParameter = functionDeclaration.parameters[0]; - const newThisParameter = ts.factory.createParameterDeclaration( + const newThisParameter = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, thisParameter.name, /*questionToken*/ undefined, thisParameter.type); - ts.suppressLeadingAndTrailingTrivia(newThisParameter.name); - ts.copyComments(thisParameter.name, newThisParameter.name); + suppressLeadingAndTrailingTrivia(newThisParameter.name); + copyComments(thisParameter.name, newThisParameter.name); if (thisParameter.type) { - ts.suppressLeadingAndTrailingTrivia(newThisParameter.type!); - ts.copyComments(thisParameter.type, newThisParameter.type!); + suppressLeadingAndTrailingTrivia(newThisParameter.type!); + copyComments(thisParameter.type, newThisParameter.type!); } - return ts.factory.createNodeArray([newThisParameter, objectParameter]); + return factory.createNodeArray([newThisParameter, objectParameter]); } - return ts.factory.createNodeArray([objectParameter]); + return factory.createNodeArray([objectParameter]); - function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): ts.BindingElement { - const element = ts.factory.createBindingElement( + function createBindingElementFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): BindingElement { + const element = factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, getParameterName(parameterDeclaration), - ts.isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? ts.factory.createArrayLiteralExpression() : parameterDeclaration.initializer); + isRestParameter(parameterDeclaration) && isOptionalParameter(parameterDeclaration) ? factory.createArrayLiteralExpression() : parameterDeclaration.initializer); - ts.suppressLeadingAndTrailingTrivia(element); + suppressLeadingAndTrailingTrivia(element); if (parameterDeclaration.initializer && element.initializer) { - ts.copyComments(parameterDeclaration.initializer, element.initializer); + copyComments(parameterDeclaration.initializer, element.initializer); } return element; } - function createParameterTypeNode(parameters: ts.NodeArray): ts.TypeLiteralNode { - const members = ts.map(parameters, createPropertySignatureFromParameterDeclaration); - const typeNode = ts.addEmitFlags(ts.factory.createTypeLiteralNode(members), ts.EmitFlags.SingleLine); + function createParameterTypeNode(parameters: NodeArray): TypeLiteralNode { + const members = map(parameters, createPropertySignatureFromParameterDeclaration); + const typeNode = addEmitFlags(factory.createTypeLiteralNode(members), EmitFlags.SingleLine); return typeNode; } - function createPropertySignatureFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): ts.PropertySignature { + function createPropertySignatureFromParameterDeclaration(parameterDeclaration: ValidParameterDeclaration): PropertySignature { let parameterType = parameterDeclaration.type; - if (!parameterType && (parameterDeclaration.initializer || ts.isRestParameter(parameterDeclaration))) { + if (!parameterType && (parameterDeclaration.initializer || isRestParameter(parameterDeclaration))) { parameterType = getTypeNode(parameterDeclaration); } - const propertySignature = ts.factory.createPropertySignature( + const propertySignature = factory.createPropertySignature( /*modifiers*/ undefined, getParameterName(parameterDeclaration), - isOptionalParameter(parameterDeclaration) ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : parameterDeclaration.questionToken, + isOptionalParameter(parameterDeclaration) ? factory.createToken(SyntaxKind.QuestionToken) : parameterDeclaration.questionToken, parameterType); - ts.suppressLeadingAndTrailingTrivia(propertySignature); - ts.copyComments(parameterDeclaration.name, propertySignature.name); + suppressLeadingAndTrailingTrivia(propertySignature); + copyComments(parameterDeclaration.name, propertySignature.name); if (parameterDeclaration.type && propertySignature.type) { - ts.copyComments(parameterDeclaration.type, propertySignature.type); + copyComments(parameterDeclaration.type, propertySignature.type); } return propertySignature; } - function getTypeNode(node: ts.Node): ts.TypeNode | undefined { + function getTypeNode(node: Node): TypeNode | undefined { const type = checker.getTypeAtLocation(node); - return ts.getTypeNodeIfAccessible(type, node, program, host); + return getTypeNodeIfAccessible(type, node, program, host); } function isOptionalParameter(parameterDeclaration: ValidParameterDeclaration): boolean { - if (ts.isRestParameter(parameterDeclaration)) { + if (isRestParameter(parameterDeclaration)) { const type = checker.getTypeAtLocation(parameterDeclaration); return !checker.isTupleType(type); } @@ -557,21 +577,21 @@ function createNewParameters(functionDeclaration: ValidFunctionDeclaration | Val } function getParameterName(paramDeclaration: ValidParameterDeclaration) { - return ts.getTextOfIdentifierOrLiteral(paramDeclaration.name); + return getTextOfIdentifierOrLiteral(paramDeclaration.name); } -function getClassNames(constructorDeclaration: ValidConstructor): (ts.Identifier | ts.Modifier)[] { +function getClassNames(constructorDeclaration: ValidConstructor): (Identifier | Modifier)[] { switch (constructorDeclaration.parent.kind) { - case ts.SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassDeclaration: const classDeclaration = constructorDeclaration.parent; if (classDeclaration.name) return [classDeclaration.name]; // If the class declaration doesn't have a name, it should have a default modifier. // We validated this in `isValidFunctionDeclaration` through `hasNameOrDefault` - const defaultModifier = ts.Debug.checkDefined( - ts.findModifier(classDeclaration, ts.SyntaxKind.DefaultKeyword), + const defaultModifier = Debug.checkDefined( + findModifier(classDeclaration, SyntaxKind.DefaultKeyword), "Nameless class declaration should be a default export"); return [defaultModifier]; - case ts.SyntaxKind.ClassExpression: + case SyntaxKind.ClassExpression: const classExpression = constructorDeclaration.parent; const variableDeclaration = constructorDeclaration.parent.parent; const className = classExpression.name; @@ -580,90 +600,90 @@ function getClassNames(constructorDeclaration: ValidConstructor): (ts.Identifier } } -function getFunctionNames(functionDeclaration: ValidFunctionDeclaration): ts.Node[] { +function getFunctionNames(functionDeclaration: ValidFunctionDeclaration): Node[] { switch (functionDeclaration.kind) { - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionDeclaration: if (functionDeclaration.name) return [functionDeclaration.name]; // If the function declaration doesn't have a name, it should have a default modifier. // We validated this in `isValidFunctionDeclaration` through `hasNameOrDefault` - const defaultModifier = ts.Debug.checkDefined( - ts.findModifier(functionDeclaration, ts.SyntaxKind.DefaultKeyword), + const defaultModifier = Debug.checkDefined( + findModifier(functionDeclaration, SyntaxKind.DefaultKeyword), "Nameless function declaration should be a default export"); return [defaultModifier]; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: return [functionDeclaration.name]; - case ts.SyntaxKind.Constructor: - const ctrKeyword = ts.Debug.checkDefined( - ts.findChildOfKind(functionDeclaration, ts.SyntaxKind.ConstructorKeyword, functionDeclaration.getSourceFile()), + case SyntaxKind.Constructor: + const ctrKeyword = Debug.checkDefined( + findChildOfKind(functionDeclaration, SyntaxKind.ConstructorKeyword, functionDeclaration.getSourceFile()), "Constructor declaration should have constructor keyword"); - if (functionDeclaration.parent.kind === ts.SyntaxKind.ClassExpression) { + if (functionDeclaration.parent.kind === SyntaxKind.ClassExpression) { const variableDeclaration = functionDeclaration.parent.parent; return [variableDeclaration.name, ctrKeyword]; } return [ctrKeyword]; - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ArrowFunction: return [functionDeclaration.parent.name]; - case ts.SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionExpression: if (functionDeclaration.name) return [functionDeclaration.name, functionDeclaration.parent.name]; return [functionDeclaration.parent.name]; default: - return ts.Debug.assertNever(functionDeclaration, `Unexpected function declaration kind ${(functionDeclaration as ValidFunctionDeclaration).kind}`); + return Debug.assertNever(functionDeclaration, `Unexpected function declaration kind ${(functionDeclaration as ValidFunctionDeclaration).kind}`); } } -type ValidParameterNodeArray = ts.NodeArray; +type ValidParameterNodeArray = NodeArray; -interface ValidVariableDeclaration extends ts.VariableDeclaration { - name: ts.Identifier; +interface ValidVariableDeclaration extends VariableDeclaration { + name: Identifier; type: undefined; } -interface ValidConstructor extends ts.ConstructorDeclaration { - parent: ts.ClassDeclaration | (ts.ClassExpression & { parent: ValidVariableDeclaration }); - parameters: ts.NodeArray; - body: ts.FunctionBody; +interface ValidConstructor extends ConstructorDeclaration { + parent: ClassDeclaration | (ClassExpression & { parent: ValidVariableDeclaration }); + parameters: NodeArray; + body: FunctionBody; } -interface ValidFunction extends ts.FunctionDeclaration { - parameters: ts.NodeArray; - body: ts.FunctionBody; +interface ValidFunction extends FunctionDeclaration { + parameters: NodeArray; + body: FunctionBody; } -interface ValidMethod extends ts.MethodDeclaration { - parameters: ts.NodeArray; - body: ts.FunctionBody; +interface ValidMethod extends MethodDeclaration { + parameters: NodeArray; + body: FunctionBody; } -interface ValidFunctionExpression extends ts.FunctionExpression { +interface ValidFunctionExpression extends FunctionExpression { parent: ValidVariableDeclaration; - parameters: ts.NodeArray; + parameters: NodeArray; } -interface ValidArrowFunction extends ts.ArrowFunction { +interface ValidArrowFunction extends ArrowFunction { parent: ValidVariableDeclaration; - parameters: ts.NodeArray; + parameters: NodeArray; } -interface ValidMethodSignature extends ts.MethodSignature { - parameters: ts.NodeArray; +interface ValidMethodSignature extends MethodSignature { + parameters: NodeArray; } type ValidFunctionDeclaration = ValidConstructor | ValidFunction | ValidMethod | ValidArrowFunction | ValidFunctionExpression; -interface ValidParameterDeclaration extends ts.ParameterDeclaration { - name: ts.Identifier; +interface ValidParameterDeclaration extends ParameterDeclaration { + name: Identifier; modifiers: undefined; illegalDecorators: undefined; } interface GroupedReferences { - functionCalls: (ts.CallExpression | ts.NewExpression)[]; - declarations: ts.Node[]; + functionCalls: (CallExpression | NewExpression)[]; + declarations: Node[]; signature?: ValidMethodSignature; classReferences?: ClassReferences; valid: boolean; } interface ClassReferences { - accessExpressions: ts.Node[]; - typeUsages: ts.Node[]; + accessExpressions: Node[]; + typeUsages: Node[]; } diff --git a/src/services/refactors/convertStringOrTemplateLiteral.ts b/src/services/refactors/convertStringOrTemplateLiteral.ts index 0aac4ad28febf..f3bff71ac5849 100644 --- a/src/services/refactors/convertStringOrTemplateLiteral.ts +++ b/src/services/refactors/convertStringOrTemplateLiteral.ts @@ -1,54 +1,62 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, BinaryExpression, BinaryOperator, copyTrailingAsLeadingComments, copyTrailingComments, + Debug, Diagnostics, emptyArray, Expression, factory, findAncestor, getLocaleSpecificMessage, getTextOfNode, + getTokenAtPosition, getTrailingCommentRanges, isBinaryExpression, isNoSubstitutionTemplateLiteral, + isParenthesizedExpression, isStringLiteral, isStringLiteralLike, isTemplateExpression, isTemplateHead, + isTemplateMiddle, map, Node, ParenthesizedExpression, RefactorContext, RefactorEditInfo, SourceFile, SyntaxKind, + TemplateHead, TemplateMiddle, TemplateSpan, TemplateTail, textChanges, Token, +} from "../_namespaces/ts"; +import { registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert to template string"; -const refactorDescription = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_template_string); +const refactorDescription = getLocaleSpecificMessage(Diagnostics.Convert_to_template_string); const convertStringAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.string" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [convertStringAction.kind], getEditsForAction: getRefactorEditsToConvertToTemplateString, getAvailableActions: getRefactorActionsToConvertToTemplateString }); -function getRefactorActionsToConvertToTemplateString(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToConvertToTemplateString(context: RefactorContext): readonly ApplicableRefactorInfo[] { const { file, startPosition } = context; const node = getNodeOrParentOfParentheses(file, startPosition); const maybeBinary = getParentBinaryExpression(node); - const refactorInfo: ts.ApplicableRefactorInfo = { name: refactorName, description: refactorDescription, actions: [] }; + const refactorInfo: ApplicableRefactorInfo = { name: refactorName, description: refactorDescription, actions: [] }; - if (ts.isBinaryExpression(maybeBinary) && treeToArray(maybeBinary).isValidConcatenation) { + if (isBinaryExpression(maybeBinary) && treeToArray(maybeBinary).isValidConcatenation) { refactorInfo.actions.push(convertStringAction); return [refactorInfo]; } else if (context.preferences.provideRefactorNotApplicableReason) { refactorInfo.actions.push({ ...convertStringAction, - notApplicableReason: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_string_concatenation) + notApplicableReason: getLocaleSpecificMessage(Diagnostics.Can_only_convert_string_concatenation) }); return [refactorInfo]; } - return ts.emptyArray; + return emptyArray; } -function getNodeOrParentOfParentheses(file: ts.SourceFile, startPosition: number) { - const node = ts.getTokenAtPosition(file, startPosition); +function getNodeOrParentOfParentheses(file: SourceFile, startPosition: number) { + const node = getTokenAtPosition(file, startPosition); const nestedBinary = getParentBinaryExpression(node); const isNonStringBinary = !treeToArray(nestedBinary).isValidConcatenation; if ( isNonStringBinary && - ts.isParenthesizedExpression(nestedBinary.parent) && - ts.isBinaryExpression(nestedBinary.parent.parent) + isParenthesizedExpression(nestedBinary.parent) && + isBinaryExpression(nestedBinary.parent.parent) ) { return nestedBinary.parent.parent; } return node; } -function getRefactorEditsToConvertToTemplateString(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { +function getRefactorEditsToConvertToTemplateString(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const { file, startPosition } = context; const node = getNodeOrParentOfParentheses(file, startPosition); @@ -56,16 +64,16 @@ function getRefactorEditsToConvertToTemplateString(context: ts.RefactorContext, case refactorDescription: return { edits: getEditsForToTemplateLiteral(context, node) }; default: - return ts.Debug.fail("invalid action"); + return Debug.fail("invalid action"); } } -function getEditsForToTemplateLiteral(context: ts.RefactorContext, node: ts.Node) { +function getEditsForToTemplateLiteral(context: RefactorContext, node: Node) { const maybeBinary = getParentBinaryExpression(node); const file = context.file; const templateLiteral = nodesToTemplate(treeToArray(maybeBinary), file); - const trailingCommentRanges = ts.getTrailingCommentRanges(file.text, maybeBinary.end); + const trailingCommentRanges = getTrailingCommentRanges(file.text, maybeBinary.end); if (trailingCommentRanges) { const lastComment = trailingCommentRanges[trailingCommentRanges.length - 1]; @@ -73,50 +81,50 @@ function getEditsForToTemplateLiteral(context: ts.RefactorContext, node: ts.Node // since suppressTrailingTrivia(maybeBinary) does not work, the trailing comment is removed manually // otherwise it would have the trailing comment twice - return ts.textChanges.ChangeTracker.with(context, t => { + return textChanges.ChangeTracker.with(context, t => { t.deleteRange(file, trailingRange); t.replaceNode(file, maybeBinary, templateLiteral); }); } else { - return ts.textChanges.ChangeTracker.with(context, t => t.replaceNode(file, maybeBinary, templateLiteral)); + return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, maybeBinary, templateLiteral)); } } -function isNotEqualsOperator(node: ts.BinaryExpression) { - return node.operatorToken.kind !== ts.SyntaxKind.EqualsToken; +function isNotEqualsOperator(node: BinaryExpression) { + return node.operatorToken.kind !== SyntaxKind.EqualsToken; } -function getParentBinaryExpression(expr: ts.Node) { - const container = ts.findAncestor(expr.parent, n => { +function getParentBinaryExpression(expr: Node) { + const container = findAncestor(expr.parent, n => { switch (n.kind) { - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: return false; - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.BinaryExpression: - return !(ts.isBinaryExpression(n.parent) && isNotEqualsOperator(n.parent)); + case SyntaxKind.TemplateExpression: + case SyntaxKind.BinaryExpression: + return !(isBinaryExpression(n.parent) && isNotEqualsOperator(n.parent)); default: return "quit"; } }); - return (container || expr) as ts.Expression; + return (container || expr) as Expression; } -function treeToArray(current: ts.Expression) { - const loop = (current: ts.Node): { nodes: ts.Expression[], operators: ts.Token[], hasString: boolean, validOperators: boolean} => { - if (!ts.isBinaryExpression(current)) { - return { nodes: [current as ts.Expression], operators: [], validOperators: true, - hasString: ts.isStringLiteral(current) || ts.isNoSubstitutionTemplateLiteral(current) }; +function treeToArray(current: Expression) { + const loop = (current: Node): { nodes: Expression[], operators: Token[], hasString: boolean, validOperators: boolean} => { + if (!isBinaryExpression(current)) { + return { nodes: [current as Expression], operators: [], validOperators: true, + hasString: isStringLiteral(current) || isNoSubstitutionTemplateLiteral(current) }; } const { nodes, operators, hasString: leftHasString, validOperators: leftOperatorValid } = loop(current.left); - if (!(leftHasString || ts.isStringLiteral(current.right) || ts.isTemplateExpression(current.right))) { + if (!(leftHasString || isStringLiteral(current.right) || isTemplateExpression(current.right))) { return { nodes: [current], operators: [], hasString: false, validOperators: true }; } - const currentOperatorValid = current.operatorToken.kind === ts.SyntaxKind.PlusToken; + const currentOperatorValid = current.operatorToken.kind === SyntaxKind.PlusToken; const validOperators = leftOperatorValid && currentOperatorValid; nodes.push(current.right); @@ -130,19 +138,19 @@ function treeToArray(current: ts.Expression) { // to copy comments following the operator // "foo" + /* comment */ "bar" -const copyTrailingOperatorComments = (operators: ts.Token[], file: ts.SourceFile) => (index: number, targetNode: ts.Node) => { +const copyTrailingOperatorComments = (operators: Token[], file: SourceFile) => (index: number, targetNode: Node) => { if (index < operators.length) { - ts.copyTrailingComments(operators[index], targetNode, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyTrailingComments(operators[index], targetNode, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); } }; // to copy comments following the string // "foo" /* comment */ + "bar" /* comment */ + "bar2" -const copyCommentFromMultiNode = (nodes: readonly ts.Expression[], file: ts.SourceFile, copyOperatorComments: (index: number, targetNode: ts.Node) => void) => -(indexes: number[], targetNode: ts.Node) => { +const copyCommentFromMultiNode = (nodes: readonly Expression[], file: SourceFile, copyOperatorComments: (index: number, targetNode: Node) => void) => +(indexes: number[], targetNode: Node) => { while (indexes.length > 0) { const index = indexes.shift()!; - ts.copyTrailingComments(nodes[index], targetNode, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyTrailingComments(nodes[index], targetNode, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); copyOperatorComments(index, targetNode); } }; @@ -157,24 +165,24 @@ function escapeRawStringForTemplate(s: string) { // but `\$${foo}` is likely more clear than the more-confusing-but-still-working `$${foo}`. } -function getRawTextOfTemplate(node: ts.TemplateHead | ts.TemplateMiddle | ts.TemplateTail) { +function getRawTextOfTemplate(node: TemplateHead | TemplateMiddle | TemplateTail) { // in these cases the right side is ${ - const rightShaving = ts.isTemplateHead(node) || ts.isTemplateMiddle(node) ? -2 : -1; - return ts.getTextOfNode(node).slice(1, rightShaving); + const rightShaving = isTemplateHead(node) || isTemplateMiddle(node) ? -2 : -1; + return getTextOfNode(node).slice(1, rightShaving); } -function concatConsecutiveString(index: number, nodes: readonly ts.Expression[]): [nextIndex: number, text: string, rawText: string, usedIndexes: number[]] { +function concatConsecutiveString(index: number, nodes: readonly Expression[]): [nextIndex: number, text: string, rawText: string, usedIndexes: number[]] { const indexes = []; let text = "", rawText = ""; while (index < nodes.length) { const node = nodes[index]; - if (ts.isStringLiteralLike(node)) { // includes isNoSubstitutionTemplateLiteral(node) + if (isStringLiteralLike(node)) { // includes isNoSubstitutionTemplateLiteral(node) text += node.text; - rawText += escapeRawStringForTemplate(ts.getTextOfNode(node).slice(1, -1)); + rawText += escapeRawStringForTemplate(getTextOfNode(node).slice(1, -1)); indexes.push(index); index++; } - else if (ts.isTemplateExpression(node)) { + else if (isTemplateExpression(node)) { text += node.head.text; rawText += getRawTextOfTemplate(node.head); break; @@ -186,19 +194,19 @@ function concatConsecutiveString(index: number, nodes: readonly ts.Expression[]) return [index, text, rawText, indexes]; } -function nodesToTemplate({ nodes, operators }: { nodes: readonly ts.Expression[], operators: ts.Token[] }, file: ts.SourceFile) { +function nodesToTemplate({ nodes, operators }: { nodes: readonly Expression[], operators: Token[] }, file: SourceFile) { const copyOperatorComments = copyTrailingOperatorComments(operators, file); const copyCommentFromStringLiterals = copyCommentFromMultiNode(nodes, file, copyOperatorComments); const [begin, headText, rawHeadText, headIndexes] = concatConsecutiveString(0, nodes); if (begin === nodes.length) { - const noSubstitutionTemplateLiteral = ts.factory.createNoSubstitutionTemplateLiteral(headText, rawHeadText); + const noSubstitutionTemplateLiteral = factory.createNoSubstitutionTemplateLiteral(headText, rawHeadText); copyCommentFromStringLiterals(headIndexes, noSubstitutionTemplateLiteral); return noSubstitutionTemplateLiteral; } - const templateSpans: ts.TemplateSpan[] = []; - const templateHead = ts.factory.createTemplateHead(headText, rawHeadText); + const templateSpans: TemplateSpan[] = []; + const templateHead = factory.createTemplateHead(headText, rawHeadText); copyCommentFromStringLiterals(headIndexes, templateHead); for (let i = begin; i < nodes.length; i++) { @@ -209,40 +217,40 @@ function nodesToTemplate({ nodes, operators }: { nodes: readonly ts.Expression[] i = newIndex - 1; const isLast = i === nodes.length - 1; - if (ts.isTemplateExpression(currentNode)) { - const spans = ts.map(currentNode.templateSpans, (span, index) => { + if (isTemplateExpression(currentNode)) { + const spans = map(currentNode.templateSpans, (span, index) => { copyExpressionComments(span); const isLastSpan = index === currentNode.templateSpans.length - 1; const text = span.literal.text + (isLastSpan ? subsequentText : ""); const rawText = getRawTextOfTemplate(span.literal) + (isLastSpan ? rawSubsequentText : ""); - return ts.factory.createTemplateSpan(span.expression, isLast && isLastSpan - ? ts.factory.createTemplateTail(text, rawText) - : ts.factory.createTemplateMiddle(text, rawText)); + return factory.createTemplateSpan(span.expression, isLast && isLastSpan + ? factory.createTemplateTail(text, rawText) + : factory.createTemplateMiddle(text, rawText)); }); templateSpans.push(...spans); } else { const templatePart = isLast - ? ts.factory.createTemplateTail(subsequentText, rawSubsequentText) - : ts.factory.createTemplateMiddle(subsequentText, rawSubsequentText); + ? factory.createTemplateTail(subsequentText, rawSubsequentText) + : factory.createTemplateMiddle(subsequentText, rawSubsequentText); copyCommentFromStringLiterals(stringIndexes, templatePart); - templateSpans.push(ts.factory.createTemplateSpan(currentNode, templatePart)); + templateSpans.push(factory.createTemplateSpan(currentNode, templatePart)); } } - return ts.factory.createTemplateExpression(templateHead, templateSpans); + return factory.createTemplateExpression(templateHead, templateSpans); } // to copy comments following the opening & closing parentheses // "foo" + ( /* comment */ 5 + 5 ) /* comment */ + "bar" -function copyExpressionComments(node: ts.ParenthesizedExpression | ts.TemplateSpan) { +function copyExpressionComments(node: ParenthesizedExpression | TemplateSpan) { const file = node.getSourceFile(); - ts.copyTrailingComments(node, node.expression, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); - ts.copyTrailingAsLeadingComments(node.expression, node.expression, file, ts.SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyTrailingComments(node, node.expression, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); + copyTrailingAsLeadingComments(node.expression, node.expression, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false); } -function getExpressionFromParenthesesOrExpression(node: ts.Expression) { - if (ts.isParenthesizedExpression(node)) { +function getExpressionFromParenthesesOrExpression(node: Expression) { + if (isParenthesizedExpression(node)) { copyExpressionComments(node); node = node.expression; } diff --git a/src/services/refactors/convertToOptionalChainExpression.ts b/src/services/refactors/convertToOptionalChainExpression.ts index 4845367702010..5c8153ef5f876 100644 --- a/src/services/refactors/convertToOptionalChainExpression.ts +++ b/src/services/refactors/convertToOptionalChainExpression.ts @@ -1,24 +1,34 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, BinaryExpression, CallExpression, ConditionalExpression, createTextSpanFromBounds, Debug, + Diagnostics, ElementAccessExpression, emptyArray, Expression, ExpressionStatement, factory, + findTokenOnLeftOfPosition, getLocaleSpecificMessage, getRefactorContextSpan, getSingleVariableOfVariableStatement, + getTokenAtPosition, Identifier, isBinaryExpression, isCallExpression, isConditionalExpression, + isElementAccessExpression, isExpressionStatement, isIdentifier, isOptionalChain, isPropertyAccessExpression, + isReturnStatement, isStringOrNumericLiteralLike, isVariableStatement, Node, PropertyAccessExpression, + RefactorContext, RefactorEditInfo, ReturnStatement, skipParentheses, SourceFile, SyntaxKind, textChanges, TextSpan, + TypeChecker, VariableStatement, +} from "../_namespaces/ts"; +import { isRefactorErrorInfo, RefactorErrorInfo, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Convert to optional chain expression"; -const convertToOptionalChainExpressionMessage = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_optional_chain_expression); +const convertToOptionalChainExpressionMessage = getLocaleSpecificMessage(Diagnostics.Convert_to_optional_chain_expression); const toOptionalChainAction = { name: refactorName, description: convertToOptionalChainExpressionMessage, kind: "refactor.rewrite.expression.optionalChain", }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [toOptionalChainAction.kind], getEditsForAction: getRefactorEditsToConvertToOptionalChain, getAvailableActions: getRefactorActionsToConvertToOptionalChain, }); -function getRefactorActionsToConvertToOptionalChain(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToConvertToOptionalChain(context: RefactorContext): readonly ApplicableRefactorInfo[] { const info = getInfo(context, context.triggerReason === "invoked"); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { return [{ name: refactorName, description: convertToOptionalChainExpressionMessage, @@ -33,22 +43,22 @@ function getRefactorActionsToConvertToOptionalChain(context: ts.RefactorContext) actions: [{ ...toOptionalChainAction, notApplicableReason: info.error }], }]; } - return ts.emptyArray; + return emptyArray; } -function getRefactorEditsToConvertToOptionalChain(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { +function getRefactorEditsToConvertToOptionalChain(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { const info = getInfo(context); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = ts.textChanges.ChangeTracker.with(context, t => + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); + const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program.getTypeChecker(), t, info, actionName) ); return { edits, renameFilename: undefined, renameLocation: undefined }; } -type Occurrence = ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.Identifier; +type Occurrence = PropertyAccessExpression | ElementAccessExpression | Identifier; interface OptionalChainInfo { - finalExpression: ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.CallExpression, + finalExpression: PropertyAccessExpression | ElementAccessExpression | CallExpression, occurrences: Occurrence[], expression: ValidExpression, } @@ -58,84 +68,84 @@ type ValidExpressionOrStatement = ValidExpression | ValidStatement; /** * Types for which a "Convert to optional chain refactor" are offered. */ -type ValidExpression = ts.BinaryExpression | ts.ConditionalExpression; +type ValidExpression = BinaryExpression | ConditionalExpression; /** * Types of statements which are likely to include a valid expression for extraction. */ -type ValidStatement = ts.ExpressionStatement | ts.ReturnStatement | ts.VariableStatement; +type ValidStatement = ExpressionStatement | ReturnStatement | VariableStatement; -function isValidExpression(node: ts.Node): node is ValidExpression { - return ts.isBinaryExpression(node) || ts.isConditionalExpression(node); +function isValidExpression(node: Node): node is ValidExpression { + return isBinaryExpression(node) || isConditionalExpression(node); } -function isValidStatement(node: ts.Node): node is ValidStatement { - return ts.isExpressionStatement(node) || ts.isReturnStatement(node) || ts.isVariableStatement(node); +function isValidStatement(node: Node): node is ValidStatement { + return isExpressionStatement(node) || isReturnStatement(node) || isVariableStatement(node); } -function isValidExpressionOrStatement(node: ts.Node): node is ValidExpressionOrStatement { +function isValidExpressionOrStatement(node: Node): node is ValidExpressionOrStatement { return isValidExpression(node) || isValidStatement(node); } -function getInfo(context: ts.RefactorContext, considerEmptySpans = true): OptionalChainInfo | ts.refactor.RefactorErrorInfo | undefined { +function getInfo(context: RefactorContext, considerEmptySpans = true): OptionalChainInfo | RefactorErrorInfo | undefined { const { file, program } = context; - const span = ts.getRefactorContextSpan(context); + const span = getRefactorContextSpan(context); const forEmptySpan = span.length === 0; if (forEmptySpan && !considerEmptySpans) return undefined; // selecting fo[|o && foo.ba|]r should be valid, so adjust span to fit start and end tokens - const startToken = ts.getTokenAtPosition(file, span.start); - const endToken = ts.findTokenOnLeftOfPosition(file, span.start + span.length); - const adjustedSpan = ts.createTextSpanFromBounds(startToken.pos, endToken && endToken.end >= startToken.pos ? endToken.getEnd() : startToken.getEnd()); + const startToken = getTokenAtPosition(file, span.start); + const endToken = findTokenOnLeftOfPosition(file, span.start + span.length); + const adjustedSpan = createTextSpanFromBounds(startToken.pos, endToken && endToken.end >= startToken.pos ? endToken.getEnd() : startToken.getEnd()); const parent = forEmptySpan ? getValidParentNodeOfEmptySpan(startToken) : getValidParentNodeContainingSpan(startToken, adjustedSpan); const expression = parent && isValidExpressionOrStatement(parent) ? getExpression(parent) : undefined; - if (!expression) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; + if (!expression) return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; const checker = program.getTypeChecker(); - return ts.isConditionalExpression(expression) ? getConditionalInfo(expression, checker) : getBinaryInfo(expression); + return isConditionalExpression(expression) ? getConditionalInfo(expression, checker) : getBinaryInfo(expression); } -function getConditionalInfo(expression: ts.ConditionalExpression, checker: ts.TypeChecker): OptionalChainInfo | ts.refactor.RefactorErrorInfo | undefined { +function getConditionalInfo(expression: ConditionalExpression, checker: TypeChecker): OptionalChainInfo | RefactorErrorInfo | undefined { const condition = expression.condition; const finalExpression = getFinalExpressionInChain(expression.whenTrue); if (!finalExpression || checker.isNullableType(checker.getTypeAtLocation(finalExpression))) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; } - if ((ts.isPropertyAccessExpression(condition) || ts.isIdentifier(condition)) + if ((isPropertyAccessExpression(condition) || isIdentifier(condition)) && getMatchingStart(condition, finalExpression.expression)) { return { finalExpression, occurrences: [condition], expression }; } - else if (ts.isBinaryExpression(condition)) { + else if (isBinaryExpression(condition)) { const occurrences = getOccurrencesInExpression(finalExpression.expression, condition); return occurrences ? { finalExpression, occurrences, expression } : - { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_matching_access_expressions) }; + { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; } } -function getBinaryInfo(expression: ts.BinaryExpression): OptionalChainInfo | ts.refactor.RefactorErrorInfo | undefined { - if (expression.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Can_only_convert_logical_AND_access_chains) }; +function getBinaryInfo(expression: BinaryExpression): OptionalChainInfo | RefactorErrorInfo | undefined { + if (expression.operatorToken.kind !== SyntaxKind.AmpersandAmpersandToken) { + return { error: getLocaleSpecificMessage(Diagnostics.Can_only_convert_logical_AND_access_chains) }; } const finalExpression = getFinalExpressionInChain(expression.right); - if (!finalExpression) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_convertible_access_expression) }; + if (!finalExpression) return { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_convertible_access_expression) }; const occurrences = getOccurrencesInExpression(finalExpression.expression, expression.left); return occurrences ? { finalExpression, occurrences, expression } : - { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_find_matching_access_expressions) }; + { error: getLocaleSpecificMessage(Diagnostics.Could_not_find_matching_access_expressions) }; } /** * Gets a list of property accesses that appear in matchTo and occur in sequence in expression. */ -function getOccurrencesInExpression(matchTo: ts.Expression, expression: ts.Expression): Occurrence[] | undefined { +function getOccurrencesInExpression(matchTo: Expression, expression: Expression): Occurrence[] | undefined { const occurrences: Occurrence[] = []; - while (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) { - const match = getMatchingStart(ts.skipParentheses(matchTo), ts.skipParentheses(expression.right)); + while (isBinaryExpression(expression) && expression.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) { + const match = getMatchingStart(skipParentheses(matchTo), skipParentheses(expression.right)); if (!match) { break; } @@ -153,8 +163,8 @@ function getOccurrencesInExpression(matchTo: ts.Expression, expression: ts.Expre /** * Returns subchain if chain begins with subchain syntactically. */ -function getMatchingStart(chain: ts.Expression, subchain: ts.Expression): ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.Identifier | undefined { - if (!ts.isIdentifier(subchain) && !ts.isPropertyAccessExpression(subchain) && !ts.isElementAccessExpression(subchain)) { +function getMatchingStart(chain: Expression, subchain: Expression): PropertyAccessExpression | ElementAccessExpression | Identifier | undefined { + if (!isIdentifier(subchain) && !isPropertyAccessExpression(subchain) && !isElementAccessExpression(subchain)) { return undefined; } return chainStartsWith(chain, subchain) ? subchain : undefined; @@ -163,31 +173,31 @@ function getMatchingStart(chain: ts.Expression, subchain: ts.Expression): ts.Pro /** * Returns true if chain begins with subchain syntactically. */ -function chainStartsWith(chain: ts.Node, subchain: ts.Node): boolean { +function chainStartsWith(chain: Node, subchain: Node): boolean { // skip until we find a matching identifier. - while (ts.isCallExpression(chain) || ts.isPropertyAccessExpression(chain) || ts.isElementAccessExpression(chain)) { + while (isCallExpression(chain) || isPropertyAccessExpression(chain) || isElementAccessExpression(chain)) { if (getTextOfChainNode(chain) === getTextOfChainNode(subchain)) break; chain = chain.expression; } // check that the chains match at each access. Call chains in subchain are not valid. - while ((ts.isPropertyAccessExpression(chain) && ts.isPropertyAccessExpression(subchain)) || - (ts.isElementAccessExpression(chain) && ts.isElementAccessExpression(subchain))) { + while ((isPropertyAccessExpression(chain) && isPropertyAccessExpression(subchain)) || + (isElementAccessExpression(chain) && isElementAccessExpression(subchain))) { if (getTextOfChainNode(chain) !== getTextOfChainNode(subchain)) return false; chain = chain.expression; subchain = subchain.expression; } // check if we have reached a final identifier. - return ts.isIdentifier(chain) && ts.isIdentifier(subchain) && chain.getText() === subchain.getText(); + return isIdentifier(chain) && isIdentifier(subchain) && chain.getText() === subchain.getText(); } -function getTextOfChainNode(node: ts.Node): string | undefined { - if (ts.isIdentifier(node) || ts.isStringOrNumericLiteralLike(node)) { +function getTextOfChainNode(node: Node): string | undefined { + if (isIdentifier(node) || isStringOrNumericLiteralLike(node)) { return node.getText(); } - if (ts.isPropertyAccessExpression(node)) { + if (isPropertyAccessExpression(node)) { return getTextOfChainNode(node.name); } - if (ts.isElementAccessExpression(node)) { + if (isElementAccessExpression(node)) { return getTextOfChainNode(node.argumentExpression); } return undefined; @@ -196,7 +206,7 @@ function getTextOfChainNode(node: ts.Node): string | undefined { /** * Find the least ancestor of the input node that is a valid type for extraction and contains the input span. */ -function getValidParentNodeContainingSpan(node: ts.Node, span: ts.TextSpan): ValidExpressionOrStatement | undefined { +function getValidParentNodeContainingSpan(node: Node, span: TextSpan): ValidExpressionOrStatement | undefined { while (node.parent) { if (isValidExpressionOrStatement(node) && span.length !== 0 && node.end >= span.start + span.length) { return node; @@ -209,7 +219,7 @@ function getValidParentNodeContainingSpan(node: ts.Node, span: ts.TextSpan): Val /** * Finds an ancestor of the input node that is a valid type for extraction, skipping subexpressions. */ -function getValidParentNodeOfEmptySpan(node: ts.Node): ValidExpressionOrStatement | undefined { +function getValidParentNodeOfEmptySpan(node: Node): ValidExpressionOrStatement | undefined { while (node.parent) { if (isValidExpressionOrStatement(node) && !isValidExpressionOrStatement(node.parent)) { return node; @@ -226,8 +236,8 @@ function getExpression(node: ValidExpressionOrStatement): ValidExpression | unde if (isValidExpression(node)) { return node; } - if (ts.isVariableStatement(node)) { - const variable = ts.getSingleVariableOfVariableStatement(node); + if (isVariableStatement(node)) { + const variable = getSingleVariableOfVariableStatement(node); const initializer = variable?.initializer; return initializer && isValidExpression(initializer) ? initializer : undefined; } @@ -240,15 +250,15 @@ function getExpression(node: ValidExpressionOrStatement): ValidExpression | unde * it is followed by a different binary operator. * @param node the right child of a binary expression or a call expression. */ -function getFinalExpressionInChain(node: ts.Expression): ts.CallExpression | ts.PropertyAccessExpression | ts.ElementAccessExpression | undefined { +function getFinalExpressionInChain(node: Expression): CallExpression | PropertyAccessExpression | ElementAccessExpression | undefined { // foo && |foo.bar === 1|; - here the right child of the && binary expression is another binary expression. // the rightmost member of the && chain should be the leftmost child of that expression. - node = ts.skipParentheses(node); - if (ts.isBinaryExpression(node)) { + node = skipParentheses(node); + if (isBinaryExpression(node)) { return getFinalExpressionInChain(node.left); } // foo && |foo.bar()()| - nested calls are treated like further accesses. - else if ((ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node) || ts.isCallExpression(node)) && !ts.isOptionalChain(node)) { + else if ((isPropertyAccessExpression(node) || isElementAccessExpression(node) || isCallExpression(node)) && !isOptionalChain(node)) { return node; } return undefined; @@ -257,42 +267,42 @@ function getFinalExpressionInChain(node: ts.Expression): ts.CallExpression | ts. /** * Creates an access chain from toConvert with '?.' accesses at expressions appearing in occurrences. */ -function convertOccurrences(checker: ts.TypeChecker, toConvert: ts.Expression, occurrences: Occurrence[]): ts.Expression { - if (ts.isPropertyAccessExpression(toConvert) || ts.isElementAccessExpression(toConvert) || ts.isCallExpression(toConvert)) { +function convertOccurrences(checker: TypeChecker, toConvert: Expression, occurrences: Occurrence[]): Expression { + if (isPropertyAccessExpression(toConvert) || isElementAccessExpression(toConvert) || isCallExpression(toConvert)) { const chain = convertOccurrences(checker, toConvert.expression, occurrences); const lastOccurrence = occurrences.length > 0 ? occurrences[occurrences.length - 1] : undefined; const isOccurrence = lastOccurrence?.getText() === toConvert.expression.getText(); if (isOccurrence) occurrences.pop(); - if (ts.isCallExpression(toConvert)) { + if (isCallExpression(toConvert)) { return isOccurrence ? - ts.factory.createCallChain(chain, ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), toConvert.typeArguments, toConvert.arguments) : - ts.factory.createCallChain(chain, toConvert.questionDotToken, toConvert.typeArguments, toConvert.arguments); + factory.createCallChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.typeArguments, toConvert.arguments) : + factory.createCallChain(chain, toConvert.questionDotToken, toConvert.typeArguments, toConvert.arguments); } - else if (ts.isPropertyAccessExpression(toConvert)) { + else if (isPropertyAccessExpression(toConvert)) { return isOccurrence ? - ts.factory.createPropertyAccessChain(chain, ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), toConvert.name) : - ts.factory.createPropertyAccessChain(chain, toConvert.questionDotToken, toConvert.name); + factory.createPropertyAccessChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.name) : + factory.createPropertyAccessChain(chain, toConvert.questionDotToken, toConvert.name); } - else if (ts.isElementAccessExpression(toConvert)) { + else if (isElementAccessExpression(toConvert)) { return isOccurrence ? - ts.factory.createElementAccessChain(chain, ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), toConvert.argumentExpression) : - ts.factory.createElementAccessChain(chain, toConvert.questionDotToken, toConvert.argumentExpression); + factory.createElementAccessChain(chain, factory.createToken(SyntaxKind.QuestionDotToken), toConvert.argumentExpression) : + factory.createElementAccessChain(chain, toConvert.questionDotToken, toConvert.argumentExpression); } } return toConvert; } -function doChange(sourceFile: ts.SourceFile, checker: ts.TypeChecker, changes: ts.textChanges.ChangeTracker, info: OptionalChainInfo, _actionName: string): void { +function doChange(sourceFile: SourceFile, checker: TypeChecker, changes: textChanges.ChangeTracker, info: OptionalChainInfo, _actionName: string): void { const { finalExpression, occurrences, expression } = info; const firstOccurrence = occurrences[occurrences.length - 1]; const convertedChain = convertOccurrences(checker, finalExpression, occurrences); - if (convertedChain && (ts.isPropertyAccessExpression(convertedChain) || ts.isElementAccessExpression(convertedChain) || ts.isCallExpression(convertedChain))) { - if (ts.isBinaryExpression(expression)) { + if (convertedChain && (isPropertyAccessExpression(convertedChain) || isElementAccessExpression(convertedChain) || isCallExpression(convertedChain))) { + if (isBinaryExpression(expression)) { changes.replaceNodeRange(sourceFile, firstOccurrence, finalExpression, convertedChain); } - else if (ts.isConditionalExpression(expression)) { + else if (isConditionalExpression(expression)) { changes.replaceNode(sourceFile, expression, - ts.factory.createBinaryExpression(convertedChain, ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), expression.whenFalse) + factory.createBinaryExpression(convertedChain, factory.createToken(SyntaxKind.QuestionQuestionToken), expression.whenFalse) ); } } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 4470114e796bf..5658571535987 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -1,18 +1,46 @@ -import * as ts from "../_namespaces/ts"; +import { + __String, ANONYMOUS, ApplicableRefactorInfo, arrayFrom, assertType, BindingElement, Block, BlockLike, + BreakStatement, CancellationToken, canHaveModifiers, CharacterCodes, ClassElement, ClassLikeDeclaration, codefix, + compareProperties, compareStringsCaseSensitive, compareValues, contains, ContinueStatement, createDiagnosticForNode, + createFileDiagnostic, Debug, Declaration, Diagnostic, DiagnosticCategory, DiagnosticMessage, Diagnostics, EmitFlags, + emptyArray, EntityName, ESMap, Expression, ExpressionStatement, factory, find, findAncestor, + findFirstNonJsxWhitespaceToken, findTokenOnLeftOfPosition, first, firstOrUndefined, forEachChild, + formatStringFromArgs, FunctionDeclaration, FunctionLikeDeclaration, getContainingClass, getContainingFunction, + getEffectiveTypeParameterDeclarations, getEmitScriptTarget, getEnclosingBlockScopeContainer, + getLocaleSpecificMessage, getModifiers, getNodeId, getParentNodeInSpan, getRefactorContextSpan, getRenameLocation, + getSymbolId, getSynthesizedDeepClone, getThisContainer, getUniqueName, hasEffectiveModifier, hasSyntacticModifier, + Identifier, isArray, isArrowFunction, isAssignmentExpression, isBinaryExpression, isBlock, isBlockScope, + isCaseClause, isClassLike, isConstructorDeclaration, isDeclaration, isDeclarationWithTypeParameters, + isElementAccessExpression, isExpression, isExpressionNode, isExpressionStatement, isFunctionBody, + isFunctionExpression, isFunctionLike, isFunctionLikeDeclaration, isIdentifier, isInJSFile, isIterationStatement, + isJsxAttribute, isJsxElement, isJsxFragment, isJsxSelfClosingElement, isKeyword, isModuleBlock, + isParenthesizedTypeNode, isPartOfTypeNode, isPrivateIdentifier, isPropertyAccessExpression, isPropertyDeclaration, + isQualifiedName, isReturnStatement, isShorthandPropertyAssignment, isSourceFile, isStatement, isStatic, + isStringLiteral, isSwitchStatement, isThis, isUnaryExpressionWithWrite, isUnionTypeNode, isVariableDeclaration, + isVariableDeclarationList, isVariableStatement, LabeledStatement, last, map, Map, MethodDeclaration, Modifier, + ModifierFlags, ModuleBlock, NamedDeclaration, Node, NodeBuilderFlags, NodeFlags, nullTransformationContext, + ObjectLiteralElementLike, ParameterDeclaration, positionIsSynthesized, PropertyAccessExpression, + rangeContainsStartEnd, ReadonlyESMap, RefactorActionInfo, RefactorContext, RefactorEditInfo, setEmitFlags, + ShorthandPropertyAssignment, SignatureKind, singleOrUndefined, skipParentheses, SourceFile, Statement, + StringLiteral, suppressLeadingAndTrailingTrivia, Symbol, SymbolFlags, SyntaxKind, textChanges, TextRange, TextSpan, + textSpanEnd, TryStatement, Type, TypeChecker, TypeElement, TypeFlags, TypeLiteralNode, TypeNode, TypeParameter, + TypeParameterDeclaration, VariableDeclaration, visitEachChild, visitNode, visitNodes, VisitResult, +} from "../_namespaces/ts"; +import { refactorKindBeginsWith, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Extract Symbol"; const extractConstantAction = { name: "Extract Constant", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), + description: getLocaleSpecificMessage(Diagnostics.Extract_constant), kind: "refactor.extract.constant", }; const extractFunctionAction = { name: "Extract Function", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), + description: getLocaleSpecificMessage(Diagnostics.Extract_function), kind: "refactor.extract.function", }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [ extractConstantAction.kind, extractFunctionAction.kind @@ -26,25 +54,25 @@ ts.refactor.registerRefactor(refactorName, { * Compute the associated code actions * Exported for tests. */ -export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +export function getRefactorActionsToExtractSymbol(context: RefactorContext): readonly ApplicableRefactorInfo[] { const requestedRefactor = context.kind; - const rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context), context.triggerReason === "invoked"); + const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context), context.triggerReason === "invoked"); const targetRange = rangeToExtract.targetRange; if (targetRange === undefined) { if (!rangeToExtract.errors || rangeToExtract.errors.length === 0 || !context.preferences.provideRefactorNotApplicableReason) { - return ts.emptyArray; + return emptyArray; } const errors = []; - if (ts.refactor.refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { errors.push({ name: refactorName, description: extractFunctionAction.description, actions: [{ ...extractFunctionAction, notApplicableReason: getStringError(rangeToExtract.errors) }] }); } - if (ts.refactor.refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { errors.push({ name: refactorName, description: extractConstantAction.description, @@ -57,20 +85,20 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): const extractions = getPossibleExtractions(targetRange, context); if (extractions === undefined) { // No extractions possible - return ts.emptyArray; + return emptyArray; } - const functionActions: ts.RefactorActionInfo[] = []; - const usedFunctionNames = new ts.Map(); - let innermostErrorFunctionAction: ts.RefactorActionInfo | undefined; + const functionActions: RefactorActionInfo[] = []; + const usedFunctionNames = new Map(); + let innermostErrorFunctionAction: RefactorActionInfo | undefined; - const constantActions: ts.RefactorActionInfo[] = []; - const usedConstantNames = new ts.Map(); - let innermostErrorConstantAction: ts.RefactorActionInfo | undefined; + const constantActions: RefactorActionInfo[] = []; + const usedConstantNames = new Map(); + let innermostErrorConstantAction: RefactorActionInfo | undefined; let i = 0; for (const { functionExtraction, constantExtraction } of extractions) { - if (ts.refactor.refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractFunctionAction.kind, requestedRefactor)) { const description = functionExtraction.description; if (functionExtraction.errors.length === 0) { // Don't issue refactorings with duplicated names. @@ -95,7 +123,7 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): } } - if (ts.refactor.refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { + if (refactorKindBeginsWith(extractConstantAction.kind, requestedRefactor)) { const description = constantExtraction.description; if (constantExtraction.errors.length === 0) { // Don't issue refactorings with duplicated names. @@ -125,19 +153,19 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): i++; } - const infos: ts.ApplicableRefactorInfo[] = []; + const infos: ApplicableRefactorInfo[] = []; if (functionActions.length) { infos.push({ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), + description: getLocaleSpecificMessage(Diagnostics.Extract_function), actions: functionActions, }); } else if (context.preferences.provideRefactorNotApplicableReason && innermostErrorFunctionAction) { infos.push({ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function), + description: getLocaleSpecificMessage(Diagnostics.Extract_function), actions: [ innermostErrorFunctionAction ] }); } @@ -145,21 +173,21 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): if (constantActions.length) { infos.push({ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), + description: getLocaleSpecificMessage(Diagnostics.Extract_constant), actions: constantActions }); } else if (context.preferences.provideRefactorNotApplicableReason && innermostErrorConstantAction) { infos.push({ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant), + description: getLocaleSpecificMessage(Diagnostics.Extract_constant), actions: [ innermostErrorConstantAction ] }); } - return infos.length ? infos : ts.emptyArray; + return infos.length ? infos : emptyArray; - function getStringError(errors: readonly ts.Diagnostic[]) { + function getStringError(errors: readonly Diagnostic[]) { let error = errors[0].messageText; if (typeof error !== "string") { error = error.messageText; @@ -170,46 +198,46 @@ export function getRefactorActionsToExtractSymbol(context: ts.RefactorContext): /* Exported for tests */ /** @internal */ -export function getRefactorEditsToExtractSymbol(context: ts.RefactorContext, actionName: string): ts.RefactorEditInfo | undefined { - const rangeToExtract = getRangeToExtract(context.file, ts.getRefactorContextSpan(context)); +export function getRefactorEditsToExtractSymbol(context: RefactorContext, actionName: string): RefactorEditInfo | undefined { + const rangeToExtract = getRangeToExtract(context.file, getRefactorContextSpan(context)); const targetRange = rangeToExtract.targetRange!; // TODO:GH#18217 const parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName); if (parsedFunctionIndexMatch) { const index = +parsedFunctionIndexMatch[1]; - ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the function scope index"); + Debug.assert(isFinite(index), "Expected to parse a finite number from the function scope index"); return getFunctionExtractionAtIndex(targetRange, context, index); } const parsedConstantIndexMatch = /^constant_scope_(\d+)$/.exec(actionName); if (parsedConstantIndexMatch) { const index = +parsedConstantIndexMatch[1]; - ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the constant scope index"); + Debug.assert(isFinite(index), "Expected to parse a finite number from the constant scope index"); return getConstantExtractionAtIndex(targetRange, context, index); } - ts.Debug.fail("Unrecognized action name"); + Debug.fail("Unrecognized action name"); } // Move these into diagnostic messages if they become user-facing /** @internal */ export namespace Messages { - function createMessage(message: string): ts.DiagnosticMessage { - return { message, code: 0, category: ts.DiagnosticCategory.Message, key: message }; - } - - export const cannotExtractRange: ts.DiagnosticMessage = createMessage("Cannot extract range."); - export const cannotExtractImport: ts.DiagnosticMessage = createMessage("Cannot extract import statement."); - export const cannotExtractSuper: ts.DiagnosticMessage = createMessage("Cannot extract super call."); - export const cannotExtractJSDoc: ts.DiagnosticMessage = createMessage("Cannot extract JSDoc."); - export const cannotExtractEmpty: ts.DiagnosticMessage = createMessage("Cannot extract empty range."); - export const expressionExpected: ts.DiagnosticMessage = createMessage("expression expected."); - export const uselessConstantType: ts.DiagnosticMessage = createMessage("No reason to extract constant of type."); - export const statementOrExpressionExpected: ts.DiagnosticMessage = createMessage("Statement or expression expected."); - export const cannotExtractRangeContainingConditionalBreakOrContinueStatements: ts.DiagnosticMessage = createMessage("Cannot extract range containing conditional break or continue statements."); - export const cannotExtractRangeContainingConditionalReturnStatement: ts.DiagnosticMessage = createMessage("Cannot extract range containing conditional return statement."); - export const cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange: ts.DiagnosticMessage = createMessage("Cannot extract range containing labeled break or continue with target outside of the range."); - export const cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: ts.DiagnosticMessage = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); + function createMessage(message: string): DiagnosticMessage { + return { message, code: 0, category: DiagnosticCategory.Message, key: message }; + } + + export const cannotExtractRange: DiagnosticMessage = createMessage("Cannot extract range."); + export const cannotExtractImport: DiagnosticMessage = createMessage("Cannot extract import statement."); + export const cannotExtractSuper: DiagnosticMessage = createMessage("Cannot extract super call."); + export const cannotExtractJSDoc: DiagnosticMessage = createMessage("Cannot extract JSDoc."); + export const cannotExtractEmpty: DiagnosticMessage = createMessage("Cannot extract empty range."); + export const expressionExpected: DiagnosticMessage = createMessage("expression expected."); + export const uselessConstantType: DiagnosticMessage = createMessage("No reason to extract constant of type."); + export const statementOrExpressionExpected: DiagnosticMessage = createMessage("Statement or expression expected."); + export const cannotExtractRangeContainingConditionalBreakOrContinueStatements: DiagnosticMessage = createMessage("Cannot extract range containing conditional break or continue statements."); + export const cannotExtractRangeContainingConditionalReturnStatement: DiagnosticMessage = createMessage("Cannot extract range containing conditional return statement."); + export const cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange: DiagnosticMessage = createMessage("Cannot extract range containing labeled break or continue with target outside of the range."); + export const cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators: DiagnosticMessage = createMessage("Cannot extract range containing writes to references located outside of the target range in generators."); export const typeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope."); export const functionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope."); export const cannotExtractIdentifier = createMessage("Select more than a single identifier."); @@ -240,12 +268,12 @@ enum RangeFacts { * Represents an expression or a list of statements that should be extracted with some extra information */ interface TargetRange { - readonly range: ts.Expression | ts.Statement[]; + readonly range: Expression | Statement[]; readonly facts: RangeFacts; /** * If `this` is referring to a function instead of class, we need to retrieve its type. */ - readonly thisNode: ts.Node | undefined; + readonly thisNode: Node | undefined; } /** @@ -253,7 +281,7 @@ interface TargetRange { */ type RangeToExtract = { readonly targetRange?: never; - readonly errors: readonly ts.Diagnostic[]; + readonly errors: readonly Diagnostic[]; } | { readonly targetRange: TargetRange; readonly errors?: never; @@ -262,7 +290,7 @@ type RangeToExtract = { /* * Scopes that can store newly extracted method */ -type Scope = ts.FunctionLikeDeclaration | ts.SourceFile | ts.ModuleBlock | ts.ClassLikeDeclaration; +type Scope = FunctionLikeDeclaration | SourceFile | ModuleBlock | ClassLikeDeclaration; /** @internal */ /** @@ -272,15 +300,15 @@ type Scope = ts.FunctionLikeDeclaration | ts.SourceFile | ts.ModuleBlock | ts.Cl * users if they have the provideRefactorNotApplicableReason option set. */ // exported only for tests -export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, invoked = true): RangeToExtract { +export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoked = true): RangeToExtract { const { length } = span; if (length === 0 && !invoked) { - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] }; } const cursorRequest = length === 0 && invoked; - const startToken = ts.findFirstNonJsxWhitespaceToken(sourceFile, span.start); - const endToken = ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)); + const startToken = findFirstNonJsxWhitespaceToken(sourceFile, span.start); + const endToken = findTokenOnLeftOfPosition(sourceFile, textSpanEnd(span)); /* If the refactoring command is invoked through a keyboard action it's safe to assume that the user is actively looking for refactoring actions at the span location. As they may not know the exact range that will trigger a refactoring, we expand the searched span to cover a real node range making it more likely that something useful will show up. */ @@ -288,37 +316,37 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span. // This may fail (e.g. you select two statements in the root of a source file) - const start = cursorRequest ? getExtractableParent(startToken) : ts.getParentNodeInSpan(startToken, sourceFile, adjustedSpan); + const start = cursorRequest ? getExtractableParent(startToken) : getParentNodeInSpan(startToken, sourceFile, adjustedSpan); // Do the same for the ending position - const end = cursorRequest ? start : ts.getParentNodeInSpan(endToken, sourceFile, adjustedSpan); + const end = cursorRequest ? start : getParentNodeInSpan(endToken, sourceFile, adjustedSpan); // We'll modify these flags as we walk the tree to collect data // about what things need to be done as part of the extraction. let rangeFacts = RangeFacts.None; - let thisNode: ts.Node | undefined; + let thisNode: Node | undefined; if (!start || !end) { // cannot find either start or end node - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } - if (start.flags & ts.NodeFlags.JSDoc) { - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractJSDoc)] }; + if (start.flags & NodeFlags.JSDoc) { + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractJSDoc)] }; } if (start.parent !== end.parent) { // start and end nodes belong to different subtrees - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } if (start !== end) { // start and end should be statements and parent should be either block or a source file if (!isBlockLike(start.parent)) { - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } - const statements: ts.Statement[] = []; + const statements: Statement[] = []; for (const statement of start.parent.statements) { if (statement === start || statements.length) { const errors = checkNode(statement); @@ -338,15 +366,15 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, // they will never find `start` in `start.parent.statements`. // Consider: We could support ranges like [|case 1:|] by refining them to just // the expression. - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } return { targetRange: { range: statements, facts: rangeFacts, thisNode } }; } - if (ts.isReturnStatement(start) && !start.expression) { + if (isReturnStatement(start) && !start.expression) { // Makes no sense to extract an expression-less return statement. - return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + return { errors: [createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; } // We have a single node (start) @@ -362,16 +390,16 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, * Attempt to refine the extraction node (generally, by shrinking it) to produce better results. * @param node The unrefined extraction node. */ - function refineNode(node: ts.Node): ts.Node { - if (ts.isReturnStatement(node)) { + function refineNode(node: Node): Node { + if (isReturnStatement(node)) { if (node.expression) { return node.expression; } } - else if (ts.isVariableStatement(node) || ts.isVariableDeclarationList(node)) { - const declarations = ts.isVariableStatement(node) ? node.declarationList.declarations : node.declarations; + else if (isVariableStatement(node) || isVariableDeclarationList(node)) { + const declarations = isVariableStatement(node) ? node.declarationList.declarations : node.declarations; let numInitializers = 0; - let lastInitializer: ts.Expression | undefined; + let lastInitializer: Expression | undefined; for (const declaration of declarations) { if (declaration.initializer) { numInitializers++; @@ -383,7 +411,7 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, } // No special handling if there are multiple initializers. } - else if (ts.isVariableDeclaration(node)) { + else if (isVariableDeclaration(node)) { if (node.initializer) { return node.initializer; } @@ -391,31 +419,31 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, return node; } - function checkRootNode(node: ts.Node): ts.Diagnostic[] | undefined { - if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) { - return [ts.createDiagnosticForNode(node, Messages.cannotExtractIdentifier)]; + function checkRootNode(node: Node): Diagnostic[] | undefined { + if (isIdentifier(isExpressionStatement(node) ? node.expression : node)) { + return [createDiagnosticForNode(node, Messages.cannotExtractIdentifier)]; } return undefined; } - function checkForStaticContext(nodeToCheck: ts.Node, containingClass: ts.Node) { - let current: ts.Node = nodeToCheck; + function checkForStaticContext(nodeToCheck: Node, containingClass: Node) { + let current: Node = nodeToCheck; while (current !== containingClass) { - if (current.kind === ts.SyntaxKind.PropertyDeclaration) { - if (ts.isStatic(current)) { + if (current.kind === SyntaxKind.PropertyDeclaration) { + if (isStatic(current)) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === ts.SyntaxKind.Parameter) { - const ctorOrMethod = ts.getContainingFunction(current)!; - if (ctorOrMethod.kind === ts.SyntaxKind.Constructor) { + else if (current.kind === SyntaxKind.Parameter) { + const ctorOrMethod = getContainingFunction(current)!; + if (ctorOrMethod.kind === SyntaxKind.Constructor) { rangeFacts |= RangeFacts.InStaticRegion; } break; } - else if (current.kind === ts.SyntaxKind.MethodDeclaration) { - if (ts.isStatic(current)) { + else if (current.kind === SyntaxKind.MethodDeclaration) { + if (isStatic(current)) { rangeFacts |= RangeFacts.InStaticRegion; } } @@ -424,7 +452,7 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, } // Verifies whether we can actually extract this node or not. - function checkNode(nodeToCheck: ts.Node): ts.Diagnostic[] | undefined { + function checkNode(nodeToCheck: Node): Diagnostic[] | undefined { const enum PermittedJumps { None = 0, Break = 1 << 0, @@ -433,37 +461,37 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, } // We believe it's true because the node is from the (unmodified) tree. - ts.Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (1)"); + Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (1)"); // For understanding how skipTrivia functioned: - ts.Debug.assert(!ts.positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (2)"); + Debug.assert(!positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809 (2)"); - if (!ts.isStatement(nodeToCheck) && !(ts.isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck)) && !isStringLiteralJsxAttribute(nodeToCheck)) { - return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; + if (!isStatement(nodeToCheck) && !(isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck)) && !isStringLiteralJsxAttribute(nodeToCheck)) { + return [createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)]; } - if (nodeToCheck.flags & ts.NodeFlags.Ambient) { - return [ts.createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)]; + if (nodeToCheck.flags & NodeFlags.Ambient) { + return [createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)]; } // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default) - const containingClass = ts.getContainingClass(nodeToCheck); + const containingClass = getContainingClass(nodeToCheck); if (containingClass) { checkForStaticContext(nodeToCheck, containingClass); } - let errors: ts.Diagnostic[] | undefined; + let errors: Diagnostic[] | undefined; let permittedJumps = PermittedJumps.Return; - let seenLabels: ts.__String[]; + let seenLabels: __String[]; visit(nodeToCheck); if (rangeFacts & RangeFacts.UsesThis) { - const container = ts.getThisContainer(nodeToCheck, /** includeArrowFunctions */ false); + const container = getThisContainer(nodeToCheck, /** includeArrowFunctions */ false); if ( - container.kind === ts.SyntaxKind.FunctionDeclaration || - (container.kind === ts.SyntaxKind.MethodDeclaration && container.parent.kind === ts.SyntaxKind.ObjectLiteralExpression) || - container.kind === ts.SyntaxKind.FunctionExpression + container.kind === SyntaxKind.FunctionDeclaration || + (container.kind === SyntaxKind.MethodDeclaration && container.parent.kind === SyntaxKind.ObjectLiteralExpression) || + container.kind === SyntaxKind.FunctionExpression ) { rangeFacts |= RangeFacts.UsesThisInFunction; } @@ -471,39 +499,39 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, return errors; - function visit(node: ts.Node) { + function visit(node: Node) { if (errors) { // already found an error - can stop now return true; } - if (ts.isDeclaration(node)) { - const declaringNode = (node.kind === ts.SyntaxKind.VariableDeclaration) ? node.parent.parent : node; - if (ts.hasSyntacticModifier(declaringNode, ts.ModifierFlags.Export)) { + if (isDeclaration(node)) { + const declaringNode = (node.kind === SyntaxKind.VariableDeclaration) ? node.parent.parent : node; + if (hasSyntacticModifier(declaringNode, ModifierFlags.Export)) { // TODO: GH#18217 Silly to use `errors ||` since it's definitely not defined (see top of `visit`) // Also, if we're only pushing one error, just use `let error: Diagnostic | undefined`! // Also TODO: GH#19956 - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; } } // Some things can't be extracted in certain situations switch (node.kind) { - case ts.SyntaxKind.ImportDeclaration: - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport)); + case SyntaxKind.ImportDeclaration: + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractImport)); return true; - case ts.SyntaxKind.ExportAssignment: - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); + case SyntaxKind.ExportAssignment: + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractExportedEntity)); return true; - case ts.SyntaxKind.SuperKeyword: + case SyntaxKind.SuperKeyword: // For a super *constructor call*, we have to be extracting the entire class, // but a super *method call* simply implies a 'this' reference - if (node.parent.kind === ts.SyntaxKind.CallExpression) { + if (node.parent.kind === SyntaxKind.CallExpression) { // Super constructor call - const containingClass = ts.getContainingClass(node); + const containingClass = getContainingClass(node); if (containingClass === undefined || containingClass.pos < span.start || containingClass.end >= (span.start + span.length)) { - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractSuper)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractSuper)); return true; } } @@ -512,60 +540,60 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, thisNode = node; } break; - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.ArrowFunction: // check if arrow function uses this - ts.forEachChild(node, function check(n) { - if (ts.isThis(n)) { + forEachChild(node, function check(n) { + if (isThis(n)) { rangeFacts |= RangeFacts.UsesThis; thisNode = node; } - else if (ts.isClassLike(n) || (ts.isFunctionLike(n) && !ts.isArrowFunction(n))) { + else if (isClassLike(n) || (isFunctionLike(n) && !isArrowFunction(n))) { return false; } else { - ts.forEachChild(n, check); + forEachChild(n, check); } }); // falls through - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.FunctionDeclaration: + if (isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) { // You cannot extract global declarations - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope)); } // falls through - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.ClassExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: // do not dive into functions or classes return false; } const savedPermittedJumps = permittedJumps; switch (node.kind) { - case ts.SyntaxKind.IfStatement: + case SyntaxKind.IfStatement: permittedJumps &= ~PermittedJumps.Return; break; - case ts.SyntaxKind.TryStatement: + case SyntaxKind.TryStatement: // forbid all jumps inside try blocks permittedJumps = PermittedJumps.None; break; - case ts.SyntaxKind.Block: - if (node.parent && node.parent.kind === ts.SyntaxKind.TryStatement && (node.parent as ts.TryStatement).finallyBlock === node) { + case SyntaxKind.Block: + if (node.parent && node.parent.kind === SyntaxKind.TryStatement && (node.parent as TryStatement).finallyBlock === node) { // allow unconditional returns from finally blocks permittedJumps = PermittedJumps.Return; } break; - case ts.SyntaxKind.DefaultClause: - case ts.SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: + case SyntaxKind.CaseClause: // allow unlabeled break inside case clauses permittedJumps |= PermittedJumps.Break; break; default: - if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) { + if (isIterationStatement(node, /*lookInLabeledStatements*/ false)) { // allow unlabeled break/continue inside loops permittedJumps |= PermittedJumps.Break | PermittedJumps.Continue; } @@ -573,51 +601,51 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, } switch (node.kind) { - case ts.SyntaxKind.ThisType: - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.ThisType: + case SyntaxKind.ThisKeyword: rangeFacts |= RangeFacts.UsesThis; thisNode = node; break; - case ts.SyntaxKind.LabeledStatement: { - const label = (node as ts.LabeledStatement).label; + case SyntaxKind.LabeledStatement: { + const label = (node as LabeledStatement).label; (seenLabels || (seenLabels = [])).push(label.escapedText); - ts.forEachChild(node, visit); + forEachChild(node, visit); seenLabels.pop(); break; } - case ts.SyntaxKind.BreakStatement: - case ts.SyntaxKind.ContinueStatement: { - const label = (node as ts.BreakStatement | ts.ContinueStatement).label; + case SyntaxKind.BreakStatement: + case SyntaxKind.ContinueStatement: { + const label = (node as BreakStatement | ContinueStatement).label; if (label) { - if (!ts.contains(seenLabels, label.escapedText)) { + if (!contains(seenLabels, label.escapedText)) { // attempts to jump to label that is not in range to be extracted - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange)); } } else { - if (!(permittedJumps & (node.kind === ts.SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) { + if (!(permittedJumps & (node.kind === SyntaxKind.BreakStatement ? PermittedJumps.Break : PermittedJumps.Continue))) { // attempt to break or continue in a forbidden context - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements)); } } break; } - case ts.SyntaxKind.AwaitExpression: + case SyntaxKind.AwaitExpression: rangeFacts |= RangeFacts.IsAsyncFunction; break; - case ts.SyntaxKind.YieldExpression: + case SyntaxKind.YieldExpression: rangeFacts |= RangeFacts.IsGenerator; break; - case ts.SyntaxKind.ReturnStatement: + case SyntaxKind.ReturnStatement: if (permittedJumps & PermittedJumps.Return) { rangeFacts |= RangeFacts.HasReturn; } else { - (errors ||= []).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement)); + (errors ||= []).push(createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement)); } break; default: - ts.forEachChild(node, visit); + forEachChild(node, visit); break; } @@ -630,25 +658,25 @@ export function getRangeToExtract(sourceFile: ts.SourceFile, span: ts.TextSpan, * Includes the final semicolon so that the span covers statements in cases where it would otherwise * only cover the declaration list. */ -function getAdjustedSpanFromNodes(startNode: ts.Node, endNode: ts.Node, sourceFile: ts.SourceFile): ts.TextSpan { +function getAdjustedSpanFromNodes(startNode: Node, endNode: Node, sourceFile: SourceFile): TextSpan { const start = startNode.getStart(sourceFile); let end = endNode.getEnd(); - if (sourceFile.text.charCodeAt(end) === ts.CharacterCodes.semicolon) { + if (sourceFile.text.charCodeAt(end) === CharacterCodes.semicolon) { end++; } return { start, length: end - start }; } -function getStatementOrExpressionRange(node: ts.Node): ts.Statement[] | ts.Expression | undefined { - if (ts.isStatement(node)) { +function getStatementOrExpressionRange(node: Node): Statement[] | Expression | undefined { + if (isStatement(node)) { return [node]; } - if (ts.isExpressionNode(node)) { + if (isExpressionNode(node)) { // If our selection is the expression in an ExpressionStatement, expand // the selection to include the enclosing Statement (this stops us // from trying to care about the return value of the extracted function // and eliminates double semicolon insertion in certain scenarios) - return ts.isExpressionStatement(node.parent) ? [node.parent] : node as ts.Expression; + return isExpressionStatement(node.parent) ? [node.parent] : node as Expression; } if (isStringLiteralJsxAttribute(node)) { return node; @@ -656,9 +684,9 @@ function getStatementOrExpressionRange(node: ts.Node): ts.Statement[] | ts.Expre return undefined; } -function isScope(node: ts.Node): node is Scope { - return ts.isArrowFunction(node) ? ts.isFunctionBody(node.body) : - ts.isFunctionLikeDeclaration(node) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node); +function isScope(node: Node): node is Scope { + return isArrowFunction(node) ? isFunctionBody(node.body) : + isFunctionLikeDeclaration(node) || isSourceFile(node) || isModuleBlock(node) || isClassLike(node); } /** @@ -667,12 +695,12 @@ function isScope(node: ts.Node): node is Scope { * depending on what's in the extracted body. */ function collectEnclosingScopes(range: TargetRange): Scope[] { - let current: ts.Node = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; + let current: Node = isReadonlyArray(range.range) ? first(range.range) : range.range; if (range.facts & RangeFacts.UsesThis && !(range.facts & RangeFacts.UsesThisInFunction)) { // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class - const containingClass = ts.getContainingClass(current); + const containingClass = getContainingClass(current); if (containingClass) { - const containingFunction = ts.findAncestor(current, ts.isFunctionLikeDeclaration); + const containingFunction = findAncestor(current, isFunctionLikeDeclaration); return containingFunction ? [containingFunction, containingClass] : [containingClass]; @@ -683,9 +711,9 @@ function collectEnclosingScopes(range: TargetRange): Scope[] { while (true) { current = current.parent; // A function parameter's initializer is actually in the outer scope, not the function declaration - if (current.kind === ts.SyntaxKind.Parameter) { + if (current.kind === SyntaxKind.Parameter) { // Skip all the way to the outer scope of the function that declared this parameter - current = ts.findAncestor(current, parent => ts.isFunctionLikeDeclaration(parent))!.parent; + current = findAncestor(current, parent => isFunctionLikeDeclaration(parent))!.parent; } // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of. @@ -695,34 +723,34 @@ function collectEnclosingScopes(range: TargetRange): Scope[] { // * Module/namespace or source file if (isScope(current)) { scopes.push(current); - if (current.kind === ts.SyntaxKind.SourceFile) { + if (current.kind === SyntaxKind.SourceFile) { return scopes; } } } } -function getFunctionExtractionAtIndex(targetRange: TargetRange, context: ts.RefactorContext, requestedChangesIndex: number): ts.RefactorEditInfo { +function getFunctionExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { const { scopes, readsAndWrites: { target, usagesPerScope, functionErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); - ts.Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); + Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); context.cancellationToken!.throwIfCancellationRequested(); // TODO: GH#18217 return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context); } -function getConstantExtractionAtIndex(targetRange: TargetRange, context: ts.RefactorContext, requestedChangesIndex: number): ts.RefactorEditInfo { +function getConstantExtractionAtIndex(targetRange: TargetRange, context: RefactorContext, requestedChangesIndex: number): RefactorEditInfo { const { scopes, readsAndWrites: { target, usagesPerScope, constantErrorsPerScope, exposedVariableDeclarations } } = getPossibleExtractionsWorker(targetRange, context); - ts.Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); - ts.Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?"); + Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?"); + Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?"); context.cancellationToken!.throwIfCancellationRequested(); - const expression = ts.isExpression(target) + const expression = isExpression(target) ? target - : (target.statements[0] as ts.ExpressionStatement).expression; + : (target.statements[0] as ExpressionStatement).expression; return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context); } interface Extraction { readonly description: string; - readonly errors: readonly ts.Diagnostic[]; + readonly errors: readonly Diagnostic[]; } interface ScopeExtractions { @@ -735,37 +763,37 @@ interface ScopeExtractions { * Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes * or an error explaining why we can't extract into that scope. */ -function getPossibleExtractions(targetRange: TargetRange, context: ts.RefactorContext): readonly ScopeExtractions[] | undefined { +function getPossibleExtractions(targetRange: TargetRange, context: RefactorContext): readonly ScopeExtractions[] | undefined { const { scopes, readsAndWrites: { functionErrorsPerScope, constantErrorsPerScope } } = getPossibleExtractionsWorker(targetRange, context); // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547 const extractions = scopes.map((scope, i): ScopeExtractions => { const functionDescriptionPart = getDescriptionForFunctionInScope(scope); const constantDescriptionPart = getDescriptionForConstantInScope(scope); - const scopeDescription = ts.isFunctionLikeDeclaration(scope) + const scopeDescription = isFunctionLikeDeclaration(scope) ? getDescriptionForFunctionLikeDeclaration(scope) - : ts.isClassLike(scope) + : isClassLike(scope) ? getDescriptionForClassLikeDeclaration(scope) : getDescriptionForModuleLikeDeclaration(scope); let functionDescription: string; let constantDescription: string; if (scopeDescription === SpecialScope.Global) { - functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]); - constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]); } else if (scopeDescription === SpecialScope.Module) { - functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]); - constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]); } else { - functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]); - constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]); + functionDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]); + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]); } // Customize the phrasing for the innermost scope to increase clarity. - if (i === 0 && !ts.isClassLike(scope)) { - constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]); + if (i === 0 && !isClassLike(scope)) { + constantDescription = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]); } return { @@ -782,7 +810,7 @@ function getPossibleExtractions(targetRange: TargetRange, context: ts.RefactorCo return extractions; } -function getPossibleExtractionsWorker(targetRange: TargetRange, context: ts.RefactorContext): { readonly scopes: Scope[], readonly readsAndWrites: ReadsAndWrites } { +function getPossibleExtractionsWorker(targetRange: TargetRange, context: RefactorContext): { readonly scopes: Scope[], readonly readsAndWrites: ReadsAndWrites } { const { file: sourceFile } = context; const scopes = collectEnclosingScopes(targetRange); @@ -798,45 +826,45 @@ function getPossibleExtractionsWorker(targetRange: TargetRange, context: ts.Refa } function getDescriptionForFunctionInScope(scope: Scope): string { - return ts.isFunctionLikeDeclaration(scope) + return isFunctionLikeDeclaration(scope) ? "inner function" - : ts.isClassLike(scope) + : isClassLike(scope) ? "method" : "function"; } function getDescriptionForConstantInScope(scope: Scope): string { - return ts.isClassLike(scope) + return isClassLike(scope) ? "readonly field" : "constant"; } -function getDescriptionForFunctionLikeDeclaration(scope: ts.FunctionLikeDeclaration): string { +function getDescriptionForFunctionLikeDeclaration(scope: FunctionLikeDeclaration): string { switch (scope.kind) { - case ts.SyntaxKind.Constructor: + case SyntaxKind.Constructor: return "constructor"; - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionDeclaration: return scope.name ? `function '${scope.name.text}'` - : ts.ANONYMOUS; - case ts.SyntaxKind.ArrowFunction: + : ANONYMOUS; + case SyntaxKind.ArrowFunction: return "arrow function"; - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodDeclaration: return `method '${scope.name.getText()}'`; - case ts.SyntaxKind.GetAccessor: + case SyntaxKind.GetAccessor: return `'get ${scope.name.getText()}'`; - case ts.SyntaxKind.SetAccessor: + case SyntaxKind.SetAccessor: return `'set ${scope.name.getText()}'`; default: - throw ts.Debug.assertNever(scope, `Unexpected scope kind ${(scope as ts.FunctionLikeDeclaration).kind}`); + throw Debug.assertNever(scope, `Unexpected scope kind ${(scope as FunctionLikeDeclaration).kind}`); } } -function getDescriptionForClassLikeDeclaration(scope: ts.ClassLikeDeclaration): string { - return scope.kind === ts.SyntaxKind.ClassDeclaration +function getDescriptionForClassLikeDeclaration(scope: ClassLikeDeclaration): string { + return scope.kind === SyntaxKind.ClassDeclaration ? scope.name ? `class '${scope.name.text}'` : "anonymous class declaration" : scope.name ? `class expression '${scope.name.text}'` : "anonymous class expression"; } -function getDescriptionForModuleLikeDeclaration(scope: ts.SourceFile | ts.ModuleBlock): string | SpecialScope { - return scope.kind === ts.SyntaxKind.ModuleBlock +function getDescriptionForModuleLikeDeclaration(scope: SourceFile | ModuleBlock): string | SpecialScope { + return scope.kind === SyntaxKind.ModuleBlock ? `namespace '${scope.parent.name.getText()}'` : scope.externalModuleIndicator ? SpecialScope.Module : SpecialScope.Global; } @@ -851,38 +879,38 @@ const enum SpecialScope { * Stores either a list of changes that should be applied to extract a range or a list of errors */ function extractFunctionInScope( - node: ts.Statement | ts.Expression | ts.Block, + node: Statement | Expression | Block, scope: Scope, { usages: usagesInScope, typeParameterUsages, substitutions }: ScopeUsages, - exposedVariableDeclarations: readonly ts.VariableDeclaration[], + exposedVariableDeclarations: readonly VariableDeclaration[], range: TargetRange, - context: ts.RefactorContext): ts.RefactorEditInfo { + context: RefactorContext): RefactorEditInfo { const checker = context.program.getTypeChecker(); - const scriptTarget = ts.getEmitScriptTarget(context.program.getCompilerOptions()); - const importAdder = ts.codefix.createImportAdder(context.file, context.program, context.preferences, context.host); + const scriptTarget = getEmitScriptTarget(context.program.getCompilerOptions()); + const importAdder = codefix.createImportAdder(context.file, context.program, context.preferences, context.host); // Make a unique name for the extracted function const file = scope.getSourceFile(); - const functionNameText = ts.getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file); - const isJS = ts.isInJSFile(scope); + const functionNameText = getUniqueName(isClassLike(scope) ? "newMethod" : "newFunction", file); + const isJS = isInJSFile(scope); - const functionName = ts.factory.createIdentifier(functionNameText); + const functionName = factory.createIdentifier(functionNameText); - let returnType: ts.TypeNode | undefined; - const parameters: ts.ParameterDeclaration[] = []; - const callArguments: ts.Identifier[] = []; + let returnType: TypeNode | undefined; + const parameters: ParameterDeclaration[] = []; + const callArguments: Identifier[] = []; let writes: UsageEntry[] | undefined; usagesInScope.forEach((usage, name) => { - let typeNode: ts.TypeNode | undefined; + let typeNode: TypeNode | undefined; if (!isJS) { let type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node); // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {" type = checker.getBaseTypeOfLiteralType(type); - typeNode = ts.codefix.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, ts.NodeBuilderFlags.NoTruncation); + typeNode = codefix.typeToAutoImportableTypeNode(checker, importAdder, type, scope, scriptTarget, NodeBuilderFlags.NoTruncation); } - const paramDecl = ts.factory.createParameterDeclaration( + const paramDecl = factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ name, @@ -893,48 +921,48 @@ function extractFunctionInScope( if (usage.usage === Usage.Write) { (writes || (writes = [])).push(usage); } - callArguments.push(ts.factory.createIdentifier(name)); + callArguments.push(factory.createIdentifier(name)); }); - const typeParametersAndDeclarations = ts.arrayFrom(typeParameterUsages.values()).map(type => ({ type, declaration: getFirstDeclaration(type) })); + const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values()).map(type => ({ type, declaration: getFirstDeclaration(type) })); const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); - const typeParameters: readonly ts.TypeParameterDeclaration[] | undefined = sortedTypeParametersAndDeclarations.length === 0 + const typeParameters: readonly TypeParameterDeclaration[] | undefined = sortedTypeParametersAndDeclarations.length === 0 ? undefined - : sortedTypeParametersAndDeclarations.map(t => t.declaration as ts.TypeParameterDeclaration); + : sortedTypeParametersAndDeclarations.map(t => t.declaration as TypeParameterDeclaration); // Strictly speaking, we should check whether each name actually binds to the appropriate type // parameter. In cases of shadowing, they may not. - const callTypeArguments: readonly ts.TypeNode[] | undefined = typeParameters !== undefined - ? typeParameters.map(decl => ts.factory.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined)) + const callTypeArguments: readonly TypeNode[] | undefined = typeParameters !== undefined + ? typeParameters.map(decl => factory.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined)) : undefined; // Provide explicit return types for contextually-typed functions // to avoid problems when there are literal types present - if (ts.isExpression(node) && !isJS) { + if (isExpression(node) && !isJS) { const contextualType = checker.getContextualType(node); - returnType = checker.typeToTypeNode(contextualType!, scope, ts.NodeBuilderFlags.NoTruncation); // TODO: GH#18217 + returnType = checker.typeToTypeNode(contextualType!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 } const { body, returnValueProperty } = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)); - ts.suppressLeadingAndTrailingTrivia(body); + suppressLeadingAndTrailingTrivia(body); - let newFunction: ts.MethodDeclaration | ts.FunctionDeclaration; + let newFunction: MethodDeclaration | FunctionDeclaration; const callThis = !!(range.facts & RangeFacts.UsesThisInFunction); - if (ts.isClassLike(scope)) { + if (isClassLike(scope)) { // always create private method in TypeScript files - const modifiers: ts.Modifier[] = isJS ? [] : [ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword)]; + const modifiers: Modifier[] = isJS ? [] : [factory.createModifier(SyntaxKind.PrivateKeyword)]; if (range.facts & RangeFacts.InStaticRegion) { - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.StaticKeyword)); } if (range.facts & RangeFacts.IsAsyncFunction) { - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.AsyncKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.AsyncKeyword)); } - newFunction = ts.factory.createMethodDeclaration( + newFunction = factory.createMethodDeclaration( modifiers.length ? modifiers : undefined, - range.facts & RangeFacts.IsGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : undefined, + range.facts & RangeFacts.IsGenerator ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, functionName, /*questionToken*/ undefined, typeParameters, @@ -946,7 +974,7 @@ function extractFunctionInScope( else { if (callThis) { parameters.unshift( - ts.factory.createParameterDeclaration( + factory.createParameterDeclaration( /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, /*name*/ "this", @@ -954,15 +982,15 @@ function extractFunctionInScope( checker.typeToTypeNode( checker.getTypeAtLocation(range.thisNode!), scope, - ts.NodeBuilderFlags.NoTruncation + NodeBuilderFlags.NoTruncation ), /*initializer*/ undefined, ) ); } - newFunction = ts.factory.createFunctionDeclaration( - range.facts & RangeFacts.IsAsyncFunction ? [ts.factory.createToken(ts.SyntaxKind.AsyncKeyword)] : undefined, - range.facts & RangeFacts.IsGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : undefined, + newFunction = factory.createFunctionDeclaration( + range.facts & RangeFacts.IsAsyncFunction ? [factory.createToken(SyntaxKind.AsyncKeyword)] : undefined, + range.facts & RangeFacts.IsGenerator ? factory.createToken(SyntaxKind.AsteriskToken) : undefined, functionName, typeParameters, parameters, @@ -971,8 +999,8 @@ function extractFunctionInScope( ); } - const changeTracker = ts.textChanges.ChangeTracker.fromContext(context); - const minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end; + const changeTracker = textChanges.ChangeTracker.fromContext(context); + const minInsertionPos = (isReadonlyArray(range.range) ? last(range.range) : range.range).end; const nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope); if (nodeToInsertBefore) { changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, /*blankLineBetween*/ true); @@ -982,67 +1010,67 @@ function extractFunctionInScope( } importAdder.writeFixes(changeTracker); - const newNodes: ts.Node[] = []; + const newNodes: Node[] = []; // replace range with function call const called = getCalledExpression(scope, range, functionNameText); if (callThis) { - callArguments.unshift(ts.factory.createIdentifier("this")); + callArguments.unshift(factory.createIdentifier("this")); } - let call: ts.Expression = ts.factory.createCallExpression( - callThis ? ts.factory.createPropertyAccessExpression( + let call: Expression = factory.createCallExpression( + callThis ? factory.createPropertyAccessExpression( called, "call" ) : called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference callArguments); if (range.facts & RangeFacts.IsGenerator) { - call = ts.factory.createYieldExpression(ts.factory.createToken(ts.SyntaxKind.AsteriskToken), call); + call = factory.createYieldExpression(factory.createToken(SyntaxKind.AsteriskToken), call); } if (range.facts & RangeFacts.IsAsyncFunction) { - call = ts.factory.createAwaitExpression(call); + call = factory.createAwaitExpression(call); } if (isInJSXContent(node)) { - call = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, call); + call = factory.createJsxExpression(/*dotDotDotToken*/ undefined, call); } if (exposedVariableDeclarations.length && !writes) { // No need to mix declarations and writes. // How could any variables be exposed if there's a return statement? - ts.Debug.assert(!returnValueProperty, "Expected no returnValueProperty"); - ts.Debug.assert(!(range.facts & RangeFacts.HasReturn), "Expected RangeFacts.HasReturn flag to be unset"); + Debug.assert(!returnValueProperty, "Expected no returnValueProperty"); + Debug.assert(!(range.facts & RangeFacts.HasReturn), "Expected RangeFacts.HasReturn flag to be unset"); if (exposedVariableDeclarations.length === 1) { // Declaring exactly one variable: let x = newFunction(); const variableDeclaration = exposedVariableDeclarations[0]; - newNodes.push(ts.factory.createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList( - [ts.factory.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*type*/ ts.getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(getSynthesizedDeepClone(variableDeclaration.name), /*exclamationToken*/ undefined, /*type*/ getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], variableDeclaration.parent.flags))); } else { // Declaring multiple variables / return properties: // let {x, y} = newFunction(); - const bindingElements: ts.BindingElement[] = []; - const typeElements: ts.TypeElement[] = []; + const bindingElements: BindingElement[] = []; + const typeElements: TypeElement[] = []; let commonNodeFlags = exposedVariableDeclarations[0].parent.flags; let sawExplicitType = false; for (const variableDeclaration of exposedVariableDeclarations) { - bindingElements.push(ts.factory.createBindingElement( + bindingElements.push(factory.createBindingElement( /*dotDotDotToken*/ undefined, /*propertyName*/ undefined, - /*name*/ ts.getSynthesizedDeepClone(variableDeclaration.name))); + /*name*/ getSynthesizedDeepClone(variableDeclaration.name))); // Being returned through an object literal will have widened the type. - const variableType: ts.TypeNode | undefined = checker.typeToTypeNode( + const variableType: TypeNode | undefined = checker.typeToTypeNode( checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, - ts.NodeBuilderFlags.NoTruncation); + NodeBuilderFlags.NoTruncation); - typeElements.push(ts.factory.createPropertySignature( + typeElements.push(factory.createPropertySignature( /*modifiers*/ undefined, /*name*/ variableDeclaration.symbol.name, /*questionToken*/ undefined, @@ -1051,16 +1079,16 @@ function extractFunctionInScope( commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags; } - const typeLiteral: ts.TypeLiteralNode | undefined = sawExplicitType ? ts.factory.createTypeLiteralNode(typeElements) : undefined; + const typeLiteral: TypeLiteralNode | undefined = sawExplicitType ? factory.createTypeLiteralNode(typeElements) : undefined; if (typeLiteral) { - ts.setEmitFlags(typeLiteral, ts.EmitFlags.SingleLine); + setEmitFlags(typeLiteral, EmitFlags.SingleLine); } - newNodes.push(ts.factory.createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList( - [ts.factory.createVariableDeclaration( - ts.factory.createObjectBindingPattern(bindingElements), + factory.createVariableDeclarationList( + [factory.createVariableDeclaration( + factory.createObjectBindingPattern(bindingElements), /*exclamationToken*/ undefined, /*type*/ typeLiteral, /*initializer*/call)], @@ -1071,61 +1099,61 @@ function extractFunctionInScope( if (exposedVariableDeclarations.length) { // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping. for (const variableDeclaration of exposedVariableDeclarations) { - let flags: ts.NodeFlags = variableDeclaration.parent.flags; - if (flags & ts.NodeFlags.Const) { - flags = (flags & ~ts.NodeFlags.Const) | ts.NodeFlags.Let; + let flags: NodeFlags = variableDeclaration.parent.flags; + if (flags & NodeFlags.Const) { + flags = (flags & ~NodeFlags.Const) | NodeFlags.Let; } - newNodes.push(ts.factory.createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList( - [ts.factory.createVariableDeclaration(variableDeclaration.symbol.name, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(variableDeclaration.symbol.name, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags))); } } if (returnValueProperty) { // has both writes and return, need to create variable declaration to hold return value; - newNodes.push(ts.factory.createVariableStatement( + newNodes.push(factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList( - [ts.factory.createVariableDeclaration(returnValueProperty, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(returnType))], - ts.NodeFlags.Let))); + factory.createVariableDeclarationList( + [factory.createVariableDeclaration(returnValueProperty, /*exclamationToken*/ undefined, getTypeDeepCloneUnionUndefined(returnType))], + NodeFlags.Let))); } const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (returnValueProperty) { - assignments.unshift(ts.factory.createShorthandPropertyAssignment(returnValueProperty)); + assignments.unshift(factory.createShorthandPropertyAssignment(returnValueProperty)); } // propagate writes back if (assignments.length === 1) { // We would only have introduced a return value property if there had been // other assignments to make. - ts.Debug.assert(!returnValueProperty, "Shouldn't have returnValueProperty here"); + Debug.assert(!returnValueProperty, "Shouldn't have returnValueProperty here"); - newNodes.push(ts.factory.createExpressionStatement(ts.factory.createAssignment(assignments[0].name, call))); + newNodes.push(factory.createExpressionStatement(factory.createAssignment(assignments[0].name, call))); if (range.facts & RangeFacts.HasReturn) { - newNodes.push(ts.factory.createReturnStatement()); + newNodes.push(factory.createReturnStatement()); } } else { // emit e.g. // { a, b, __return } = newFunction(a, b); // return __return; - newNodes.push(ts.factory.createExpressionStatement(ts.factory.createAssignment(ts.factory.createObjectLiteralExpression(assignments), call))); + newNodes.push(factory.createExpressionStatement(factory.createAssignment(factory.createObjectLiteralExpression(assignments), call))); if (returnValueProperty) { - newNodes.push(ts.factory.createReturnStatement(ts.factory.createIdentifier(returnValueProperty))); + newNodes.push(factory.createReturnStatement(factory.createIdentifier(returnValueProperty))); } } } else { if (range.facts & RangeFacts.HasReturn) { - newNodes.push(ts.factory.createReturnStatement(call)); + newNodes.push(factory.createReturnStatement(call)); } else if (isReadonlyArray(range.range)) { - newNodes.push(ts.factory.createExpressionStatement(call)); + newNodes.push(factory.createExpressionStatement(call)); } else { newNodes.push(call); @@ -1133,32 +1161,32 @@ function extractFunctionInScope( } if (isReadonlyArray(range.range)) { - changeTracker.replaceNodeRangeWithNodes(context.file, ts.first(range.range), ts.last(range.range), newNodes); + changeTracker.replaceNodeRangeWithNodes(context.file, first(range.range), last(range.range), newNodes); } else { changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes); } const edits = changeTracker.getChanges(); - const renameRange = isReadonlyArray(range.range) ? ts.first(range.range) : range.range; + const renameRange = isReadonlyArray(range.range) ? first(range.range) : range.range; const renameFilename = renameRange.getSourceFile().fileName; - const renameLocation = ts.getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false); + const renameLocation = getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false); return { renameFilename, renameLocation, edits }; - function getTypeDeepCloneUnionUndefined(typeNode: ts.TypeNode | undefined): ts.TypeNode | undefined { + function getTypeDeepCloneUnionUndefined(typeNode: TypeNode | undefined): TypeNode | undefined { if (typeNode === undefined) { return undefined; } - const clone = ts.getSynthesizedDeepClone(typeNode); + const clone = getSynthesizedDeepClone(typeNode); let withoutParens = clone; - while (ts.isParenthesizedTypeNode(withoutParens)) { + while (isParenthesizedTypeNode(withoutParens)) { withoutParens = withoutParens.type; } - return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, t => t.kind === ts.SyntaxKind.UndefinedKeyword) + return isUnionTypeNode(withoutParens) && find(withoutParens.types, t => t.kind === SyntaxKind.UndefinedKeyword) ? clone - : ts.factory.createUnionTypeNode([clone, ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]); + : factory.createUnionTypeNode([clone, factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]); } } @@ -1167,57 +1195,57 @@ function extractFunctionInScope( * Stores either a list of changes that should be applied to extract a range or a list of errors */ function extractConstantInScope( - node: ts.Expression, + node: Expression, scope: Scope, { substitutions }: ScopeUsages, rangeFacts: RangeFacts, - context: ts.RefactorContext): ts.RefactorEditInfo { + context: RefactorContext): RefactorEditInfo { const checker = context.program.getTypeChecker(); // Make a unique name for the extracted variable const file = scope.getSourceFile(); - const localNameText = ts.isPropertyAccessExpression(node) && !ts.isClassLike(scope) && !checker.resolveName(node.name.text, node, ts.SymbolFlags.Value, /*excludeGlobals*/ false) && !ts.isPrivateIdentifier(node.name) && !ts.isKeyword(node.name.originalKeywordKind!) + const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !isKeyword(node.name.originalKeywordKind!) ? node.name.text - : ts.getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file); - const isJS = ts.isInJSFile(scope); + : getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file); + const isJS = isInJSFile(scope); let variableType = isJS || !checker.isContextSensitive(node) ? undefined - : checker.typeToTypeNode(checker.getContextualType(node)!, scope, ts.NodeBuilderFlags.NoTruncation); // TODO: GH#18217 + : checker.typeToTypeNode(checker.getContextualType(node)!, scope, NodeBuilderFlags.NoTruncation); // TODO: GH#18217 - let initializer = transformConstantInitializer(ts.skipParentheses(node), substitutions); + let initializer = transformConstantInitializer(skipParentheses(node), substitutions); ({ variableType, initializer } = transformFunctionInitializerAndType(variableType, initializer)); - ts.suppressLeadingAndTrailingTrivia(initializer); + suppressLeadingAndTrailingTrivia(initializer); - const changeTracker = ts.textChanges.ChangeTracker.fromContext(context); + const changeTracker = textChanges.ChangeTracker.fromContext(context); - if (ts.isClassLike(scope)) { - ts.Debug.assert(!isJS, "Cannot extract to a JS class"); // See CannotExtractToJSClass - const modifiers: ts.Modifier[] = []; - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword)); + if (isClassLike(scope)) { + Debug.assert(!isJS, "Cannot extract to a JS class"); // See CannotExtractToJSClass + const modifiers: Modifier[] = []; + modifiers.push(factory.createModifier(SyntaxKind.PrivateKeyword)); if (rangeFacts & RangeFacts.InStaticRegion) { - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.StaticKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.StaticKeyword)); } - modifiers.push(ts.factory.createModifier(ts.SyntaxKind.ReadonlyKeyword)); + modifiers.push(factory.createModifier(SyntaxKind.ReadonlyKeyword)); - const newVariable = ts.factory.createPropertyDeclaration( + const newVariable = factory.createPropertyDeclaration( modifiers, localNameText, /*questionToken*/ undefined, variableType, initializer); - let localReference: ts.Expression = ts.factory.createPropertyAccessExpression( + let localReference: Expression = factory.createPropertyAccessExpression( rangeFacts & RangeFacts.InStaticRegion - ? ts.factory.createIdentifier(scope.name!.getText()) // TODO: GH#18217 - : ts.factory.createThis(), - ts.factory.createIdentifier(localNameText)); + ? factory.createIdentifier(scope.name!.getText()) // TODO: GH#18217 + : factory.createThis(), + factory.createIdentifier(localNameText)); if (isInJSXContent(node)) { - localReference = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); + localReference = factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); } // Declare @@ -1229,7 +1257,7 @@ function extractConstantInScope( changeTracker.replaceNode(context.file, node, localReference); } else { - const newVariableDeclaration = ts.factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, variableType, initializer); + const newVariableDeclaration = factory.createVariableDeclaration(localNameText, /*exclamationToken*/ undefined, variableType, initializer); // If the node is part of an initializer in a list of variable declarations, insert a new // variable declaration into the list (in case it depends on earlier ones). @@ -1242,21 +1270,21 @@ function extractConstantInScope( changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration); // Consume - const localReference = ts.factory.createIdentifier(localNameText); + const localReference = factory.createIdentifier(localNameText); changeTracker.replaceNode(context.file, node, localReference); } - else if (node.parent.kind === ts.SyntaxKind.ExpressionStatement && scope === ts.findAncestor(node, isScope)) { + else if (node.parent.kind === SyntaxKind.ExpressionStatement && scope === findAncestor(node, isScope)) { // If the parent is an expression statement and the target scope is the immediately enclosing one, // replace the statement with the declaration. - const newVariableStatement = ts.factory.createVariableStatement( + const newVariableStatement = factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList([newVariableDeclaration], ts.NodeFlags.Const)); + factory.createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); changeTracker.replaceNode(context.file, node.parent, newVariableStatement); } else { - const newVariableStatement = ts.factory.createVariableStatement( + const newVariableStatement = factory.createVariableStatement( /*modifiers*/ undefined, - ts.factory.createVariableDeclarationList([newVariableDeclaration], ts.NodeFlags.Const)); + factory.createVariableDeclarationList([newVariableDeclaration], NodeFlags.Const)); // Declare const nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope); @@ -1268,16 +1296,16 @@ function extractConstantInScope( } // Consume - if (node.parent.kind === ts.SyntaxKind.ExpressionStatement) { + if (node.parent.kind === SyntaxKind.ExpressionStatement) { // If the parent is an expression statement, delete it. changeTracker.delete(context.file, node.parent); } else { - let localReference: ts.Expression = ts.factory.createIdentifier(localNameText); + let localReference: Expression = factory.createIdentifier(localNameText); // When extract to a new variable in JSX content, need to wrap a {} out of the new variable // or it will become a plain text if (isInJSXContent(node)) { - localReference = ts.factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); + localReference = factory.createJsxExpression(/*dotDotDotToken*/ undefined, localReference); } changeTracker.replaceNode(context.file, node, localReference); } @@ -1287,16 +1315,16 @@ function extractConstantInScope( const edits = changeTracker.getChanges(); const renameFilename = node.getSourceFile().fileName; - const renameLocation = ts.getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true); + const renameLocation = getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true); return { renameFilename, renameLocation, edits }; - function transformFunctionInitializerAndType(variableType: ts.TypeNode | undefined, initializer: ts.Expression): { variableType: ts.TypeNode | undefined, initializer: ts.Expression } { + function transformFunctionInitializerAndType(variableType: TypeNode | undefined, initializer: Expression): { variableType: TypeNode | undefined, initializer: Expression } { // If no contextual type exists there is nothing to transfer to the function signature if (variableType === undefined) return { variableType, initializer }; // Only do this for function expressions and arrow functions that are not generic - if (!ts.isFunctionExpression(initializer) && !ts.isArrowFunction(initializer) || !!initializer.typeParameters) return { variableType, initializer }; + if (!isFunctionExpression(initializer) && !isArrowFunction(initializer) || !!initializer.typeParameters) return { variableType, initializer }; const functionType = checker.getTypeAtLocation(node); - const functionSignature = ts.singleOrUndefined(checker.getSignaturesOfType(functionType, ts.SignatureKind.Call)); + const functionSignature = singleOrUndefined(checker.getSignaturesOfType(functionType, SignatureKind.Call)); // If no function signature, maybe there was an error, do nothing if (!functionSignature) return { variableType, initializer }; @@ -1304,7 +1332,7 @@ function extractConstantInScope( if (!!functionSignature.getTypeParameters()) return { variableType, initializer }; // We add parameter types if needed - const parameters: ts.ParameterDeclaration[] = []; + const parameters: ParameterDeclaration[] = []; let hasAny = false; for (const p of initializer.parameters) { if (p.type) { @@ -1314,9 +1342,9 @@ function extractConstantInScope( const paramType = checker.getTypeAtLocation(p); if (paramType === checker.getAnyType()) hasAny = true; - parameters.push(ts.factory.updateParameterDeclaration(p, + parameters.push(factory.updateParameterDeclaration(p, p.modifiers, p.dotDotDotToken, - p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, ts.NodeBuilderFlags.NoTruncation), p.initializer)); + p.name, p.questionToken, p.type || checker.typeToTypeNode(paramType, scope, NodeBuilderFlags.NoTruncation), p.initializer)); } } // If a parameter was inferred as any we skip adding function parameters at all. @@ -1324,45 +1352,45 @@ function extractConstantInScope( // is probably actually a worse refactor outcome. if (hasAny) return { variableType, initializer }; variableType = undefined; - if (ts.isArrowFunction(initializer)) { - initializer = ts.factory.updateArrowFunction(initializer, ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined, initializer.typeParameters, + if (isArrowFunction(initializer)) { + initializer = factory.updateArrowFunction(initializer, canHaveModifiers(node) ? getModifiers(node) : undefined, initializer.typeParameters, parameters, - initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, ts.NodeBuilderFlags.NoTruncation), + initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), initializer.equalsGreaterThanToken, initializer.body); } else { if (functionSignature && !!functionSignature.thisParameter) { - const firstParameter = ts.firstOrUndefined(parameters); + const firstParameter = firstOrUndefined(parameters); // If the function signature has a this parameter and if the first defined parameter is not the this parameter, we must add it // Note: If this parameter was already there, it would have been previously updated with the type if not type was present - if ((!firstParameter || (ts.isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this"))) { + if ((!firstParameter || (isIdentifier(firstParameter.name) && firstParameter.name.escapedText !== "this"))) { const thisType = checker.getTypeOfSymbolAtLocation(functionSignature.thisParameter, node); - parameters.splice(0, 0, ts.factory.createParameterDeclaration( + parameters.splice(0, 0, factory.createParameterDeclaration( /* modifiers */ undefined, /* dotDotDotToken */ undefined, "this", /* questionToken */ undefined, - checker.typeToTypeNode(thisType, scope, ts.NodeBuilderFlags.NoTruncation) + checker.typeToTypeNode(thisType, scope, NodeBuilderFlags.NoTruncation) )); } } - initializer = ts.factory.updateFunctionExpression(initializer, ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined, initializer.asteriskToken, + initializer = factory.updateFunctionExpression(initializer, canHaveModifiers(node) ? getModifiers(node) : undefined, initializer.asteriskToken, initializer.name, initializer.typeParameters, parameters, - initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, ts.NodeBuilderFlags.NoTruncation), + initializer.type || checker.typeToTypeNode(functionSignature.getReturnType(), scope, NodeBuilderFlags.NoTruncation), initializer.body); } return { variableType, initializer }; } } -function getContainingVariableDeclarationIfInList(node: ts.Node, scope: Scope) { +function getContainingVariableDeclarationIfInList(node: Node, scope: Scope) { let prevNode; while (node !== undefined && node !== scope) { - if (ts.isVariableDeclaration(node) && + if (isVariableDeclaration(node) && node.initializer === prevNode && - ts.isVariableDeclarationList(node.parent) && + isVariableDeclarationList(node.parent) && node.parent.declarations.length > 1) { return node; @@ -1373,7 +1401,7 @@ function getContainingVariableDeclarationIfInList(node: ts.Node, scope: Scope) { } } -function getFirstDeclaration(type: ts.Type): ts.Declaration | undefined { +function getFirstDeclaration(type: Type): Declaration | undefined { let firstDeclaration; const symbol = type.symbol; @@ -1389,134 +1417,134 @@ function getFirstDeclaration(type: ts.Type): ts.Declaration | undefined { } function compareTypesByDeclarationOrder( - { type: type1, declaration: declaration1 }: { type: ts.Type, declaration?: ts.Declaration }, - { type: type2, declaration: declaration2 }: { type: ts.Type, declaration?: ts.Declaration }) { + { type: type1, declaration: declaration1 }: { type: Type, declaration?: Declaration }, + { type: type2, declaration: declaration2 }: { type: Type, declaration?: Declaration }) { - return ts.compareProperties(declaration1, declaration2, "pos", ts.compareValues) - || ts.compareStringsCaseSensitive( + return compareProperties(declaration1, declaration2, "pos", compareValues) + || compareStringsCaseSensitive( type1.symbol ? type1.symbol.getName() : "", type2.symbol ? type2.symbol.getName() : "") - || ts.compareValues(type1.id, type2.id); + || compareValues(type1.id, type2.id); } -function getCalledExpression(scope: ts.Node, range: TargetRange, functionNameText: string): ts.Expression { - const functionReference = ts.factory.createIdentifier(functionNameText); - if (ts.isClassLike(scope)) { - const lhs = range.facts & RangeFacts.InStaticRegion ? ts.factory.createIdentifier(scope.name!.text) : ts.factory.createThis(); // TODO: GH#18217 - return ts.factory.createPropertyAccessExpression(lhs, functionReference); +function getCalledExpression(scope: Node, range: TargetRange, functionNameText: string): Expression { + const functionReference = factory.createIdentifier(functionNameText); + if (isClassLike(scope)) { + const lhs = range.facts & RangeFacts.InStaticRegion ? factory.createIdentifier(scope.name!.text) : factory.createThis(); // TODO: GH#18217 + return factory.createPropertyAccessExpression(lhs, functionReference); } else { return functionReference; } } -function transformFunctionBody(body: ts.Node, exposedVariableDeclarations: readonly ts.VariableDeclaration[], writes: readonly UsageEntry[] | undefined, substitutions: ts.ReadonlyESMap, hasReturn: boolean): { body: ts.Block, returnValueProperty: string | undefined } { +function transformFunctionBody(body: Node, exposedVariableDeclarations: readonly VariableDeclaration[], writes: readonly UsageEntry[] | undefined, substitutions: ReadonlyESMap, hasReturn: boolean): { body: Block, returnValueProperty: string | undefined } { const hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0; - if (ts.isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { + if (isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) { // already block, no declarations or writes to propagate back, no substitutions - can use node as is - return { body: ts.factory.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; + return { body: factory.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined }; } let returnValueProperty: string | undefined; let ignoreReturns = false; - const statements = ts.factory.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.factory.createReturnStatement(ts.skipParentheses(body as ts.Expression))]); + const statements = factory.createNodeArray(isBlock(body) ? body.statements.slice(0) : [isStatement(body) ? body : factory.createReturnStatement(skipParentheses(body as Expression))]); // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions if (hasWritesOrVariableDeclarations || substitutions.size) { - const rewrittenStatements = ts.visitNodes(statements, visitor).slice(); - if (hasWritesOrVariableDeclarations && !hasReturn && ts.isStatement(body)) { + const rewrittenStatements = visitNodes(statements, visitor).slice(); + if (hasWritesOrVariableDeclarations && !hasReturn && isStatement(body)) { // add return at the end to propagate writes back in case if control flow falls out of the function body // it is ok to know that range has at least one return since it we only allow unconditional returns const assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (assignments.length === 1) { - rewrittenStatements.push(ts.factory.createReturnStatement(assignments[0].name)); + rewrittenStatements.push(factory.createReturnStatement(assignments[0].name)); } else { - rewrittenStatements.push(ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression(assignments))); + rewrittenStatements.push(factory.createReturnStatement(factory.createObjectLiteralExpression(assignments))); } } - return { body: ts.factory.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty }; + return { body: factory.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty }; } else { - return { body: ts.factory.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; + return { body: factory.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined }; } - function visitor(node: ts.Node): ts.VisitResult { - if (!ignoreReturns && ts.isReturnStatement(node) && hasWritesOrVariableDeclarations) { - const assignments: ts.ObjectLiteralElementLike[] = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); + function visitor(node: Node): VisitResult { + if (!ignoreReturns && isReturnStatement(node) && hasWritesOrVariableDeclarations) { + const assignments: ObjectLiteralElementLike[] = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes); if (node.expression) { if (!returnValueProperty) { returnValueProperty = "__return"; } - assignments.unshift(ts.factory.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor))); + assignments.unshift(factory.createPropertyAssignment(returnValueProperty, visitNode(node.expression, visitor))); } if (assignments.length === 1) { - return ts.factory.createReturnStatement(assignments[0].name as ts.Expression); + return factory.createReturnStatement(assignments[0].name as Expression); } else { - return ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression(assignments)); + return factory.createReturnStatement(factory.createObjectLiteralExpression(assignments)); } } else { const oldIgnoreReturns = ignoreReturns; - ignoreReturns = ignoreReturns || ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node); - const substitution = substitutions.get(ts.getNodeId(node).toString()); - const result = substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext); + ignoreReturns = ignoreReturns || isFunctionLikeDeclaration(node) || isClassLike(node); + const substitution = substitutions.get(getNodeId(node).toString()); + const result = substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); ignoreReturns = oldIgnoreReturns; return result; } } } -function transformConstantInitializer(initializer: ts.Expression, substitutions: ts.ReadonlyESMap): ts.Expression { +function transformConstantInitializer(initializer: Expression, substitutions: ReadonlyESMap): Expression { return substitutions.size - ? visitor(initializer) as ts.Expression + ? visitor(initializer) as Expression : initializer; - function visitor(node: ts.Node): ts.VisitResult { - const substitution = substitutions.get(ts.getNodeId(node).toString()); - return substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext); + function visitor(node: Node): VisitResult { + const substitution = substitutions.get(getNodeId(node).toString()); + return substitution ? getSynthesizedDeepClone(substitution) : visitEachChild(node, visitor, nullTransformationContext); } } -function getStatementsOrClassElements(scope: Scope): readonly ts.Statement[] | readonly ts.ClassElement[] { - if (ts.isFunctionLikeDeclaration(scope)) { +function getStatementsOrClassElements(scope: Scope): readonly Statement[] | readonly ClassElement[] { + if (isFunctionLikeDeclaration(scope)) { const body = scope.body!; // TODO: GH#18217 - if (ts.isBlock(body)) { + if (isBlock(body)) { return body.statements; } } - else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) { + else if (isModuleBlock(scope) || isSourceFile(scope)) { return scope.statements; } - else if (ts.isClassLike(scope)) { + else if (isClassLike(scope)) { return scope.members; } else { - ts.assertType(scope); + assertType(scope); } - return ts.emptyArray; + return emptyArray; } /** * If `scope` contains a function after `minPos`, then return the first such function. * Otherwise, return `undefined`. */ -function getNodeToInsertFunctionBefore(minPos: number, scope: Scope): ts.Statement | ts.ClassElement | undefined { - return ts.find(getStatementsOrClassElements(scope), child => - child.pos >= minPos && ts.isFunctionLikeDeclaration(child) && !ts.isConstructorDeclaration(child)); +function getNodeToInsertFunctionBefore(minPos: number, scope: Scope): Statement | ClassElement | undefined { + return find(getStatementsOrClassElements(scope), child => + child.pos >= minPos && isFunctionLikeDeclaration(child) && !isConstructorDeclaration(child)); } -function getNodeToInsertPropertyBefore(maxPos: number, scope: ts.ClassLikeDeclaration): ts.ClassElement { +function getNodeToInsertPropertyBefore(maxPos: number, scope: ClassLikeDeclaration): ClassElement { const members = scope.members; - ts.Debug.assert(members.length > 0, "Found no members"); // There must be at least one child, since we extracted from one. + Debug.assert(members.length > 0, "Found no members"); // There must be at least one child, since we extracted from one. - let prevMember: ts.ClassElement | undefined; + let prevMember: ClassElement | undefined; let allProperties = true; for (const member of members) { if (member.pos > maxPos) { return prevMember || members[0]; } - if (allProperties && !ts.isPropertyDeclaration(member)) { + if (allProperties && !isPropertyDeclaration(member)) { // If it is non-vacuously true that all preceding members are properties, // insert before the current member (i.e. at the end of the list of properties). if (prevMember !== undefined) { @@ -1528,12 +1556,12 @@ function getNodeToInsertPropertyBefore(maxPos: number, scope: ts.ClassLikeDeclar prevMember = member; } - if (prevMember === undefined) return ts.Debug.fail(); // If the loop didn't return, then it did set prevMember. + if (prevMember === undefined) return Debug.fail(); // If the loop didn't return, then it did set prevMember. return prevMember; } -function getNodeToInsertConstantBefore(node: ts.Node, scope: Scope): ts.Statement { - ts.Debug.assert(!ts.isClassLike(scope)); +function getNodeToInsertConstantBefore(node: Node, scope: Scope): Statement { + Debug.assert(!isClassLike(scope)); let prevScope: Scope | undefined; for (let curr = node; curr !== scope; curr = curr.parent) { @@ -1544,7 +1572,7 @@ function getNodeToInsertConstantBefore(node: ts.Node, scope: Scope): ts.Statemen for (let curr = (prevScope || node).parent; ; curr = curr.parent) { if (isBlockLike(curr)) { - let prevStatement: ts.Statement | undefined; + let prevStatement: Statement | undefined; for (const statement of curr.statements) { if (statement.pos > node.pos) { break; @@ -1552,26 +1580,26 @@ function getNodeToInsertConstantBefore(node: ts.Node, scope: Scope): ts.Statemen prevStatement = statement; } - if (!prevStatement && ts.isCaseClause(curr)) { + if (!prevStatement && isCaseClause(curr)) { // We must have been in the expression of the case clause. - ts.Debug.assert(ts.isSwitchStatement(curr.parent.parent), "Grandparent isn't a switch statement"); + Debug.assert(isSwitchStatement(curr.parent.parent), "Grandparent isn't a switch statement"); return curr.parent.parent; } // There must be at least one statement since we started in one. - return ts.Debug.checkDefined(prevStatement, "prevStatement failed to get set"); + return Debug.checkDefined(prevStatement, "prevStatement failed to get set"); } - ts.Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope"); + Debug.assert(curr !== scope, "Didn't encounter a block-like before encountering scope"); } } function getPropertyAssignmentsForWritesAndVariableDeclarations( - exposedVariableDeclarations: readonly ts.VariableDeclaration[], + exposedVariableDeclarations: readonly VariableDeclaration[], writes: readonly UsageEntry[] | undefined -): ts.ShorthandPropertyAssignment[] { - const variableAssignments = ts.map(exposedVariableDeclarations, v => ts.factory.createShorthandPropertyAssignment(v.symbol.name)); - const writeAssignments = ts.map(writes, w => ts.factory.createShorthandPropertyAssignment(w.symbol.name)); +): ShorthandPropertyAssignment[] { + const variableAssignments = map(exposedVariableDeclarations, v => factory.createShorthandPropertyAssignment(v.symbol.name)); + const writeAssignments = map(writes, w => factory.createShorthandPropertyAssignment(w.symbol.name)); // TODO: GH#18217 `variableAssignments` not possibly undefined! return variableAssignments === undefined @@ -1582,7 +1610,7 @@ function getPropertyAssignmentsForWritesAndVariableDeclarations( } function isReadonlyArray(v: any): v is readonly any[] { - return ts.isArray(v); + return isArray(v); } /** @@ -1594,9 +1622,9 @@ function isReadonlyArray(v: any): v is readonly any[] { * var someThing = foo + bar; * this returns ^-------^ */ -function getEnclosingTextRange(targetRange: TargetRange, sourceFile: ts.SourceFile): ts.TextRange { +function getEnclosingTextRange(targetRange: TargetRange, sourceFile: SourceFile): TextRange { return isReadonlyArray(targetRange.range) - ? { pos: ts.first(targetRange.range).getStart(sourceFile), end: ts.last(targetRange.range).getEnd() } + ? { pos: first(targetRange.range).getStart(sourceFile), end: last(targetRange.range).getEnd() } : targetRange.range; } @@ -1609,62 +1637,62 @@ const enum Usage { interface UsageEntry { readonly usage: Usage; - readonly symbol: ts.Symbol; - readonly node: ts.Node; + readonly symbol: Symbol; + readonly node: Node; } interface ScopeUsages { - readonly usages: ts.ESMap; - readonly typeParameterUsages: ts.ESMap; // Key is type ID - readonly substitutions: ts.ESMap; + readonly usages: ESMap; + readonly typeParameterUsages: ESMap; // Key is type ID + readonly substitutions: ESMap; } interface ReadsAndWrites { - readonly target: ts.Expression | ts.Block; + readonly target: Expression | Block; readonly usagesPerScope: readonly ScopeUsages[]; - readonly functionErrorsPerScope: readonly (readonly ts.Diagnostic[])[]; - readonly constantErrorsPerScope: readonly (readonly ts.Diagnostic[])[]; - readonly exposedVariableDeclarations: readonly ts.VariableDeclaration[]; + readonly functionErrorsPerScope: readonly (readonly Diagnostic[])[]; + readonly constantErrorsPerScope: readonly (readonly Diagnostic[])[]; + readonly exposedVariableDeclarations: readonly VariableDeclaration[]; } function collectReadsAndWrites( targetRange: TargetRange, scopes: Scope[], - enclosingTextRange: ts.TextRange, - sourceFile: ts.SourceFile, - checker: ts.TypeChecker, - cancellationToken: ts.CancellationToken): ReadsAndWrites { + enclosingTextRange: TextRange, + sourceFile: SourceFile, + checker: TypeChecker, + cancellationToken: CancellationToken): ReadsAndWrites { - const allTypeParameterUsages = new ts.Map(); // Key is type ID + const allTypeParameterUsages = new Map(); // Key is type ID const usagesPerScope: ScopeUsages[] = []; - const substitutionsPerScope: ts.ESMap[] = []; - const functionErrorsPerScope: ts.Diagnostic[][] = []; - const constantErrorsPerScope: ts.Diagnostic[][] = []; - const visibleDeclarationsInExtractedRange: ts.NamedDeclaration[] = []; - const exposedVariableSymbolSet = new ts.Map(); // Key is symbol ID - const exposedVariableDeclarations: ts.VariableDeclaration[] = []; - let firstExposedNonVariableDeclaration: ts.NamedDeclaration | undefined; + const substitutionsPerScope: ESMap[] = []; + const functionErrorsPerScope: Diagnostic[][] = []; + const constantErrorsPerScope: Diagnostic[][] = []; + const visibleDeclarationsInExtractedRange: NamedDeclaration[] = []; + const exposedVariableSymbolSet = new Map(); // Key is symbol ID + const exposedVariableDeclarations: VariableDeclaration[] = []; + let firstExposedNonVariableDeclaration: NamedDeclaration | undefined; const expression = !isReadonlyArray(targetRange.range) ? targetRange.range - : targetRange.range.length === 1 && ts.isExpressionStatement(targetRange.range[0]) + : targetRange.range.length === 1 && isExpressionStatement(targetRange.range[0]) ? targetRange.range[0].expression : undefined; - let expressionDiagnostic: ts.Diagnostic | undefined; + let expressionDiagnostic: Diagnostic | undefined; if (expression === undefined) { - const statements = targetRange.range as readonly ts.Statement[]; - const start = ts.first(statements).getStart(); - const end = ts.last(statements).end; - expressionDiagnostic = ts.createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected); + const statements = targetRange.range as readonly Statement[]; + const start = first(statements).getStart(); + const end = last(statements).end; + expressionDiagnostic = createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected); } - else if (checker.getTypeAtLocation(expression).flags & (ts.TypeFlags.Void | ts.TypeFlags.Never)) { - expressionDiagnostic = ts.createDiagnosticForNode(expression, Messages.uselessConstantType); + else if (checker.getTypeAtLocation(expression).flags & (TypeFlags.Void | TypeFlags.Never)) { + expressionDiagnostic = createDiagnosticForNode(expression, Messages.uselessConstantType); } // initialize results for (const scope of scopes) { - usagesPerScope.push({ usages: new ts.Map(), typeParameterUsages: new ts.Map(), substitutions: new ts.Map() }); - substitutionsPerScope.push(new ts.Map()); + usagesPerScope.push({ usages: new Map(), typeParameterUsages: new Map(), substitutions: new Map() }); + substitutionsPerScope.push(new Map()); functionErrorsPerScope.push([]); @@ -1672,20 +1700,20 @@ function collectReadsAndWrites( if (expressionDiagnostic) { constantErrors.push(expressionDiagnostic); } - if (ts.isClassLike(scope) && ts.isInJSFile(scope)) { - constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToJSClass)); + if (isClassLike(scope) && isInJSFile(scope)) { + constantErrors.push(createDiagnosticForNode(scope, Messages.cannotExtractToJSClass)); } - if (ts.isArrowFunction(scope) && !ts.isBlock(scope.body)) { + if (isArrowFunction(scope) && !isBlock(scope.body)) { // TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this - constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction)); + constantErrors.push(createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction)); } constantErrorsPerScope.push(constantErrors); } - const seenUsages = new ts.Map(); - const target = isReadonlyArray(targetRange.range) ? ts.factory.createBlock(targetRange.range) : targetRange.range; + const seenUsages = new Map(); + const target = isReadonlyArray(targetRange.range) ? factory.createBlock(targetRange.range) : targetRange.range; - const unmodifiedNode = isReadonlyArray(targetRange.range) ? ts.first(targetRange.range) : targetRange.range; + const unmodifiedNode = isReadonlyArray(targetRange.range) ? first(targetRange.range) : targetRange.range; const inGenericContext = isInGenericContext(unmodifiedNode); collectUsages(target); @@ -1693,16 +1721,16 @@ function collectReadsAndWrites( // Unfortunately, this code takes advantage of the knowledge that the generated method // will use the contextual type of an expression as the return type of the extracted // method (and will therefore "use" all the types involved). - if (inGenericContext && !isReadonlyArray(targetRange.range) && !ts.isJsxAttribute(targetRange.range)) { + if (inGenericContext && !isReadonlyArray(targetRange.range) && !isJsxAttribute(targetRange.range)) { const contextualType = checker.getContextualType(targetRange.range)!; // TODO: GH#18217 recordTypeParameterUsages(contextualType); } if (allTypeParameterUsages.size > 0) { - const seenTypeParameterUsages = new ts.Map(); // Key is type ID + const seenTypeParameterUsages = new Map(); // Key is type ID let i = 0; - for (let curr: ts.Node = unmodifiedNode; curr !== undefined && i < scopes.length; curr = curr.parent) { + for (let curr: Node = unmodifiedNode; curr !== undefined && i < scopes.length; curr = curr.parent) { if (curr === scopes[i]) { // Copy current contents of seenTypeParameterUsages into scope. seenTypeParameterUsages.forEach((typeParameter, id) => { @@ -1713,9 +1741,9 @@ function collectReadsAndWrites( } // Note that we add the current node's type parameters *after* updating the corresponding scope. - if (ts.isDeclarationWithTypeParameters(curr)) { - for (const typeParameterDecl of ts.getEffectiveTypeParameterDeclarations(curr)) { - const typeParameter = checker.getTypeAtLocation(typeParameterDecl) as ts.TypeParameter; + if (isDeclarationWithTypeParameters(curr)) { + for (const typeParameterDecl of getEffectiveTypeParameterDeclarations(curr)) { + const typeParameter = checker.getTypeAtLocation(typeParameterDecl) as TypeParameter; if (allTypeParameterUsages.has(typeParameter.id.toString())) { seenTypeParameterUsages.set(typeParameter.id.toString(), typeParameter); } @@ -1726,16 +1754,16 @@ function collectReadsAndWrites( // If we didn't get through all the scopes, then there were some that weren't in our // parent chain (impossible at time of writing). A conservative solution would be to // copy allTypeParameterUsages into all remaining scopes. - ts.Debug.assert(i === scopes.length, "Should have iterated all scopes"); + Debug.assert(i === scopes.length, "Should have iterated all scopes"); } // If there are any declarations in the extracted block that are used in the same enclosing // lexical scope, we can't move the extraction "up" as those declarations will become unreachable if (visibleDeclarationsInExtractedRange.length) { - const containingLexicalScopeOfExtraction = ts.isBlockScope(scopes[0], scopes[0].parent) + const containingLexicalScopeOfExtraction = isBlockScope(scopes[0], scopes[0].parent) ? scopes[0] - : ts.getEnclosingBlockScopeContainer(scopes[0]); - ts.forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations); + : getEnclosingBlockScopeContainer(scopes[0]); + forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations); } for (let i = 0; i < scopes.length; i++) { @@ -1745,41 +1773,41 @@ function collectReadsAndWrites( // local will actually be declared at the same level as the extracted expression). if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) { const errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range; - constantErrorsPerScope[i].push(ts.createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes)); + constantErrorsPerScope[i].push(createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes)); } - if (targetRange.facts & RangeFacts.UsesThisInFunction && ts.isClassLike(scopes[i])) { - functionErrorsPerScope[i].push(ts.createDiagnosticForNode(targetRange.thisNode!, Messages.cannotExtractFunctionsContainingThisToMethod)); + if (targetRange.facts & RangeFacts.UsesThisInFunction && isClassLike(scopes[i])) { + functionErrorsPerScope[i].push(createDiagnosticForNode(targetRange.thisNode!, Messages.cannotExtractFunctionsContainingThisToMethod)); } let hasWrite = false; - let readonlyClassPropertyWrite: ts.Declaration | undefined; + let readonlyClassPropertyWrite: Declaration | undefined; usagesPerScope[i].usages.forEach(value => { if (value.usage === Usage.Write) { hasWrite = true; - if (value.symbol.flags & ts.SymbolFlags.ClassMember && + if (value.symbol.flags & SymbolFlags.ClassMember && value.symbol.valueDeclaration && - ts.hasEffectiveModifier(value.symbol.valueDeclaration, ts.ModifierFlags.Readonly)) { + hasEffectiveModifier(value.symbol.valueDeclaration, ModifierFlags.Readonly)) { readonlyClassPropertyWrite = value.symbol.valueDeclaration; } } }); // If an expression was extracted, then there shouldn't have been any variable declarations. - ts.Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0, "No variable declarations expected if something was extracted"); + Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0, "No variable declarations expected if something was extracted"); if (hasWrite && !isReadonlyArray(targetRange.range)) { - const diag = ts.createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression); + const diag = createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } else if (readonlyClassPropertyWrite && i > 0) { - const diag = ts.createDiagnosticForNode(readonlyClassPropertyWrite, Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor); + const diag = createDiagnosticForNode(readonlyClassPropertyWrite, Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } else if (firstExposedNonVariableDeclaration) { - const diag = ts.createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.cannotExtractExportedEntity); + const diag = createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.cannotExtractExportedEntity); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } @@ -1787,11 +1815,11 @@ function collectReadsAndWrites( return { target, usagesPerScope, functionErrorsPerScope, constantErrorsPerScope, exposedVariableDeclarations }; - function isInGenericContext(node: ts.Node) { - return !!ts.findAncestor(node, n => ts.isDeclarationWithTypeParameters(n) && ts.getEffectiveTypeParameterDeclarations(n).length !== 0); + function isInGenericContext(node: Node) { + return !!findAncestor(node, n => isDeclarationWithTypeParameters(n) && getEffectiveTypeParameterDeclarations(n).length !== 0); } - function recordTypeParameterUsages(type: ts.Type) { + function recordTypeParameterUsages(type: Type) { // PERF: This is potentially very expensive. `type` could be a library type with // a lot of properties, each of which the walker will visit. Unfortunately, the // solution isn't as trivial as filtering to user types because of (e.g.) Array. @@ -1805,65 +1833,65 @@ function collectReadsAndWrites( } } - function collectUsages(node: ts.Node, valueUsage = Usage.Read) { + function collectUsages(node: Node, valueUsage = Usage.Read) { if (inGenericContext) { const type = checker.getTypeAtLocation(node); recordTypeParameterUsages(type); } - if (ts.isDeclaration(node) && node.symbol) { + if (isDeclaration(node) && node.symbol) { visibleDeclarationsInExtractedRange.push(node); } - if (ts.isAssignmentExpression(node)) { + if (isAssignmentExpression(node)) { // use 'write' as default usage for values collectUsages(node.left, Usage.Write); collectUsages(node.right); } - else if (ts.isUnaryExpressionWithWrite(node)) { + else if (isUnaryExpressionWithWrite(node)) { collectUsages(node.operand, Usage.Write); } - else if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) { + else if (isPropertyAccessExpression(node) || isElementAccessExpression(node)) { // use 'write' as default usage for values - ts.forEachChild(node, collectUsages); + forEachChild(node, collectUsages); } - else if (ts.isIdentifier(node)) { + else if (isIdentifier(node)) { if (!node.parent) { return; } - if (ts.isQualifiedName(node.parent) && node !== node.parent.left) { + if (isQualifiedName(node.parent) && node !== node.parent.left) { return; } - if (ts.isPropertyAccessExpression(node.parent) && node !== node.parent.expression) { + if (isPropertyAccessExpression(node.parent) && node !== node.parent.expression) { return; } - recordUsage(node, valueUsage, /*isTypeNode*/ ts.isPartOfTypeNode(node)); + recordUsage(node, valueUsage, /*isTypeNode*/ isPartOfTypeNode(node)); } else { - ts.forEachChild(node, collectUsages); + forEachChild(node, collectUsages); } } - function recordUsage(n: ts.Identifier, usage: Usage, isTypeNode: boolean) { + function recordUsage(n: Identifier, usage: Usage, isTypeNode: boolean) { const symbolId = recordUsagebySymbol(n, usage, isTypeNode); if (symbolId) { for (let i = 0; i < scopes.length; i++) { // push substitution from map to map to simplify rewriting const substitution = substitutionsPerScope[i].get(symbolId); if (substitution) { - usagesPerScope[i].substitutions.set(ts.getNodeId(n).toString(), substitution); + usagesPerScope[i].substitutions.set(getNodeId(n).toString(), substitution); } } } } - function recordUsagebySymbol(identifier: ts.Identifier, usage: Usage, isTypeName: boolean) { + function recordUsagebySymbol(identifier: Identifier, usage: Usage, isTypeName: boolean) { const symbol = getSymbolReferencedByIdentifier(identifier); if (!symbol) { // cannot find symbol - do nothing return undefined; } - const symbolId = ts.getSymbolId(symbol).toString(); + const symbolId = getSymbolId(symbol).toString(); const lastUsage = seenUsages.get(symbolId); // there are two kinds of value usages // - reads - if range contains a read from the value located outside of the range then value should be passed as a parameter @@ -1889,18 +1917,18 @@ function collectReadsAndWrites( } // find first declaration in this file const decls = symbol.getDeclarations(); - const declInFile = decls && ts.find(decls, d => d.getSourceFile() === sourceFile); + const declInFile = decls && find(decls, d => d.getSourceFile() === sourceFile); if (!declInFile) { return undefined; } - if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { + if (rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) { // declaration is located in range to be extracted - do nothing return undefined; } if (targetRange.facts & RangeFacts.IsGenerator && usage === Usage.Write) { // this is write to a reference located outside of the target scope and range is extracted into generator // currently this is unsupported scenario - const diag = ts.createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); + const diag = createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators); for (const errors of functionErrorsPerScope) { errors.push(diag); } @@ -1922,8 +1950,8 @@ function collectReadsAndWrites( else if (isTypeName) { // If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument // so there's no problem. - if (!(symbol.flags & ts.SymbolFlags.TypeParameter)) { - const diag = ts.createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope); + if (!(symbol.flags & SymbolFlags.TypeParameter)) { + const diag = createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope); functionErrorsPerScope[i].push(diag); constantErrorsPerScope[i].push(diag); } @@ -1936,20 +1964,20 @@ function collectReadsAndWrites( return symbolId; } - function checkForUsedDeclarations(node: ts.Node) { + function checkForUsedDeclarations(node: Node) { // If this node is entirely within the original extraction range, we don't need to do anything. - if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node as ts.Statement) >= 0)) { + if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node as Statement) >= 0)) { return; } // Otherwise check and recurse. - const sym = ts.isIdentifier(node) + const sym = isIdentifier(node) ? getSymbolReferencedByIdentifier(node) : checker.getSymbolAtLocation(node); if (sym) { - const decl = ts.find(visibleDeclarationsInExtractedRange, d => d.symbol === sym); + const decl = find(visibleDeclarationsInExtractedRange, d => d.symbol === sym); if (decl) { - if (ts.isVariableDeclaration(decl)) { + if (isVariableDeclaration(decl)) { const idString = decl.symbol.id!.toString(); if (!exposedVariableSymbolSet.has(idString)) { exposedVariableDeclarations.push(decl); @@ -1964,40 +1992,40 @@ function collectReadsAndWrites( } } - ts.forEachChild(node, checkForUsedDeclarations); + forEachChild(node, checkForUsedDeclarations); } /** * Return the symbol referenced by an identifier (even if it declares a different symbol). */ - function getSymbolReferencedByIdentifier(identifier: ts.Identifier) { + function getSymbolReferencedByIdentifier(identifier: Identifier) { // If the identifier is both a property name and its value, we're only interested in its value // (since the name is a declaration and will be included in the extracted range). - return identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier + return identifier.parent && isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier ? checker.getShorthandAssignmentValueSymbol(identifier.parent) : checker.getSymbolAtLocation(identifier); } - function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: ts.Symbol | undefined, scopeDecl: ts.Node, isTypeNode: boolean): ts.PropertyAccessExpression | ts.EntityName | undefined { + function tryReplaceWithQualifiedNameOrPropertyAccess(symbol: Symbol | undefined, scopeDecl: Node, isTypeNode: boolean): PropertyAccessExpression | EntityName | undefined { if (!symbol) { return undefined; } const decls = symbol.getDeclarations(); if (decls && decls.some(d => d.parent === scopeDecl)) { - return ts.factory.createIdentifier(symbol.name); + return factory.createIdentifier(symbol.name); } const prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode); if (prefix === undefined) { return undefined; } return isTypeNode - ? ts.factory.createQualifiedName(prefix as ts.EntityName, ts.factory.createIdentifier(symbol.name)) - : ts.factory.createPropertyAccessExpression(prefix as ts.Expression, symbol.name); + ? factory.createQualifiedName(prefix as EntityName, factory.createIdentifier(symbol.name)) + : factory.createPropertyAccessExpression(prefix as Expression, symbol.name); } } -function getExtractableParent(node: ts.Node | undefined): ts.Node | undefined { - return ts.findAncestor(node, node => node.parent && isExtractableExpression(node) && !ts.isBinaryExpression(node.parent)); +function getExtractableParent(node: Node | undefined): Node | undefined { + return findAncestor(node, node => node.parent && isExtractableExpression(node) && !isBinaryExpression(node.parent)); } /** @@ -2007,48 +2035,48 @@ function getExtractableParent(node: ts.Node | undefined): ts.Node | undefined { * such as `import x from 'y'` -- the 'y' is a StringLiteral but is *not* an expression * in the sense of something that you could extract on */ -function isExtractableExpression(node: ts.Node): boolean { +function isExtractableExpression(node: Node): boolean { const { parent } = node; switch (parent.kind) { - case ts.SyntaxKind.EnumMember: + case SyntaxKind.EnumMember: return false; } switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - return parent.kind !== ts.SyntaxKind.ImportDeclaration && - parent.kind !== ts.SyntaxKind.ImportSpecifier; + case SyntaxKind.StringLiteral: + return parent.kind !== SyntaxKind.ImportDeclaration && + parent.kind !== SyntaxKind.ImportSpecifier; - case ts.SyntaxKind.SpreadElement: - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.BindingElement: + case SyntaxKind.SpreadElement: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.BindingElement: return false; - case ts.SyntaxKind.Identifier: - return parent.kind !== ts.SyntaxKind.BindingElement && - parent.kind !== ts.SyntaxKind.ImportSpecifier && - parent.kind !== ts.SyntaxKind.ExportSpecifier; + case SyntaxKind.Identifier: + return parent.kind !== SyntaxKind.BindingElement && + parent.kind !== SyntaxKind.ImportSpecifier && + parent.kind !== SyntaxKind.ExportSpecifier; } return true; } -function isBlockLike(node: ts.Node): node is ts.BlockLike { +function isBlockLike(node: Node): node is BlockLike { switch (node.kind) { - case ts.SyntaxKind.Block: - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.CaseClause: + case SyntaxKind.Block: + case SyntaxKind.SourceFile: + case SyntaxKind.ModuleBlock: + case SyntaxKind.CaseClause: return true; default: return false; } } -function isInJSXContent(node: ts.Node) { +function isInJSXContent(node: Node) { return isStringLiteralJsxAttribute(node) || - (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node)) && (ts.isJsxElement(node.parent) || ts.isJsxFragment(node.parent)); + (isJsxElement(node) || isJsxSelfClosingElement(node) || isJsxFragment(node)) && (isJsxElement(node.parent) || isJsxFragment(node.parent)); } -function isStringLiteralJsxAttribute(node: ts.Node): node is ts.StringLiteral { - return ts.isStringLiteral(node) && node.parent && ts.isJsxAttribute(node.parent); +function isStringLiteralJsxAttribute(node: Node): node is StringLiteral { + return isStringLiteral(node) && node.parent && isJsxAttribute(node.parent); } diff --git a/src/services/refactors/extractType.ts b/src/services/refactors/extractType.ts index fa44567a61798..a026a1091455b 100644 --- a/src/services/refactors/extractType.ts +++ b/src/services/refactors/extractType.ts @@ -1,46 +1,58 @@ -import * as ts from "../_namespaces/ts"; +import { + addRange, addToSeen, append, ApplicableRefactorInfo, cast, concatenate, createTextRangeFromSpan, Debug, Diagnostics, + EmitFlags, emptyArray, factory, findAncestor, forEach, forEachChild, getEffectiveConstraintOfTypeParameter, + getLineAndCharacterOfPosition, getLocaleSpecificMessage, getNameFromPropertyName, getRefactorContextSpan, + getRenameLocation, getTokenAtPosition, getUniqueName, ignoreSourceNewlines, isConditionalTypeNode, isFunctionLike, + isIdentifier, isInferTypeNode, isIntersectionTypeNode, isJSDocTypeExpression, isParenthesizedTypeNode, + isSourceFileJS, isStatement, isThisIdentifier, isThisTypeNode, isTupleTypeNode, isTypeLiteralNode, isTypeNode, + isTypeParameterDeclaration, isTypePredicateNode, isTypeQueryNode, isTypeReferenceNode, JSDocTag, JSDocTemplateTag, + Map, Node, nodeOverlapsWithStartEnd, pushIfUnique, rangeContainsStartEnd, RefactorContext, RefactorEditInfo, + setEmitFlags, setTextRange, skipTrivia, SourceFile, Statement, SymbolFlags, textChanges, TextRange, TypeChecker, + TypeElement, TypeNode, TypeParameterDeclaration, +} from "../_namespaces/ts"; +import { isRefactorErrorInfo, RefactorErrorInfo, registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Extract type"; const extractToTypeAliasAction = { name: "Extract to type alias", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_type_alias), + description: getLocaleSpecificMessage(Diagnostics.Extract_to_type_alias), kind: "refactor.extract.type", }; const extractToInterfaceAction = { name: "Extract to interface", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_interface), + description: getLocaleSpecificMessage(Diagnostics.Extract_to_interface), kind: "refactor.extract.interface", }; const extractToTypeDefAction = { name: "Extract to typedef", - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_typedef), + description: getLocaleSpecificMessage(Diagnostics.Extract_to_typedef), kind: "refactor.extract.typedef" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [ extractToTypeAliasAction.kind, extractToInterfaceAction.kind, extractToTypeDefAction.kind ], - getAvailableActions: function getRefactorActionsToExtractType(context): readonly ts.ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToExtractType(context): readonly ApplicableRefactorInfo[] { const info = getRangeToExtract(context, context.triggerReason === "invoked"); - if (!info) return ts.emptyArray; + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { return [{ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_type), + description: getLocaleSpecificMessage(Diagnostics.Extract_type), actions: info.isJS ? - [extractToTypeDefAction] : ts.append([extractToTypeAliasAction], info.typeElements && extractToInterfaceAction) + [extractToTypeDefAction] : append([extractToTypeAliasAction], info.typeElements && extractToInterfaceAction) }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, - description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_type), + description: getLocaleSpecificMessage(Diagnostics.Extract_type), actions: [ { ...extractToTypeDefAction, notApplicableReason: info.error }, { ...extractToTypeAliasAction, notApplicableReason: info.error }, @@ -49,105 +61,105 @@ ts.refactor.registerRefactor(refactorName, { }]; } - return ts.emptyArray; + return emptyArray; }, - getEditsForAction: function getRefactorEditsToExtractType(context, actionName): ts.RefactorEditInfo { + getEditsForAction: function getRefactorEditsToExtractType(context, actionName): RefactorEditInfo { const { file, } = context; const info = getRangeToExtract(context); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected to find a range to extract"); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected to find a range to extract"); - const name = ts.getUniqueName("NewType", file); - const edits = ts.textChanges.ChangeTracker.with(context, changes => { + const name = getUniqueName("NewType", file); + const edits = textChanges.ChangeTracker.with(context, changes => { switch (actionName) { case extractToTypeAliasAction.name: - ts.Debug.assert(!info.isJS, "Invalid actionName/JS combo"); + Debug.assert(!info.isJS, "Invalid actionName/JS combo"); return doTypeAliasChange(changes, file, name, info); case extractToTypeDefAction.name: - ts.Debug.assert(info.isJS, "Invalid actionName/JS combo"); + Debug.assert(info.isJS, "Invalid actionName/JS combo"); return doTypedefChange(changes, file, name, info); case extractToInterfaceAction.name: - ts.Debug.assert(!info.isJS && !!info.typeElements, "Invalid actionName/JS combo"); + Debug.assert(!info.isJS && !!info.typeElements, "Invalid actionName/JS combo"); return doInterfaceChange(changes, file, name, info as InterfaceInfo); default: - ts.Debug.fail("Unexpected action name"); + Debug.fail("Unexpected action name"); } }); const renameFilename = file.fileName; - const renameLocation = ts.getRenameLocation(edits, renameFilename, name, /*preferLastLocation*/ false); + const renameLocation = getRenameLocation(edits, renameFilename, name, /*preferLastLocation*/ false); return { edits, renameFilename, renameLocation }; } }); interface TypeAliasInfo { - isJS: boolean; selection: ts.TypeNode; firstStatement: ts.Statement; typeParameters: readonly ts.TypeParameterDeclaration[]; typeElements?: readonly ts.TypeElement[]; + isJS: boolean; selection: TypeNode; firstStatement: Statement; typeParameters: readonly TypeParameterDeclaration[]; typeElements?: readonly TypeElement[]; } interface InterfaceInfo { - isJS: boolean; selection: ts.TypeNode; firstStatement: ts.Statement; typeParameters: readonly ts.TypeParameterDeclaration[]; typeElements: readonly ts.TypeElement[]; + isJS: boolean; selection: TypeNode; firstStatement: Statement; typeParameters: readonly TypeParameterDeclaration[]; typeElements: readonly TypeElement[]; } type ExtractInfo = TypeAliasInfo | InterfaceInfo; -function getRangeToExtract(context: ts.RefactorContext, considerEmptySpans = true): ExtractInfo | ts.refactor.RefactorErrorInfo | undefined { +function getRangeToExtract(context: RefactorContext, considerEmptySpans = true): ExtractInfo | RefactorErrorInfo | undefined { const { file, startPosition } = context; - const isJS = ts.isSourceFileJS(file); - const current = ts.getTokenAtPosition(file, startPosition); - const range = ts.createTextRangeFromSpan(ts.getRefactorContextSpan(context)); + const isJS = isSourceFileJS(file); + const current = getTokenAtPosition(file, startPosition); + const range = createTextRangeFromSpan(getRefactorContextSpan(context)); const cursorRequest = range.pos === range.end && considerEmptySpans; - const selection = ts.findAncestor(current, (node => node.parent && ts.isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) && - (cursorRequest || ts.nodeOverlapsWithStartEnd(current, file, range.pos, range.end)))); - if (!selection || !ts.isTypeNode(selection)) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Selection_is_not_a_valid_type_node) }; + const selection = findAncestor(current, (node => node.parent && isTypeNode(node) && !rangeContainsSkipTrivia(range, node.parent, file) && + (cursorRequest || nodeOverlapsWithStartEnd(current, file, range.pos, range.end)))); + if (!selection || !isTypeNode(selection)) return { error: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_type_node) }; const checker = context.program.getTypeChecker(); - const firstStatement = ts.Debug.checkDefined(ts.findAncestor(selection, ts.isStatement), "Should find a statement"); + const firstStatement = Debug.checkDefined(findAncestor(selection, isStatement), "Should find a statement"); const typeParameters = collectTypeParameters(checker, selection, firstStatement, file); - if (!typeParameters) return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.No_type_could_be_extracted_from_this_type_node) }; + if (!typeParameters) return { error: getLocaleSpecificMessage(Diagnostics.No_type_could_be_extracted_from_this_type_node) }; const typeElements = flattenTypeLiteralNodeReference(checker, selection); return { isJS, selection, firstStatement, typeParameters, typeElements }; } -function flattenTypeLiteralNodeReference(checker: ts.TypeChecker, node: ts.TypeNode | undefined): readonly ts.TypeElement[] | undefined { +function flattenTypeLiteralNodeReference(checker: TypeChecker, node: TypeNode | undefined): readonly TypeElement[] | undefined { if (!node) return undefined; - if (ts.isIntersectionTypeNode(node)) { - const result: ts.TypeElement[] = []; - const seen = new ts.Map(); + if (isIntersectionTypeNode(node)) { + const result: TypeElement[] = []; + const seen = new Map(); for (const type of node.types) { const flattenedTypeMembers = flattenTypeLiteralNodeReference(checker, type); - if (!flattenedTypeMembers || !flattenedTypeMembers.every(type => type.name && ts.addToSeen(seen, ts.getNameFromPropertyName(type.name) as string))) { + if (!flattenedTypeMembers || !flattenedTypeMembers.every(type => type.name && addToSeen(seen, getNameFromPropertyName(type.name) as string))) { return undefined; } - ts.addRange(result, flattenedTypeMembers); + addRange(result, flattenedTypeMembers); } return result; } - else if (ts.isParenthesizedTypeNode(node)) { + else if (isParenthesizedTypeNode(node)) { return flattenTypeLiteralNodeReference(checker, node.type); } - else if (ts.isTypeLiteralNode(node)) { + else if (isTypeLiteralNode(node)) { return node.members; } return undefined; } -function rangeContainsSkipTrivia(r1: ts.TextRange, node: ts.Node, file: ts.SourceFile): boolean { - return ts.rangeContainsStartEnd(r1, ts.skipTrivia(file.text, node.pos), node.end); +function rangeContainsSkipTrivia(r1: TextRange, node: Node, file: SourceFile): boolean { + return rangeContainsStartEnd(r1, skipTrivia(file.text, node.pos), node.end); } -function collectTypeParameters(checker: ts.TypeChecker, selection: ts.TypeNode, statement: ts.Statement, file: ts.SourceFile): ts.TypeParameterDeclaration[] | undefined { - const result: ts.TypeParameterDeclaration[] = []; +function collectTypeParameters(checker: TypeChecker, selection: TypeNode, statement: Statement, file: SourceFile): TypeParameterDeclaration[] | undefined { + const result: TypeParameterDeclaration[] = []; return visitor(selection) ? undefined : result; - function visitor(node: ts.Node): true | undefined { - if (ts.isTypeReferenceNode(node)) { - if (ts.isIdentifier(node.typeName)) { + function visitor(node: Node): true | undefined { + if (isTypeReferenceNode(node)) { + if (isIdentifier(node.typeName)) { const typeName = node.typeName; - const symbol = checker.resolveName(typeName.text, typeName, ts.SymbolFlags.TypeParameter, /* excludeGlobals */ true); - for (const decl of symbol?.declarations || ts.emptyArray) { - if (ts.isTypeParameterDeclaration(decl) && decl.getSourceFile() === file) { + const symbol = checker.resolveName(typeName.text, typeName, SymbolFlags.TypeParameter, /* excludeGlobals */ true); + for (const decl of symbol?.declarations || emptyArray) { + if (isTypeParameterDeclaration(decl) && decl.getSourceFile() === file) { // skip extraction if the type node is in the range of the type parameter declaration. // function foo(): void; if (decl.name.escapedText === typeName.escapedText && rangeContainsSkipTrivia(decl, selection, file)) { @@ -155,97 +167,97 @@ function collectTypeParameters(checker: ts.TypeChecker, selection: ts.TypeNode, } if (rangeContainsSkipTrivia(statement, decl, file) && !rangeContainsSkipTrivia(selection, decl, file)) { - ts.pushIfUnique(result, decl); + pushIfUnique(result, decl); break; } } } } } - else if (ts.isInferTypeNode(node)) { - const conditionalTypeNode = ts.findAncestor(node, n => ts.isConditionalTypeNode(n) && rangeContainsSkipTrivia(n.extendsType, node, file)); + else if (isInferTypeNode(node)) { + const conditionalTypeNode = findAncestor(node, n => isConditionalTypeNode(n) && rangeContainsSkipTrivia(n.extendsType, node, file)); if (!conditionalTypeNode || !rangeContainsSkipTrivia(selection, conditionalTypeNode, file)) { return true; } } - else if ((ts.isTypePredicateNode(node) || ts.isThisTypeNode(node))) { - const functionLikeNode = ts.findAncestor(node.parent, ts.isFunctionLike); + else if ((isTypePredicateNode(node) || isThisTypeNode(node))) { + const functionLikeNode = findAncestor(node.parent, isFunctionLike); if (functionLikeNode && functionLikeNode.type && rangeContainsSkipTrivia(functionLikeNode.type, node, file) && !rangeContainsSkipTrivia(selection, functionLikeNode, file)) { return true; } } - else if (ts.isTypeQueryNode(node)) { - if (ts.isIdentifier(node.exprName)) { - const symbol = checker.resolveName(node.exprName.text, node.exprName, ts.SymbolFlags.Value, /* excludeGlobals */ false); + else if (isTypeQueryNode(node)) { + if (isIdentifier(node.exprName)) { + const symbol = checker.resolveName(node.exprName.text, node.exprName, SymbolFlags.Value, /* excludeGlobals */ false); if (symbol?.valueDeclaration && rangeContainsSkipTrivia(statement, symbol.valueDeclaration, file) && !rangeContainsSkipTrivia(selection, symbol.valueDeclaration, file)) { return true; } } else { - if (ts.isThisIdentifier(node.exprName.left) && !rangeContainsSkipTrivia(selection, node.parent, file)) { + if (isThisIdentifier(node.exprName.left) && !rangeContainsSkipTrivia(selection, node.parent, file)) { return true; } } } - if (file && ts.isTupleTypeNode(node) && (ts.getLineAndCharacterOfPosition(file, node.pos).line === ts.getLineAndCharacterOfPosition(file, node.end).line)) { - ts.setEmitFlags(node, ts.EmitFlags.SingleLine); + if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) { + setEmitFlags(node, EmitFlags.SingleLine); } - return ts.forEachChild(node, visitor); + return forEachChild(node, visitor); } } -function doTypeAliasChange(changes: ts.textChanges.ChangeTracker, file: ts.SourceFile, name: string, info: TypeAliasInfo) { +function doTypeAliasChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: TypeAliasInfo) { const { firstStatement, selection, typeParameters } = info; - const newTypeNode = ts.factory.createTypeAliasDeclaration( + const newTypeNode = factory.createTypeAliasDeclaration( /* modifiers */ undefined, name, - typeParameters.map(id => ts.factory.updateTypeParameterDeclaration(id, id.modifiers, id.name, id.constraint, /* defaultType */ undefined)), + typeParameters.map(id => factory.updateTypeParameterDeclaration(id, id.modifiers, id.name, id.constraint, /* defaultType */ undefined)), selection ); - changes.insertNodeBefore(file, firstStatement, ts.ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); - changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(id => ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined))), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.ExcludeWhitespace }); + changes.insertNodeBefore(file, firstStatement, ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined))), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace }); } -function doInterfaceChange(changes: ts.textChanges.ChangeTracker, file: ts.SourceFile, name: string, info: InterfaceInfo) { +function doInterfaceChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: InterfaceInfo) { const { firstStatement, selection, typeParameters, typeElements } = info; - const newTypeNode = ts.factory.createInterfaceDeclaration( + const newTypeNode = factory.createInterfaceDeclaration( /* modifiers */ undefined, name, typeParameters, /* heritageClauses */ undefined, typeElements ); - ts.setTextRange(newTypeNode, typeElements[0]?.parent); - changes.insertNodeBefore(file, firstStatement, ts.ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); - changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(id => ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined))), { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: ts.textChanges.TrailingTriviaOption.ExcludeWhitespace }); + setTextRange(newTypeNode, typeElements[0]?.parent); + changes.insertNodeBefore(file, firstStatement, ignoreSourceNewlines(newTypeNode), /* blankLineBetween */ true); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined))), { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude, trailingTriviaOption: textChanges.TrailingTriviaOption.ExcludeWhitespace }); } -function doTypedefChange(changes: ts.textChanges.ChangeTracker, file: ts.SourceFile, name: string, info: ExtractInfo) { +function doTypedefChange(changes: textChanges.ChangeTracker, file: SourceFile, name: string, info: ExtractInfo) { const { firstStatement, selection, typeParameters } = info; - ts.setEmitFlags(selection, ts.EmitFlags.NoComments | ts.EmitFlags.NoNestedComments); + setEmitFlags(selection, EmitFlags.NoComments | EmitFlags.NoNestedComments); - const node = ts.factory.createJSDocTypedefTag( - ts.factory.createIdentifier("typedef"), - ts.factory.createJSDocTypeExpression(selection), - ts.factory.createIdentifier(name)); + const node = factory.createJSDocTypedefTag( + factory.createIdentifier("typedef"), + factory.createJSDocTypeExpression(selection), + factory.createIdentifier(name)); - const templates: ts.JSDocTemplateTag[] = []; - ts.forEach(typeParameters, typeParameter => { - const constraint = ts.getEffectiveConstraintOfTypeParameter(typeParameter); - const parameter = ts.factory.createTypeParameterDeclaration(/*modifiers*/ undefined, typeParameter.name); - const template = ts.factory.createJSDocTemplateTag( - ts.factory.createIdentifier("template"), - constraint && ts.cast(constraint, ts.isJSDocTypeExpression), + const templates: JSDocTemplateTag[] = []; + forEach(typeParameters, typeParameter => { + const constraint = getEffectiveConstraintOfTypeParameter(typeParameter); + const parameter = factory.createTypeParameterDeclaration(/*modifiers*/ undefined, typeParameter.name); + const template = factory.createJSDocTemplateTag( + factory.createIdentifier("template"), + constraint && cast(constraint, isJSDocTypeExpression), [parameter] ); templates.push(template); }); - changes.insertNodeBefore(file, firstStatement, ts.factory.createJSDocComment(/* comment */ undefined, ts.factory.createNodeArray(ts.concatenate(templates, [node]))), /* blankLineBetween */ true); - changes.replaceNode(file, selection, ts.factory.createTypeReferenceNode(name, typeParameters.map(id => ts.factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); + changes.insertNodeBefore(file, firstStatement, factory.createJSDocComment(/* comment */ undefined, factory.createNodeArray(concatenate(templates, [node]))), /* blankLineBetween */ true); + changes.replaceNode(file, selection, factory.createTypeReferenceNode(name, typeParameters.map(id => factory.createTypeReferenceNode(id.name, /* typeArguments */ undefined)))); } diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index b3559d1d3a242..d8d70a1ea3abf 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -1,35 +1,39 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, codefix, Debug, Diagnostics, emptyArray, getRenameLocation, isIdentifier, isParameter, + RefactorContext, +} from "../_namespaces/ts"; +import { isRefactorErrorInfo, registerRefactor } from "../_namespaces/ts.refactor"; const actionName = "Generate 'get' and 'set' accessors"; -const actionDescription = ts.Diagnostics.Generate_get_and_set_accessors.message; +const actionDescription = Diagnostics.Generate_get_and_set_accessors.message; const generateGetSetAction = { name: actionName, description: actionDescription, kind: "refactor.rewrite.property.generateAccessors", }; -ts.refactor.registerRefactor(actionName, { +registerRefactor(actionName, { kinds: [generateGetSetAction.kind], getEditsForAction: function getRefactorActionsToGenerateGetAndSetAccessors(context, actionName) { if (!context.endPosition) return undefined; - const info = ts.codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition); - ts.Debug.assert(info && !ts.refactor.isRefactorErrorInfo(info), "Expected applicable refactor info"); - const edits = ts.codefix.generateAccessorFromProperty(context.file, context.program, context.startPosition, context.endPosition, context, actionName); + const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition); + Debug.assert(info && !isRefactorErrorInfo(info), "Expected applicable refactor info"); + const edits = codefix.generateAccessorFromProperty(context.file, context.program, context.startPosition, context.endPosition, context, actionName); if (!edits) return undefined; const renameFilename = context.file.fileName; const nameNeedRename = info.renameAccessor ? info.accessorName : info.fieldName; - const renameLocationOffset = ts.isIdentifier(nameNeedRename) ? 0 : -1; - const renameLocation = renameLocationOffset + ts.getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ ts.isParameter(info.declaration)); + const renameLocationOffset = isIdentifier(nameNeedRename) ? 0 : -1; + const renameLocation = renameLocationOffset + getRenameLocation(edits, renameFilename, nameNeedRename.text, /*preferLastLocation*/ isParameter(info.declaration)); return { renameFilename, renameLocation, edits }; }, - getAvailableActions(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { - if (!context.endPosition) return ts.emptyArray; - const info = ts.codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition, context.triggerReason === "invoked"); - if (!info) return ts.emptyArray; + getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[] { + if (!context.endPosition) return emptyArray; + const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition, context.triggerReason === "invoked"); + if (!info) return emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!isRefactorErrorInfo(info)) { return [{ name: actionName, description: actionDescription, @@ -45,6 +49,6 @@ ts.refactor.registerRefactor(actionName, { }]; } - return ts.emptyArray; + return emptyArray; } }); diff --git a/src/services/refactors/inferFunctionReturnType.ts b/src/services/refactors/inferFunctionReturnType.ts index ca1989188a925..c81a08bf4b164 100644 --- a/src/services/refactors/inferFunctionReturnType.ts +++ b/src/services/refactors/inferFunctionReturnType.ts @@ -1,32 +1,40 @@ -import * as ts from "../_namespaces/ts"; +import { + ApplicableRefactorInfo, ArrowFunction, Diagnostics, emptyArray, factory, findAncestor, findChildOfKind, first, + FunctionDeclaration, FunctionExpression, getLocaleSpecificMessage, getTokenAtPosition, isArrowFunction, isBlock, + isInJSFile, mapDefined, MethodDeclaration, Node, NodeBuilderFlags, RefactorContext, RefactorEditInfo, SourceFile, + SyntaxKind, textChanges, Type, TypeChecker, TypeNode, +} from "../_namespaces/ts"; +import { + isRefactorErrorInfo, RefactorErrorInfo, refactorKindBeginsWith, registerRefactor, +} from "../_namespaces/ts.refactor"; const refactorName = "Infer function return type"; -const refactorDescription = ts.Diagnostics.Infer_function_return_type.message; +const refactorDescription = Diagnostics.Infer_function_return_type.message; const inferReturnTypeAction = { name: refactorName, description: refactorDescription, kind: "refactor.rewrite.function.returnType" }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [inferReturnTypeAction.kind], getEditsForAction: getRefactorEditsToInferReturnType, getAvailableActions: getRefactorActionsToInferReturnType }); -function getRefactorEditsToInferReturnType(context: ts.RefactorContext): ts.RefactorEditInfo | undefined { +function getRefactorEditsToInferReturnType(context: RefactorContext): RefactorEditInfo | undefined { const info = getInfo(context); - if (info && !ts.refactor.isRefactorErrorInfo(info)) { - const edits = ts.textChanges.ChangeTracker.with(context, t => doChange(context.file, t, info.declaration, info.returnTypeNode)); + if (info && !isRefactorErrorInfo(info)) { + const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, t, info.declaration, info.returnTypeNode)); return { renameFilename: undefined, renameLocation: undefined, edits }; } return undefined; } -function getRefactorActionsToInferReturnType(context: ts.RefactorContext): readonly ts.ApplicableRefactorInfo[] { +function getRefactorActionsToInferReturnType(context: RefactorContext): readonly ApplicableRefactorInfo[] { const info = getInfo(context); - if (!info) return ts.emptyArray; - if (!ts.refactor.isRefactorErrorInfo(info)) { + if (!info) return emptyArray; + if (!isRefactorErrorInfo(info)) { return [{ name: refactorName, description: refactorDescription, @@ -40,73 +48,73 @@ function getRefactorActionsToInferReturnType(context: ts.RefactorContext): reado actions: [{ ...inferReturnTypeAction, notApplicableReason: info.error }] }]; } - return ts.emptyArray; + return emptyArray; } type ConvertibleDeclaration = - | ts.FunctionDeclaration - | ts.FunctionExpression - | ts.ArrowFunction - | ts.MethodDeclaration; + | FunctionDeclaration + | FunctionExpression + | ArrowFunction + | MethodDeclaration; interface FunctionInfo { declaration: ConvertibleDeclaration; - returnTypeNode: ts.TypeNode; + returnTypeNode: TypeNode; } -function doChange(sourceFile: ts.SourceFile, changes: ts.textChanges.ChangeTracker, declaration: ConvertibleDeclaration, typeNode: ts.TypeNode) { - const closeParen = ts.findChildOfKind(declaration, ts.SyntaxKind.CloseParenToken, sourceFile); - const needParens = ts.isArrowFunction(declaration) && closeParen === undefined; - const endNode = needParens ? ts.first(declaration.parameters) : closeParen; +function doChange(sourceFile: SourceFile, changes: textChanges.ChangeTracker, declaration: ConvertibleDeclaration, typeNode: TypeNode) { + const closeParen = findChildOfKind(declaration, SyntaxKind.CloseParenToken, sourceFile); + const needParens = isArrowFunction(declaration) && closeParen === undefined; + const endNode = needParens ? first(declaration.parameters) : closeParen; if (endNode) { if (needParens) { - changes.insertNodeBefore(sourceFile, endNode, ts.factory.createToken(ts.SyntaxKind.OpenParenToken)); - changes.insertNodeAfter(sourceFile, endNode, ts.factory.createToken(ts.SyntaxKind.CloseParenToken)); + changes.insertNodeBefore(sourceFile, endNode, factory.createToken(SyntaxKind.OpenParenToken)); + changes.insertNodeAfter(sourceFile, endNode, factory.createToken(SyntaxKind.CloseParenToken)); } changes.insertNodeAt(sourceFile, endNode.end, typeNode, { prefix: ": " }); } } -function getInfo(context: ts.RefactorContext): FunctionInfo | ts.refactor.RefactorErrorInfo | undefined { - if (ts.isInJSFile(context.file) || !ts.refactor.refactorKindBeginsWith(inferReturnTypeAction.kind, context.kind)) return; +function getInfo(context: RefactorContext): FunctionInfo | RefactorErrorInfo | undefined { + if (isInJSFile(context.file) || !refactorKindBeginsWith(inferReturnTypeAction.kind, context.kind)) return; - const token = ts.getTokenAtPosition(context.file, context.startPosition); - const declaration = ts.findAncestor(token, n => - ts.isBlock(n) || n.parent && ts.isArrowFunction(n.parent) && (n.kind === ts.SyntaxKind.EqualsGreaterThanToken || n.parent.body === n) ? "quit" : + const token = getTokenAtPosition(context.file, context.startPosition); + const declaration = findAncestor(token, n => + isBlock(n) || n.parent && isArrowFunction(n.parent) && (n.kind === SyntaxKind.EqualsGreaterThanToken || n.parent.body === n) ? "quit" : isConvertibleDeclaration(n)) as ConvertibleDeclaration | undefined; if (!declaration || !declaration.body || declaration.type) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Return_type_must_be_inferred_from_a_function) }; + return { error: getLocaleSpecificMessage(Diagnostics.Return_type_must_be_inferred_from_a_function) }; } const typeChecker = context.program.getTypeChecker(); const returnType = tryGetReturnType(typeChecker, declaration); if (!returnType) { - return { error: ts.getLocaleSpecificMessage(ts.Diagnostics.Could_not_determine_function_return_type) }; + return { error: getLocaleSpecificMessage(Diagnostics.Could_not_determine_function_return_type) }; } - const returnTypeNode = typeChecker.typeToTypeNode(returnType, declaration, ts.NodeBuilderFlags.NoTruncation); + const returnTypeNode = typeChecker.typeToTypeNode(returnType, declaration, NodeBuilderFlags.NoTruncation); if (returnTypeNode) { return { declaration, returnTypeNode }; } } -function isConvertibleDeclaration(node: ts.Node): node is ConvertibleDeclaration { +function isConvertibleDeclaration(node: Node): node is ConvertibleDeclaration { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: return true; default: return false; } } -function tryGetReturnType(typeChecker: ts.TypeChecker, node: ConvertibleDeclaration): ts.Type | undefined { +function tryGetReturnType(typeChecker: TypeChecker, node: ConvertibleDeclaration): Type | undefined { if (typeChecker.isImplementationOfOverload(node)) { const signatures = typeChecker.getTypeAtLocation(node).getCallSignatures(); if (signatures.length > 1) { - return typeChecker.getUnionType(ts.mapDefined(signatures, s => s.getReturnType())); + return typeChecker.getUnionType(mapDefined(signatures, s => s.getReturnType())); } } const signature = typeChecker.getSignatureFromDeclaration(node); diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index 09cb56a8ca2b4..8963d7d7534bf 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -1,52 +1,75 @@ -import * as ts from "../_namespaces/ts"; +import { + AnyImportOrRequireStatement, append, ApplicableRefactorInfo, AssignmentDeclarationKind, BinaryExpression, + BindingElement, BindingName, CallExpression, canHaveDecorators, canHaveModifiers, cast, ClassDeclaration, codefix, + combinePaths, concatenate, contains, copyEntries, createTextRangeFromSpan, Debug, Declaration, DeclarationStatement, + Diagnostics, emptyArray, ensurePathIsNonModuleName, EnumDeclaration, escapeLeadingUnderscores, Expression, + ExpressionStatement, extensionFromPath, ExternalModuleReference, factory, find, FindAllReferences, findIndex, + firstDefined, flatMap, forEachEntry, FunctionDeclaration, getAssignmentDeclarationKind, getBaseFileName, + GetCanonicalFileName, getDecorators, getDirectoryPath, getLocaleSpecificMessage, getModifiers, + getPropertySymbolFromBindingElement, getQuotePreference, getRangesWhere, getRefactorContextSpan, + getRelativePathFromFile, getSymbolId, getUniqueName, hasSyntacticModifier, hostGetCanonicalFileName, Identifier, + ImportDeclaration, ImportEqualsDeclaration, insertImports, InterfaceDeclaration, InternalSymbolName, + isArrayLiteralExpression, isBinaryExpression, isBindingElement, isDeclarationName, isExpressionStatement, + isExternalModuleReference, isIdentifier, isImportDeclaration, isImportEqualsDeclaration, isNamedDeclaration, + isObjectLiteralExpression, isOmittedExpression, isPrologueDirective, isPropertyAccessExpression, + isPropertyAssignment, isRequireCall, isSourceFile, isStringLiteral, isStringLiteralLike, isVariableDeclaration, + isVariableDeclarationList, isVariableStatement, LanguageServiceHost, last, length, makeImportIfNecessary, Map, + mapDefined, ModifierFlags, ModifierLike, ModuleDeclaration, NamedImportBindings, Node, NodeFlags, nodeSeenTracker, + normalizePath, ObjectBindingElementWithoutPropertyName, Program, PropertyAccessExpression, PropertyAssignment, + QuotePreference, rangeContainsRange, RefactorContext, RefactorEditInfo, removeFileExtension, RequireOrImportCall, + RequireVariableStatement, ScriptTarget, skipAlias, some, SourceFile, Statement, StringLiteralLike, Symbol, + SymbolFlags, symbolNameNoDefault, SyntaxKind, takeWhile, textChanges, TransformFlags, tryCast, TypeAliasDeclaration, + TypeChecker, TypeNode, UserPreferences, VariableDeclaration, VariableDeclarationList, VariableStatement, +} from "../_namespaces/ts"; +import { registerRefactor } from "../_namespaces/ts.refactor"; const refactorName = "Move to a new file"; -const description = ts.getLocaleSpecificMessage(ts.Diagnostics.Move_to_a_new_file); +const description = getLocaleSpecificMessage(Diagnostics.Move_to_a_new_file); const moveToNewFileAction = { name: refactorName, description, kind: "refactor.move.newFile", }; -ts.refactor.registerRefactor(refactorName, { +registerRefactor(refactorName, { kinds: [moveToNewFileAction.kind], - getAvailableActions: function getRefactorActionsToMoveToNewFile(context): readonly ts.ApplicableRefactorInfo[] { + getAvailableActions: function getRefactorActionsToMoveToNewFile(context): readonly ApplicableRefactorInfo[] { const statements = getStatementsToMove(context); if (context.preferences.allowTextChangesInNewFiles && statements) { return [{ name: refactorName, description, actions: [moveToNewFileAction] }]; } if (context.preferences.provideRefactorNotApplicableReason) { return [{ name: refactorName, description, actions: - [{ ...moveToNewFileAction, notApplicableReason: ts.getLocaleSpecificMessage(ts.Diagnostics.Selection_is_not_a_valid_statement_or_statements) }] + [{ ...moveToNewFileAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Selection_is_not_a_valid_statement_or_statements) }] }]; } - return ts.emptyArray; + return emptyArray; }, - getEditsForAction: function getRefactorEditsToMoveToNewFile(context, actionName): ts.RefactorEditInfo { - ts.Debug.assert(actionName === refactorName, "Wrong refactor invoked"); - const statements = ts.Debug.checkDefined(getStatementsToMove(context)); - const edits = ts.textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, statements, t, context.host, context.preferences)); + getEditsForAction: function getRefactorEditsToMoveToNewFile(context, actionName): RefactorEditInfo { + Debug.assert(actionName === refactorName, "Wrong refactor invoked"); + const statements = Debug.checkDefined(getStatementsToMove(context)); + const edits = textChanges.ChangeTracker.with(context, t => doChange(context.file, context.program, statements, t, context.host, context.preferences)); return { edits, renameFilename: undefined, renameLocation: undefined }; } }); -interface RangeToMove { readonly toMove: readonly ts.Statement[]; readonly afterLast: ts.Statement | undefined; } -function getRangeToMove(context: ts.RefactorContext): RangeToMove | undefined { +interface RangeToMove { readonly toMove: readonly Statement[]; readonly afterLast: Statement | undefined; } +function getRangeToMove(context: RefactorContext): RangeToMove | undefined { const { file } = context; - const range = ts.createTextRangeFromSpan(ts.getRefactorContextSpan(context)); + const range = createTextRangeFromSpan(getRefactorContextSpan(context)); const { statements } = file; - const startNodeIndex = ts.findIndex(statements, s => s.end > range.pos); + const startNodeIndex = findIndex(statements, s => s.end > range.pos); if (startNodeIndex === -1) return undefined; const startStatement = statements[startNodeIndex]; - if (ts.isNamedDeclaration(startStatement) && startStatement.name && ts.rangeContainsRange(startStatement.name, range)) { + if (isNamedDeclaration(startStatement) && startStatement.name && rangeContainsRange(startStatement.name, range)) { return { toMove: [statements[startNodeIndex]], afterLast: statements[startNodeIndex + 1] }; } // Can't only partially include the start node or be partially into the next node if (range.pos > startStatement.getStart(file)) return undefined; - const afterEndNodeIndex = ts.findIndex(statements, s => s.end > range.end, startNodeIndex); + const afterEndNodeIndex = findIndex(statements, s => s.end > range.end, startNodeIndex); // Can't be partially into the next node if (afterEndNodeIndex !== -1 && (afterEndNodeIndex === 0 || statements[afterEndNodeIndex].getStart(file) < range.end)) return undefined; @@ -56,93 +79,93 @@ function getRangeToMove(context: ts.RefactorContext): RangeToMove | undefined { }; } -function doChange(oldFile: ts.SourceFile, program: ts.Program, toMove: ToMove, changes: ts.textChanges.ChangeTracker, host: ts.LanguageServiceHost, preferences: ts.UserPreferences): void { +function doChange(oldFile: SourceFile, program: Program, toMove: ToMove, changes: textChanges.ChangeTracker, host: LanguageServiceHost, preferences: UserPreferences): void { const checker = program.getTypeChecker(); const usage = getUsageInfo(oldFile, toMove.all, checker); - const currentDirectory = ts.getDirectoryPath(oldFile.fileName); - const extension = ts.extensionFromPath(oldFile.fileName); + const currentDirectory = getDirectoryPath(oldFile.fileName); + const extension = extensionFromPath(oldFile.fileName); const newModuleName = makeUniqueModuleName(getNewModuleName(usage.oldFileImportsFromNewFile, usage.movedSymbols), extension, currentDirectory, host); const newFileNameWithExtension = newModuleName + extension; // If previous file was global, this is easy. - changes.createNewFile(oldFile, ts.combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences)); + changes.createNewFile(oldFile, combinePaths(currentDirectory, newFileNameWithExtension), getNewStatementsAndRemoveFromOldFile(oldFile, usage, changes, toMove, program, newModuleName, preferences)); - addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, ts.hostGetCanonicalFileName(host)); + addNewFileToTsconfig(program, changes, oldFile.fileName, newFileNameWithExtension, hostGetCanonicalFileName(host)); } interface StatementRange { - readonly first: ts.Statement; - readonly afterLast: ts.Statement | undefined; + readonly first: Statement; + readonly afterLast: Statement | undefined; } interface ToMove { - readonly all: readonly ts.Statement[]; + readonly all: readonly Statement[]; readonly ranges: readonly StatementRange[]; } -function getStatementsToMove(context: ts.RefactorContext): ToMove | undefined { +function getStatementsToMove(context: RefactorContext): ToMove | undefined { const rangeToMove = getRangeToMove(context); if (rangeToMove === undefined) return undefined; - const all: ts.Statement[] = []; + const all: Statement[] = []; const ranges: StatementRange[] = []; const { toMove, afterLast } = rangeToMove; - ts.getRangesWhere(toMove, isAllowedStatementToMove, (start, afterEndIndex) => { + getRangesWhere(toMove, isAllowedStatementToMove, (start, afterEndIndex) => { for (let i = start; i < afterEndIndex; i++) all.push(toMove[i]); ranges.push({ first: toMove[start], afterLast }); }); return all.length === 0 ? undefined : { all, ranges }; } -function isAllowedStatementToMove(statement: ts.Statement): boolean { +function isAllowedStatementToMove(statement: Statement): boolean { // Filters imports and prologue directives out of the range of statements to move. // Imports will be copied to the new file anyway, and may still be needed in the old file. // Prologue directives will be copied to the new file and should be left in the old file. - return !isPureImport(statement) && !ts.isPrologueDirective(statement); + return !isPureImport(statement) && !isPrologueDirective(statement); } -function isPureImport(node: ts.Node): boolean { +function isPureImport(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportDeclaration: return true; - case ts.SyntaxKind.ImportEqualsDeclaration: - return !ts.hasSyntacticModifier(node, ts.ModifierFlags.Export); - case ts.SyntaxKind.VariableStatement: - return (node as ts.VariableStatement).declarationList.declarations.every(d => !!d.initializer && ts.isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true)); + case SyntaxKind.ImportEqualsDeclaration: + return !hasSyntacticModifier(node, ModifierFlags.Export); + case SyntaxKind.VariableStatement: + return (node as VariableStatement).declarationList.declarations.every(d => !!d.initializer && isRequireCall(d.initializer, /*checkArgumentIsStringLiteralLike*/ true)); default: return false; } } -function addNewFileToTsconfig(program: ts.Program, changes: ts.textChanges.ChangeTracker, oldFileName: string, newFileNameWithExtension: string, getCanonicalFileName: ts.GetCanonicalFileName): void { +function addNewFileToTsconfig(program: Program, changes: textChanges.ChangeTracker, oldFileName: string, newFileNameWithExtension: string, getCanonicalFileName: GetCanonicalFileName): void { const cfg = program.getCompilerOptions().configFile; if (!cfg) return; - const newFileAbsolutePath = ts.normalizePath(ts.combinePaths(oldFileName, "..", newFileNameWithExtension)); - const newFilePath = ts.getRelativePathFromFile(cfg.fileName, newFileAbsolutePath, getCanonicalFileName); + const newFileAbsolutePath = normalizePath(combinePaths(oldFileName, "..", newFileNameWithExtension)); + const newFilePath = getRelativePathFromFile(cfg.fileName, newFileAbsolutePath, getCanonicalFileName); - const cfgObject = cfg.statements[0] && ts.tryCast(cfg.statements[0].expression, ts.isObjectLiteralExpression); - const filesProp = cfgObject && ts.find(cfgObject.properties, (prop): prop is ts.PropertyAssignment => - ts.isPropertyAssignment(prop) && ts.isStringLiteral(prop.name) && prop.name.text === "files"); - if (filesProp && ts.isArrayLiteralExpression(filesProp.initializer)) { - changes.insertNodeInListAfter(cfg, ts.last(filesProp.initializer.elements), ts.factory.createStringLiteral(newFilePath), filesProp.initializer.elements); + const cfgObject = cfg.statements[0] && tryCast(cfg.statements[0].expression, isObjectLiteralExpression); + const filesProp = cfgObject && find(cfgObject.properties, (prop): prop is PropertyAssignment => + isPropertyAssignment(prop) && isStringLiteral(prop.name) && prop.name.text === "files"); + if (filesProp && isArrayLiteralExpression(filesProp.initializer)) { + changes.insertNodeInListAfter(cfg, last(filesProp.initializer.elements), factory.createStringLiteral(newFilePath), filesProp.initializer.elements); } } function getNewStatementsAndRemoveFromOldFile( - oldFile: ts.SourceFile, usage: UsageInfo, changes: ts.textChanges.ChangeTracker, toMove: ToMove, program: ts.Program, newModuleName: string, preferences: ts.UserPreferences, + oldFile: SourceFile, usage: UsageInfo, changes: textChanges.ChangeTracker, toMove: ToMove, program: Program, newModuleName: string, preferences: UserPreferences, ) { const checker = program.getTypeChecker(); - const prologueDirectives = ts.takeWhile(oldFile.statements, ts.isPrologueDirective); + const prologueDirectives = takeWhile(oldFile.statements, isPrologueDirective); if (oldFile.externalModuleIndicator === undefined && oldFile.commonJsModuleIndicator === undefined && usage.oldImportsNeededByNewFile.size() === 0) { deleteMovedStatements(oldFile, toMove.ranges, changes); return [...prologueDirectives, ...toMove.all]; } const useEsModuleSyntax = !!oldFile.externalModuleIndicator; - const quotePreference = ts.getQuotePreference(oldFile, preferences); + const quotePreference = getQuotePreference(oldFile, preferences); const importsFromNewFile = createOldFileImportsFromNewFile(usage.oldFileImportsFromNewFile, newModuleName, useEsModuleSyntax, quotePreference); if (importsFromNewFile) { - ts.insertImports(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true); + insertImports(changes, oldFile, importsFromNewFile, /*blankLineBetween*/ true); } deleteUnusedOldImports(oldFile, toMove.all, changes, usage.unusedImportsFromOldFile, checker); @@ -155,7 +178,7 @@ function getNewStatementsAndRemoveFromOldFile( return [ ...prologueDirectives, ...imports, - ts.SyntaxKind.NewLineTrivia as const, + SyntaxKind.NewLineTrivia as const, ...body ]; } @@ -167,20 +190,20 @@ function getNewStatementsAndRemoveFromOldFile( ]; } -function deleteMovedStatements(sourceFile: ts.SourceFile, moved: readonly StatementRange[], changes: ts.textChanges.ChangeTracker) { +function deleteMovedStatements(sourceFile: SourceFile, moved: readonly StatementRange[], changes: textChanges.ChangeTracker) { for (const { first, afterLast } of moved) { changes.deleteNodeRangeExcludingEnd(sourceFile, first, afterLast); } } -function deleteUnusedOldImports(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], changes: ts.textChanges.ChangeTracker, toDelete: ReadonlySymbolSet, checker: ts.TypeChecker) { +function deleteUnusedOldImports(oldFile: SourceFile, toMove: readonly Statement[], changes: textChanges.ChangeTracker, toDelete: ReadonlySymbolSet, checker: TypeChecker) { for (const statement of oldFile.statements) { - if (ts.contains(toMove, statement)) continue; + if (contains(toMove, statement)) continue; forEachImportInStatement(statement, i => deleteUnusedImports(oldFile, i, changes, name => toDelete.has(checker.getSymbolAtLocation(name)!))); } } -function updateImportsInOtherFiles(changes: ts.textChanges.ChangeTracker, program: ts.Program, oldFile: ts.SourceFile, movedSymbols: ReadonlySymbolSet, newModuleName: string): void { +function updateImportsInOtherFiles(changes: textChanges.ChangeTracker, program: Program, oldFile: SourceFile, movedSymbols: ReadonlySymbolSet, newModuleName: string): void { const checker = program.getTypeChecker(); for (const sourceFile of program.getSourceFiles()) { if (sourceFile === oldFile) continue; @@ -188,15 +211,15 @@ function updateImportsInOtherFiles(changes: ts.textChanges.ChangeTracker, progra forEachImportInStatement(statement, importNode => { if (checker.getSymbolAtLocation(moduleSpecifierFromImport(importNode)) !== oldFile.symbol) return; - const shouldMove = (name: ts.Identifier): boolean => { - const symbol = ts.isBindingElement(name.parent) - ? ts.getPropertySymbolFromBindingElement(checker, name.parent as ts.ObjectBindingElementWithoutPropertyName) - : ts.skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217 + const shouldMove = (name: Identifier): boolean => { + const symbol = isBindingElement(name.parent) + ? getPropertySymbolFromBindingElement(checker, name.parent as ObjectBindingElementWithoutPropertyName) + : skipAlias(checker.getSymbolAtLocation(name)!, checker); // TODO: GH#18217 return !!symbol && movedSymbols.has(symbol); }; deleteUnusedImports(sourceFile, importNode, changes, shouldMove); // These will be changed to imports from the new file - const newModuleSpecifier = ts.combinePaths(ts.getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); - const newImportDeclaration = filterImport(importNode, ts.factory.createStringLiteral(newModuleSpecifier), shouldMove); + const newModuleSpecifier = combinePaths(getDirectoryPath(moduleSpecifierFromImport(importNode).text), newModuleName); + const newImportDeclaration = filterImport(importNode, factory.createStringLiteral(newModuleSpecifier), shouldMove); if (newImportDeclaration) changes.insertNodeAfter(sourceFile, statement, newImportDeclaration); const ns = getNamespaceLikeImport(importNode); @@ -206,87 +229,87 @@ function updateImportsInOtherFiles(changes: ts.textChanges.ChangeTracker, progra } } -function getNamespaceLikeImport(node: SupportedImport): ts.Identifier | undefined { +function getNamespaceLikeImport(node: SupportedImport): Identifier | undefined { switch (node.kind) { - case ts.SyntaxKind.ImportDeclaration: - return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport ? + case SyntaxKind.ImportDeclaration: + return node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? node.importClause.namedBindings.name : undefined; - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return node.name; - case ts.SyntaxKind.VariableDeclaration: - return ts.tryCast(node.name, ts.isIdentifier); + case SyntaxKind.VariableDeclaration: + return tryCast(node.name, isIdentifier); default: - return ts.Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); + return Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); } } function updateNamespaceLikeImport( - changes: ts.textChanges.ChangeTracker, - sourceFile: ts.SourceFile, - checker: ts.TypeChecker, + changes: textChanges.ChangeTracker, + sourceFile: SourceFile, + checker: TypeChecker, movedSymbols: ReadonlySymbolSet, newModuleName: string, newModuleSpecifier: string, - oldImportId: ts.Identifier, + oldImportId: Identifier, oldImportNode: SupportedImport, ): void { - const preferredNewNamespaceName = ts.codefix.moduleSpecifierToValidIdentifier(newModuleName, ts.ScriptTarget.ESNext); + const preferredNewNamespaceName = codefix.moduleSpecifierToValidIdentifier(newModuleName, ScriptTarget.ESNext); let needUniqueName = false; - const toChange: ts.Identifier[] = []; - ts.FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, ref => { - if (!ts.isPropertyAccessExpression(ref.parent)) return; - needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, ts.SymbolFlags.All, /*excludeGlobals*/ true); + const toChange: Identifier[] = []; + FindAllReferences.Core.eachSymbolReferenceInFile(oldImportId, checker, sourceFile, ref => { + if (!isPropertyAccessExpression(ref.parent)) return; + needUniqueName = needUniqueName || !!checker.resolveName(preferredNewNamespaceName, ref, SymbolFlags.All, /*excludeGlobals*/ true); if (movedSymbols.has(checker.getSymbolAtLocation(ref.parent.name)!)) { toChange.push(ref); } }); if (toChange.length) { - const newNamespaceName = needUniqueName ? ts.getUniqueName(preferredNewNamespaceName, sourceFile) : preferredNewNamespaceName; + const newNamespaceName = needUniqueName ? getUniqueName(preferredNewNamespaceName, sourceFile) : preferredNewNamespaceName; for (const ref of toChange) { - changes.replaceNode(sourceFile, ref, ts.factory.createIdentifier(newNamespaceName)); + changes.replaceNode(sourceFile, ref, factory.createIdentifier(newNamespaceName)); } changes.insertNodeAfter(sourceFile, oldImportNode, updateNamespaceLikeImportNode(oldImportNode, newModuleName, newModuleSpecifier)); } } -function updateNamespaceLikeImportNode(node: SupportedImport, newNamespaceName: string, newModuleSpecifier: string): ts.Node { - const newNamespaceId = ts.factory.createIdentifier(newNamespaceName); - const newModuleString = ts.factory.createStringLiteral(newModuleSpecifier); +function updateNamespaceLikeImportNode(node: SupportedImport, newNamespaceName: string, newModuleSpecifier: string): Node { + const newNamespaceId = factory.createIdentifier(newNamespaceName); + const newModuleString = factory.createStringLiteral(newModuleSpecifier); switch (node.kind) { - case ts.SyntaxKind.ImportDeclaration: - return ts.factory.createImportDeclaration( + case SyntaxKind.ImportDeclaration: + return factory.createImportDeclaration( /*modifiers*/ undefined, - ts.factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, ts.factory.createNamespaceImport(newNamespaceId)), + factory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, factory.createNamespaceImport(newNamespaceId)), newModuleString, /*assertClause*/ undefined); - case ts.SyntaxKind.ImportEqualsDeclaration: - return ts.factory.createImportEqualsDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, newNamespaceId, ts.factory.createExternalModuleReference(newModuleString)); - case ts.SyntaxKind.VariableDeclaration: - return ts.factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); + case SyntaxKind.ImportEqualsDeclaration: + return factory.createImportEqualsDeclaration(/*modifiers*/ undefined, /*isTypeOnly*/ false, newNamespaceId, factory.createExternalModuleReference(newModuleString)); + case SyntaxKind.VariableDeclaration: + return factory.createVariableDeclaration(newNamespaceId, /*exclamationToken*/ undefined, /*type*/ undefined, createRequireCall(newModuleString)); default: - return ts.Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); + return Debug.assertNever(node, `Unexpected node kind ${(node as SupportedImport).kind}`); } } -function moduleSpecifierFromImport(i: SupportedImport): ts.StringLiteralLike { - return (i.kind === ts.SyntaxKind.ImportDeclaration ? i.moduleSpecifier - : i.kind === ts.SyntaxKind.ImportEqualsDeclaration ? i.moduleReference.expression +function moduleSpecifierFromImport(i: SupportedImport): StringLiteralLike { + return (i.kind === SyntaxKind.ImportDeclaration ? i.moduleSpecifier + : i.kind === SyntaxKind.ImportEqualsDeclaration ? i.moduleReference.expression : i.initializer.arguments[0]); } -function forEachImportInStatement(statement: ts.Statement, cb: (importNode: SupportedImport) => void): void { - if (ts.isImportDeclaration(statement)) { - if (ts.isStringLiteral(statement.moduleSpecifier)) cb(statement as SupportedImport); +function forEachImportInStatement(statement: Statement, cb: (importNode: SupportedImport) => void): void { + if (isImportDeclaration(statement)) { + if (isStringLiteral(statement.moduleSpecifier)) cb(statement as SupportedImport); } - else if (ts.isImportEqualsDeclaration(statement)) { - if (ts.isExternalModuleReference(statement.moduleReference) && ts.isStringLiteralLike(statement.moduleReference.expression)) { + else if (isImportEqualsDeclaration(statement)) { + if (isExternalModuleReference(statement.moduleReference) && isStringLiteralLike(statement.moduleReference.expression)) { cb(statement as SupportedImport); } } - else if (ts.isVariableStatement(statement)) { + else if (isVariableStatement(statement)) { for (const decl of statement.declarationList.declarations) { - if (decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true)) { + if (decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true)) { cb(decl as SupportedImport); } } @@ -294,20 +317,20 @@ function forEachImportInStatement(statement: ts.Statement, cb: (importNode: Supp } type SupportedImport = - | ts.ImportDeclaration & { moduleSpecifier: ts.StringLiteralLike } - | ts.ImportEqualsDeclaration & { moduleReference: ts.ExternalModuleReference & { expression: ts.StringLiteralLike } } - | ts.VariableDeclaration & { initializer: ts.RequireOrImportCall }; + | ImportDeclaration & { moduleSpecifier: StringLiteralLike } + | ImportEqualsDeclaration & { moduleReference: ExternalModuleReference & { expression: StringLiteralLike } } + | VariableDeclaration & { initializer: RequireOrImportCall }; type SupportedImportStatement = - | ts.ImportDeclaration - | ts.ImportEqualsDeclaration - | ts.VariableStatement; + | ImportDeclaration + | ImportEqualsDeclaration + | VariableStatement; -function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, newFileNameWithExtension: string, useEs6Imports: boolean, quotePreference: ts.QuotePreference): ts.AnyImportOrRequireStatement | undefined { - let defaultImport: ts.Identifier | undefined; +function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, newFileNameWithExtension: string, useEs6Imports: boolean, quotePreference: QuotePreference): AnyImportOrRequireStatement | undefined { + let defaultImport: Identifier | undefined; const imports: string[] = []; newFileNeedExport.forEach(symbol => { - if (symbol.escapedName === ts.InternalSymbolName.Default) { - defaultImport = ts.factory.createIdentifier(ts.symbolNameNoDefault(symbol)!); // TODO: GH#18217 + if (symbol.escapedName === InternalSymbolName.Default) { + defaultImport = factory.createIdentifier(symbolNameNoDefault(symbol)!); // TODO: GH#18217 } else { imports.push(symbol.name); @@ -316,34 +339,34 @@ function createOldFileImportsFromNewFile(newFileNeedExport: ReadonlySymbolSet, n return makeImportOrRequire(defaultImport, imports, newFileNameWithExtension, useEs6Imports, quotePreference); } -function makeImportOrRequire(defaultImport: ts.Identifier | undefined, imports: readonly string[], path: string, useEs6Imports: boolean, quotePreference: ts.QuotePreference): ts.AnyImportOrRequireStatement | undefined { - path = ts.ensurePathIsNonModuleName(path); +function makeImportOrRequire(defaultImport: Identifier | undefined, imports: readonly string[], path: string, useEs6Imports: boolean, quotePreference: QuotePreference): AnyImportOrRequireStatement | undefined { + path = ensurePathIsNonModuleName(path); if (useEs6Imports) { - const specifiers = imports.map(i => ts.factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, ts.factory.createIdentifier(i))); - return ts.makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); + const specifiers = imports.map(i => factory.createImportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, factory.createIdentifier(i))); + return makeImportIfNecessary(defaultImport, specifiers, path, quotePreference); } else { - ts.Debug.assert(!defaultImport, "No default import should exist"); // If there's a default export, it should have been an es6 module. - const bindingElements = imports.map(i => ts.factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i)); + Debug.assert(!defaultImport, "No default import should exist"); // If there's a default export, it should have been an es6 module. + const bindingElements = imports.map(i => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, i)); return bindingElements.length - ? makeVariableStatement(ts.factory.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(ts.factory.createStringLiteral(path))) as ts.RequireVariableStatement + ? makeVariableStatement(factory.createObjectBindingPattern(bindingElements), /*type*/ undefined, createRequireCall(factory.createStringLiteral(path))) as RequireVariableStatement : undefined; } } -function makeVariableStatement(name: ts.BindingName, type: ts.TypeNode | undefined, initializer: ts.Expression | undefined, flags: ts.NodeFlags = ts.NodeFlags.Const) { - return ts.factory.createVariableStatement(/*modifiers*/ undefined, ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer)], flags)); +function makeVariableStatement(name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined, flags: NodeFlags = NodeFlags.Const) { + return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, initializer)], flags)); } -function createRequireCall(moduleSpecifier: ts.StringLiteralLike): ts.CallExpression { - return ts.factory.createCallExpression(ts.factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); +function createRequireCall(moduleSpecifier: StringLiteralLike): CallExpression { + return factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [moduleSpecifier]); } -function addExports(sourceFile: ts.SourceFile, toMove: readonly ts.Statement[], needExport: ReadonlySymbolSet, useEs6Exports: boolean): readonly ts.Statement[] { - return ts.flatMap(toMove, statement => { +function addExports(sourceFile: SourceFile, toMove: readonly Statement[], needExport: ReadonlySymbolSet, useEs6Exports: boolean): readonly Statement[] { + return flatMap(toMove, statement => { if (isTopLevelDeclarationStatement(statement) && !isExported(sourceFile, statement, useEs6Exports) && - forEachTopLevelDeclaration(statement, d => needExport.has(ts.Debug.checkDefined(d.symbol)))) { + forEachTopLevelDeclaration(statement, d => needExport.has(Debug.checkDefined(d.symbol)))) { const exports = addExport(statement, useEs6Exports); if (exports) return exports; } @@ -351,29 +374,29 @@ function addExports(sourceFile: ts.SourceFile, toMove: readonly ts.Statement[], }); } -function deleteUnusedImports(sourceFile: ts.SourceFile, importDecl: SupportedImport, changes: ts.textChanges.ChangeTracker, isUnused: (name: ts.Identifier) => boolean): void { +function deleteUnusedImports(sourceFile: SourceFile, importDecl: SupportedImport, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void { switch (importDecl.kind) { - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportDeclaration: deleteUnusedImportsInDeclaration(sourceFile, importDecl, changes, isUnused); break; - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: if (isUnused(importDecl.name)) { changes.delete(sourceFile, importDecl); } break; - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableDeclaration: deleteUnusedImportsInVariableDeclaration(sourceFile, importDecl, changes, isUnused); break; default: - ts.Debug.assertNever(importDecl, `Unexpected import decl kind ${(importDecl as SupportedImport).kind}`); + Debug.assertNever(importDecl, `Unexpected import decl kind ${(importDecl as SupportedImport).kind}`); } } -function deleteUnusedImportsInDeclaration(sourceFile: ts.SourceFile, importDecl: ts.ImportDeclaration, changes: ts.textChanges.ChangeTracker, isUnused: (name: ts.Identifier) => boolean): void { +function deleteUnusedImportsInDeclaration(sourceFile: SourceFile, importDecl: ImportDeclaration, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean): void { if (!importDecl.importClause) return; const { name, namedBindings } = importDecl.importClause; const defaultUnused = !name || isUnused(name); const namedBindingsUnused = !namedBindings || - (namedBindings.kind === ts.SyntaxKind.NamespaceImport ? isUnused(namedBindings.name) : namedBindings.elements.length !== 0 && namedBindings.elements.every(e => isUnused(e.name))); + (namedBindings.kind === SyntaxKind.NamespaceImport ? isUnused(namedBindings.name) : namedBindings.elements.length !== 0 && namedBindings.elements.every(e => isUnused(e.name))); if (defaultUnused && namedBindingsUnused) { changes.delete(sourceFile, importDecl); } @@ -386,10 +409,10 @@ function deleteUnusedImportsInDeclaration(sourceFile: ts.SourceFile, importDecl: changes.replaceNode( sourceFile, importDecl.importClause, - ts.factory.updateImportClause(importDecl.importClause, importDecl.importClause.isTypeOnly, name, /*namedBindings*/ undefined) + factory.updateImportClause(importDecl.importClause, importDecl.importClause.isTypeOnly, name, /*namedBindings*/ undefined) ); } - else if (namedBindings.kind === ts.SyntaxKind.NamedImports) { + else if (namedBindings.kind === SyntaxKind.NamedImports) { for (const element of namedBindings.elements) { if (isUnused(element.name)) changes.delete(sourceFile, element); } @@ -397,30 +420,30 @@ function deleteUnusedImportsInDeclaration(sourceFile: ts.SourceFile, importDecl: } } } -function deleteUnusedImportsInVariableDeclaration(sourceFile: ts.SourceFile, varDecl: ts.VariableDeclaration, changes: ts.textChanges.ChangeTracker, isUnused: (name: ts.Identifier) => boolean) { +function deleteUnusedImportsInVariableDeclaration(sourceFile: SourceFile, varDecl: VariableDeclaration, changes: textChanges.ChangeTracker, isUnused: (name: Identifier) => boolean) { const { name } = varDecl; switch (name.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: if (isUnused(name)) { - if (varDecl.initializer && ts.isRequireCall(varDecl.initializer, /*requireStringLiteralLikeArgument*/ true)) { + if (varDecl.initializer && isRequireCall(varDecl.initializer, /*requireStringLiteralLikeArgument*/ true)) { changes.delete(sourceFile, - ts.isVariableDeclarationList(varDecl.parent) && ts.length(varDecl.parent.declarations) === 1 ? varDecl.parent.parent : varDecl); + isVariableDeclarationList(varDecl.parent) && length(varDecl.parent.declarations) === 1 ? varDecl.parent.parent : varDecl); } else { changes.delete(sourceFile, name); } } break; - case ts.SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayBindingPattern: break; - case ts.SyntaxKind.ObjectBindingPattern: - if (name.elements.every(e => ts.isIdentifier(e.name) && isUnused(e.name))) { + case SyntaxKind.ObjectBindingPattern: + if (name.elements.every(e => isIdentifier(e.name) && isUnused(e.name))) { changes.delete(sourceFile, - ts.isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); + isVariableDeclarationList(varDecl.parent) && varDecl.parent.declarations.length === 1 ? varDecl.parent.parent : varDecl); } else { for (const element of name.elements) { - if (ts.isIdentifier(element.name) && isUnused(element.name)) { + if (isIdentifier(element.name) && isUnused(element.name)) { changes.delete(sourceFile, element.name); } } @@ -430,25 +453,25 @@ function deleteUnusedImportsInVariableDeclaration(sourceFile: ts.SourceFile, var } function getNewFileImportsAndAddExportInOldFile( - oldFile: ts.SourceFile, + oldFile: SourceFile, importsToCopy: ReadonlySymbolSet, newFileImportsFromOldFile: ReadonlySymbolSet, - changes: ts.textChanges.ChangeTracker, - checker: ts.TypeChecker, + changes: textChanges.ChangeTracker, + checker: TypeChecker, useEsModuleSyntax: boolean, - quotePreference: ts.QuotePreference, + quotePreference: QuotePreference, ): readonly SupportedImportStatement[] { const copiedOldImports: SupportedImportStatement[] = []; for (const oldStatement of oldFile.statements) { forEachImportInStatement(oldStatement, i => { - ts.append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); + append(copiedOldImports, filterImport(i, moduleSpecifierFromImport(i), name => importsToCopy.has(checker.getSymbolAtLocation(name)!))); }); } // Also, import things used from the old file, and insert 'export' modifiers as necessary in the old file. - let oldFileDefault: ts.Identifier | undefined; + let oldFileDefault: Identifier | undefined; const oldFileNamedImports: string[] = []; - const markSeenTop = ts.nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. + const markSeenTop = nodeSeenTracker(); // Needed because multiple declarations may appear in `const x = 0, y = 1;`. newFileImportsFromOldFile.forEach(symbol => { if (!symbol.declarations) { return; @@ -462,7 +485,7 @@ function getNewFileImportsAndAddExportInOldFile( if (markSeenTop(top)) { addExportToChanges(oldFile, top, name, changes, useEsModuleSyntax); } - if (ts.hasSyntacticModifier(decl, ts.ModifierFlags.Default)) { + if (hasSyntacticModifier(decl, ModifierFlags.Default)) { oldFileDefault = name; } else { @@ -471,21 +494,21 @@ function getNewFileImportsAndAddExportInOldFile( } }); - ts.append(copiedOldImports, makeImportOrRequire(oldFileDefault, oldFileNamedImports, ts.removeFileExtension(ts.getBaseFileName(oldFile.fileName)), useEsModuleSyntax, quotePreference)); + append(copiedOldImports, makeImportOrRequire(oldFileDefault, oldFileNamedImports, removeFileExtension(getBaseFileName(oldFile.fileName)), useEsModuleSyntax, quotePreference)); return copiedOldImports; } -function makeUniqueModuleName(moduleName: string, extension: string, inDirectory: string, host: ts.LanguageServiceHost): string { +function makeUniqueModuleName(moduleName: string, extension: string, inDirectory: string, host: LanguageServiceHost): string { let newModuleName = moduleName; for (let i = 1; ; i++) { - const name = ts.combinePaths(inDirectory, newModuleName + extension); + const name = combinePaths(inDirectory, newModuleName + extension); if (!host.fileExists(name)) return newModuleName; newModuleName = `${moduleName}.${i}`; } } function getNewModuleName(importsFromNewFile: ReadonlySymbolSet, movedSymbols: ReadonlySymbolSet): string { - return importsFromNewFile.forEachEntry(ts.symbolNameNoDefault) || movedSymbols.forEachEntry(ts.symbolNameNoDefault) || "newFile"; + return importsFromNewFile.forEachEntry(symbolNameNoDefault) || movedSymbols.forEachEntry(symbolNameNoDefault) || "newFile"; } interface UsageInfo { @@ -501,12 +524,12 @@ interface UsageInfo { // Subset of oldImportsNeededByNewFile that are will no longer be used in the old file. readonly unusedImportsFromOldFile: ReadonlySymbolSet; } -function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], checker: ts.TypeChecker): UsageInfo { +function getUsageInfo(oldFile: SourceFile, toMove: readonly Statement[], checker: TypeChecker): UsageInfo { const movedSymbols = new SymbolSet(); const oldImportsNeededByNewFile = new SymbolSet(); const newFileImportsFromOldFile = new SymbolSet(); - const containsJsx = ts.find(toMove, statement => !!(statement.transformFlags & ts.TransformFlags.ContainsJsx)); + const containsJsx = find(toMove, statement => !!(statement.transformFlags & TransformFlags.ContainsJsx)); const jsxNamespaceSymbol = getJsxNamespaceSymbol(containsJsx); if (jsxNamespaceSymbol) { // Might not exist (e.g. in non-compiling code) oldImportsNeededByNewFile.add(jsxNamespaceSymbol); @@ -514,7 +537,7 @@ function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], c for (const statement of toMove) { forEachTopLevelDeclaration(statement, decl => { - movedSymbols.add(ts.Debug.checkDefined(ts.isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol, "Need a symbol here")); + movedSymbols.add(Debug.checkDefined(isExpressionStatement(decl) ? checker.getSymbolAtLocation(decl.expression.left) : decl.symbol, "Need a symbol here")); }); } for (const statement of toMove) { @@ -535,10 +558,10 @@ function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], c const oldFileImportsFromNewFile = new SymbolSet(); for (const statement of oldFile.statements) { - if (ts.contains(toMove, statement)) continue; + if (contains(toMove, statement)) continue; // jsxNamespaceSymbol will only be set iff it is in oldImportsNeededByNewFile. - if (jsxNamespaceSymbol && !!(statement.transformFlags & ts.TransformFlags.ContainsJsx)) { + if (jsxNamespaceSymbol && !!(statement.transformFlags & TransformFlags.ContainsJsx)) { unusedImportsFromOldFile.delete(jsxNamespaceSymbol); } @@ -550,7 +573,7 @@ function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], c return { movedSymbols, newFileImportsFromOldFile, oldFileImportsFromNewFile, oldImportsNeededByNewFile, unusedImportsFromOldFile }; - function getJsxNamespaceSymbol(containsJsx: ts.Node | undefined) { + function getJsxNamespaceSymbol(containsJsx: Node | undefined) { if (containsJsx === undefined) { return undefined; } @@ -560,9 +583,9 @@ function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], c // Strictly speaking, this could resolve to a symbol other than the JSX namespace. // This will produce erroneous output (probably, an incorrectly copied import) but // is expected to be very rare and easily reversible. - const jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, ts.SymbolFlags.Namespace, /*excludeGlobals*/ true); + const jsxNamespaceSymbol = checker.resolveName(jsxNamespace, containsJsx, SymbolFlags.Namespace, /*excludeGlobals*/ true); - return !!jsxNamespaceSymbol && ts.some(jsxNamespaceSymbol.declarations, isInImport) + return !!jsxNamespaceSymbol && some(jsxNamespaceSymbol.declarations, isInImport) ? jsxNamespaceSymbol : undefined; } @@ -570,73 +593,73 @@ function getUsageInfo(oldFile: ts.SourceFile, toMove: readonly ts.Statement[], c // Below should all be utilities -function isInImport(decl: ts.Declaration) { +function isInImport(decl: Declaration) { switch (decl.kind) { - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceImport: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: return true; - case ts.SyntaxKind.VariableDeclaration: - return isVariableDeclarationInImport(decl as ts.VariableDeclaration); - case ts.SyntaxKind.BindingElement: - return ts.isVariableDeclaration(decl.parent.parent) && isVariableDeclarationInImport(decl.parent.parent); + case SyntaxKind.VariableDeclaration: + return isVariableDeclarationInImport(decl as VariableDeclaration); + case SyntaxKind.BindingElement: + return isVariableDeclaration(decl.parent.parent) && isVariableDeclarationInImport(decl.parent.parent); default: return false; } } -function isVariableDeclarationInImport(decl: ts.VariableDeclaration) { - return ts.isSourceFile(decl.parent.parent.parent) && - !!decl.initializer && ts.isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true); +function isVariableDeclarationInImport(decl: VariableDeclaration) { + return isSourceFile(decl.parent.parent.parent) && + !!decl.initializer && isRequireCall(decl.initializer, /*checkArgumentIsStringLiteralLike*/ true); } -function filterImport(i: SupportedImport, moduleSpecifier: ts.StringLiteralLike, keep: (name: ts.Identifier) => boolean): SupportedImportStatement | undefined { +function filterImport(i: SupportedImport, moduleSpecifier: StringLiteralLike, keep: (name: Identifier) => boolean): SupportedImportStatement | undefined { switch (i.kind) { - case ts.SyntaxKind.ImportDeclaration: { + case SyntaxKind.ImportDeclaration: { const clause = i.importClause; if (!clause) return undefined; const defaultImport = clause.name && keep(clause.name) ? clause.name : undefined; const namedBindings = clause.namedBindings && filterNamedBindings(clause.namedBindings, keep); return defaultImport || namedBindings - ? ts.factory.createImportDeclaration(/*modifiers*/ undefined, ts.factory.createImportClause(/*isTypeOnly*/ false, defaultImport, namedBindings), moduleSpecifier, /*assertClause*/ undefined) + ? factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImport, namedBindings), moduleSpecifier, /*assertClause*/ undefined) : undefined; } - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return keep(i.name) ? i : undefined; - case ts.SyntaxKind.VariableDeclaration: { + case SyntaxKind.VariableDeclaration: { const name = filterBindingName(i.name, keep); return name ? makeVariableStatement(name, i.type, createRequireCall(moduleSpecifier), i.parent.flags) : undefined; } default: - return ts.Debug.assertNever(i, `Unexpected import kind ${(i as SupportedImport).kind}`); + return Debug.assertNever(i, `Unexpected import kind ${(i as SupportedImport).kind}`); } } -function filterNamedBindings(namedBindings: ts.NamedImportBindings, keep: (name: ts.Identifier) => boolean): ts.NamedImportBindings | undefined { - if (namedBindings.kind === ts.SyntaxKind.NamespaceImport) { +function filterNamedBindings(namedBindings: NamedImportBindings, keep: (name: Identifier) => boolean): NamedImportBindings | undefined { + if (namedBindings.kind === SyntaxKind.NamespaceImport) { return keep(namedBindings.name) ? namedBindings : undefined; } else { const newElements = namedBindings.elements.filter(e => keep(e.name)); - return newElements.length ? ts.factory.createNamedImports(newElements) : undefined; + return newElements.length ? factory.createNamedImports(newElements) : undefined; } } -function filterBindingName(name: ts.BindingName, keep: (name: ts.Identifier) => boolean): ts.BindingName | undefined { +function filterBindingName(name: BindingName, keep: (name: Identifier) => boolean): BindingName | undefined { switch (name.kind) { - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: return keep(name) ? name : undefined; - case ts.SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ArrayBindingPattern: return name; - case ts.SyntaxKind.ObjectBindingPattern: { + case SyntaxKind.ObjectBindingPattern: { // We can't handle nested destructurings or property names well here, so just copy them all. - const newElements = name.elements.filter(prop => prop.propertyName || !ts.isIdentifier(prop.name) || keep(prop.name)); - return newElements.length ? ts.factory.createObjectBindingPattern(newElements) : undefined; + const newElements = name.elements.filter(prop => prop.propertyName || !isIdentifier(prop.name) || keep(prop.name)); + return newElements.length ? factory.createObjectBindingPattern(newElements) : undefined; } } } -function forEachReference(node: ts.Node, checker: ts.TypeChecker, onReference: (s: ts.Symbol) => void) { +function forEachReference(node: Node, checker: TypeChecker, onReference: (s: Symbol) => void) { node.forEachChild(function cb(node) { - if (ts.isIdentifier(node) && !ts.isDeclarationName(node)) { + if (isIdentifier(node) && !isDeclarationName(node)) { const sym = checker.getSymbolAtLocation(node); if (sym) onReference(sym); } @@ -648,31 +671,31 @@ function forEachReference(node: ts.Node, checker: ts.TypeChecker, onReference: ( interface ReadonlySymbolSet { size(): number; - has(symbol: ts.Symbol): boolean; - forEach(cb: (symbol: ts.Symbol) => void): void; - forEachEntry(cb: (symbol: ts.Symbol) => T | undefined): T | undefined; + has(symbol: Symbol): boolean; + forEach(cb: (symbol: Symbol) => void): void; + forEachEntry(cb: (symbol: Symbol) => T | undefined): T | undefined; } class SymbolSet implements ReadonlySymbolSet { - private map = new ts.Map(); - add(symbol: ts.Symbol): void { - this.map.set(String(ts.getSymbolId(symbol)), symbol); + private map = new Map(); + add(symbol: Symbol): void { + this.map.set(String(getSymbolId(symbol)), symbol); } - has(symbol: ts.Symbol): boolean { - return this.map.has(String(ts.getSymbolId(symbol))); + has(symbol: Symbol): boolean { + return this.map.has(String(getSymbolId(symbol))); } - delete(symbol: ts.Symbol): void { - this.map.delete(String(ts.getSymbolId(symbol))); + delete(symbol: Symbol): void { + this.map.delete(String(getSymbolId(symbol))); } - forEach(cb: (symbol: ts.Symbol) => void): void { + forEach(cb: (symbol: Symbol) => void): void { this.map.forEach(cb); } - forEachEntry(cb: (symbol: ts.Symbol) => T | undefined): T | undefined { - return ts.forEachEntry(this.map, cb); + forEachEntry(cb: (symbol: Symbol) => T | undefined): T | undefined { + return forEachEntry(this.map, cb); } clone(): SymbolSet { const clone = new SymbolSet(); - ts.copyEntries(this.map, clone.map); + copyEntries(this.map, clone.map); return clone; } size() { @@ -680,101 +703,101 @@ class SymbolSet implements ReadonlySymbolSet { } } -type TopLevelExpressionStatement = ts.ExpressionStatement & { expression: ts.BinaryExpression & { left: ts.PropertyAccessExpression } }; // 'exports.x = ...' +type TopLevelExpressionStatement = ExpressionStatement & { expression: BinaryExpression & { left: PropertyAccessExpression } }; // 'exports.x = ...' type NonVariableTopLevelDeclaration = - | ts.FunctionDeclaration - | ts.ClassDeclaration - | ts.EnumDeclaration - | ts.TypeAliasDeclaration - | ts.InterfaceDeclaration - | ts.ModuleDeclaration + | FunctionDeclaration + | ClassDeclaration + | EnumDeclaration + | TypeAliasDeclaration + | InterfaceDeclaration + | ModuleDeclaration | TopLevelExpressionStatement - | ts.ImportEqualsDeclaration; -type TopLevelDeclarationStatement = NonVariableTopLevelDeclaration | ts.VariableStatement; -interface TopLevelVariableDeclaration extends ts.VariableDeclaration { parent: ts.VariableDeclarationList & { parent: ts.VariableStatement; }; } -type TopLevelDeclaration = NonVariableTopLevelDeclaration | TopLevelVariableDeclaration | ts.BindingElement; -function isTopLevelDeclaration(node: ts.Node): node is TopLevelDeclaration { - return isNonVariableTopLevelDeclaration(node) && ts.isSourceFile(node.parent) || ts.isVariableDeclaration(node) && ts.isSourceFile(node.parent.parent.parent); + | ImportEqualsDeclaration; +type TopLevelDeclarationStatement = NonVariableTopLevelDeclaration | VariableStatement; +interface TopLevelVariableDeclaration extends VariableDeclaration { parent: VariableDeclarationList & { parent: VariableStatement; }; } +type TopLevelDeclaration = NonVariableTopLevelDeclaration | TopLevelVariableDeclaration | BindingElement; +function isTopLevelDeclaration(node: Node): node is TopLevelDeclaration { + return isNonVariableTopLevelDeclaration(node) && isSourceFile(node.parent) || isVariableDeclaration(node) && isSourceFile(node.parent.parent.parent); } -function sourceFileOfTopLevelDeclaration(node: TopLevelDeclaration): ts.Node { - return ts.isVariableDeclaration(node) ? node.parent.parent.parent : node.parent; +function sourceFileOfTopLevelDeclaration(node: TopLevelDeclaration): Node { + return isVariableDeclaration(node) ? node.parent.parent.parent : node.parent; } -function isTopLevelDeclarationStatement(node: ts.Node): node is TopLevelDeclarationStatement { - ts.Debug.assert(ts.isSourceFile(node.parent), "Node parent should be a SourceFile"); - return isNonVariableTopLevelDeclaration(node) || ts.isVariableStatement(node); +function isTopLevelDeclarationStatement(node: Node): node is TopLevelDeclarationStatement { + Debug.assert(isSourceFile(node.parent), "Node parent should be a SourceFile"); + return isNonVariableTopLevelDeclaration(node) || isVariableStatement(node); } -function isNonVariableTopLevelDeclaration(node: ts.Node): node is NonVariableTopLevelDeclaration { +function isNonVariableTopLevelDeclaration(node: Node): node is NonVariableTopLevelDeclaration { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return true; default: return false; } } -function forEachTopLevelDeclaration(statement: ts.Statement, cb: (node: TopLevelDeclaration) => T): T | undefined { +function forEachTopLevelDeclaration(statement: Statement, cb: (node: TopLevelDeclaration) => T): T | undefined { switch (statement.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - return cb(statement as ts.FunctionDeclaration | ts.ClassDeclaration | ts.EnumDeclaration | ts.ModuleDeclaration | ts.TypeAliasDeclaration | ts.InterfaceDeclaration | ts.ImportEqualsDeclaration); - - case ts.SyntaxKind.VariableStatement: - return ts.firstDefined((statement as ts.VariableStatement).declarationList.declarations, decl => forEachTopLevelDeclarationInBindingName(decl.name, cb)); - - case ts.SyntaxKind.ExpressionStatement: { - const { expression } = statement as ts.ExpressionStatement; - return ts.isBinaryExpression(expression) && ts.getAssignmentDeclarationKind(expression) === ts.AssignmentDeclarationKind.ExportsProperty + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + return cb(statement as FunctionDeclaration | ClassDeclaration | EnumDeclaration | ModuleDeclaration | TypeAliasDeclaration | InterfaceDeclaration | ImportEqualsDeclaration); + + case SyntaxKind.VariableStatement: + return firstDefined((statement as VariableStatement).declarationList.declarations, decl => forEachTopLevelDeclarationInBindingName(decl.name, cb)); + + case SyntaxKind.ExpressionStatement: { + const { expression } = statement as ExpressionStatement; + return isBinaryExpression(expression) && getAssignmentDeclarationKind(expression) === AssignmentDeclarationKind.ExportsProperty ? cb(statement as TopLevelExpressionStatement) : undefined; } } } -function forEachTopLevelDeclarationInBindingName(name: ts.BindingName, cb: (node: TopLevelDeclaration) => T): T | undefined { +function forEachTopLevelDeclarationInBindingName(name: BindingName, cb: (node: TopLevelDeclaration) => T): T | undefined { switch (name.kind) { - case ts.SyntaxKind.Identifier: - return cb(ts.cast(name.parent, (x): x is TopLevelVariableDeclaration | ts.BindingElement => ts.isVariableDeclaration(x) || ts.isBindingElement(x))); - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ObjectBindingPattern: - return ts.firstDefined(name.elements, em => ts.isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb)); + case SyntaxKind.Identifier: + return cb(cast(name.parent, (x): x is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(x) || isBindingElement(x))); + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ObjectBindingPattern: + return firstDefined(name.elements, em => isOmittedExpression(em) ? undefined : forEachTopLevelDeclarationInBindingName(em.name, cb)); default: - return ts.Debug.assertNever(name, `Unexpected name kind ${(name as ts.BindingName).kind}`); + return Debug.assertNever(name, `Unexpected name kind ${(name as BindingName).kind}`); } } -function nameOfTopLevelDeclaration(d: TopLevelDeclaration): ts.Identifier | undefined { - return ts.isExpressionStatement(d) ? ts.tryCast(d.expression.left.name, ts.isIdentifier) : ts.tryCast(d.name, ts.isIdentifier); +function nameOfTopLevelDeclaration(d: TopLevelDeclaration): Identifier | undefined { + return isExpressionStatement(d) ? tryCast(d.expression.left.name, isIdentifier) : tryCast(d.name, isIdentifier); } function getTopLevelDeclarationStatement(d: TopLevelDeclaration): TopLevelDeclarationStatement { switch (d.kind) { - case ts.SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableDeclaration: return d.parent.parent; - case ts.SyntaxKind.BindingElement: + case SyntaxKind.BindingElement: return getTopLevelDeclarationStatement( - ts.cast(d.parent.parent, (p): p is TopLevelVariableDeclaration | ts.BindingElement => ts.isVariableDeclaration(p) || ts.isBindingElement(p))); + cast(d.parent.parent, (p): p is TopLevelVariableDeclaration | BindingElement => isVariableDeclaration(p) || isBindingElement(p))); default: return d; } } -function addExportToChanges(sourceFile: ts.SourceFile, decl: TopLevelDeclarationStatement, name: ts.Identifier, changes: ts.textChanges.ChangeTracker, useEs6Exports: boolean): void { +function addExportToChanges(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, name: Identifier, changes: textChanges.ChangeTracker, useEs6Exports: boolean): void { if (isExported(sourceFile, decl, useEs6Exports, name)) return; if (useEs6Exports) { - if (!ts.isExpressionStatement(decl)) changes.insertExportModifier(sourceFile, decl); + if (!isExpressionStatement(decl)) changes.insertExportModifier(sourceFile, decl); } else { const names = getNamesToExportInCommonJS(decl); @@ -782,71 +805,71 @@ function addExportToChanges(sourceFile: ts.SourceFile, decl: TopLevelDeclaration } } -function isExported(sourceFile: ts.SourceFile, decl: TopLevelDeclarationStatement, useEs6Exports: boolean, name?: ts.Identifier): boolean { +function isExported(sourceFile: SourceFile, decl: TopLevelDeclarationStatement, useEs6Exports: boolean, name?: Identifier): boolean { if (useEs6Exports) { - return !ts.isExpressionStatement(decl) && ts.hasSyntacticModifier(decl, ts.ModifierFlags.Export) || !!(name && sourceFile.symbol.exports?.has(name.escapedText)); + return !isExpressionStatement(decl) && hasSyntacticModifier(decl, ModifierFlags.Export) || !!(name && sourceFile.symbol.exports?.has(name.escapedText)); } return !!sourceFile.symbol && !!sourceFile.symbol.exports && - getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(ts.escapeLeadingUnderscores(name))); + getNamesToExportInCommonJS(decl).some(name => sourceFile.symbol.exports!.has(escapeLeadingUnderscores(name))); } -function addExport(decl: TopLevelDeclarationStatement, useEs6Exports: boolean): readonly ts.Statement[] | undefined { +function addExport(decl: TopLevelDeclarationStatement, useEs6Exports: boolean): readonly Statement[] | undefined { return useEs6Exports ? [addEs6Export(decl)] : addCommonjsExport(decl); } function addEs6Export(d: TopLevelDeclarationStatement): TopLevelDeclarationStatement { - const modifiers = ts.canHaveModifiers(d) ? ts.concatenate([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.getModifiers(d)) : undefined; + const modifiers = canHaveModifiers(d) ? concatenate([factory.createModifier(SyntaxKind.ExportKeyword)], getModifiers(d)) : undefined; switch (d.kind) { - case ts.SyntaxKind.FunctionDeclaration: - return ts.factory.updateFunctionDeclaration(d, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); - case ts.SyntaxKind.ClassDeclaration: - const decorators = ts.canHaveDecorators(d) ? ts.getDecorators(d) : undefined; - return ts.factory.updateClassDeclaration(d, ts.concatenate(decorators, modifiers), d.name, d.typeParameters, d.heritageClauses, d.members); - case ts.SyntaxKind.VariableStatement: - return ts.factory.updateVariableStatement(d, modifiers, d.declarationList); - case ts.SyntaxKind.ModuleDeclaration: - return ts.factory.updateModuleDeclaration(d, modifiers, d.name, d.body); - case ts.SyntaxKind.EnumDeclaration: - return ts.factory.updateEnumDeclaration(d, modifiers, d.name, d.members); - case ts.SyntaxKind.TypeAliasDeclaration: - return ts.factory.updateTypeAliasDeclaration(d, modifiers, d.name, d.typeParameters, d.type); - case ts.SyntaxKind.InterfaceDeclaration: - return ts.factory.updateInterfaceDeclaration(d, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); - case ts.SyntaxKind.ImportEqualsDeclaration: - return ts.factory.updateImportEqualsDeclaration(d, modifiers, d.isTypeOnly, d.name, d.moduleReference); - case ts.SyntaxKind.ExpressionStatement: - return ts.Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` + case SyntaxKind.FunctionDeclaration: + return factory.updateFunctionDeclaration(d, modifiers, d.asteriskToken, d.name, d.typeParameters, d.parameters, d.type, d.body); + case SyntaxKind.ClassDeclaration: + const decorators = canHaveDecorators(d) ? getDecorators(d) : undefined; + return factory.updateClassDeclaration(d, concatenate(decorators, modifiers), d.name, d.typeParameters, d.heritageClauses, d.members); + case SyntaxKind.VariableStatement: + return factory.updateVariableStatement(d, modifiers, d.declarationList); + case SyntaxKind.ModuleDeclaration: + return factory.updateModuleDeclaration(d, modifiers, d.name, d.body); + case SyntaxKind.EnumDeclaration: + return factory.updateEnumDeclaration(d, modifiers, d.name, d.members); + case SyntaxKind.TypeAliasDeclaration: + return factory.updateTypeAliasDeclaration(d, modifiers, d.name, d.typeParameters, d.type); + case SyntaxKind.InterfaceDeclaration: + return factory.updateInterfaceDeclaration(d, modifiers, d.name, d.typeParameters, d.heritageClauses, d.members); + case SyntaxKind.ImportEqualsDeclaration: + return factory.updateImportEqualsDeclaration(d, modifiers, d.isTypeOnly, d.name, d.moduleReference); + case SyntaxKind.ExpressionStatement: + return Debug.fail(); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: - return ts.Debug.assertNever(d, `Unexpected declaration kind ${(d as ts.DeclarationStatement).kind}`); + return Debug.assertNever(d, `Unexpected declaration kind ${(d as DeclarationStatement).kind}`); } } -function addCommonjsExport(decl: TopLevelDeclarationStatement): readonly ts.Statement[] | undefined { +function addCommonjsExport(decl: TopLevelDeclarationStatement): readonly Statement[] | undefined { return [decl, ...getNamesToExportInCommonJS(decl).map(createExportAssignment)]; } function getNamesToExportInCommonJS(decl: TopLevelDeclarationStatement): readonly string[] { switch (decl.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.ClassDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: return [decl.name!.text]; // TODO: GH#18217 - case ts.SyntaxKind.VariableStatement: - return ts.mapDefined(decl.declarationList.declarations, d => ts.isIdentifier(d.name) ? d.name.text : undefined); - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - return ts.emptyArray; - case ts.SyntaxKind.ExpressionStatement: - return ts.Debug.fail("Can't export an ExpressionStatement"); // Shouldn't try to add 'export' keyword to `exports.x = ...` + case SyntaxKind.VariableStatement: + return mapDefined(decl.declarationList.declarations, d => isIdentifier(d.name) ? d.name.text : undefined); + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + return emptyArray; + case SyntaxKind.ExpressionStatement: + return Debug.fail("Can't export an ExpressionStatement"); // Shouldn't try to add 'export' keyword to `exports.x = ...` default: - return ts.Debug.assertNever(decl, `Unexpected decl kind ${(decl as TopLevelDeclarationStatement).kind}`); + return Debug.assertNever(decl, `Unexpected decl kind ${(decl as TopLevelDeclarationStatement).kind}`); } } /** Creates `exports.x = x;` */ -function createExportAssignment(name: string): ts.Statement { - return ts.factory.createExpressionStatement( - ts.factory.createBinaryExpression( - ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("exports"), ts.factory.createIdentifier(name)), - ts.SyntaxKind.EqualsToken, - ts.factory.createIdentifier(name))); +function createExportAssignment(name: string): Statement { + return factory.createExpressionStatement( + factory.createBinaryExpression( + factory.createPropertyAccessExpression(factory.createIdentifier("exports"), factory.createIdentifier(name)), + SyntaxKind.EqualsToken, + factory.createIdentifier(name))); } diff --git a/src/services/rename.ts b/src/services/rename.ts index 0ff1d52d9d34e..7508c150d41b4 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -1,36 +1,46 @@ -import * as ts from "./_namespaces/ts"; +import { + compareStringsCaseSensitive, Comparison, createTextSpan, DiagnosticMessage, Diagnostics, endsWith, every, Extension, + fileExtensionIs, find, getAdjustedRenameLocation, getContextualTypeFromParentOrAncestorTypeNode, + getLocaleSpecificMessage, getPathComponents, getTextOfIdentifierOrLiteral, getTextOfNode, getTouchingPropertyName, + ImportSpecifier, isExternalModuleNameRelative, isIdentifier, isImportOrExportSpecifierName, isImportSpecifier, + isInsideNodeModules, isLabelName, isLiteralNameOfPropertyDeclarationOrIndexAccess, isSourceFile, + isStringLiteralLike, isStringOrNumericLiteralLike, Node, NumericLiteral, Path, Program, removeFileExtension, + RenameInfo, RenameInfoFailure, RenameInfoSuccess, ScriptElementKind, ScriptElementKindModifier, some, SourceFile, + StringLiteralLike, stripQuotes, Symbol, SymbolDisplay, SymbolFlags, SyntaxKind, tryGetImportFromModuleSpecifier, + tryRemoveSuffix, TypeChecker, TypeFlags, UnionType, UserPreferences, +} from "./_namespaces/ts"; /** @internal */ -export function getRenameInfo(program: ts.Program, sourceFile: ts.SourceFile, position: number, preferences: ts.UserPreferences): ts.RenameInfo { - const node = ts.getAdjustedRenameLocation(ts.getTouchingPropertyName(sourceFile, position)); +export function getRenameInfo(program: Program, sourceFile: SourceFile, position: number, preferences: UserPreferences): RenameInfo { + const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position)); if (nodeIsEligibleForRename(node)) { const renameInfo = getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, program, preferences); if (renameInfo) { return renameInfo; } } - return getRenameInfoError(ts.Diagnostics.You_cannot_rename_this_element); + return getRenameInfoError(Diagnostics.You_cannot_rename_this_element); } function getRenameInfoForNode( - node: ts.Node, - typeChecker: ts.TypeChecker, - sourceFile: ts.SourceFile, - program: ts.Program, - preferences: ts.UserPreferences): ts.RenameInfo | undefined { + node: Node, + typeChecker: TypeChecker, + sourceFile: SourceFile, + program: Program, + preferences: UserPreferences): RenameInfo | undefined { const symbol = typeChecker.getSymbolAtLocation(node); if (!symbol) { - if (ts.isStringLiteralLike(node)) { - const type = ts.getContextualTypeFromParentOrAncestorTypeNode(node, typeChecker); - if (type && ((type.flags & ts.TypeFlags.StringLiteral) || ( - (type.flags & ts.TypeFlags.Union) && ts.every((type as ts.UnionType).types, type => !!(type.flags & ts.TypeFlags.StringLiteral)) + if (isStringLiteralLike(node)) { + const type = getContextualTypeFromParentOrAncestorTypeNode(node, typeChecker); + if (type && ((type.flags & TypeFlags.StringLiteral) || ( + (type.flags & TypeFlags.Union) && every((type as UnionType).types, type => !!(type.flags & TypeFlags.StringLiteral)) ))) { - return getRenameInfoSuccess(node.text, node.text, ts.ScriptElementKind.string, "", node, sourceFile); + return getRenameInfoSuccess(node.text, node.text, ScriptElementKind.string, "", node, sourceFile); } } - else if (ts.isLabelName(node)) { - const name = ts.getTextOfNode(node); - return getRenameInfoSuccess(name, name, ts.ScriptElementKind.label, ts.ScriptElementKindModifier.none, node, sourceFile); + else if (isLabelName(node)) { + const name = getTextOfNode(node); + return getRenameInfoSuccess(name, name, ScriptElementKind.label, ScriptElementKindModifier.none, node, sourceFile); } return undefined; } @@ -40,15 +50,15 @@ function getRenameInfoForNode( // Disallow rename for elements that are defined in the standard TypeScript library. if (declarations.some(declaration => isDefinedInLibraryFile(program, declaration))) { - return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); + return getRenameInfoError(Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library); } // Cannot rename `default` as in `import { default as foo } from "./someModule"; - if (ts.isIdentifier(node) && node.originalKeywordKind === ts.SyntaxKind.DefaultKeyword && symbol.parent && symbol.parent.flags & ts.SymbolFlags.Module) { + if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent && symbol.parent.flags & SymbolFlags.Module) { return undefined; } - if (ts.isStringLiteralLike(node) && ts.tryGetImportFromModuleSpecifier(node)) { + if (isStringLiteralLike(node) && tryGetImportFromModuleSpecifier(node)) { return preferences.allowRenameOfImportPath ? getRenameInfoForModule(node, sourceFile, symbol) : undefined; } @@ -58,29 +68,29 @@ function getRenameInfoForNode( return getRenameInfoError(wouldRenameNodeModules); } - const kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node); - const specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteralLike(node) && node.parent.kind === ts.SyntaxKind.ComputedPropertyName) - ? ts.stripQuotes(ts.getTextOfIdentifierOrLiteral(node)) + const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node); + const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName) + ? stripQuotes(getTextOfIdentifierOrLiteral(node)) : undefined; const displayName = specifierName || typeChecker.symbolToString(symbol); const fullDisplayName = specifierName || typeChecker.getFullyQualifiedName(symbol); - return getRenameInfoSuccess(displayName, fullDisplayName, kind, ts.SymbolDisplay.getSymbolModifiers(typeChecker,symbol), node, sourceFile); + return getRenameInfoSuccess(displayName, fullDisplayName, kind, SymbolDisplay.getSymbolModifiers(typeChecker,symbol), node, sourceFile); } -function isDefinedInLibraryFile(program: ts.Program, declaration: ts.Node) { +function isDefinedInLibraryFile(program: Program, declaration: Node) { const sourceFile = declaration.getSourceFile(); - return program.isSourceFileDefaultLibrary(sourceFile) && ts.fileExtensionIs(sourceFile.fileName, ts.Extension.Dts); + return program.isSourceFileDefaultLibrary(sourceFile) && fileExtensionIs(sourceFile.fileName, Extension.Dts); } function wouldRenameInOtherNodeModules( - originalFile: ts.SourceFile, - symbol: ts.Symbol, - checker: ts.TypeChecker, - preferences: ts.UserPreferences -): ts.DiagnosticMessage | undefined { - if (!preferences.providePrefixAndSuffixTextForRename && symbol.flags & ts.SymbolFlags.Alias) { - const importSpecifier = symbol.declarations && ts.find(symbol.declarations, decl => ts.isImportSpecifier(decl)); - if (importSpecifier && !(importSpecifier as ts.ImportSpecifier).propertyName) { + originalFile: SourceFile, + symbol: Symbol, + checker: TypeChecker, + preferences: UserPreferences +): DiagnosticMessage | undefined { + if (!preferences.providePrefixAndSuffixTextForRename && symbol.flags & SymbolFlags.Alias) { + const importSpecifier = symbol.declarations && find(symbol.declarations, decl => isImportSpecifier(decl)); + if (importSpecifier && !(importSpecifier as ImportSpecifier).propertyName) { symbol = checker.getAliasedSymbol(symbol); } } @@ -90,8 +100,8 @@ function wouldRenameInOtherNodeModules( } const originalPackage = getPackagePathComponents(originalFile.path); if (originalPackage === undefined) { // original source file is not in node_modules - if (ts.some(declarations, declaration => ts.isInsideNodeModules(declaration.getSourceFile().path))) { - return ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_a_node_modules_folder; + if (some(declarations, declaration => isInsideNodeModules(declaration.getSourceFile().path))) { + return Diagnostics.You_cannot_rename_elements_that_are_defined_in_a_node_modules_folder; } else { return undefined; @@ -103,8 +113,8 @@ function wouldRenameInOtherNodeModules( if (declPackage) { const length = Math.min(originalPackage.length, declPackage.length); for (let i = 0; i <= length; i++) { - if (ts.compareStringsCaseSensitive(originalPackage[i], declPackage[i]) !== ts.Comparison.EqualTo) { - return ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_another_node_modules_folder; + if (compareStringsCaseSensitive(originalPackage[i], declPackage[i]) !== Comparison.EqualTo) { + return Diagnostics.You_cannot_rename_elements_that_are_defined_in_another_node_modules_folder; } } } @@ -112,8 +122,8 @@ function wouldRenameInOtherNodeModules( return undefined; } -function getPackagePathComponents(filePath: ts.Path): string[] | undefined { - const components = ts.getPathComponents(filePath); +function getPackagePathComponents(filePath: Path): string[] | undefined { + const components = getPathComponents(filePath); const nodeModulesIdx = components.lastIndexOf("node_modules"); if (nodeModulesIdx === -1) { return undefined; @@ -121,31 +131,31 @@ function getPackagePathComponents(filePath: ts.Path): string[] | undefined { return components.slice(0, nodeModulesIdx + 2); } -function getRenameInfoForModule(node: ts.StringLiteralLike, sourceFile: ts.SourceFile, moduleSymbol: ts.Symbol): ts.RenameInfo | undefined { - if (!ts.isExternalModuleNameRelative(node.text)) { - return getRenameInfoError(ts.Diagnostics.You_cannot_rename_a_module_via_a_global_import); +function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined { + if (!isExternalModuleNameRelative(node.text)) { + return getRenameInfoError(Diagnostics.You_cannot_rename_a_module_via_a_global_import); } - const moduleSourceFile = moduleSymbol.declarations && ts.find(moduleSymbol.declarations, ts.isSourceFile); + const moduleSourceFile = moduleSymbol.declarations && find(moduleSymbol.declarations, isSourceFile); if (!moduleSourceFile) return undefined; - const withoutIndex = ts.endsWith(node.text, "/index") || ts.endsWith(node.text, "/index.js") ? undefined : ts.tryRemoveSuffix(ts.removeFileExtension(moduleSourceFile.fileName), "/index"); + const withoutIndex = endsWith(node.text, "/index") || endsWith(node.text, "/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index"); const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex; - const kind = withoutIndex === undefined ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.directory; + const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory; const indexAfterLastSlash = node.text.lastIndexOf("/") + 1; // Span should only be the last component of the path. + 1 to account for the quote character. - const triggerSpan = ts.createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash); + const triggerSpan = createTextSpan(node.getStart(sourceFile) + 1 + indexAfterLastSlash, node.text.length - indexAfterLastSlash); return { canRename: true, fileToRename: name, kind, displayName: name, fullDisplayName: name, - kindModifiers: ts.ScriptElementKindModifier.none, + kindModifiers: ScriptElementKindModifier.none, triggerSpan, }; } -function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ts.ScriptElementKind, kindModifiers: string, node: ts.Node, sourceFile: ts.SourceFile): ts.RenameInfoSuccess { +function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfoSuccess { return { canRename: true, fileToRename: undefined, @@ -157,32 +167,32 @@ function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind }; } -function getRenameInfoError(diagnostic: ts.DiagnosticMessage): ts.RenameInfoFailure { - return { canRename: false, localizedErrorMessage: ts.getLocaleSpecificMessage(diagnostic) }; +function getRenameInfoError(diagnostic: DiagnosticMessage): RenameInfoFailure { + return { canRename: false, localizedErrorMessage: getLocaleSpecificMessage(diagnostic) }; } -function createTriggerSpanForNode(node: ts.Node, sourceFile: ts.SourceFile) { +function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) { let start = node.getStart(sourceFile); let width = node.getWidth(sourceFile); - if (ts.isStringLiteralLike(node)) { + if (isStringLiteralLike(node)) { // Exclude the quotes start += 1; width -= 2; } - return ts.createTextSpan(start, width); + return createTextSpan(start, width); } /** @internal */ -export function nodeIsEligibleForRename(node: ts.Node): boolean { +export function nodeIsEligibleForRename(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PrivateIdentifier: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.ThisKeyword: return true; - case ts.SyntaxKind.NumericLiteral: - return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node as ts.NumericLiteral); + case SyntaxKind.NumericLiteral: + return isLiteralNameOfPropertyDeclarationOrIndexAccess(node as NumericLiteral); default: return false; } diff --git a/src/services/services.ts b/src/services/services.ts index 42861b04adb65..4588c64ea9bc0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1,53 +1,110 @@ import * as ts from "./_namespaces/ts"; +import * as NavigateTo from "./_namespaces/ts.NavigateTo"; +import * as NavigationBar from "./_namespaces/ts.NavigationBar"; +import { + __String, ApplicableRefactorInfo, ApplyCodeActionCommandResult, AssignmentDeclarationKind, BaseType, + BinaryExpression, BreakpointResolver, CallHierarchy, CallHierarchyIncomingCall, CallHierarchyItem, + CallHierarchyOutgoingCall, CancellationToken, changeCompilerHostLikeToUseCache, CharacterCodes, CheckJsDirective, + Classifications, ClassifiedSpan, ClassifiedSpan2020, classifier, CodeActionCommand, codefix, CodeFixAction, + CombinedCodeActions, CombinedCodeFixScope, combinePaths, compareValues, CompilerHost, CompilerOptions, + CompletionEntryData, CompletionEntryDetails, CompletionInfo, Completions, computePositionOfLineAndCharacter, + computeSuggestionDiagnostics, createDocumentRegistry, createGetCanonicalFileName, createMultiMap, createProgram, + CreateProgramOptions, createSourceFile, CreateSourceFileOptions, createTextSpanFromBounds, createTextSpanFromNode, + createTextSpanFromRange, Debug, Declaration, deduplicate, DefinitionInfo, DefinitionInfoAndBoundSpan, Diagnostic, + DiagnosticWithLocation, directoryProbablyExists, DocCommentTemplateOptions, DocumentHighlights, DocumentRegistry, + DocumentSpan, EditorOptions, EditorSettings, ElementAccessExpression, EmitTextWriter, emptyArray, emptyOptions, + EndOfFileToken, EntityName, equateValues, ESMap, ExportDeclaration, FileReference, FileTextChanges, filter, find, + FindAllReferences, findChildOfKind, findPrecedingToken, first, firstDefined, firstOrOnly, flatMap, forEach, + forEachChild, FormatCodeOptions, FormatCodeSettings, formatting, FunctionLikeDeclaration, GeneratedIdentifierFlags, + getAdjustedRenameLocation, getAllSuperTypeNodes, getAssignmentDeclarationKind, GetCompletionsAtPositionOptions, + getContainerNode, getDefaultLibFileName, getDirectoryPath, getEmitDeclarations, getEntries, + getEscapedTextOfIdentifierOrLiteral, getFileEmitOutput, getImpliedNodeFormatForFile, getJSDocTags, + getLineAndCharacterOfPosition, getLineStarts, getMappedDocumentSpan, getNameFromPropertyName, getNewLineCharacter, + getNewLineOrDefaultFromHost, getNonAssignedNameOfDeclaration, getNormalizedAbsolutePath, getObjectFlags, + getScriptKind, getSetExternalModuleIndicator, getSnapshotText, getSourceFileOfNode, getSourceMapper, + getTokenPosOfNode, getTouchingPropertyName, getTouchingToken, GoToDefinition, HasInvalidatedResolutions, + hasJSDocNodes, hasProperty, hasStaticModifier, hasSyntacticModifier, HighlightSpanKind, HostCancellationToken, + hostGetCanonicalFileName, hostUsesCaseSensitiveFileNames, Identifier, identity, idText, ImplementationLocation, + ImportDeclaration, IndexKind, IndexType, InlayHint, InlayHints, InlayHintsContext, insertSorted, InterfaceType, + IntersectionType, isArray, isBindingPattern, isComputedPropertyName, isConstTypeReference, IScriptSnapshot, + isDeclarationName, isGetAccessor, isIdentifier, isImportMeta, isInComment, isInsideJsxElement, + isInsideJsxElementOrAttribute, isInString, isInTemplateString, isIntrinsicJsxName, isJSDocCommentContainingNode, + isJsxAttributes, isJsxClosingElement, isJsxElement, isJsxFragment, isJsxOpeningElement, isJsxOpeningFragment, + isJsxText, isLabelName, isLiteralComputedPropertyDeclarationName, isNamedExports, isNamedTupleMember, + isNameOfModuleDeclaration, isNewExpression, isNodeKind, isObjectLiteralElement, isObjectLiteralExpression, + isPrivateIdentifier, isProgramUptoDate, isPropertyAccessExpression, isPropertyName, isRightSideOfPropertyAccess, + isRightSideOfQualifiedName, isSetAccessor, isStringOrNumericLiteralLike, isTagName, isTextWhiteSpaceLike, + isThisTypeParameter, JsDoc, JSDoc, JSDocContainer, JSDocTagInfo, JsonSourceFile, JsxAttributes, JsxClosingTagInfo, + JsxElement, JsxEmit, JsxFragment, LanguageService, LanguageServiceHost, LanguageServiceMode, LanguageVariant, + lastOrUndefined, length, LineAndCharacter, lineBreakPart, LiteralType, map, Map, mapDefined, MapLike, mapOneOrMany, + maybeBind, maybeSetLocalizedDiagnosticMessages, ModeAwareCache, ModifierFlags, ModuleDeclaration, NavigateToItem, + NavigationBarItem, NavigationTree, Node, NodeArray, NodeFlags, noop, normalizePath, NumberLiteralType, + NumericLiteral, ObjectAllocator, ObjectFlags, ObjectLiteralElement, ObjectLiteralExpression, + OperationCanceledException, OrganizeImports, OrganizeImportsArgs, OrganizeImportsMode, OutliningElementsCollector, + OutliningSpan, ParseConfigFileHost, ParsedCommandLine, parseJsonSourceFileConfigFileContent, Path, + positionIsSynthesized, PossibleProgramFileInfo, PragmaMap, PrivateIdentifier, Program, PropertyName, Push, + QuickInfo, refactor, RefactorContext, RefactorEditInfo, RefactorTriggerReason, ReferencedSymbol, ReferenceEntry, + Rename, RenameInfo, RenameInfoOptions, RenameLocation, ResolvedModuleFull, ResolvedProjectReference, + ResolvedTypeReferenceDirective, returnFalse, scanner, ScriptElementKind, ScriptElementKindModifier, ScriptKind, + ScriptTarget, SelectionRange, SemanticClassificationFormat, Set, setObjectAllocator, Signature, + SignatureDeclaration, SignatureFlags, SignatureHelp, SignatureHelpItems, SignatureHelpItemsOptions, SignatureKind, + singleElementArray, SmartSelectionRange, SortedArray, SourceFile, SourceFileLike, SourceMapSource, Statement, + stringContains, StringLiteral, StringLiteralLike, StringLiteralType, Symbol, SymbolDisplay, SymbolDisplayPart, + SymbolFlags, symbolName, SyntaxKind, SyntaxList, tagNamesAreEquivalent, TextChange, TextChangeRange, TextInsertion, + TextRange, TextSpan, textSpanEnd, timestamp, TodoComment, TodoCommentDescriptor, Token, toPath, tracing, + TransformFlags, TransientSymbol, Type, TypeChecker, TypeFlags, TypeNode, TypeParameter, TypePredicate, + TypeReference, typeToDisplayParts, UnderscoreEscapedMap, UnionOrIntersectionType, UnionType, updateSourceFile, + UserPreferences, VariableDeclaration, +} from "./_namespaces/ts"; /** The version of the language service API */ export const servicesVersion = "0.8"; -function createNode(kind: TKind, pos: number, end: number, parent: ts.Node): NodeObject | TokenObject | IdentifierObject | PrivateIdentifierObject { - const node = ts.isNodeKind(kind) ? new NodeObject(kind, pos, end) : - kind === ts.SyntaxKind.Identifier ? new IdentifierObject(ts.SyntaxKind.Identifier, pos, end) : - kind === ts.SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(ts.SyntaxKind.PrivateIdentifier, pos, end) : +function createNode(kind: TKind, pos: number, end: number, parent: Node): NodeObject | TokenObject | IdentifierObject | PrivateIdentifierObject { + const node = isNodeKind(kind) ? new NodeObject(kind, pos, end) : + kind === SyntaxKind.Identifier ? new IdentifierObject(SyntaxKind.Identifier, pos, end) : + kind === SyntaxKind.PrivateIdentifier ? new PrivateIdentifierObject(SyntaxKind.PrivateIdentifier, pos, end) : new TokenObject(kind, pos, end); node.parent = parent; - node.flags = parent.flags & ts.NodeFlags.ContextFlags; + node.flags = parent.flags & NodeFlags.ContextFlags; return node; } -class NodeObject implements ts.Node { - public kind: ts.SyntaxKind; +class NodeObject implements Node { + public kind: SyntaxKind; public pos: number; public end: number; - public flags: ts.NodeFlags; - public modifierFlagsCache: ts.ModifierFlags; - public transformFlags: ts.TransformFlags; - public parent: ts.Node; - public symbol!: ts.Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined - public jsDoc?: ts.JSDoc[]; - public original?: ts.Node; - private _children: ts.Node[] | undefined; - - constructor(kind: ts.SyntaxKind, pos: number, end: number) { + public flags: NodeFlags; + public modifierFlagsCache: ModifierFlags; + public transformFlags: TransformFlags; + public parent: Node; + public symbol!: Symbol; // Actually optional, but it was too annoying to access `node.symbol!` everywhere since in many cases we know it must be defined + public jsDoc?: JSDoc[]; + public original?: Node; + private _children: Node[] | undefined; + + constructor(kind: SyntaxKind, pos: number, end: number) { this.pos = pos; this.end = end; - this.flags = ts.NodeFlags.None; - this.modifierFlagsCache = ts.ModifierFlags.None; - this.transformFlags = ts.TransformFlags.None; + this.flags = NodeFlags.None; + this.modifierFlagsCache = ModifierFlags.None; + this.transformFlags = TransformFlags.None; this.parent = undefined!; this.kind = kind; } private assertHasRealPosition(message?: string) { // eslint-disable-next-line local/debug-assert - ts.Debug.assert(!ts.positionIsSynthesized(this.pos) && !ts.positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); + Debug.assert(!positionIsSynthesized(this.pos) && !positionIsSynthesized(this.end), message || "Node must have a real position for this operation"); } - public getSourceFile(): ts.SourceFile { - return ts.getSourceFileOfNode(this); + public getSourceFile(): SourceFile { + return getSourceFileOfNode(this); } - public getStart(sourceFile?: ts.SourceFileLike, includeJsDocComment?: boolean): number { + public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number { this.assertHasRealPosition(); - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + return getTokenPosOfNode(this, sourceFile, includeJsDocComment); } public getFullStart(): number { @@ -60,7 +117,7 @@ class NodeObject implements ts.Node { return this.end; } - public getWidth(sourceFile?: ts.SourceFile): number { + public getWidth(sourceFile?: SourceFile): number { this.assertHasRealPosition(); return this.getEnd() - this.getStart(sourceFile); } @@ -70,17 +127,17 @@ class NodeObject implements ts.Node { return this.end - this.pos; } - public getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number { + public getLeadingTriviaWidth(sourceFile?: SourceFile): number { this.assertHasRealPosition(); return this.getStart(sourceFile) - this.pos; } - public getFullText(sourceFile?: ts.SourceFile): string { + public getFullText(sourceFile?: SourceFile): string { this.assertHasRealPosition(); return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); } - public getText(sourceFile?: ts.SourceFile): string { + public getText(sourceFile?: SourceFile): string { this.assertHasRealPosition(); if (!sourceFile) { sourceFile = this.getSourceFile(); @@ -88,57 +145,57 @@ class NodeObject implements ts.Node { return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd()); } - public getChildCount(sourceFile?: ts.SourceFile): number { + public getChildCount(sourceFile?: SourceFile): number { return this.getChildren(sourceFile).length; } - public getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node { + public getChildAt(index: number, sourceFile?: SourceFile): Node { return this.getChildren(sourceFile)[index]; } - public getChildren(sourceFile?: ts.SourceFileLike): ts.Node[] { + public getChildren(sourceFile?: SourceFileLike): Node[] { this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine"); return this._children || (this._children = createChildren(this, sourceFile)); } - public getFirstToken(sourceFile?: ts.SourceFileLike): ts.Node | undefined { + public getFirstToken(sourceFile?: SourceFileLike): Node | undefined { this.assertHasRealPosition(); const children = this.getChildren(sourceFile); if (!children.length) { return undefined; } - const child = ts.find(children, kid => kid.kind < ts.SyntaxKind.FirstJSDocNode || kid.kind > ts.SyntaxKind.LastJSDocNode)!; - return child.kind < ts.SyntaxKind.FirstNode ? + const child = find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode)!; + return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile); } - public getLastToken(sourceFile?: ts.SourceFileLike): ts.Node | undefined { + public getLastToken(sourceFile?: SourceFileLike): Node | undefined { this.assertHasRealPosition(); const children = this.getChildren(sourceFile); - const child = ts.lastOrUndefined(children); + const child = lastOrUndefined(children); if (!child) { return undefined; } - return child.kind < ts.SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile); + return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile); } - public forEachChild(cbNode: (node: ts.Node) => T, cbNodeArray?: (nodes: ts.NodeArray) => T): T | undefined { - return ts.forEachChild(this, cbNode, cbNodeArray); + public forEachChild(cbNode: (node: Node) => T, cbNodeArray?: (nodes: NodeArray) => T): T | undefined { + return forEachChild(this, cbNode, cbNodeArray); } } -function createChildren(node: ts.Node, sourceFile: ts.SourceFileLike | undefined): ts.Node[] { - if (!ts.isNodeKind(node.kind)) { - return ts.emptyArray; +function createChildren(node: Node, sourceFile: SourceFileLike | undefined): Node[] { + if (!isNodeKind(node.kind)) { + return emptyArray; } - const children: ts.Node[] = []; + const children: Node[] = []; - if (ts.isJSDocCommentContainingNode(node)) { + if (isJSDocCommentContainingNode(node)) { /** Don't add trivia for "tokens" since this is in a comment. */ node.forEachChild(child => { children.push(child); @@ -146,50 +203,50 @@ function createChildren(node: ts.Node, sourceFile: ts.SourceFileLike | undefined return children; } - ts.scanner.setText((sourceFile || node.getSourceFile()).text); + scanner.setText((sourceFile || node.getSourceFile()).text); let pos = node.pos; - const processNode = (child: ts.Node) => { + const processNode = (child: Node) => { addSyntheticNodes(children, pos, child.pos, node); children.push(child); pos = child.end; }; - const processNodes = (nodes: ts.NodeArray) => { + const processNodes = (nodes: NodeArray) => { addSyntheticNodes(children, pos, nodes.pos, node); children.push(createSyntaxList(nodes, node)); pos = nodes.end; }; // jsDocComments need to be the first children - ts.forEach((node as ts.JSDocContainer).jsDoc, processNode); + forEach((node as JSDocContainer).jsDoc, processNode); // For syntactic classifications, all trivia are classified together, including jsdoc comments. // For that to work, the jsdoc comments should still be the leading trivia of the first child. // Restoring the scanner position ensures that. pos = node.pos; node.forEachChild(processNode, processNodes); addSyntheticNodes(children, pos, node.end, node); - ts.scanner.setText(undefined); + scanner.setText(undefined); return children; } -function addSyntheticNodes(nodes: ts.Push, pos: number, end: number, parent: ts.Node): void { - ts.scanner.setTextPos(pos); +function addSyntheticNodes(nodes: Push, pos: number, end: number, parent: Node): void { + scanner.setTextPos(pos); while (pos < end) { - const token = ts.scanner.scan(); - const textPos = ts.scanner.getTextPos(); + const token = scanner.scan(); + const textPos = scanner.getTextPos(); if (textPos <= end) { - if (token === ts.SyntaxKind.Identifier) { - ts.Debug.fail(`Did not expect ${ts.Debug.formatSyntaxKind(parent.kind)} to have an Identifier in its trivia`); + if (token === SyntaxKind.Identifier) { + Debug.fail(`Did not expect ${Debug.formatSyntaxKind(parent.kind)} to have an Identifier in its trivia`); } nodes.push(createNode(token, pos, textPos, parent)); } pos = textPos; - if (token === ts.SyntaxKind.EndOfFileToken) { + if (token === SyntaxKind.EndOfFileToken) { break; } } } -function createSyntaxList(nodes: ts.NodeArray, parent: ts.Node): ts.Node { - const list = createNode(ts.SyntaxKind.SyntaxList, nodes.pos, nodes.end, parent) as any as ts.SyntaxList; +function createSyntaxList(nodes: NodeArray, parent: Node): Node { + const list = createNode(SyntaxKind.SyntaxList, nodes.pos, nodes.end, parent) as any as SyntaxList; list._children = []; let pos = nodes.pos; for (const node of nodes) { @@ -201,33 +258,33 @@ function createSyntaxList(nodes: ts.NodeArray, parent: ts.Node): ts.Nod return list; } -class TokenOrIdentifierObject implements ts.Node { - public kind!: ts.SyntaxKind; +class TokenOrIdentifierObject implements Node { + public kind!: SyntaxKind; public pos: number; public end: number; - public flags: ts.NodeFlags; - public modifierFlagsCache: ts.ModifierFlags; - public transformFlags: ts.TransformFlags; - public parent: ts.Node; - public symbol!: ts.Symbol; - public jsDocComments?: ts.JSDoc[]; + public flags: NodeFlags; + public modifierFlagsCache: ModifierFlags; + public transformFlags: TransformFlags; + public parent: Node; + public symbol!: Symbol; + public jsDocComments?: JSDoc[]; constructor(pos: number, end: number) { // Set properties in same order as NodeObject this.pos = pos; this.end = end; - this.flags = ts.NodeFlags.None; - this.modifierFlagsCache = ts.ModifierFlags.None; - this.transformFlags = ts.TransformFlags.None; + this.flags = NodeFlags.None; + this.modifierFlagsCache = ModifierFlags.None; + this.transformFlags = TransformFlags.None; this.parent = undefined!; } - public getSourceFile(): ts.SourceFile { - return ts.getSourceFileOfNode(this); + public getSourceFile(): SourceFile { + return getSourceFileOfNode(this); } - public getStart(sourceFile?: ts.SourceFileLike, includeJsDocComment?: boolean): number { - return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment); + public getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number { + return getTokenPosOfNode(this, sourceFile, includeJsDocComment); } public getFullStart(): number { @@ -238,7 +295,7 @@ class TokenOrIdentifierObject implements ts.Node { return this.end; } - public getWidth(sourceFile?: ts.SourceFile): number { + public getWidth(sourceFile?: SourceFile): number { return this.getEnd() - this.getStart(sourceFile); } @@ -246,15 +303,15 @@ class TokenOrIdentifierObject implements ts.Node { return this.end - this.pos; } - public getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number { + public getLeadingTriviaWidth(sourceFile?: SourceFile): number { return this.getStart(sourceFile) - this.pos; } - public getFullText(sourceFile?: ts.SourceFile): string { + public getFullText(sourceFile?: SourceFile): string { return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end); } - public getText(sourceFile?: ts.SourceFile): string { + public getText(sourceFile?: SourceFile): string { if (!sourceFile) { sourceFile = this.getSourceFile(); } @@ -265,19 +322,19 @@ class TokenOrIdentifierObject implements ts.Node { return this.getChildren().length; } - public getChildAt(index: number): ts.Node { + public getChildAt(index: number): Node { return this.getChildren()[index]; } - public getChildren(): ts.Node[] { - return this.kind === ts.SyntaxKind.EndOfFileToken ? (this as ts.EndOfFileToken).jsDoc || ts.emptyArray : ts.emptyArray; + public getChildren(): Node[] { + return this.kind === SyntaxKind.EndOfFileToken ? (this as EndOfFileToken).jsDoc || emptyArray : emptyArray; } - public getFirstToken(): ts.Node | undefined { + public getFirstToken(): Node | undefined { return undefined; } - public getLastToken(): ts.Node | undefined { + public getLastToken(): Node | undefined { return undefined; } @@ -286,37 +343,37 @@ class TokenOrIdentifierObject implements ts.Node { } } -class SymbolObject implements ts.Symbol { - flags: ts.SymbolFlags; - escapedName: ts.__String; - declarations!: ts.Declaration[]; - valueDeclaration!: ts.Declaration; +class SymbolObject implements Symbol { + flags: SymbolFlags; + escapedName: __String; + declarations!: Declaration[]; + valueDeclaration!: Declaration; // Undefined is used to indicate the value has not been computed. If, after computing, the // symbol has no doc comment, then the empty array will be returned. - documentationComment?: ts.SymbolDisplayPart[]; - tags?: ts.JSDocTagInfo[]; // same + documentationComment?: SymbolDisplayPart[]; + tags?: JSDocTagInfo[]; // same - contextualGetAccessorDocumentationComment?: ts.SymbolDisplayPart[]; - contextualSetAccessorDocumentationComment?: ts.SymbolDisplayPart[]; + contextualGetAccessorDocumentationComment?: SymbolDisplayPart[]; + contextualSetAccessorDocumentationComment?: SymbolDisplayPart[]; - contextualGetAccessorTags?: ts.JSDocTagInfo[]; - contextualSetAccessorTags?: ts.JSDocTagInfo[]; + contextualGetAccessorTags?: JSDocTagInfo[]; + contextualSetAccessorTags?: JSDocTagInfo[]; - constructor(flags: ts.SymbolFlags, name: ts.__String) { + constructor(flags: SymbolFlags, name: __String) { this.flags = flags; this.escapedName = name; } - getFlags(): ts.SymbolFlags { + getFlags(): SymbolFlags { return this.flags; } get name(): string { - return ts.symbolName(this); + return symbolName(this); } - getEscapedName(): ts.__String { + getEscapedName(): __String { return this.escapedName; } @@ -324,16 +381,16 @@ class SymbolObject implements ts.Symbol { return this.name; } - getDeclarations(): ts.Declaration[] | undefined { + getDeclarations(): Declaration[] | undefined { return this.declarations; } - getDocumentationComment(checker: ts.TypeChecker | undefined): ts.SymbolDisplayPart[] { + getDocumentationComment(checker: TypeChecker | undefined): SymbolDisplayPart[] { if (!this.documentationComment) { - this.documentationComment = ts.emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs + this.documentationComment = emptyArray; // Set temporarily to avoid an infinite loop finding inherited docs - if (!this.declarations && (this as ts.Symbol as ts.TransientSymbol).target && ((this as ts.Symbol as ts.TransientSymbol).target as ts.TransientSymbol).tupleLabelDeclaration) { - const labelDecl = ((this as ts.Symbol as ts.TransientSymbol).target as ts.TransientSymbol).tupleLabelDeclaration!; + if (!this.declarations && (this as Symbol as TransientSymbol).target && ((this as Symbol as TransientSymbol).target as TransientSymbol).tupleLabelDeclaration) { + const labelDecl = ((this as Symbol as TransientSymbol).target as TransientSymbol).tupleLabelDeclaration!; this.documentationComment = getDocumentationComment([labelDecl], checker); } else { @@ -343,21 +400,21 @@ class SymbolObject implements ts.Symbol { return this.documentationComment; } - getContextualDocumentationComment(context: ts.Node | undefined, checker: ts.TypeChecker | undefined): ts.SymbolDisplayPart[] { + getContextualDocumentationComment(context: Node | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[] { if (context) { - if (ts.isGetAccessor(context)) { + if (isGetAccessor(context)) { if (!this.contextualGetAccessorDocumentationComment) { - this.contextualGetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isGetAccessor), checker); + this.contextualGetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isGetAccessor), checker); } - if (ts.length(this.contextualGetAccessorDocumentationComment)) { + if (length(this.contextualGetAccessorDocumentationComment)) { return this.contextualGetAccessorDocumentationComment; } } - if (ts.isSetAccessor(context)) { + if (isSetAccessor(context)) { if (!this.contextualSetAccessorDocumentationComment) { - this.contextualSetAccessorDocumentationComment = getDocumentationComment(ts.filter(this.declarations, ts.isSetAccessor), checker); + this.contextualSetAccessorDocumentationComment = getDocumentationComment(filter(this.declarations, isSetAccessor), checker); } - if (ts.length(this.contextualSetAccessorDocumentationComment)) { + if (length(this.contextualSetAccessorDocumentationComment)) { return this.contextualSetAccessorDocumentationComment; } } @@ -365,7 +422,7 @@ class SymbolObject implements ts.Symbol { return this.getDocumentationComment(checker); } - getJsDocTags(checker?: ts.TypeChecker): ts.JSDocTagInfo[] { + getJsDocTags(checker?: TypeChecker): JSDocTagInfo[] { if (this.tags === undefined) { this.tags = getJsDocTagsOfDeclarations(this.declarations, checker); } @@ -373,21 +430,21 @@ class SymbolObject implements ts.Symbol { return this.tags; } - getContextualJsDocTags(context: ts.Node | undefined, checker: ts.TypeChecker | undefined): ts.JSDocTagInfo[] { + getContextualJsDocTags(context: Node | undefined, checker: TypeChecker | undefined): JSDocTagInfo[] { if (context) { - if (ts.isGetAccessor(context)) { + if (isGetAccessor(context)) { if (!this.contextualGetAccessorTags) { - this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isGetAccessor), checker); + this.contextualGetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isGetAccessor), checker); } - if (ts.length(this.contextualGetAccessorTags)) { + if (length(this.contextualGetAccessorTags)) { return this.contextualGetAccessorTags; } } - if (ts.isSetAccessor(context)) { + if (isSetAccessor(context)) { if (!this.contextualSetAccessorTags) { - this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(ts.filter(this.declarations, ts.isSetAccessor), checker); + this.contextualSetAccessorTags = getJsDocTagsOfDeclarations(filter(this.declarations, isSetAccessor), checker); } - if (ts.length(this.contextualSetAccessorTags)) { + if (length(this.contextualSetAccessorTags)) { return this.contextualSetAccessorTags; } } @@ -396,7 +453,7 @@ class SymbolObject implements ts.Symbol { } } -class TokenObject extends TokenOrIdentifierObject implements ts.Token { +class TokenObject extends TokenOrIdentifierObject implements Token { public kind: TKind; constructor(kind: TKind, pos: number, end: number) { @@ -405,10 +462,10 @@ class TokenObject extends TokenOrIdentifierObject i } } -class IdentifierObject extends TokenOrIdentifierObject implements ts.Identifier { - public kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier; - public escapedText!: ts.__String; - public autoGenerateFlags!: ts.GeneratedIdentifierFlags; +class IdentifierObject extends TokenOrIdentifierObject implements Identifier { + public kind: SyntaxKind.Identifier = SyntaxKind.Identifier; + public escapedText!: __String; + public autoGenerateFlags!: GeneratedIdentifierFlags; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; @@ -416,170 +473,170 @@ class IdentifierObject extends TokenOrIdentifierObject implements ts.Identifier _unaryExpressionBrand: any; _expressionBrand: any; _declarationBrand: any; - /*@internal*/typeArguments!: ts.NodeArray; - constructor(_kind: ts.SyntaxKind.Identifier, pos: number, end: number) { + /*@internal*/typeArguments!: NodeArray; + constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) { super(pos, end); } get text(): string { - return ts.idText(this); + return idText(this); } } -IdentifierObject.prototype.kind = ts.SyntaxKind.Identifier; -class PrivateIdentifierObject extends TokenOrIdentifierObject implements ts.PrivateIdentifier { - public kind!: ts.SyntaxKind.PrivateIdentifier; - public escapedText!: ts.__String; - public symbol!: ts.Symbol; +IdentifierObject.prototype.kind = SyntaxKind.Identifier; +class PrivateIdentifierObject extends TokenOrIdentifierObject implements PrivateIdentifier { + public kind!: SyntaxKind.PrivateIdentifier; + public escapedText!: __String; + public symbol!: Symbol; _primaryExpressionBrand: any; _memberExpressionBrand: any; _leftHandSideExpressionBrand: any; _updateExpressionBrand: any; _unaryExpressionBrand: any; _expressionBrand: any; - constructor(_kind: ts.SyntaxKind.PrivateIdentifier, pos: number, end: number) { + constructor(_kind: SyntaxKind.PrivateIdentifier, pos: number, end: number) { super(pos, end); } get text(): string { - return ts.idText(this); + return idText(this); } } -PrivateIdentifierObject.prototype.kind = ts.SyntaxKind.PrivateIdentifier; +PrivateIdentifierObject.prototype.kind = SyntaxKind.PrivateIdentifier; -class TypeObject implements ts.Type { - checker: ts.TypeChecker; - flags: ts.TypeFlags; - objectFlags?: ts.ObjectFlags; +class TypeObject implements Type { + checker: TypeChecker; + flags: TypeFlags; + objectFlags?: ObjectFlags; id!: number; - symbol!: ts.Symbol; - constructor(checker: ts.TypeChecker, flags: ts.TypeFlags) { + symbol!: Symbol; + constructor(checker: TypeChecker, flags: TypeFlags) { this.checker = checker; this.flags = flags; } - getFlags(): ts.TypeFlags { + getFlags(): TypeFlags { return this.flags; } - getSymbol(): ts.Symbol | undefined { + getSymbol(): Symbol | undefined { return this.symbol; } - getProperties(): ts.Symbol[] { + getProperties(): Symbol[] { return this.checker.getPropertiesOfType(this); } - getProperty(propertyName: string): ts.Symbol | undefined { + getProperty(propertyName: string): Symbol | undefined { return this.checker.getPropertyOfType(this, propertyName); } - getApparentProperties(): ts.Symbol[] { + getApparentProperties(): Symbol[] { return this.checker.getAugmentedPropertiesOfType(this); } - getCallSignatures(): readonly ts.Signature[] { - return this.checker.getSignaturesOfType(this, ts.SignatureKind.Call); + getCallSignatures(): readonly Signature[] { + return this.checker.getSignaturesOfType(this, SignatureKind.Call); } - getConstructSignatures(): readonly ts.Signature[] { - return this.checker.getSignaturesOfType(this, ts.SignatureKind.Construct); + getConstructSignatures(): readonly Signature[] { + return this.checker.getSignaturesOfType(this, SignatureKind.Construct); } - getStringIndexType(): ts.Type | undefined { - return this.checker.getIndexTypeOfType(this, ts.IndexKind.String); + getStringIndexType(): Type | undefined { + return this.checker.getIndexTypeOfType(this, IndexKind.String); } - getNumberIndexType(): ts.Type | undefined { - return this.checker.getIndexTypeOfType(this, ts.IndexKind.Number); + getNumberIndexType(): Type | undefined { + return this.checker.getIndexTypeOfType(this, IndexKind.Number); } - getBaseTypes(): ts.BaseType[] | undefined { + getBaseTypes(): BaseType[] | undefined { return this.isClassOrInterface() ? this.checker.getBaseTypes(this) : undefined; } isNullableType(): boolean { return this.checker.isNullableType(this); } - getNonNullableType(): ts.Type { + getNonNullableType(): Type { return this.checker.getNonNullableType(this); } - getNonOptionalType(): ts.Type { + getNonOptionalType(): Type { return this.checker.getNonOptionalType(this); } - getConstraint(): ts.Type | undefined { + getConstraint(): Type | undefined { return this.checker.getBaseConstraintOfType(this); } - getDefault(): ts.Type | undefined { + getDefault(): Type | undefined { return this.checker.getDefaultFromTypeParameter(this); } - isUnion(): this is ts.UnionType { - return !!(this.flags & ts.TypeFlags.Union); + isUnion(): this is UnionType { + return !!(this.flags & TypeFlags.Union); } - isIntersection(): this is ts.IntersectionType { - return !!(this.flags & ts.TypeFlags.Intersection); + isIntersection(): this is IntersectionType { + return !!(this.flags & TypeFlags.Intersection); } - isUnionOrIntersection(): this is ts.UnionOrIntersectionType { - return !!(this.flags & ts.TypeFlags.UnionOrIntersection); + isUnionOrIntersection(): this is UnionOrIntersectionType { + return !!(this.flags & TypeFlags.UnionOrIntersection); } - isLiteral(): this is ts.LiteralType { - return !!(this.flags & (ts.TypeFlags.StringLiteral | ts.TypeFlags.NumberLiteral | ts.TypeFlags.BigIntLiteral)); + isLiteral(): this is LiteralType { + return !!(this.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.BigIntLiteral)); } - isStringLiteral(): this is ts.StringLiteralType { - return !!(this.flags & ts.TypeFlags.StringLiteral); + isStringLiteral(): this is StringLiteralType { + return !!(this.flags & TypeFlags.StringLiteral); } - isNumberLiteral(): this is ts.NumberLiteralType { - return !!(this.flags & ts.TypeFlags.NumberLiteral); + isNumberLiteral(): this is NumberLiteralType { + return !!(this.flags & TypeFlags.NumberLiteral); } - isTypeParameter(): this is ts.TypeParameter { - return !!(this.flags & ts.TypeFlags.TypeParameter); + isTypeParameter(): this is TypeParameter { + return !!(this.flags & TypeFlags.TypeParameter); } - isClassOrInterface(): this is ts.InterfaceType { - return !!(ts.getObjectFlags(this) & ts.ObjectFlags.ClassOrInterface); + isClassOrInterface(): this is InterfaceType { + return !!(getObjectFlags(this) & ObjectFlags.ClassOrInterface); } - isClass(): this is ts.InterfaceType { - return !!(ts.getObjectFlags(this) & ts.ObjectFlags.Class); + isClass(): this is InterfaceType { + return !!(getObjectFlags(this) & ObjectFlags.Class); } - isIndexType(): this is ts.IndexType { - return !!(this.flags & ts.TypeFlags.Index); + isIndexType(): this is IndexType { + return !!(this.flags & TypeFlags.Index); } /** * This polyfills `referenceType.typeArguments` for API consumers */ get typeArguments() { - if (ts.getObjectFlags(this) & ts.ObjectFlags.Reference) { - return this.checker.getTypeArguments(this as ts.Type as ts.TypeReference); + if (getObjectFlags(this) & ObjectFlags.Reference) { + return this.checker.getTypeArguments(this as Type as TypeReference); } return undefined; } } -class SignatureObject implements ts.Signature { - flags: ts.SignatureFlags; - checker: ts.TypeChecker; - declaration!: ts.SignatureDeclaration; - typeParameters?: ts.TypeParameter[]; - parameters!: ts.Symbol[]; - thisParameter!: ts.Symbol; - resolvedReturnType!: ts.Type; - resolvedTypePredicate: ts.TypePredicate | undefined; +class SignatureObject implements Signature { + flags: SignatureFlags; + checker: TypeChecker; + declaration!: SignatureDeclaration; + typeParameters?: TypeParameter[]; + parameters!: Symbol[]; + thisParameter!: Symbol; + resolvedReturnType!: Type; + resolvedTypePredicate: TypePredicate | undefined; minTypeArgumentCount!: number; minArgumentCount!: number; // Undefined is used to indicate the value has not been computed. If, after computing, the // symbol has no doc comment, then the empty array will be returned. - documentationComment?: ts.SymbolDisplayPart[]; - jsDocTags?: ts.JSDocTagInfo[]; // same + documentationComment?: SymbolDisplayPart[]; + jsDocTags?: JSDocTagInfo[]; // same - constructor(checker: ts.TypeChecker, flags: ts.SignatureFlags) { + constructor(checker: TypeChecker, flags: SignatureFlags) { this.checker = checker; this.flags = flags; } - getDeclaration(): ts.SignatureDeclaration { + getDeclaration(): SignatureDeclaration { return this.declaration; } - getTypeParameters(): ts.TypeParameter[] | undefined { + getTypeParameters(): TypeParameter[] | undefined { return this.typeParameters; } - getParameters(): ts.Symbol[] { + getParameters(): Symbol[] { return this.parameters; } - getReturnType(): ts.Type { + getReturnType(): Type { return this.checker.getReturnTypeOfSignature(this); } - getTypeParameterAtPosition(pos: number): ts.Type { + getTypeParameterAtPosition(pos: number): Type { const type = this.checker.getParameterType(this, pos); - if (type.isIndexType() && ts.isThisTypeParameter(type.type)) { + if (type.isIndexType() && isThisTypeParameter(type.type)) { const constraint = type.type.getConstraint(); if (constraint) { return this.checker.getIndexType(constraint); @@ -588,12 +645,12 @@ class SignatureObject implements ts.Signature { return type; } - getDocumentationComment(): ts.SymbolDisplayPart[] { - return this.documentationComment || (this.documentationComment = getDocumentationComment(ts.singleElementArray(this.declaration), this.checker)); + getDocumentationComment(): SymbolDisplayPart[] { + return this.documentationComment || (this.documentationComment = getDocumentationComment(singleElementArray(this.declaration), this.checker)); } - getJsDocTags(): ts.JSDocTagInfo[] { - return this.jsDocTags || (this.jsDocTags = getJsDocTagsOfDeclarations(ts.singleElementArray(this.declaration), this.checker)); + getJsDocTags(): JSDocTagInfo[] { + return this.jsDocTags || (this.jsDocTags = getJsDocTagsOfDeclarations(singleElementArray(this.declaration), this.checker)); } } @@ -602,21 +659,21 @@ class SignatureObject implements ts.Signature { * @param node the Node in question. * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`. */ -function hasJSDocInheritDocTag(node: ts.Node) { - return ts.getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc" || tag.tagName.text === "inheritdoc"); +function hasJSDocInheritDocTag(node: Node) { + return getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc" || tag.tagName.text === "inheritdoc"); } -function getJsDocTagsOfDeclarations(declarations: ts.Declaration[] | undefined, checker: ts.TypeChecker | undefined): ts.JSDocTagInfo[] { - if (!declarations) return ts.emptyArray; +function getJsDocTagsOfDeclarations(declarations: Declaration[] | undefined, checker: TypeChecker | undefined): JSDocTagInfo[] { + if (!declarations) return emptyArray; - let tags = ts.JsDoc.getJsDocTagsFromDeclarations(declarations, checker); + let tags = JsDoc.getJsDocTagsFromDeclarations(declarations, checker); if (checker && (tags.length === 0 || declarations.some(hasJSDocInheritDocTag))) { - const seenSymbols = new ts.Set(); + const seenSymbols = new Set(); for (const declaration of declarations) { const inheritedTags = findBaseOfDeclaration(checker, declaration, symbol => { if (!seenSymbols.has(symbol)) { seenSymbols.add(symbol); - if (declaration.kind === ts.SyntaxKind.GetAccessor || declaration.kind === ts.SyntaxKind.SetAccessor) { + if (declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) { return symbol.getContextualJsDocTags(declaration, checker); } return symbol.declarations?.length === 1 ? symbol.getJsDocTags() : undefined; @@ -630,35 +687,35 @@ function getJsDocTagsOfDeclarations(declarations: ts.Declaration[] | undefined, return tags; } -function getDocumentationComment(declarations: readonly ts.Declaration[] | undefined, checker: ts.TypeChecker | undefined): ts.SymbolDisplayPart[] { - if (!declarations) return ts.emptyArray; +function getDocumentationComment(declarations: readonly Declaration[] | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[] { + if (!declarations) return emptyArray; - let doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations, checker); + let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations, checker); if (checker && (doc.length === 0 || declarations.some(hasJSDocInheritDocTag))) { - const seenSymbols = new ts.Set(); + const seenSymbols = new Set(); for (const declaration of declarations) { const inheritedDocs = findBaseOfDeclaration(checker, declaration, symbol => { if (!seenSymbols.has(symbol)) { seenSymbols.add(symbol); - if (declaration.kind === ts.SyntaxKind.GetAccessor || declaration.kind === ts.SyntaxKind.SetAccessor) { + if (declaration.kind === SyntaxKind.GetAccessor || declaration.kind === SyntaxKind.SetAccessor) { return symbol.getContextualDocumentationComment(declaration, checker); } return symbol.getDocumentationComment(checker); } }); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs - if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(ts.lineBreakPart(), doc); + if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc); } } return doc; } -function findBaseOfDeclaration(checker: ts.TypeChecker, declaration: ts.Declaration, cb: (symbol: ts.Symbol) => T[] | undefined): T[] | undefined { - const classOrInterfaceDeclaration = declaration.parent?.kind === ts.SyntaxKind.Constructor ? declaration.parent.parent : declaration.parent; +function findBaseOfDeclaration(checker: TypeChecker, declaration: Declaration, cb: (symbol: Symbol) => T[] | undefined): T[] | undefined { + const classOrInterfaceDeclaration = declaration.parent?.kind === SyntaxKind.Constructor ? declaration.parent.parent : declaration.parent; if (!classOrInterfaceDeclaration) return; - const isStaticMember = ts.hasStaticModifier(declaration); - return ts.firstDefined(ts.getAllSuperTypeNodes(classOrInterfaceDeclaration), superTypeNode => { + const isStaticMember = hasStaticModifier(declaration); + return firstDefined(getAllSuperTypeNodes(classOrInterfaceDeclaration), superTypeNode => { const baseType = checker.getTypeAtLocation(superTypeNode); const type = isStaticMember && baseType.symbol ? checker.getTypeOfSymbol(baseType.symbol) : baseType; const symbol = checker.getPropertyOfType(type, declaration.symbol.name); @@ -666,76 +723,76 @@ function findBaseOfDeclaration(checker: ts.TypeChecker, declaration: ts.Decla }); } -class SourceFileObject extends NodeObject implements ts.SourceFile { - public kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile; +class SourceFileObject extends NodeObject implements SourceFile { + public kind: SyntaxKind.SourceFile = SyntaxKind.SourceFile; public _declarationBrand: any; public fileName!: string; - public path!: ts.Path; - public resolvedPath!: ts.Path; + public path!: Path; + public resolvedPath!: Path; public originalFileName!: string; public text!: string; - public scriptSnapshot!: ts.IScriptSnapshot; + public scriptSnapshot!: IScriptSnapshot; public lineMap!: readonly number[]; - public statements!: ts.NodeArray; - public endOfFileToken!: ts.Token; + public statements!: NodeArray; + public endOfFileToken!: Token; public amdDependencies!: { name: string; path: string }[]; public moduleName!: string; - public referencedFiles!: ts.FileReference[]; - public typeReferenceDirectives!: ts.FileReference[]; - public libReferenceDirectives!: ts.FileReference[]; + public referencedFiles!: FileReference[]; + public typeReferenceDirectives!: FileReference[]; + public libReferenceDirectives!: FileReference[]; - public syntacticDiagnostics!: ts.DiagnosticWithLocation[]; - public parseDiagnostics!: ts.DiagnosticWithLocation[]; - public bindDiagnostics!: ts.DiagnosticWithLocation[]; - public bindSuggestionDiagnostics?: ts.DiagnosticWithLocation[]; + public syntacticDiagnostics!: DiagnosticWithLocation[]; + public parseDiagnostics!: DiagnosticWithLocation[]; + public bindDiagnostics!: DiagnosticWithLocation[]; + public bindSuggestionDiagnostics?: DiagnosticWithLocation[]; public isDeclarationFile!: boolean; public isDefaultLib!: boolean; public hasNoDefaultLib!: boolean; - public externalModuleIndicator!: ts.Node; // The first node that causes this file to be an external module - public commonJsModuleIndicator!: ts.Node; // The first node that causes this file to be a CommonJS module + public externalModuleIndicator!: Node; // The first node that causes this file to be an external module + public commonJsModuleIndicator!: Node; // The first node that causes this file to be a CommonJS module public nodeCount!: number; public identifierCount!: number; public symbolCount!: number; public version!: string; - public scriptKind!: ts.ScriptKind; - public languageVersion!: ts.ScriptTarget; - public languageVariant!: ts.LanguageVariant; - public identifiers!: ts.ESMap; - public nameTable: ts.UnderscoreEscapedMap | undefined; - public resolvedModules: ts.ModeAwareCache | undefined; - public resolvedTypeReferenceDirectiveNames!: ts.ModeAwareCache; - public imports!: readonly ts.StringLiteralLike[]; - public moduleAugmentations!: ts.StringLiteral[]; - private namedDeclarations: ts.ESMap | undefined; + public scriptKind!: ScriptKind; + public languageVersion!: ScriptTarget; + public languageVariant!: LanguageVariant; + public identifiers!: ESMap; + public nameTable: UnderscoreEscapedMap | undefined; + public resolvedModules: ModeAwareCache | undefined; + public resolvedTypeReferenceDirectiveNames!: ModeAwareCache; + public imports!: readonly StringLiteralLike[]; + public moduleAugmentations!: StringLiteral[]; + private namedDeclarations: ESMap | undefined; public ambientModuleNames!: string[]; - public checkJsDirective: ts.CheckJsDirective | undefined; - public errorExpectations: ts.TextRange[] | undefined; + public checkJsDirective: CheckJsDirective | undefined; + public errorExpectations: TextRange[] | undefined; public possiblyContainDynamicImport?: boolean; - public pragmas!: ts.PragmaMap; - public localJsxFactory: ts.EntityName | undefined; - public localJsxNamespace: ts.__String | undefined; + public pragmas!: PragmaMap; + public localJsxFactory: EntityName | undefined; + public localJsxNamespace: __String | undefined; - constructor(kind: ts.SyntaxKind, pos: number, end: number) { + constructor(kind: SyntaxKind, pos: number, end: number) { super(kind, pos, end); } - public update(newText: string, textChangeRange: ts.TextChangeRange): ts.SourceFile { - return ts.updateSourceFile(this, newText, textChangeRange); + public update(newText: string, textChangeRange: TextChangeRange): SourceFile { + return updateSourceFile(this, newText, textChangeRange); } - public getLineAndCharacterOfPosition(position: number): ts.LineAndCharacter { - return ts.getLineAndCharacterOfPosition(this, position); + public getLineAndCharacterOfPosition(position: number): LineAndCharacter { + return getLineAndCharacterOfPosition(this, position); } public getLineStarts(): readonly number[] { - return ts.getLineStarts(this); + return getLineStarts(this); } public getPositionOfLineAndCharacter(line: number, character: number, allowEdits?: true): number { - return ts.computePositionOfLineAndCharacter(ts.getLineStarts(this), line, character, this.text, allowEdits); + return computePositionOfLineAndCharacter(getLineStarts(this), line, character, this.text, allowEdits); } public getLineEndOfPosition(pos: number): number { @@ -755,7 +812,7 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { return fullText[lastCharPos] === "\n" && fullText[lastCharPos - 1] === "\r" ? lastCharPos - 1 : lastCharPos; } - public getNamedDeclarations(): ts.ESMap { + public getNamedDeclarations(): ESMap { if (!this.namedDeclarations) { this.namedDeclarations = this.computeNamedDeclarations(); } @@ -763,14 +820,14 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { return this.namedDeclarations; } - private computeNamedDeclarations(): ts.ESMap { - const result = ts.createMultiMap(); + private computeNamedDeclarations(): ESMap { + const result = createMultiMap(); this.forEachChild(visit); return result; - function addDeclaration(declaration: ts.Declaration) { + function addDeclaration(declaration: Declaration) { const name = getDeclarationName(declaration); if (name) { result.add(name, declaration); @@ -785,30 +842,30 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { return declarations; } - function getDeclarationName(declaration: ts.Declaration) { - const name = ts.getNonAssignedNameOfDeclaration(declaration); - return name && (ts.isComputedPropertyName(name) && ts.isPropertyAccessExpression(name.expression) ? name.expression.name.text - : ts.isPropertyName(name) ? ts.getNameFromPropertyName(name) : undefined); + function getDeclarationName(declaration: Declaration) { + const name = getNonAssignedNameOfDeclaration(declaration); + return name && (isComputedPropertyName(name) && isPropertyAccessExpression(name.expression) ? name.expression.name.text + : isPropertyName(name) ? getNameFromPropertyName(name) : undefined); } - function visit(node: ts.Node): void { + function visit(node: Node): void { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - const functionDeclaration = node as ts.FunctionLikeDeclaration; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + const functionDeclaration = node as FunctionLikeDeclaration; const declarationName = getDeclarationName(functionDeclaration); if (declarationName) { const declarations = getDeclarations(declarationName); - const lastDeclaration = ts.lastOrUndefined(declarations); + const lastDeclaration = lastOrUndefined(declarations); // Check whether this declaration belongs to an "overload group". if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) { // Overwrite the last declaration if it was an overload // and this one is an implementation. - if (functionDeclaration.body && !(lastDeclaration as ts.FunctionLikeDeclaration).body) { + if (functionDeclaration.body && !(lastDeclaration as FunctionLikeDeclaration).body) { declarations[declarations.length - 1] = functionDeclaration; } } @@ -816,39 +873,39 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { declarations.push(functionDeclaration); } } - ts.forEachChild(node, visit); + forEachChild(node, visit); break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ImportClause: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.TypeLiteral: - addDeclaration(node as ts.Declaration); - ts.forEachChild(node, visit); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.TypeLiteral: + addDeclaration(node as Declaration); + forEachChild(node, visit); break; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: // Only consider parameter properties - if (!ts.hasSyntacticModifier(node, ts.ModifierFlags.ParameterPropertyModifier)) { + if (!hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier)) { break; } // falls through - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.BindingElement: { - const decl = node as ts.VariableDeclaration; - if (ts.isBindingPattern(decl.name)) { - ts.forEachChild(decl.name, visit); + case SyntaxKind.VariableDeclaration: + case SyntaxKind.BindingElement: { + const decl = node as VariableDeclaration; + if (isBindingPattern(decl.name)) { + forEachChild(decl.name, visit); break; } if (decl.initializer) { @@ -856,19 +913,19 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { } } // falls through - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - addDeclaration(node as ts.Declaration); + case SyntaxKind.EnumMember: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + addDeclaration(node as Declaration); break; - case ts.SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportDeclaration: // Handle named exports case e.g.: // export {a, b as B} from "mod"; - const exportDeclaration = node as ts.ExportDeclaration; + const exportDeclaration = node as ExportDeclaration; if (exportDeclaration.exportClause) { - if (ts.isNamedExports(exportDeclaration.exportClause)) { - ts.forEach(exportDeclaration.exportClause.elements, visit); + if (isNamedExports(exportDeclaration.exportClause)) { + forEach(exportDeclaration.exportClause.elements, visit); } else { visit(exportDeclaration.exportClause.name); @@ -876,8 +933,8 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { } break; - case ts.SyntaxKind.ImportDeclaration: - const importClause = (node as ts.ImportDeclaration).importClause; + case SyntaxKind.ImportDeclaration: + const importClause = (node as ImportDeclaration).importClause; if (importClause) { // Handle default import case e.g.: // import d from "mod"; @@ -889,39 +946,39 @@ class SourceFileObject extends NodeObject implements ts.SourceFile { // import * as NS from "mod"; // import {a, b as B} from "mod"; if (importClause.namedBindings) { - if (importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport) { + if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { addDeclaration(importClause.namedBindings); } else { - ts.forEach(importClause.namedBindings.elements, visit); + forEach(importClause.namedBindings.elements, visit); } } } break; - case ts.SyntaxKind.BinaryExpression: - if (ts.getAssignmentDeclarationKind(node as ts.BinaryExpression) !== ts.AssignmentDeclarationKind.None) { - addDeclaration(node as ts.BinaryExpression); + case SyntaxKind.BinaryExpression: + if (getAssignmentDeclarationKind(node as BinaryExpression) !== AssignmentDeclarationKind.None) { + addDeclaration(node as BinaryExpression); } // falls through default: - ts.forEachChild(node, visit); + forEachChild(node, visit); } } } } -class SourceMapSourceObject implements ts.SourceMapSource { +class SourceMapSourceObject implements SourceMapSource { lineMap!: number[]; constructor(public fileName: string, public text: string, public skipTrivia?: (pos: number) => number) { } - public getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter { - return ts.getLineAndCharacterOfPosition(this, pos); + public getLineAndCharacterOfPosition(pos: number): LineAndCharacter { + return getLineAndCharacterOfPosition(this, pos); } } -function getServicesObjectAllocator(): ts.ObjectAllocator { +function getServicesObjectAllocator(): ObjectAllocator { return { getNodeConstructor: () => NodeObject, getTokenConstructor: () => TokenObject, @@ -939,17 +996,17 @@ function getServicesObjectAllocator(): ts.ObjectAllocator { /// Language Service /* @internal */ -export interface DisplayPartsSymbolWriter extends ts.EmitTextWriter { - displayParts(): ts.SymbolDisplayPart[]; +export interface DisplayPartsSymbolWriter extends EmitTextWriter { + displayParts(): SymbolDisplayPart[]; } /* @internal */ -export function toEditorSettings(options: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.FormatCodeSettings; -export function toEditorSettings(options: ts.EditorOptions | ts.EditorSettings): ts.EditorSettings; -export function toEditorSettings(optionsAsMap: ts.MapLike): ts.MapLike { +export function toEditorSettings(options: FormatCodeOptions | FormatCodeSettings): FormatCodeSettings; +export function toEditorSettings(options: EditorOptions | EditorSettings): EditorSettings; +export function toEditorSettings(optionsAsMap: MapLike): MapLike { let allPropertiesAreCamelCased = true; for (const key in optionsAsMap) { - if (ts.hasProperty(optionsAsMap, key) && !isCamelCase(key)) { + if (hasProperty(optionsAsMap, key) && !isCamelCase(key)) { allPropertiesAreCamelCased = false; break; } @@ -957,9 +1014,9 @@ export function toEditorSettings(optionsAsMap: ts.MapLike): ts.MapLike if (allPropertiesAreCamelCased) { return optionsAsMap; } - const settings: ts.MapLike = {}; + const settings: MapLike = {}; for (const key in optionsAsMap) { - if (ts.hasProperty(optionsAsMap, key)) { + if (hasProperty(optionsAsMap, key)) { const newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1); settings[newKey] = optionsAsMap[key]; } @@ -971,24 +1028,24 @@ function isCamelCase(s: string) { return !s.length || s.charAt(0) === s.charAt(0).toLowerCase(); } -export function displayPartsToString(displayParts: ts.SymbolDisplayPart[] | undefined) { +export function displayPartsToString(displayParts: SymbolDisplayPart[] | undefined) { if (displayParts) { - return ts.map(displayParts, displayPart => displayPart.text).join(""); + return map(displayParts, displayPart => displayPart.text).join(""); } return ""; } -export function getDefaultCompilerOptions(): ts.CompilerOptions { +export function getDefaultCompilerOptions(): CompilerOptions { // Always default to "ScriptTarget.ES5" for the language service return { - target: ts.ScriptTarget.ES5, - jsx: ts.JsxEmit.Preserve + target: ScriptTarget.ES5, + jsx: JsxEmit.Preserve }; } export function getSupportedCodeFixes() { - return ts.codefix.getSupportedErrorCodes(); + return codefix.getSupportedErrorCodes(); } class SyntaxTreeCache { @@ -996,34 +1053,34 @@ class SyntaxTreeCache { // currently edited file. private currentFileName: string | undefined; private currentFileVersion: string | undefined; - private currentFileScriptSnapshot: ts.IScriptSnapshot | undefined; - private currentSourceFile: ts.SourceFile | undefined; + private currentFileScriptSnapshot: IScriptSnapshot | undefined; + private currentSourceFile: SourceFile | undefined; - constructor(private host: ts.LanguageServiceHost) { + constructor(private host: LanguageServiceHost) { } - public getCurrentSourceFile(fileName: string): ts.SourceFile { + public getCurrentSourceFile(fileName: string): SourceFile { const scriptSnapshot = this.host.getScriptSnapshot(fileName); if (!scriptSnapshot) { // The host does not know about this file. throw new Error("Could not find file: '" + fileName + "'."); } - const scriptKind = ts.getScriptKind(fileName, this.host); + const scriptKind = getScriptKind(fileName, this.host); const version = this.host.getScriptVersion(fileName); - let sourceFile: ts.SourceFile | undefined; + let sourceFile: SourceFile | undefined; if (this.currentFileName !== fileName) { // This is a new file, just parse it - const options: ts.CreateSourceFileOptions = { - languageVersion: ts.ScriptTarget.Latest, - impliedNodeFormat: ts.getImpliedNodeFormatForFile( - ts.toPath(fileName, this.host.getCurrentDirectory(), this.host.getCompilerHost?.()?.getCanonicalFileName || ts.hostGetCanonicalFileName(this.host)), + const options: CreateSourceFileOptions = { + languageVersion: ScriptTarget.Latest, + impliedNodeFormat: getImpliedNodeFormatForFile( + toPath(fileName, this.host.getCurrentDirectory(), this.host.getCompilerHost?.()?.getCanonicalFileName || hostGetCanonicalFileName(this.host)), this.host.getCompilerHost?.()?.getModuleResolutionCache?.()?.getPackageJsonInfoCache(), this.host, this.host.getCompilationSettings() ), - setExternalModuleIndicator: ts.getSetExternalModuleIndicator(this.host.getCompilationSettings()) + setExternalModuleIndicator: getSetExternalModuleIndicator(this.host.getCompilationSettings()) }; sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, scriptKind); } @@ -1045,18 +1102,18 @@ class SyntaxTreeCache { } } -function setSourceFileFields(sourceFile: ts.SourceFile, scriptSnapshot: ts.IScriptSnapshot, version: string) { +function setSourceFileFields(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string) { sourceFile.version = version; sourceFile.scriptSnapshot = scriptSnapshot; } -export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: ts.IScriptSnapshot, scriptTargetOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, version: string, setNodeParents: boolean, scriptKind?: ts.ScriptKind): ts.SourceFile { - const sourceFile = ts.createSourceFile(fileName, ts.getSnapshotText(scriptSnapshot), scriptTargetOrOptions, setNodeParents, scriptKind); +export function createLanguageServiceSourceFile(fileName: string, scriptSnapshot: IScriptSnapshot, scriptTargetOrOptions: ScriptTarget | CreateSourceFileOptions, version: string, setNodeParents: boolean, scriptKind?: ScriptKind): SourceFile { + const sourceFile = createSourceFile(fileName, getSnapshotText(scriptSnapshot), scriptTargetOrOptions, setNodeParents, scriptKind); setSourceFileFields(sourceFile, scriptSnapshot, version); return sourceFile; } -export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scriptSnapshot: ts.IScriptSnapshot, version: string, textChangeRange: ts.TextChangeRange | undefined, aggressiveChecks?: boolean): ts.SourceFile { +export function updateLanguageServiceSourceFile(sourceFile: SourceFile, scriptSnapshot: IScriptSnapshot, version: string, textChangeRange: TextChangeRange | undefined, aggressiveChecks?: boolean): SourceFile { // If we were given a text change range, and our version or open-ness changed, then // incrementally parse this file. if (textChangeRange) { @@ -1069,8 +1126,8 @@ export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scrip : ""; // grab the fragment from the end of the span till the end of the original text - const suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length - ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span)) + const suffix = textSpanEnd(textChangeRange.span) !== sourceFile.text.length + ? sourceFile.text.substr(textSpanEnd(textChangeRange.span)) : ""; if (textChangeRange.newLength === 0) { @@ -1088,7 +1145,7 @@ export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scrip : (changedText + suffix); } - const newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); setSourceFileFields(newSourceFile, scriptSnapshot, version); // after incremental parsing nameTable might not be up-to-date // drop it so it can be lazily recreated later @@ -1107,7 +1164,7 @@ export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scrip } } - const options: ts.CreateSourceFileOptions = { + const options: CreateSourceFileOptions = { languageVersion: sourceFile.languageVersion, impliedNodeFormat: sourceFile.impliedNodeFormat, setExternalModuleIndicator: sourceFile.setExternalModuleIndicator, @@ -1116,13 +1173,13 @@ export function updateLanguageServiceSourceFile(sourceFile: ts.SourceFile, scrip return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, options, version, /*setNodeParents*/ true, sourceFile.scriptKind); } -const NoopCancellationToken: ts.CancellationToken = { - isCancellationRequested: ts.returnFalse, - throwIfCancellationRequested: ts.noop, +const NoopCancellationToken: CancellationToken = { + isCancellationRequested: returnFalse, + throwIfCancellationRequested: noop, }; -class CancellationTokenObject implements ts.CancellationToken { - constructor(private cancellationToken: ts.HostCancellationToken) { +class CancellationTokenObject implements CancellationToken { + constructor(private cancellationToken: HostCancellationToken) { } public isCancellationRequested(): boolean { @@ -1131,25 +1188,25 @@ class CancellationTokenObject implements ts.CancellationToken { public throwIfCancellationRequested(): void { if (this.isCancellationRequested()) { - ts.tracing?.instant(ts.tracing.Phase.Session, "cancellationThrown", { kind: "CancellationTokenObject" }); - throw new ts.OperationCanceledException(); + tracing?.instant(tracing.Phase.Session, "cancellationThrown", { kind: "CancellationTokenObject" }); + throw new OperationCanceledException(); } } } /* @internal */ /** A cancellation that throttles calls to the host */ -export class ThrottledCancellationToken implements ts.CancellationToken { +export class ThrottledCancellationToken implements CancellationToken { // Store when we last tried to cancel. Checking cancellation can be expensive (as we have // to marshall over to the host layer). So we only bother actually checking once enough // time has passed. private lastCancellationCheckTime = 0; - constructor(private hostCancellationToken: ts.HostCancellationToken, private readonly throttleWaitMilliseconds = 20) { + constructor(private hostCancellationToken: HostCancellationToken, private readonly throttleWaitMilliseconds = 20) { } public isCancellationRequested(): boolean { - const time = ts.timestamp(); + const time = timestamp(); const duration = Math.abs(time - this.lastCancellationCheckTime); if (duration >= this.throttleWaitMilliseconds) { // Check no more than once every throttle wait milliseconds @@ -1162,13 +1219,13 @@ export class ThrottledCancellationToken implements ts.CancellationToken { public throwIfCancellationRequested(): void { if (this.isCancellationRequested()) { - ts.tracing?.instant(ts.tracing.Phase.Session, "cancellationThrown", { kind: "ThrottledCancellationToken" }); - throw new ts.OperationCanceledException(); + tracing?.instant(tracing.Phase.Session, "cancellationThrown", { kind: "ThrottledCancellationToken" }); + throw new OperationCanceledException(); } } } -const invalidOperationsInPartialSemanticMode: readonly (keyof ts.LanguageService)[] = [ +const invalidOperationsInPartialSemanticMode: readonly (keyof LanguageService)[] = [ "getSemanticDiagnostics", "getSuggestionDiagnostics", "getCompilerOptionsDiagnostics", @@ -1188,7 +1245,7 @@ const invalidOperationsInPartialSemanticMode: readonly (keyof ts.LanguageService "provideInlayHints" ]; -const invalidOperationsInSyntacticMode: readonly (keyof ts.LanguageService)[] = [ +const invalidOperationsInSyntacticMode: readonly (keyof LanguageService)[] = [ ...invalidOperationsInPartialSemanticMode, "getCompletionsAtPosition", "getCompletionEntryDetails", @@ -1209,24 +1266,24 @@ const invalidOperationsInSyntacticMode: readonly (keyof ts.LanguageService)[] = "getApplicableRefactors", ]; export function createLanguageService( - host: ts.LanguageServiceHost, - documentRegistry: ts.DocumentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()), - syntaxOnlyOrLanguageServiceMode?: boolean | ts.LanguageServiceMode, -): ts.LanguageService { - let languageServiceMode: ts.LanguageServiceMode; + host: LanguageServiceHost, + documentRegistry: DocumentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()), + syntaxOnlyOrLanguageServiceMode?: boolean | LanguageServiceMode, +): LanguageService { + let languageServiceMode: LanguageServiceMode; if (syntaxOnlyOrLanguageServiceMode === undefined) { - languageServiceMode = ts.LanguageServiceMode.Semantic; + languageServiceMode = LanguageServiceMode.Semantic; } else if (typeof syntaxOnlyOrLanguageServiceMode === "boolean") { // languageServiceMode = SyntaxOnly - languageServiceMode = syntaxOnlyOrLanguageServiceMode ? ts.LanguageServiceMode.Syntactic : ts.LanguageServiceMode.Semantic; + languageServiceMode = syntaxOnlyOrLanguageServiceMode ? LanguageServiceMode.Syntactic : LanguageServiceMode.Semantic; } else { languageServiceMode = syntaxOnlyOrLanguageServiceMode; } const syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host); - let program: ts.Program; + let program: Program; let lastProjectVersion: string; let lastTypesRootVersion = 0; @@ -1237,7 +1294,7 @@ export function createLanguageService( const currentDirectory = host.getCurrentDirectory(); // Checks if the localized messages json is set, and if not, query the host for it - ts.maybeSetLocalizedDiagnosticMessages(host.getLocalizedDiagnosticMessages?.bind(host)); + maybeSetLocalizedDiagnosticMessages(host.getLocalizedDiagnosticMessages?.bind(host)); function log(message: string) { if (host.log) { @@ -1245,24 +1302,24 @@ export function createLanguageService( } } - const useCaseSensitiveFileNames = ts.hostUsesCaseSensitiveFileNames(host); - const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); + const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host); + const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); - const sourceMapper = ts.getSourceMapper({ + const sourceMapper = getSourceMapper({ useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getCurrentDirectory: () => currentDirectory, getProgram, - fileExists: ts.maybeBind(host, host.fileExists), - readFile: ts.maybeBind(host, host.readFile), - getDocumentPositionMapper: ts.maybeBind(host, host.getDocumentPositionMapper), - getSourceFileLike: ts.maybeBind(host, host.getSourceFileLike), + fileExists: maybeBind(host, host.fileExists), + readFile: maybeBind(host, host.readFile), + getDocumentPositionMapper: maybeBind(host, host.getDocumentPositionMapper), + getSourceFileLike: maybeBind(host, host.getSourceFileLike), log }); - function getValidSourceFile(fileName: string): ts.SourceFile { + function getValidSourceFile(fileName: string): SourceFile { const sourceFile = program.getSourceFile(fileName); if (!sourceFile) { - const error: Error & ts.PossibleProgramFileInfo = new Error(`Could not find source file: '${fileName}'.`); + const error: Error & PossibleProgramFileInfo = new Error(`Could not find source file: '${fileName}'.`); // We've been having trouble debugging this, so attach sidecar data for the tsserver log. // See https://github.com/microsoft/TypeScript/issues/30180. @@ -1274,7 +1331,7 @@ export function createLanguageService( } function synchronizeHostData(): void { - ts.Debug.assert(languageServiceMode !== ts.LanguageServiceMode.Syntactic); + Debug.assert(languageServiceMode !== LanguageServiceMode.Syntactic); // perform fast check if host supports it if (host.getProjectVersion) { const hostProjectVersion = host.getProjectVersion(); @@ -1301,67 +1358,67 @@ export function createLanguageService( // Get a fresh cache of the host information const newSettings = host.getCompilationSettings() || getDefaultCompilerOptions(); - const hasInvalidatedResolutions: ts.HasInvalidatedResolutions = host.hasInvalidatedResolutions || ts.returnFalse; - const hasChangedAutomaticTypeDirectiveNames = ts.maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); + const hasInvalidatedResolutions: HasInvalidatedResolutions = host.hasInvalidatedResolutions || returnFalse; + const hasChangedAutomaticTypeDirectiveNames = maybeBind(host, host.hasChangedAutomaticTypeDirectiveNames); const projectReferences = host.getProjectReferences?.(); - let parsedCommandLines: ts.ESMap | undefined; + let parsedCommandLines: ESMap | undefined; // Now create a new compiler - let compilerHost: ts.CompilerHost | undefined = { + let compilerHost: CompilerHost | undefined = { getSourceFile: getOrCreateSourceFile, getSourceFileByPath: getOrCreateSourceFileByPath, getCancellationToken: () => cancellationToken, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, - getNewLine: () => ts.getNewLineCharacter(newSettings, () => ts.getNewLineOrDefaultFromHost(host)), + getNewLine: () => getNewLineCharacter(newSettings, () => getNewLineOrDefaultFromHost(host)), getDefaultLibFileName: options => host.getDefaultLibFileName(options), - writeFile: ts.noop, + writeFile: noop, getCurrentDirectory: () => currentDirectory, fileExists: fileName => host.fileExists(fileName), readFile: fileName => host.readFile && host.readFile(fileName), - getSymlinkCache: ts.maybeBind(host, host.getSymlinkCache), - realpath: ts.maybeBind(host, host.realpath), + getSymlinkCache: maybeBind(host, host.getSymlinkCache), + realpath: maybeBind(host, host.realpath), directoryExists: directoryName => { - return ts.directoryProbablyExists(directoryName, host); + return directoryProbablyExists(directoryName, host); }, getDirectories: path => { return host.getDirectories ? host.getDirectories(path) : []; }, readDirectory: (path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number) => { - ts.Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); + Debug.checkDefined(host.readDirectory, "'LanguageServiceHost.readDirectory' must be implemented to correctly process 'projectReferences'"); return host.readDirectory!(path, extensions, exclude, include, depth); }, onReleaseOldSourceFile, onReleaseParsedCommandLine, hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, - trace: ts.maybeBind(host, host.trace), - resolveModuleNames: ts.maybeBind(host, host.resolveModuleNames), - getModuleResolutionCache: ts.maybeBind(host, host.getModuleResolutionCache), - resolveTypeReferenceDirectives: ts.maybeBind(host, host.resolveTypeReferenceDirectives), - useSourceOfProjectReferenceRedirect: ts.maybeBind(host, host.useSourceOfProjectReferenceRedirect), + trace: maybeBind(host, host.trace), + resolveModuleNames: maybeBind(host, host.resolveModuleNames), + getModuleResolutionCache: maybeBind(host, host.getModuleResolutionCache), + resolveTypeReferenceDirectives: maybeBind(host, host.resolveTypeReferenceDirectives), + useSourceOfProjectReferenceRedirect: maybeBind(host, host.useSourceOfProjectReferenceRedirect), getParsedCommandLine, }; const originalGetSourceFile = compilerHost.getSourceFile; - const { getSourceFileWithCache } = ts.changeCompilerHostLikeToUseCache( + const { getSourceFileWithCache } = changeCompilerHostLikeToUseCache( compilerHost, - fileName => ts.toPath(fileName, currentDirectory, getCanonicalFileName), + fileName => toPath(fileName, currentDirectory, getCanonicalFileName), (...args) => originalGetSourceFile.call(compilerHost, ...args) ); compilerHost.getSourceFile = getSourceFileWithCache!; host.setCompilerHost?.(compilerHost); - const parseConfigHost: ts.ParseConfigFileHost = { + const parseConfigHost: ParseConfigFileHost = { useCaseSensitiveFileNames, fileExists: fileName => compilerHost!.fileExists(fileName), readFile: fileName => compilerHost!.readFile(fileName), readDirectory: (...args) => compilerHost!.readDirectory!(...args), trace: compilerHost.trace, getCurrentDirectory: compilerHost.getCurrentDirectory, - onUnRecoverableConfigFileDiagnostic: ts.noop, + onUnRecoverableConfigFileDiagnostic: noop, }; // The call to isProgramUptoDate below may refer back to documentRegistryBucketKey; @@ -1370,7 +1427,7 @@ export function createLanguageService( const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings); // If the program is already up-to-date, we can reuse it - if (ts.isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { + if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { return; } @@ -1380,14 +1437,14 @@ export function createLanguageService( // the program points to old source files that have been invalidated because of // incremental parsing. - const options: ts.CreateProgramOptions = { + const options: CreateProgramOptions = { rootNames: rootFileNames, options: newSettings, host: compilerHost, oldProgram: program, projectReferences }; - program = ts.createProgram(options); + program = createProgram(options); // 'getOrCreateSourceFile' depends on caching but should be used past this point. // After this point, the cache needs to be cleared to allow all collected snapshots to be released @@ -1404,34 +1461,34 @@ export function createLanguageService( program.getTypeChecker(); return; - function getParsedCommandLine(fileName: string): ts.ParsedCommandLine | undefined { - const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); + function getParsedCommandLine(fileName: string): ParsedCommandLine | undefined { + const path = toPath(fileName, currentDirectory, getCanonicalFileName); const existing = parsedCommandLines?.get(path); if (existing !== undefined) return existing || undefined; const result = host.getParsedCommandLine ? host.getParsedCommandLine(fileName) : getParsedCommandLineOfConfigFileUsingSourceFile(fileName); - (parsedCommandLines ||= new ts.Map()).set(path, result || false); + (parsedCommandLines ||= new Map()).set(path, result || false); return result; } - function getParsedCommandLineOfConfigFileUsingSourceFile(configFileName: string): ts.ParsedCommandLine | undefined { - const result = getOrCreateSourceFile(configFileName, ts.ScriptTarget.JSON) as ts.JsonSourceFile | undefined; + function getParsedCommandLineOfConfigFileUsingSourceFile(configFileName: string): ParsedCommandLine | undefined { + const result = getOrCreateSourceFile(configFileName, ScriptTarget.JSON) as JsonSourceFile | undefined; if (!result) return undefined; - result.path = ts.toPath(configFileName, currentDirectory, getCanonicalFileName); + result.path = toPath(configFileName, currentDirectory, getCanonicalFileName); result.resolvedPath = result.path; result.originalFileName = result.fileName; - return ts.parseJsonSourceFileConfigFileContent( + return parseJsonSourceFileConfigFileContent( result, parseConfigHost, - ts.getNormalizedAbsolutePath(ts.getDirectoryPath(configFileName), currentDirectory), + getNormalizedAbsolutePath(getDirectoryPath(configFileName), currentDirectory), /*optionsToExtend*/ undefined, - ts.getNormalizedAbsolutePath(configFileName, currentDirectory), + getNormalizedAbsolutePath(configFileName, currentDirectory), ); } - function onReleaseParsedCommandLine(configFileName: string, oldResolvedRef: ts.ResolvedProjectReference | undefined, oldOptions: ts.CompilerOptions) { + function onReleaseParsedCommandLine(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, oldOptions: CompilerOptions) { if (host.getParsedCommandLine) { host.onReleaseParsedCommandLine?.(configFileName, oldResolvedRef, oldOptions); } @@ -1442,17 +1499,17 @@ export function createLanguageService( // Release any files we have acquired in the old program but are // not part of the new program. - function onReleaseOldSourceFile(oldSourceFile: ts.SourceFile, oldOptions: ts.CompilerOptions) { + function onReleaseOldSourceFile(oldSourceFile: SourceFile, oldOptions: CompilerOptions) { const oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions); documentRegistry.releaseDocumentWithKey(oldSourceFile.resolvedPath, oldSettingsKey, oldSourceFile.scriptKind, oldSourceFile.impliedNodeFormat); } - function getOrCreateSourceFile(fileName: string, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined { - return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile); + function getOrCreateSourceFile(fileName: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + return getOrCreateSourceFileByPath(fileName, toPath(fileName, currentDirectory, getCanonicalFileName), languageVersionOrOptions, onError, shouldCreateNewSourceFile); } - function getOrCreateSourceFileByPath(fileName: string, path: ts.Path, languageVersionOrOptions: ts.ScriptTarget | ts.CreateSourceFileOptions, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): ts.SourceFile | undefined { - ts.Debug.assert(compilerHost, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host."); + function getOrCreateSourceFileByPath(fileName: string, path: Path, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, _onError?: (message: string) => void, shouldCreateNewSourceFile?: boolean): SourceFile | undefined { + Debug.assert(compilerHost, "getOrCreateSourceFileByPath called after typical CompilerHost lifetime, check the callstack something with a reference to an old host."); // The program is asking for this file, check first if the host can locate it. // If the host can not locate the file, then it does not exist. return undefined // to the program to allow reporting of errors for missing files. @@ -1461,7 +1518,7 @@ export function createLanguageService( return undefined; } - const scriptKind = ts.getScriptKind(fileName, host); + const scriptKind = getScriptKind(fileName, host); const scriptVersion = host.getScriptVersion(fileName); // Check if the language version has changed since we last created a program; if they are the same, @@ -1514,9 +1571,9 @@ export function createLanguageService( } // TODO: GH#18217 frequently asserted as defined - function getProgram(): ts.Program | undefined { - if (languageServiceMode === ts.LanguageServiceMode.Syntactic) { - ts.Debug.assert(program === undefined); + function getProgram(): Program | undefined { + if (languageServiceMode === LanguageServiceMode.Syntactic) { + Debug.assert(program === undefined); return undefined; } @@ -1525,11 +1582,11 @@ export function createLanguageService( return program; } - function getAutoImportProvider(): ts.Program | undefined { + function getAutoImportProvider(): Program | undefined { return host.getPackageJsonAutoImportProvider?.(); } - function updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ts.ReferencedSymbol[], knownSymbolSpans: ts.Set): boolean { + function updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ReferencedSymbol[], knownSymbolSpans: Set): boolean { const checker = program.getTypeChecker(); const symbol = getSymbolForProgram(); @@ -1538,11 +1595,11 @@ export function createLanguageService( for (const referencedSymbol of referencedSymbols) { for (const ref of referencedSymbol.references) { const refNode = getNodeForSpan(ref); - ts.Debug.assertIsDefined(refNode); - if (knownSymbolSpans.has(ref) || ts.FindAllReferences.isDeclarationOfSymbol(refNode, symbol)) { + Debug.assertIsDefined(refNode); + if (knownSymbolSpans.has(ref) || FindAllReferences.isDeclarationOfSymbol(refNode, symbol)) { knownSymbolSpans.add(ref); ref.isDefinition = true; - const mappedSpan = ts.getMappedDocumentSpan(ref, sourceMapper, ts.maybeBind(host, host.fileExists)); + const mappedSpan = getMappedDocumentSpan(ref, sourceMapper, maybeBind(host, host.fileExists)); if (mappedSpan) { knownSymbolSpans.add(mappedSpan); } @@ -1555,15 +1612,15 @@ export function createLanguageService( return true; - function getSymbolForProgram(): ts.Symbol | undefined { + function getSymbolForProgram(): Symbol | undefined { for (const referencedSymbol of referencedSymbols) { for (const ref of referencedSymbol.references) { if (knownSymbolSpans.has(ref)) { const refNode = getNodeForSpan(ref); - ts.Debug.assertIsDefined(refNode); + Debug.assertIsDefined(refNode); return checker.getSymbolAtLocation(refNode); } - const mappedSpan = ts.getMappedDocumentSpan(ref, sourceMapper, ts.maybeBind(host, host.fileExists)); + const mappedSpan = getMappedDocumentSpan(ref, sourceMapper, maybeBind(host, host.fileExists)); if (mappedSpan && knownSymbolSpans.has(mappedSpan)) { const refNode = getNodeForSpan(mappedSpan); if (refNode) { @@ -1576,11 +1633,11 @@ export function createLanguageService( return undefined; } - function getNodeForSpan(docSpan: ts.DocumentSpan): ts.Node | undefined { + function getNodeForSpan(docSpan: DocumentSpan): Node | undefined { const sourceFile = program.getSourceFile(docSpan.fileName); if (!sourceFile) return undefined; - const rawNode = ts.getTouchingPropertyName(sourceFile, docSpan.textSpan.start); - const adjustedNode = ts.FindAllReferences.Core.getAdjustedNode(rawNode, { use: ts.FindAllReferences.FindReferencesUse.References }); + const rawNode = getTouchingPropertyName(sourceFile, docSpan.textSpan.start); + const adjustedNode = FindAllReferences.Core.getAdjustedNode(rawNode, { use: FindAllReferences.FindReferencesUse.References }); return adjustedNode; } } @@ -1593,7 +1650,7 @@ export function createLanguageService( if (program) { // Use paths to ensure we are using correct key and paths as document registry could be created with different current directory than host const key = documentRegistry.getKeyForCompilationSettings(program.getCompilerOptions()); - ts.forEach(program.getSourceFiles(), f => + forEach(program.getSourceFiles(), f => documentRegistry.releaseDocumentWithKey(f.resolvedPath, key, f.scriptKind, f.impliedNodeFormat)); program = undefined!; // TODO: GH#18217 } @@ -1601,7 +1658,7 @@ export function createLanguageService( } /// Diagnostics - function getSyntacticDiagnostics(fileName: string): ts.DiagnosticWithLocation[] { + function getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[] { synchronizeHostData(); return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice(); @@ -1611,7 +1668,7 @@ export function createLanguageService( * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors * If '-d' enabled, report both semantic and emitter errors */ - function getSemanticDiagnostics(fileName: string): ts.Diagnostic[] { + function getSemanticDiagnostics(fileName: string): Diagnostic[] { synchronizeHostData(); const targetSourceFile = getValidSourceFile(fileName); @@ -1620,7 +1677,7 @@ export function createLanguageService( // Therefore only get diagnostics for given file. const semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken); - if (!ts.getEmitDeclarations(program.getCompilerOptions())) { + if (!getEmitDeclarations(program.getCompilerOptions())) { return semanticDiagnostics.slice(); } @@ -1629,9 +1686,9 @@ export function createLanguageService( return [...semanticDiagnostics, ...declarationDiagnostics]; } - function getSuggestionDiagnostics(fileName: string): ts.DiagnosticWithLocation[] { + function getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[] { synchronizeHostData(); - return ts.computeSuggestionDiagnostics(getValidSourceFile(fileName), program, cancellationToken); + return computeSuggestionDiagnostics(getValidSourceFile(fileName), program, cancellationToken); } function getCompilerOptionsDiagnostics() { @@ -1639,15 +1696,15 @@ export function createLanguageService( return [...program.getOptionsDiagnostics(cancellationToken), ...program.getGlobalDiagnostics(cancellationToken)]; } - function getCompletionsAtPosition(fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions = ts.emptyOptions, formattingSettings?: ts.FormatCodeSettings): ts.CompletionInfo | undefined { + function getCompletionsAtPosition(fileName: string, position: number, options: GetCompletionsAtPositionOptions = emptyOptions, formattingSettings?: FormatCodeSettings): CompletionInfo | undefined { // Convert from deprecated options names to new names - const fullPreferences: ts.UserPreferences = { - ...ts.identity(options), // avoid excess property check + const fullPreferences: UserPreferences = { + ...identity(options), // avoid excess property check includeCompletionsForModuleExports: options.includeCompletionsForModuleExports || options.includeExternalModuleExports, includeCompletionsWithInsertText: options.includeCompletionsWithInsertText || options.includeInsertTextCompletions, }; synchronizeHostData(); - return ts.Completions.getCompletionsAtPosition( + return Completions.getCompletionsAtPosition( host, program, log, @@ -1657,34 +1714,34 @@ export function createLanguageService( options.triggerCharacter, options.triggerKind, cancellationToken, - formattingSettings && ts.formatting.getFormatContext(formattingSettings, host)); + formattingSettings && formatting.getFormatContext(formattingSettings, host)); } - function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: ts.FormatCodeSettings | undefined, source: string | undefined, preferences: ts.UserPreferences = ts.emptyOptions, data?: ts.CompletionEntryData): ts.CompletionEntryDetails | undefined { + function getCompletionEntryDetails(fileName: string, position: number, name: string, formattingOptions: FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences = emptyOptions, data?: CompletionEntryData): CompletionEntryDetails | undefined { synchronizeHostData(); - return ts.Completions.getCompletionEntryDetails( + return Completions.getCompletionEntryDetails( program, log, getValidSourceFile(fileName), position, { name, source, data }, host, - (formattingOptions && ts.formatting.getFormatContext(formattingOptions, host))!, // TODO: GH#18217 + (formattingOptions && formatting.getFormatContext(formattingOptions, host))!, // TODO: GH#18217 preferences, cancellationToken, ); } - function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string, preferences: ts.UserPreferences = ts.emptyOptions): ts.Symbol | undefined { + function getCompletionEntrySymbol(fileName: string, position: number, name: string, source?: string, preferences: UserPreferences = emptyOptions): Symbol | undefined { synchronizeHostData(); - return ts.Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source }, host, preferences); + return Completions.getCompletionEntrySymbol(program, log, getValidSourceFile(fileName), position, { name, source }, host, preferences); } - function getQuickInfoAtPosition(fileName: string, position: number): ts.QuickInfo | undefined { + function getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const node = ts.getTouchingPropertyName(sourceFile, position); + const node = getTouchingPropertyName(sourceFile, position); if (node === sourceFile) { // Avoid giving quickInfo for the sourceFile as a whole. return undefined; @@ -1697,159 +1754,159 @@ export function createLanguageService( if (!symbol || typeChecker.isUnknownSymbol(symbol)) { const type = shouldGetType(sourceFile, nodeForQuickInfo, position) ? typeChecker.getTypeAtLocation(nodeForQuickInfo) : undefined; return type && { - kind: ts.ScriptElementKind.unknown, - kindModifiers: ts.ScriptElementKindModifier.none, - textSpan: ts.createTextSpanFromNode(nodeForQuickInfo, sourceFile), - displayParts: typeChecker.runWithCancellationToken(cancellationToken, typeChecker => ts.typeToDisplayParts(typeChecker, type, ts.getContainerNode(nodeForQuickInfo))), + kind: ScriptElementKind.unknown, + kindModifiers: ScriptElementKindModifier.none, + textSpan: createTextSpanFromNode(nodeForQuickInfo, sourceFile), + displayParts: typeChecker.runWithCancellationToken(cancellationToken, typeChecker => typeToDisplayParts(typeChecker, type, getContainerNode(nodeForQuickInfo))), documentation: type.symbol ? type.symbol.getDocumentationComment(typeChecker) : undefined, tags: type.symbol ? type.symbol.getJsDocTags(typeChecker) : undefined }; } const { symbolKind, displayParts, documentation, tags } = typeChecker.runWithCancellationToken(cancellationToken, typeChecker => - ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, ts.getContainerNode(nodeForQuickInfo), nodeForQuickInfo) + SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, getContainerNode(nodeForQuickInfo), nodeForQuickInfo) ); return { kind: symbolKind, - kindModifiers: ts.SymbolDisplay.getSymbolModifiers(typeChecker, symbol), - textSpan: ts.createTextSpanFromNode(nodeForQuickInfo, sourceFile), + kindModifiers: SymbolDisplay.getSymbolModifiers(typeChecker, symbol), + textSpan: createTextSpanFromNode(nodeForQuickInfo, sourceFile), displayParts, documentation, tags, }; } - function getNodeForQuickInfo(node: ts.Node): ts.Node { - if (ts.isNewExpression(node.parent) && node.pos === node.parent.pos) { + function getNodeForQuickInfo(node: Node): Node { + if (isNewExpression(node.parent) && node.pos === node.parent.pos) { return node.parent.expression; } - if (ts.isNamedTupleMember(node.parent) && node.pos === node.parent.pos) { + if (isNamedTupleMember(node.parent) && node.pos === node.parent.pos) { return node.parent; } - if (ts.isImportMeta(node.parent) && node.parent.name === node) { + if (isImportMeta(node.parent) && node.parent.name === node) { return node.parent; } return node; } - function shouldGetType(sourceFile: ts.SourceFile, node: ts.Node, position: number): boolean { + function shouldGetType(sourceFile: SourceFile, node: Node, position: number): boolean { switch (node.kind) { - case ts.SyntaxKind.Identifier: - return !ts.isLabelName(node) && !ts.isTagName(node) && !ts.isConstTypeReference(node.parent); - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.QualifiedName: + case SyntaxKind.Identifier: + return !isLabelName(node) && !isTagName(node) && !isConstTypeReference(node.parent); + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.QualifiedName: // Don't return quickInfo if inside the comment in `a/**/.b` - return !ts.isInComment(sourceFile, position); - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.ThisType: - case ts.SyntaxKind.SuperKeyword: - case ts.SyntaxKind.NamedTupleMember: + return !isInComment(sourceFile, position); + case SyntaxKind.ThisKeyword: + case SyntaxKind.ThisType: + case SyntaxKind.SuperKeyword: + case SyntaxKind.NamedTupleMember: return true; - case ts.SyntaxKind.MetaProperty: - return ts.isImportMeta(node); + case SyntaxKind.MetaProperty: + return isImportMeta(node); default: return false; } } /// Goto definition - function getDefinitionAtPosition(fileName: string, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly ts.DefinitionInfo[] | undefined { + function getDefinitionAtPosition(fileName: string, position: number, searchOtherFilesOnly?: boolean, stopAtAlias?: boolean): readonly DefinitionInfo[] | undefined { synchronizeHostData(); - return ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position, searchOtherFilesOnly, stopAtAlias); + return GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position, searchOtherFilesOnly, stopAtAlias); } - function getDefinitionAndBoundSpan(fileName: string, position: number): ts.DefinitionInfoAndBoundSpan | undefined { + function getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined { synchronizeHostData(); - return ts.GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position); + return GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position); } - function getTypeDefinitionAtPosition(fileName: string, position: number): readonly ts.DefinitionInfo[] | undefined { + function getTypeDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined { synchronizeHostData(); - return ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); + return GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position); } /// Goto implementation - function getImplementationAtPosition(fileName: string, position: number): ts.ImplementationLocation[] | undefined { + function getImplementationAtPosition(fileName: string, position: number): ImplementationLocation[] | undefined { synchronizeHostData(); - return ts.FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); + return FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } /// References and Occurrences - function getOccurrencesAtPosition(fileName: string, position: number): readonly ts.ReferenceEntry[] | undefined { - return ts.flatMap( + function getOccurrencesAtPosition(fileName: string, position: number): readonly ReferenceEntry[] | undefined { + return flatMap( getDocumentHighlights(fileName, position, [fileName]), - entry => entry.highlightSpans.map(highlightSpan => ({ + entry => entry.highlightSpans.map(highlightSpan => ({ fileName: entry.fileName, textSpan: highlightSpan.textSpan, - isWriteAccess: highlightSpan.kind === ts.HighlightSpanKind.writtenReference, + isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference, ...highlightSpan.isInString && { isInString: true }, ...highlightSpan.contextSpan && { contextSpan: highlightSpan.contextSpan } })) ); } - function getDocumentHighlights(fileName: string, position: number, filesToSearch: readonly string[]): ts.DocumentHighlights[] | undefined { - const normalizedFileName = ts.normalizePath(fileName); - ts.Debug.assert(filesToSearch.some(f => ts.normalizePath(f) === normalizedFileName)); + function getDocumentHighlights(fileName: string, position: number, filesToSearch: readonly string[]): DocumentHighlights[] | undefined { + const normalizedFileName = normalizePath(fileName); + Debug.assert(filesToSearch.some(f => normalizePath(f) === normalizedFileName)); synchronizeHostData(); - const sourceFilesToSearch = ts.mapDefined(filesToSearch, fileName => program.getSourceFile(fileName)); + const sourceFilesToSearch = mapDefined(filesToSearch, fileName => program.getSourceFile(fileName)); const sourceFile = getValidSourceFile(fileName); - return ts.DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch); + return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch); } - function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ts.RenameLocation[] | undefined { + function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): RenameLocation[] | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const node = ts.getAdjustedRenameLocation(ts.getTouchingPropertyName(sourceFile, position)); - if (!ts.Rename.nodeIsEligibleForRename(node)) return undefined; - if (ts.isIdentifier(node) && (ts.isJsxOpeningElement(node.parent) || ts.isJsxClosingElement(node.parent)) && ts.isIntrinsicJsxName(node.escapedText)) { + const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position)); + if (!Rename.nodeIsEligibleForRename(node)) return undefined; + if (isIdentifier(node) && (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) && isIntrinsicJsxName(node.escapedText)) { const { openingElement, closingElement } = node.parent.parent; - return [openingElement, closingElement].map((node): ts.RenameLocation => { - const textSpan = ts.createTextSpanFromNode(node.tagName, sourceFile); + return [openingElement, closingElement].map((node): RenameLocation => { + const textSpan = createTextSpanFromNode(node.tagName, sourceFile); return { fileName: sourceFile.fileName, textSpan, - ...ts.FindAllReferences.toContextSpan(textSpan, sourceFile, node.parent) + ...FindAllReferences.toContextSpan(textSpan, sourceFile, node.parent) }; }); } else { - return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, use: ts.FindAllReferences.FindReferencesUse.Rename }, - (entry, originalNode, checker) => ts.FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false)); + return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, use: FindAllReferences.FindReferencesUse.Rename }, + (entry, originalNode, checker) => FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false)); } } - function getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] | undefined { + function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined { synchronizeHostData(); - return getReferencesWorker(ts.getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: ts.FindAllReferences.FindReferencesUse.References }, ts.FindAllReferences.toReferenceEntry); + return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, FindAllReferences.toReferenceEntry); } - function getReferencesWorker(node: ts.Node, position: number, options: ts.FindAllReferences.Options, cb: ts.FindAllReferences.ToReferenceOrRenameEntry): T[] | undefined { + function getReferencesWorker(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry): T[] | undefined { synchronizeHostData(); // Exclude default library when renaming as commonly user don't want to change that file. - const sourceFiles = options && options.use === ts.FindAllReferences.FindReferencesUse.Rename + const sourceFiles = options && options.use === FindAllReferences.FindReferencesUse.Rename ? program.getSourceFiles().filter(sourceFile => !program.isSourceFileDefaultLibrary(sourceFile)) : program.getSourceFiles(); - return ts.FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb); + return FindAllReferences.findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, cb); } - function findReferences(fileName: string, position: number): ts.ReferencedSymbol[] | undefined { + function findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined { synchronizeHostData(); - return ts.FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); + return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position); } - function getFileReferences(fileName: string): ts.ReferenceEntry[] { + function getFileReferences(fileName: string): ReferenceEntry[] { synchronizeHostData(); - return ts.FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(ts.FindAllReferences.toReferenceEntry); + return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry); } - function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): ts.NavigateToItem[] { + function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] { synchronizeHostData(); const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles(); - return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); + return NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles); } function getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean) { @@ -1857,47 +1914,47 @@ export function createLanguageService( const sourceFile = getValidSourceFile(fileName); const customTransformers = host.getCustomTransformers && host.getCustomTransformers(); - return ts.getFileEmitOutput(program, sourceFile, !!emitOnlyDtsFiles, cancellationToken, customTransformers, forceDtsEmit); + return getFileEmitOutput(program, sourceFile, !!emitOnlyDtsFiles, cancellationToken, customTransformers, forceDtsEmit); } // Signature help /** * This is a semantic operation. */ - function getSignatureHelpItems(fileName: string, position: number, { triggerReason }: ts.SignatureHelpItemsOptions = ts.emptyOptions): ts.SignatureHelpItems | undefined { + function getSignatureHelpItems(fileName: string, position: number, { triggerReason }: SignatureHelpItemsOptions = emptyOptions): SignatureHelpItems | undefined { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, triggerReason, cancellationToken); + return SignatureHelp.getSignatureHelpItems(program, sourceFile, position, triggerReason, cancellationToken); } /// Syntactic features - function getNonBoundSourceFile(fileName: string): ts.SourceFile { + function getNonBoundSourceFile(fileName: string): SourceFile { return syntaxTreeCache.getCurrentSourceFile(fileName); } - function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): ts.TextSpan | undefined { + function getNameOrDottedNameSpan(fileName: string, startPos: number, _endPos: number): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Get node at the location - const node = ts.getTouchingPropertyName(sourceFile, startPos); + const node = getTouchingPropertyName(sourceFile, startPos); if (node === sourceFile) { return undefined; } switch (node.kind) { - case ts.SyntaxKind.PropertyAccessExpression: - case ts.SyntaxKind.QualifiedName: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.FalseKeyword: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.NullKeyword: - case ts.SyntaxKind.SuperKeyword: - case ts.SyntaxKind.ThisKeyword: - case ts.SyntaxKind.ThisType: - case ts.SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.QualifiedName: + case SyntaxKind.StringLiteral: + case SyntaxKind.FalseKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.ThisKeyword: + case SyntaxKind.ThisType: + case SyntaxKind.Identifier: break; // Cant create the text span @@ -1907,18 +1964,18 @@ export function createLanguageService( let nodeForStartPos = node; while (true) { - if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) { + if (isRightSideOfPropertyAccess(nodeForStartPos) || isRightSideOfQualifiedName(nodeForStartPos)) { // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node nodeForStartPos = nodeForStartPos.parent; } - else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) { + else if (isNameOfModuleDeclaration(nodeForStartPos)) { // If this is name of a module declarations, check if this is right side of dotted module name // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of // Then this name is name from dotted module - if (nodeForStartPos.parent.parent.kind === ts.SyntaxKind.ModuleDeclaration && - (nodeForStartPos.parent.parent as ts.ModuleDeclaration).body === nodeForStartPos.parent) { + if (nodeForStartPos.parent.parent.kind === SyntaxKind.ModuleDeclaration && + (nodeForStartPos.parent.parent as ModuleDeclaration).body === nodeForStartPos.parent) { // Use parent module declarations name for start pos - nodeForStartPos = (nodeForStartPos.parent.parent as ts.ModuleDeclaration).name; + nodeForStartPos = (nodeForStartPos.parent.parent as ModuleDeclaration).name; } else { // We have to use this name for start pos @@ -1931,180 +1988,180 @@ export function createLanguageService( } } - return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); + return createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd()); } - function getBreakpointStatementAtPosition(fileName: string, position: number): ts.TextSpan | undefined { + function getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined { // doesn't use compiler - no need to synchronize with host const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); + return BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position); } - function getNavigationBarItems(fileName: string): ts.NavigationBarItem[] { - return ts.NavigationBar.getNavigationBarItems(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); + function getNavigationBarItems(fileName: string): NavigationBarItem[] { + return NavigationBar.getNavigationBarItems(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); } - function getNavigationTree(fileName: string): ts.NavigationTree { - return ts.NavigationBar.getNavigationTree(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); + function getNavigationTree(fileName: string): NavigationTree { + return NavigationBar.getNavigationTree(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken); } - function getSemanticClassifications(fileName: string, span: ts.TextSpan): ts.ClassifiedSpan[]; - function getSemanticClassifications(fileName: string, span: ts.TextSpan, format?: ts.SemanticClassificationFormat): ts.ClassifiedSpan[] | ts.ClassifiedSpan2020[] { + function getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + function getSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[] { synchronizeHostData(); - const responseFormat = format || ts.SemanticClassificationFormat.Original; - if (responseFormat === ts.SemanticClassificationFormat.TwentyTwenty) { - return ts.classifier.v2020.getSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); + const responseFormat = format || SemanticClassificationFormat.Original; + if (responseFormat === SemanticClassificationFormat.TwentyTwenty) { + return classifier.v2020.getSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); } else { return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } } - function getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan, format?: ts.SemanticClassificationFormat): ts.Classifications { + function getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications { synchronizeHostData(); - const responseFormat = format || ts.SemanticClassificationFormat.Original; - if (responseFormat === ts.SemanticClassificationFormat.Original) { + const responseFormat = format || SemanticClassificationFormat.Original; + if (responseFormat === SemanticClassificationFormat.Original) { return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span); } else { - return ts.classifier.v2020.getEncodedSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); + return classifier.v2020.getEncodedSemanticClassifications(program, cancellationToken, getValidSourceFile(fileName), span); } } - function getSyntacticClassifications(fileName: string, span: ts.TextSpan): ts.ClassifiedSpan[] { + function getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[] { // doesn't use compiler - no need to synchronize with host return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } - function getEncodedSyntacticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications { + function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications { // doesn't use compiler - no need to synchronize with host return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span); } - function getOutliningSpans(fileName: string): ts.OutliningSpan[] { + function getOutliningSpans(fileName: string): OutliningSpan[] { // doesn't use compiler - no need to synchronize with host const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.OutliningElementsCollector.collectElements(sourceFile, cancellationToken); + return OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } - const braceMatching = new ts.Map(ts.getEntries({ - [ts.SyntaxKind.OpenBraceToken]: ts.SyntaxKind.CloseBraceToken, - [ts.SyntaxKind.OpenParenToken]: ts.SyntaxKind.CloseParenToken, - [ts.SyntaxKind.OpenBracketToken]: ts.SyntaxKind.CloseBracketToken, - [ts.SyntaxKind.GreaterThanToken]: ts.SyntaxKind.LessThanToken, + const braceMatching = new Map(getEntries({ + [SyntaxKind.OpenBraceToken]: SyntaxKind.CloseBraceToken, + [SyntaxKind.OpenParenToken]: SyntaxKind.CloseParenToken, + [SyntaxKind.OpenBracketToken]: SyntaxKind.CloseBracketToken, + [SyntaxKind.GreaterThanToken]: SyntaxKind.LessThanToken, })); - braceMatching.forEach((value, key) => braceMatching.set(value.toString(), Number(key) as ts.SyntaxKind)); + braceMatching.forEach((value, key) => braceMatching.set(value.toString(), Number(key) as SyntaxKind)); - function getBraceMatchingAtPosition(fileName: string, position: number): ts.TextSpan[] { + function getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const token = ts.getTouchingToken(sourceFile, position); + const token = getTouchingToken(sourceFile, position); const matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined; - const match = matchKind && ts.findChildOfKind(token.parent, matchKind, sourceFile); + const match = matchKind && findChildOfKind(token.parent, matchKind, sourceFile); // We want to order the braces when we return the result. - return match ? [ts.createTextSpanFromNode(token, sourceFile), ts.createTextSpanFromNode(match, sourceFile)].sort((a, b) => a.start - b.start) : ts.emptyArray; + return match ? [createTextSpanFromNode(token, sourceFile), createTextSpanFromNode(match, sourceFile)].sort((a, b) => a.start - b.start) : emptyArray; } - function getIndentationAtPosition(fileName: string, position: number, editorOptions: ts.EditorOptions | ts.EditorSettings) { - let start = ts.timestamp(); + function getIndentationAtPosition(fileName: string, position: number, editorOptions: EditorOptions | EditorSettings) { + let start = timestamp(); const settings = toEditorSettings(editorOptions); const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - log("getIndentationAtPosition: getCurrentSourceFile: " + (ts.timestamp() - start)); + log("getIndentationAtPosition: getCurrentSourceFile: " + (timestamp() - start)); - start = ts.timestamp(); + start = timestamp(); - const result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, settings); - log("getIndentationAtPosition: computeIndentation : " + (ts.timestamp() - start)); + const result = formatting.SmartIndenter.getIndentation(position, sourceFile, settings); + log("getIndentationAtPosition: computeIndentation : " + (timestamp() - start)); return result; } - function getFormattingEditsForRange(fileName: string, start: number, end: number, options: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.TextChange[] { + function getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - return ts.formatting.formatSelection(start, end, sourceFile, ts.formatting.getFormatContext(toEditorSettings(options), host)); + return formatting.formatSelection(start, end, sourceFile, formatting.getFormatContext(toEditorSettings(options), host)); } - function getFormattingEditsForDocument(fileName: string, options: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.TextChange[] { - return ts.formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), ts.formatting.getFormatContext(toEditorSettings(options), host)); + function getFormattingEditsForDocument(fileName: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { + return formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), formatting.getFormatContext(toEditorSettings(options), host)); } - function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: ts.FormatCodeOptions | ts.FormatCodeSettings): ts.TextChange[] { + function getFormattingEditsAfterKeystroke(fileName: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const formatContext = ts.formatting.getFormatContext(toEditorSettings(options), host); + const formatContext = formatting.getFormatContext(toEditorSettings(options), host); - if (!ts.isInComment(sourceFile, position)) { + if (!isInComment(sourceFile, position)) { switch (key) { case "{": - return ts.formatting.formatOnOpeningCurly(position, sourceFile, formatContext); + return formatting.formatOnOpeningCurly(position, sourceFile, formatContext); case "}": - return ts.formatting.formatOnClosingCurly(position, sourceFile, formatContext); + return formatting.formatOnClosingCurly(position, sourceFile, formatContext); case ";": - return ts.formatting.formatOnSemicolon(position, sourceFile, formatContext); + return formatting.formatOnSemicolon(position, sourceFile, formatContext); case "\n": - return ts.formatting.formatOnEnter(position, sourceFile, formatContext); + return formatting.formatOnEnter(position, sourceFile, formatContext); } } return []; } - function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: ts.FormatCodeSettings, preferences: ts.UserPreferences = ts.emptyOptions): readonly ts.CodeFixAction[] { + function getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly CodeFixAction[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const span = ts.createTextSpanFromBounds(start, end); - const formatContext = ts.formatting.getFormatContext(formatOptions, host); + const span = createTextSpanFromBounds(start, end); + const formatContext = formatting.getFormatContext(formatOptions, host); - return ts.flatMap(ts.deduplicate(errorCodes, ts.equateValues, ts.compareValues), errorCode => { + return flatMap(deduplicate(errorCodes, equateValues, compareValues), errorCode => { cancellationToken.throwIfCancellationRequested(); - return ts.codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences }); + return codefix.getFixes({ errorCode, sourceFile, span, program, host, cancellationToken, formatContext, preferences }); }); } - function getCombinedCodeFix(scope: ts.CombinedCodeFixScope, fixId: {}, formatOptions: ts.FormatCodeSettings, preferences: ts.UserPreferences = ts.emptyOptions): ts.CombinedCodeActions { + function getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): CombinedCodeActions { synchronizeHostData(); - ts.Debug.assert(scope.type === "file"); + Debug.assert(scope.type === "file"); const sourceFile = getValidSourceFile(scope.fileName); - const formatContext = ts.formatting.getFormatContext(formatOptions, host); + const formatContext = formatting.getFormatContext(formatOptions, host); - return ts.codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext, preferences }); + return codefix.getAllFixes({ fixId, sourceFile, program, host, cancellationToken, formatContext, preferences }); } - function organizeImports(args: ts.OrganizeImportsArgs, formatOptions: ts.FormatCodeSettings, preferences: ts.UserPreferences = ts.emptyOptions): readonly ts.FileTextChanges[] { + function organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly FileTextChanges[] { synchronizeHostData(); - ts.Debug.assert(args.type === "file"); + Debug.assert(args.type === "file"); const sourceFile = getValidSourceFile(args.fileName); - const formatContext = ts.formatting.getFormatContext(formatOptions, host); + const formatContext = formatting.getFormatContext(formatOptions, host); - const mode = args.mode ?? (args.skipDestructiveCodeActions ? ts.OrganizeImportsMode.SortAndCombine : ts.OrganizeImportsMode.All); - return ts.OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, mode); + const mode = args.mode ?? (args.skipDestructiveCodeActions ? OrganizeImportsMode.SortAndCombine : OrganizeImportsMode.All); + return OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences, mode); } - function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: ts.FormatCodeSettings, preferences: ts.UserPreferences = ts.emptyOptions): readonly ts.FileTextChanges[] { - return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, ts.formatting.getFormatContext(formatOptions, host), preferences, sourceMapper); + function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences = emptyOptions): readonly FileTextChanges[] { + return ts.getEditsForFileRename(getProgram()!, oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions, host), preferences, sourceMapper); } - function applyCodeActionCommand(action: ts.CodeActionCommand, formatSettings?: ts.FormatCodeSettings): Promise; - function applyCodeActionCommand(action: ts.CodeActionCommand[], formatSettings?: ts.FormatCodeSettings): Promise; - function applyCodeActionCommand(action: ts.CodeActionCommand | ts.CodeActionCommand[], formatSettings?: ts.FormatCodeSettings): Promise; - function applyCodeActionCommand(fileName: ts.Path, action: ts.CodeActionCommand): Promise; - function applyCodeActionCommand(fileName: ts.Path, action: ts.CodeActionCommand[]): Promise; - function applyCodeActionCommand(fileName: ts.Path | ts.CodeActionCommand | ts.CodeActionCommand[], actionOrFormatSettingsOrUndefined?: ts.CodeActionCommand | ts.CodeActionCommand[] | ts.FormatCodeSettings): Promise { - const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as ts.CodeActionCommand | ts.CodeActionCommand[] : fileName as ts.CodeActionCommand[]; - return ts.isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a))) : applySingleCodeActionCommand(action); + function applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand): Promise; + function applyCodeActionCommand(fileName: Path, action: CodeActionCommand[]): Promise; + function applyCodeActionCommand(fileName: Path | CodeActionCommand | CodeActionCommand[], actionOrFormatSettingsOrUndefined?: CodeActionCommand | CodeActionCommand[] | FormatCodeSettings): Promise { + const action = typeof fileName === "string" ? actionOrFormatSettingsOrUndefined as CodeActionCommand | CodeActionCommand[] : fileName as CodeActionCommand[]; + return isArray(action) ? Promise.all(action.map(a => applySingleCodeActionCommand(a))) : applySingleCodeActionCommand(action); } - function applySingleCodeActionCommand(action: ts.CodeActionCommand): Promise { - const getPath = (path: string): ts.Path => ts.toPath(path, currentDirectory, getCanonicalFileName); - ts.Debug.assertEqual(action.type, "install package"); + function applySingleCodeActionCommand(action: CodeActionCommand): Promise { + const getPath = (path: string): Path => toPath(path, currentDirectory, getCanonicalFileName); + Debug.assertEqual(action.type, "install package"); return host.installPackage ? host.installPackage({ fileName: getPath(action.file), packageName: action.packageName }) : Promise.reject("Host does not implement `installPackage`"); } - function getDocCommentTemplateAtPosition(fileName: string, position: number, options?: ts.DocCommentTemplateOptions): ts.TextInsertion | undefined { - return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position, options); + function getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): TextInsertion | undefined { + return JsDoc.getDocCommentTemplateAtPosition(getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position, options); } function isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean { @@ -2114,52 +2171,52 @@ export function createLanguageService( // var x = new foo<| ( with class foo{} ) // or // var y = 3 <| - if (openingBrace === ts.CharacterCodes.lessThan) { + if (openingBrace === CharacterCodes.lessThan) { return false; } const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); // Check if in a context where we don't want to perform any insertion - if (ts.isInString(sourceFile, position)) { + if (isInString(sourceFile, position)) { return false; } - if (ts.isInsideJsxElementOrAttribute(sourceFile, position)) { - return openingBrace === ts.CharacterCodes.openBrace; + if (isInsideJsxElementOrAttribute(sourceFile, position)) { + return openingBrace === CharacterCodes.openBrace; } - if (ts.isInTemplateString(sourceFile, position)) { + if (isInTemplateString(sourceFile, position)) { return false; } switch (openingBrace) { - case ts.CharacterCodes.singleQuote: - case ts.CharacterCodes.doubleQuote: - case ts.CharacterCodes.backtick: - return !ts.isInComment(sourceFile, position); + case CharacterCodes.singleQuote: + case CharacterCodes.doubleQuote: + case CharacterCodes.backtick: + return !isInComment(sourceFile, position); } return true; } - function getJsxClosingTagAtPosition(fileName: string, position: number): ts.JsxClosingTagInfo | undefined { + function getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const token = ts.findPrecedingToken(position, sourceFile); + const token = findPrecedingToken(position, sourceFile); if (!token) return undefined; - const element = token.kind === ts.SyntaxKind.GreaterThanToken && ts.isJsxOpeningElement(token.parent) ? token.parent.parent - : ts.isJsxText(token) && ts.isJsxElement(token.parent) ? token.parent : undefined; + const element = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningElement(token.parent) ? token.parent.parent + : isJsxText(token) && isJsxElement(token.parent) ? token.parent : undefined; if (element && isUnclosedTag(element)) { return { newText: `` }; } - const fragment = token.kind === ts.SyntaxKind.GreaterThanToken && ts.isJsxOpeningFragment(token.parent) ? token.parent.parent - : ts.isJsxText(token) && ts.isJsxFragment(token.parent) ? token.parent : undefined; + const fragment = token.kind === SyntaxKind.GreaterThanToken && isJsxOpeningFragment(token.parent) ? token.parent.parent + : isJsxText(token) && isJsxFragment(token.parent) ? token.parent : undefined; if (fragment && isUnclosedFragment(fragment)) { return { newText: "" }; } } - function getLinesForRange(sourceFile: ts.SourceFile, textRange: ts.TextRange) { + function getLinesForRange(sourceFile: SourceFile, textRange: TextRange) { return { lineStarts: sourceFile.getLineStarts(), firstLine: sourceFile.getLineAndCharacterOfPosition(textRange.pos).line, @@ -2167,16 +2224,16 @@ export function createLanguageService( }; } - function toggleLineComment(fileName: string, textRange: ts.TextRange, insertComment?: boolean): ts.TextChange[] { + function toggleLineComment(fileName: string, textRange: TextRange, insertComment?: boolean): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const textChanges: ts.TextChange[] = []; + const textChanges: TextChange[] = []; const { lineStarts, firstLine, lastLine } = getLinesForRange(sourceFile, textRange); let isCommenting = insertComment || false; let leftMostPosition = Number.MAX_VALUE; - const lineTextStarts = new ts.Map(); + const lineTextStarts = new Map(); const firstNonWhitespaceCharacterRegex = new RegExp(/\S/); - const isJsx = ts.isInsideJsxElement(sourceFile, lineStarts[firstLine]); + const isJsx = isInsideJsxElement(sourceFile, lineStarts[firstLine]); const openComment = isJsx ? "{/*" : "//"; // Check each line before any text changes. @@ -2233,17 +2290,17 @@ export function createLanguageService( return textChanges; } - function toggleMultilineComment(fileName: string, textRange: ts.TextRange, insertComment?: boolean, isInsideJsx?: boolean): ts.TextChange[] { + function toggleMultilineComment(fileName: string, textRange: TextRange, insertComment?: boolean, isInsideJsx?: boolean): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const textChanges: ts.TextChange[] = []; + const textChanges: TextChange[] = []; const { text } = sourceFile; let hasComment = false; let isCommenting = insertComment || false; - const positions = [] as number[] as ts.SortedArray; + const positions = [] as number[] as SortedArray; let { pos } = textRange; - const isJsx = isInsideJsx !== undefined ? isInsideJsx : ts.isInsideJsxElement(sourceFile, pos); + const isJsx = isInsideJsx !== undefined ? isInsideJsx : isInsideJsxElement(sourceFile, pos); const openMultiline = isJsx ? "{/*" : "/*"; const closeMultiline = isJsx ? "*/}" : "*/"; @@ -2254,7 +2311,7 @@ export function createLanguageService( while (pos <= textRange.end) { // Start of comment is considered inside comment. const offset = text.substr(pos, openMultiline.length) === openMultiline ? openMultiline.length : 0; - const commentRange = ts.isInComment(sourceFile, pos + offset); + const commentRange = isInComment(sourceFile, pos + offset); // If position is in a comment add it to the positions array. if (commentRange) { @@ -2265,7 +2322,7 @@ export function createLanguageService( } positions.push(commentRange.pos); - if (commentRange.kind === ts.SyntaxKind.MultiLineCommentTrivia) { + if (commentRange.kind === SyntaxKind.MultiLineCommentTrivia) { positions.push(commentRange.end); } @@ -2277,7 +2334,7 @@ export function createLanguageService( isCommenting = insertComment !== undefined ? insertComment - : isCommenting || !ts.isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos); // If isCommenting is already true we don't need to check whitespace again. + : isCommenting || !isTextWhiteSpaceLike(text, pos, newPos === -1 ? textRange.end : pos + newPos); // If isCommenting is already true we don't need to check whitespace again. pos = newPos === -1 ? textRange.end + 1 : pos + newPos + closeMultiline.length; } } @@ -2285,10 +2342,10 @@ export function createLanguageService( // If it didn't found a comment and isCommenting is false means is only empty space. // We want to insert comment in this scenario. if (isCommenting || !hasComment) { - if (ts.isInComment(sourceFile, textRange.pos)?.kind !== ts.SyntaxKind.SingleLineCommentTrivia) { - ts.insertSorted(positions, textRange.pos, ts.compareValues); + if (isInComment(sourceFile, textRange.pos)?.kind !== SyntaxKind.SingleLineCommentTrivia) { + insertSorted(positions, textRange.pos, compareValues); } - ts.insertSorted(positions, textRange.end, ts.compareValues); + insertSorted(positions, textRange.end, compareValues); // Insert open comment if the first position is not a comment already. const firstPos = positions[0]; @@ -2354,7 +2411,7 @@ export function createLanguageService( return textChanges; } - function commentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] { + function commentSelection(fileName: string, textRange: TextRange): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); const { firstLine, lastLine } = getLinesForRange(sourceFile, textRange); @@ -2364,26 +2421,26 @@ export function createLanguageService( : toggleLineComment(fileName, textRange, /*insertComment*/ true); } - function uncommentSelection(fileName: string, textRange: ts.TextRange): ts.TextChange[] { + function uncommentSelection(fileName: string, textRange: TextRange): TextChange[] { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const textChanges: ts.TextChange[] = []; + const textChanges: TextChange[] = []; const { pos } = textRange; let { end } = textRange; // If cursor is not a selection we need to increase the end position // to include the start of the comment. if (pos === end) { - end += ts.isInsideJsxElement(sourceFile, pos) ? 2 : 1; + end += isInsideJsxElement(sourceFile, pos) ? 2 : 1; } for (let i = pos; i <= end; i++) { - const commentRange = ts.isInComment(sourceFile, i); + const commentRange = isInComment(sourceFile, i); if (commentRange) { switch (commentRange.kind) { - case ts.SyntaxKind.SingleLineCommentTrivia: + case SyntaxKind.SingleLineCommentTrivia: textChanges.push.apply(textChanges, toggleLineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); break; - case ts.SyntaxKind.MultiLineCommentTrivia: + case SyntaxKind.MultiLineCommentTrivia: textChanges.push.apply(textChanges, toggleMultilineComment(fileName, { end: commentRange.end, pos: commentRange.pos + 1 }, /*insertComment*/ false)); } @@ -2394,22 +2451,22 @@ export function createLanguageService( return textChanges; } - function isUnclosedTag({ openingElement, closingElement, parent }: ts.JsxElement): boolean { - return !ts.tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) || - ts.isJsxElement(parent) && ts.tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent); + function isUnclosedTag({ openingElement, closingElement, parent }: JsxElement): boolean { + return !tagNamesAreEquivalent(openingElement.tagName, closingElement.tagName) || + isJsxElement(parent) && tagNamesAreEquivalent(openingElement.tagName, parent.openingElement.tagName) && isUnclosedTag(parent); } - function isUnclosedFragment({ closingFragment, parent }: ts.JsxFragment): boolean { - return !!(closingFragment.flags & ts.NodeFlags.ThisNodeHasError) || (ts.isJsxFragment(parent) && isUnclosedFragment(parent)); + function isUnclosedFragment({ closingFragment, parent }: JsxFragment): boolean { + return !!(closingFragment.flags & NodeFlags.ThisNodeHasError) || (isJsxFragment(parent) && isUnclosedFragment(parent)); } - function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan | undefined { + function getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined { const sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName); - const range = ts.formatting.getRangeOfEnclosingComment(sourceFile, position); - return range && (!onlyMultiLine || range.kind === ts.SyntaxKind.MultiLineCommentTrivia) ? ts.createTextSpanFromRange(range) : undefined; + const range = formatting.getRangeOfEnclosingComment(sourceFile, position); + return range && (!onlyMultiLine || range.kind === SyntaxKind.MultiLineCommentTrivia) ? createTextSpanFromRange(range) : undefined; } - function getTodoComments(fileName: string, descriptors: ts.TodoCommentDescriptor[]): ts.TodoComment[] { + function getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[] { // Note: while getting todo comments seems like a syntactic operation, we actually // treat it as a semantic operation here. This is because we expect our host to call // this on every single file. If we treat this syntactically, then that will cause @@ -2423,7 +2480,7 @@ export function createLanguageService( cancellationToken.throwIfCancellationRequested(); const fileContents = sourceFile.text; - const result: ts.TodoComment[] = []; + const result: TodoComment[] = []; // Exclude node_modules files as we don't want to show the todos of external libraries. if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) { @@ -2451,24 +2508,24 @@ export function createLanguageService( // i.e. 'undefined' in position 3 above means TODO(jason) didn't match. // "hack" in position 4 means HACK did match. const firstDescriptorCaptureIndex = 3; - ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); + Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex); const preamble = matchArray[1]; const matchPosition = matchArray.index + preamble.length; // OK, we have found a match in the file. This is only an acceptable match if // it is contained within a comment. - if (!ts.isInComment(sourceFile, matchPosition)) { + if (!isInComment(sourceFile, matchPosition)) { continue; } - let descriptor: ts.TodoCommentDescriptor | undefined; + let descriptor: TodoCommentDescriptor | undefined; for (let i = 0; i < descriptors.length; i++) { if (matchArray[i + firstDescriptorCaptureIndex]) { descriptor = descriptors[i]; } } - if (descriptor === undefined) return ts.Debug.fail(); + if (descriptor === undefined) return Debug.fail(); // We don't want to match something like 'TODOBY', so we make sure a non // letter/digit follows the match. @@ -2520,7 +2577,7 @@ export function createLanguageService( // Note that the outermost group is *not* a capture group, but the innermost groups // *are* capture groups. By capturing the inner literals we can determine after // matching which descriptor we are dealing with. - const literals = "(?:" + ts.map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; + const literals = "(?:" + map(descriptors, d => "(" + escapeRegExp(d.text) + ")").join("|") + ")"; // After matching a descriptor literal, the following regexp matches the rest of the // text up to the end of the line (or */). @@ -2546,22 +2603,22 @@ export function createLanguageService( } function isLetterOrDigit(char: number): boolean { - return (char >= ts.CharacterCodes.a && char <= ts.CharacterCodes.z) || - (char >= ts.CharacterCodes.A && char <= ts.CharacterCodes.Z) || - (char >= ts.CharacterCodes._0 && char <= ts.CharacterCodes._9); + return (char >= CharacterCodes.a && char <= CharacterCodes.z) || + (char >= CharacterCodes.A && char <= CharacterCodes.Z) || + (char >= CharacterCodes._0 && char <= CharacterCodes._9); } function isNodeModulesFile(path: string): boolean { - return ts.stringContains(path, "/node_modules/"); + return stringContains(path, "/node_modules/"); } } - function getRenameInfo(fileName: string, position: number, preferences: ts.UserPreferences | ts.RenameInfoOptions | undefined): ts.RenameInfo { + function getRenameInfo(fileName: string, position: number, preferences: UserPreferences | RenameInfoOptions | undefined): RenameInfo { synchronizeHostData(); - return ts.Rename.getRenameInfo(program, getValidSourceFile(fileName), position, preferences || {}); + return Rename.getRenameInfo(program, getValidSourceFile(fileName), position, preferences || {}); } - function getRefactorContext(file: ts.SourceFile, positionOrRange: number | ts.TextRange, preferences: ts.UserPreferences, formatOptions?: ts.FormatCodeSettings, triggerReason?: ts.RefactorTriggerReason, kind?: string): ts.RefactorContext { + function getRefactorContext(file: SourceFile, positionOrRange: number | TextRange, preferences: UserPreferences, formatOptions?: FormatCodeSettings, triggerReason?: RefactorTriggerReason, kind?: string): RefactorContext { const [startPosition, endPosition] = typeof positionOrRange === "number" ? [positionOrRange, undefined] : [positionOrRange.pos, positionOrRange.end]; return { file, @@ -2569,7 +2626,7 @@ export function createLanguageService( endPosition, program: getProgram()!, host, - formatContext: ts.formatting.getFormatContext(formatOptions!, host), // TODO: GH#18217 + formatContext: formatting.getFormatContext(formatOptions!, host), // TODO: GH#18217 cancellationToken, preferences, triggerReason, @@ -2577,7 +2634,7 @@ export function createLanguageService( }; } - function getInlayHintsContext(file: ts.SourceFile, span: ts.TextSpan, preferences: ts.UserPreferences): ts.InlayHintsContext { + function getInlayHintsContext(file: SourceFile, span: TextSpan, preferences: UserPreferences): InlayHintsContext { return { file, program: getProgram()!, @@ -2588,30 +2645,30 @@ export function createLanguageService( }; } - function getSmartSelectionRange(fileName: string, position: number): ts.SelectionRange { - return ts.SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName)); + function getSmartSelectionRange(fileName: string, position: number): SelectionRange { + return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName)); } - function getApplicableRefactors(fileName: string, positionOrRange: number | ts.TextRange, preferences: ts.UserPreferences = ts.emptyOptions, triggerReason: ts.RefactorTriggerReason, kind: string): ts.ApplicableRefactorInfo[] { + function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions, triggerReason: RefactorTriggerReason, kind: string): ApplicableRefactorInfo[] { synchronizeHostData(); const file = getValidSourceFile(fileName); - return ts.refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, ts.emptyOptions, triggerReason, kind)); + return refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange, preferences, emptyOptions, triggerReason, kind)); } function getEditsForRefactor( fileName: string, - formatOptions: ts.FormatCodeSettings, - positionOrRange: number | ts.TextRange, + formatOptions: FormatCodeSettings, + positionOrRange: number | TextRange, refactorName: string, actionName: string, - preferences: ts.UserPreferences = ts.emptyOptions, - ): ts.RefactorEditInfo | undefined { + preferences: UserPreferences = emptyOptions, + ): RefactorEditInfo | undefined { synchronizeHostData(); const file = getValidSourceFile(fileName); - return ts.refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName); + return refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, preferences, formatOptions), refactorName, actionName); } - function toLineColumnOffset(fileName: string, position: number): ts.LineAndCharacter { + function toLineColumnOffset(fileName: string, position: number): LineAndCharacter { // Go to Definition supports returning a zero-length span at position 0 for // non-existent files. We need to special-case the conversion of position 0 // to avoid a crash trying to get the text for that file, since this function @@ -2622,33 +2679,33 @@ export function createLanguageService( return sourceMapper.toLineColumnOffset(fileName, position); } - function prepareCallHierarchy(fileName: string, position: number): ts.CallHierarchyItem | ts.CallHierarchyItem[] | undefined { + function prepareCallHierarchy(fileName: string, position: number): CallHierarchyItem | CallHierarchyItem[] | undefined { synchronizeHostData(); - const declarations = ts.CallHierarchy.resolveCallHierarchyDeclaration(program, ts.getTouchingPropertyName(getValidSourceFile(fileName), position)); - return declarations && ts.mapOneOrMany(declarations, declaration => ts.CallHierarchy.createCallHierarchyItem(program, declaration)); + const declarations = CallHierarchy.resolveCallHierarchyDeclaration(program, getTouchingPropertyName(getValidSourceFile(fileName), position)); + return declarations && mapOneOrMany(declarations, declaration => CallHierarchy.createCallHierarchyItem(program, declaration)); } - function provideCallHierarchyIncomingCalls(fileName: string, position: number): ts.CallHierarchyIncomingCall[] { + function provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const declaration = ts.firstOrOnly(ts.CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : ts.getTouchingPropertyName(sourceFile, position))); - return declaration ? ts.CallHierarchy.getIncomingCalls(program, declaration, cancellationToken) : []; + const declaration = firstOrOnly(CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + return declaration ? CallHierarchy.getIncomingCalls(program, declaration, cancellationToken) : []; } - function provideCallHierarchyOutgoingCalls(fileName: string, position: number): ts.CallHierarchyOutgoingCall[] { + function provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - const declaration = ts.firstOrOnly(ts.CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : ts.getTouchingPropertyName(sourceFile, position))); - return declaration ? ts.CallHierarchy.getOutgoingCalls(program, declaration) : []; + const declaration = firstOrOnly(CallHierarchy.resolveCallHierarchyDeclaration(program, position === 0 ? sourceFile : getTouchingPropertyName(sourceFile, position))); + return declaration ? CallHierarchy.getOutgoingCalls(program, declaration) : []; } - function provideInlayHints(fileName: string, span: ts.TextSpan, preferences: ts.UserPreferences = ts.emptyOptions): ts.InlayHint[] { + function provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences = emptyOptions): InlayHint[] { synchronizeHostData(); const sourceFile = getValidSourceFile(fileName); - return ts.InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); + return InlayHints.provideInlayHints(getInlayHintsContext(sourceFile, span, preferences)); } - const ls: ts.LanguageService = { + const ls: LanguageService = { dispose, cleanupSemanticCache, getSyntacticDiagnostics, @@ -2719,16 +2776,16 @@ export function createLanguageService( }; switch (languageServiceMode) { - case ts.LanguageServiceMode.Semantic: + case LanguageServiceMode.Semantic: break; - case ts.LanguageServiceMode.PartialSemantic: + case LanguageServiceMode.PartialSemantic: invalidOperationsInPartialSemanticMode.forEach(key => ls[key] = () => { throw new Error(`LanguageService Operation: ${key} not allowed in LanguageServiceMode.PartialSemantic`); } ); break; - case ts.LanguageServiceMode.Syntactic: + case LanguageServiceMode.Syntactic: invalidOperationsInSyntacticMode.forEach(key => ls[key] = () => { throw new Error(`LanguageService Operation: ${key} not allowed in LanguageServiceMode.Syntactic`); @@ -2736,14 +2793,14 @@ export function createLanguageService( ); break; default: - ts.Debug.assertNever(languageServiceMode); + Debug.assertNever(languageServiceMode); } return ls; } /* @internal */ /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */ -export function getNameTable(sourceFile: ts.SourceFile): ts.UnderscoreEscapedMap { +export function getNameTable(sourceFile: SourceFile): UnderscoreEscapedMap { if (!sourceFile.nameTable) { initializeNameTable(sourceFile); } @@ -2751,22 +2808,22 @@ export function getNameTable(sourceFile: ts.SourceFile): ts.UnderscoreEscapedMap return sourceFile.nameTable!; // TODO: GH#18217 } -function initializeNameTable(sourceFile: ts.SourceFile): void { - const nameTable = sourceFile.nameTable = new ts.Map(); +function initializeNameTable(sourceFile: SourceFile): void { + const nameTable = sourceFile.nameTable = new Map(); sourceFile.forEachChild(function walk(node) { - if (ts.isIdentifier(node) && !ts.isTagName(node) && node.escapedText || ts.isStringOrNumericLiteralLike(node) && literalIsName(node)) { - const text = ts.getEscapedTextOfIdentifierOrLiteral(node); + if (isIdentifier(node) && !isTagName(node) && node.escapedText || isStringOrNumericLiteralLike(node) && literalIsName(node)) { + const text = getEscapedTextOfIdentifierOrLiteral(node); nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } - else if (ts.isPrivateIdentifier(node)) { + else if (isPrivateIdentifier(node)) { const text = node.escapedText; nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1); } - ts.forEachChild(node, walk); - if (ts.hasJSDocNodes(node)) { + forEachChild(node, walk); + if (hasJSDocNodes(node)) { for (const jsDoc of node.jsDoc!) { - ts.forEachChild(jsDoc, walk); + forEachChild(jsDoc, walk); } } }); @@ -2778,49 +2835,49 @@ function initializeNameTable(sourceFile: ts.SourceFile): void { * then we want 'something' to be in the name table. Similarly, if we have * "a['propname']" then we want to store "propname" in the name table. */ -function literalIsName(node: ts.StringLiteralLike | ts.NumericLiteral): boolean { - return ts.isDeclarationName(node) || - node.parent.kind === ts.SyntaxKind.ExternalModuleReference || +function literalIsName(node: StringLiteralLike | NumericLiteral): boolean { + return isDeclarationName(node) || + node.parent.kind === SyntaxKind.ExternalModuleReference || isArgumentOfElementAccessExpression(node) || - ts.isLiteralComputedPropertyDeclarationName(node); + isLiteralComputedPropertyDeclarationName(node); } /** * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 } */ /* @internal */ -export function getContainingObjectLiteralElement(node: ts.Node): ObjectLiteralElementWithName | undefined { +export function getContainingObjectLiteralElement(node: Node): ObjectLiteralElementWithName | undefined { const element = getContainingObjectLiteralElementWorker(node); - return element && (ts.isObjectLiteralExpression(element.parent) || ts.isJsxAttributes(element.parent)) ? element as ObjectLiteralElementWithName : undefined; + return element && (isObjectLiteralExpression(element.parent) || isJsxAttributes(element.parent)) ? element as ObjectLiteralElementWithName : undefined; } -function getContainingObjectLiteralElementWorker(node: ts.Node): ts.ObjectLiteralElement | undefined { +function getContainingObjectLiteralElementWorker(node: Node): ObjectLiteralElement | undefined { switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.NumericLiteral: - if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) { - return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + if (node.parent.kind === SyntaxKind.ComputedPropertyName) { + return isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined; } // falls through - case ts.SyntaxKind.Identifier: - return ts.isObjectLiteralElement(node.parent) && - (node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) && + case SyntaxKind.Identifier: + return isObjectLiteralElement(node.parent) && + (node.parent.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === SyntaxKind.JsxAttributes) && node.parent.name === node ? node.parent : undefined; } return undefined; } /* @internal */ -export type ObjectLiteralElementWithName = ts.ObjectLiteralElement & { name: ts.PropertyName; parent: ts.ObjectLiteralExpression | ts.JsxAttributes }; +export type ObjectLiteralElementWithName = ObjectLiteralElement & { name: PropertyName; parent: ObjectLiteralExpression | JsxAttributes }; -function getSymbolAtLocationForQuickInfo(node: ts.Node, checker: ts.TypeChecker): ts.Symbol | undefined { +function getSymbolAtLocationForQuickInfo(node: Node, checker: TypeChecker): Symbol | undefined { const object = getContainingObjectLiteralElement(node); if (object) { const contextualType = checker.getContextualType(object.parent); const properties = contextualType && getPropertySymbolsFromContextualType(object, checker, contextualType, /*unionSymbolOk*/ false); if (properties && properties.length === 1) { - return ts.first(properties); + return first(properties); } } return checker.getSymbolAtLocation(node); @@ -2828,31 +2885,31 @@ function getSymbolAtLocationForQuickInfo(node: ts.Node, checker: ts.TypeChecker) /** Gets all symbols for one property. Does not get symbols for every property. */ /* @internal */ -export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementWithName, checker: ts.TypeChecker, contextualType: ts.Type, unionSymbolOk: boolean): readonly ts.Symbol[] { - const name = ts.getNameFromPropertyName(node.name); - if (!name) return ts.emptyArray; +export function getPropertySymbolsFromContextualType(node: ObjectLiteralElementWithName, checker: TypeChecker, contextualType: Type, unionSymbolOk: boolean): readonly Symbol[] { + const name = getNameFromPropertyName(node.name); + if (!name) return emptyArray; if (!contextualType.isUnion()) { const symbol = contextualType.getProperty(name); - return symbol ? [symbol] : ts.emptyArray; + return symbol ? [symbol] : emptyArray; } - const discriminatedPropertySymbols = ts.mapDefined(contextualType.types, t => (ts.isObjectLiteralExpression(node.parent)|| ts.isJsxAttributes(node.parent)) && checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent) ? undefined : t.getProperty(name)); + const discriminatedPropertySymbols = mapDefined(contextualType.types, t => (isObjectLiteralExpression(node.parent)|| isJsxAttributes(node.parent)) && checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent) ? undefined : t.getProperty(name)); if (unionSymbolOk && (discriminatedPropertySymbols.length === 0 || discriminatedPropertySymbols.length === contextualType.types.length)) { const symbol = contextualType.getProperty(name); if (symbol) return [symbol]; } if (discriminatedPropertySymbols.length === 0) { // Bad discriminant -- do again without discriminating - return ts.mapDefined(contextualType.types, t => t.getProperty(name)); + return mapDefined(contextualType.types, t => t.getProperty(name)); } return discriminatedPropertySymbols; } -function isArgumentOfElementAccessExpression(node: ts.Node) { +function isArgumentOfElementAccessExpression(node: Node) { return node && node.parent && - node.parent.kind === ts.SyntaxKind.ElementAccessExpression && - (node.parent as ts.ElementAccessExpression).argumentExpression === node; + node.parent.kind === SyntaxKind.ElementAccessExpression && + (node.parent as ElementAccessExpression).argumentExpression === node; } /// getDefaultLibraryFilePath @@ -2863,13 +2920,13 @@ declare const __dirname: string; * node package. * The functionality is not supported if the ts module is consumed outside of a node module. */ -export function getDefaultLibFilePath(options: ts.CompilerOptions): string { +export function getDefaultLibFilePath(options: CompilerOptions): string { // Check __dirname is defined and that we are on a node.js system. if (typeof __dirname !== "undefined") { - return ts.combinePaths(__dirname, ts.getDefaultLibFileName(options)); + return combinePaths(__dirname, getDefaultLibFileName(options)); } throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. "); } -ts.setObjectAllocator(getServicesObjectAllocator()); +setObjectAllocator(getServicesObjectAllocator()); diff --git a/src/services/shims.ts b/src/services/shims.ts index d4de66db93b3c..b3ba7f3e8ab09 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -1,4 +1,17 @@ -import * as ts from "./_namespaces/ts"; +import { + Classifications, Classifier, clear, CompilerOptions, CompletionEntryData, createClassifier, createDocumentRegistry, + createGetCanonicalFileName, createLanguageService, createTextChangeRange, createTextSpan, Diagnostic, + diagnosticCategoryName, DocCommentTemplateOptions, DocumentRegistry, EditorOptions, EmitOutput, emptyOptions, + EndOfLineState, ESMap, Extension, extensionFromPath, FileReference, filter, flattenDiagnosticMessageText, + FormatCodeOptions, FormatCodeSettings, getAutomaticTypeDirectiveNames, GetCompletionsAtPositionOptions, + getDefaultCompilerOptions, getDirectoryPath, getFileMatcherPatterns, getNewLineOrDefaultFromHost, getProperty, + getSnapshotText, HostCancellationToken, IScriptSnapshot, isString, JsTyping, LanguageService, LanguageServiceHost, + map, MapLike, ModuleResolutionHost, normalizeSlashes, OperationCanceledException, ParseConfigHost, + parseJsonSourceFileConfigFileContent, parseJsonText, preProcessFile, ReadonlyESMap, ResolvedModuleFull, + ResolvedTypeReferenceDirective, resolveModuleName, resolveTypeReferenceDirective, ScriptKind, + SemanticClassificationFormat, servicesVersion, SignatureHelpItemsOptions, TextChangeRange, TextRange, TextSpan, + ThrottledCancellationToken, timestamp, toFileNameLowerCase, toPath, TypeAcquisition, UserPreferences, +} from "./_namespaces/ts"; // // Copyright (c) Microsoft Corporation. All rights reserved. @@ -27,11 +40,11 @@ interface DiscoverTypingsInfo { fileNames: string[]; // The file names that belong to the same project. projectRootPath: string; // The path to the project root directory safeListPath: string; // The path used to retrieve the safe list - packageNameToTypingLocation: ts.ESMap; // The map of package names to their cached typing locations and installed versions - typeAcquisition: ts.TypeAcquisition; // Used to customize the type acquisition process - compilerOptions: ts.CompilerOptions; // Used as a source for typing inference + packageNameToTypingLocation: ESMap; // The map of package names to their cached typing locations and installed versions + typeAcquisition: TypeAcquisition; // Used to customize the type acquisition process + compilerOptions: CompilerOptions; // Used as a source for typing inference unresolvedImports: readonly string[]; // List of unresolved module ids from imports - typesRegistry: ts.ReadonlyESMap>; // The map of available typings in npm to maps of TS versions to their latest supported versions + typesRegistry: ReadonlyESMap>; // The map of available typings in npm to maps of TS versions to their latest supported versions } /** @internal */ @@ -68,11 +81,11 @@ export interface LanguageServiceShimHost extends Logger { /** Returns a JSON-encoded value of the type: string[] */ getScriptFileNames(): string; - getScriptKind?(fileName: string): ts.ScriptKind; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): ScriptSnapshotShim; getLocalizedDiagnosticMessages(): string; - getCancellationToken(): ts.HostCancellationToken; + getCancellationToken(): HostCancellationToken; getCurrentDirectory(): string; getDirectories(path: string): string; getDefaultLibFileName(options: string): string; @@ -141,7 +154,7 @@ export interface Shim { /** @internal */ export interface LanguageServiceShim extends Shim { - languageService: ts.LanguageService; + languageService: LanguageService; dispose(_dummy: {}): void; @@ -155,25 +168,25 @@ export interface LanguageServiceShim extends Shim { getCompilerOptionsDiagnostics(): string; getSyntacticClassifications(fileName: string, start: number, length: number): string; - getSemanticClassifications(fileName: string, start: number, length: number, format?: ts.SemanticClassificationFormat): string; + getSemanticClassifications(fileName: string, start: number, length: number, format?: SemanticClassificationFormat): string; getEncodedSyntacticClassifications(fileName: string, start: number, length: number): string; - getEncodedSemanticClassifications(fileName: string, start: number, length: number, format?: ts.SemanticClassificationFormat): string; + getEncodedSemanticClassifications(fileName: string, start: number, length: number, format?: SemanticClassificationFormat): string; - getCompletionsAtPosition(fileName: string, position: number, preferences: ts.UserPreferences | undefined, formattingSettings: ts.FormatCodeSettings | undefined): string; - getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: ts.UserPreferences | undefined, data: ts.CompletionEntryData | undefined): string; + getCompletionsAtPosition(fileName: string, position: number, preferences: UserPreferences | undefined, formattingSettings: FormatCodeSettings | undefined): string; + getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined): string; getQuickInfoAtPosition(fileName: string, position: number): string; getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): string; getBreakpointStatementAtPosition(fileName: string, position: number): string; - getSignatureHelpItems(fileName: string, position: number, options: ts.SignatureHelpItemsOptions | undefined): string; + getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): string; /** * Returns a JSON-encoded value of the type: * { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } } */ - getRenameInfo(fileName: string, position: number, preferences: ts.UserPreferences): string; + getRenameInfo(fileName: string, position: number, preferences: UserPreferences): string; getSmartSelectionRange(fileName: string, position: number): string; /** @@ -273,7 +286,7 @@ export interface LanguageServiceShim extends Shim { /** * Returns JSON-encoded value of the type TextInsertion. */ - getDocCommentTemplateAtPosition(fileName: string, position: number, options?: ts.DocCommentTemplateOptions): string; + getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): string; /** * Returns JSON-encoded boolean to indicate whether we should support brace location @@ -290,27 +303,27 @@ export interface LanguageServiceShim extends Shim { prepareCallHierarchy(fileName: string, position: number): string; provideCallHierarchyIncomingCalls(fileName: string, position: number): string; provideCallHierarchyOutgoingCalls(fileName: string, position: number): string; - provideInlayHints(fileName: string, span: ts.TextSpan, preference: ts.UserPreferences | undefined): string; + provideInlayHints(fileName: string, span: TextSpan, preference: UserPreferences | undefined): string; getEmitOutput(fileName: string): string; - getEmitOutputObject(fileName: string): ts.EmitOutput; + getEmitOutputObject(fileName: string): EmitOutput; - toggleLineComment(fileName: string, textChange: ts.TextRange): string; - toggleMultilineComment(fileName: string, textChange: ts.TextRange): string; - commentSelection(fileName: string, textChange: ts.TextRange): string; - uncommentSelection(fileName: string, textChange: ts.TextRange): string; + toggleLineComment(fileName: string, textChange: TextRange): string; + toggleMultilineComment(fileName: string, textChange: TextRange): string; + commentSelection(fileName: string, textChange: TextRange): string; + uncommentSelection(fileName: string, textChange: TextRange): string; } /** @internal */ export interface ClassifierShim extends Shim { - getEncodedLexicalClassifications(text: string, lexState: ts.EndOfLineState, syntacticClassifierAbsent?: boolean): string; - getClassificationsForLine(text: string, lexState: ts.EndOfLineState, syntacticClassifierAbsent?: boolean): string; + getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string; + getClassificationsForLine(text: string, lexState: EndOfLineState, syntacticClassifierAbsent?: boolean): string; } /** @internal */ export interface CoreServicesShim extends Shim { getAutomaticTypeDirectiveNames(compilerOptionsJson: string): string; - getPreProcessedFileInfo(fileName: string, sourceText: ts.IScriptSnapshot): string; - getTSConfigFileInfo(fileName: string, sourceText: ts.IScriptSnapshot): string; + getPreProcessedFileInfo(fileName: string, sourceText: IScriptSnapshot): string; + getTSConfigFileInfo(fileName: string, sourceText: IScriptSnapshot): string; getDefaultCompilationSettings(): string; discoverTypings(discoverTypingsJson: string): string; } @@ -321,7 +334,7 @@ function logInternalError(logger: Logger, err: Error) { } } -class ScriptSnapshotShimAdapter implements ts.IScriptSnapshot { +class ScriptSnapshotShimAdapter implements IScriptSnapshot { constructor(private scriptSnapshotShim: ScriptSnapshotShim) { } @@ -333,7 +346,7 @@ class ScriptSnapshotShimAdapter implements ts.IScriptSnapshot { return this.scriptSnapshotShim.getLength(); } - public getChangeRange(oldSnapshot: ts.IScriptSnapshot): ts.TextChangeRange | undefined { + public getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined { const oldSnapshotShim = oldSnapshot as ScriptSnapshotShimAdapter; const encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim); /* eslint-disable no-null/no-null */ @@ -343,8 +356,8 @@ class ScriptSnapshotShimAdapter implements ts.IScriptSnapshot { /* eslint-enable no-null/no-null */ const decoded: { span: { start: number; length: number; }; newLength: number; } = JSON.parse(encoded!); // TODO: GH#18217 - return ts.createTextChangeRange( - ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); + return createTextChangeRange( + createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength); } public dispose(): void { @@ -357,12 +370,12 @@ class ScriptSnapshotShimAdapter implements ts.IScriptSnapshot { } /** @internal */ -export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { +export class LanguageServiceShimHostAdapter implements LanguageServiceHost { private loggingEnabled = false; private tracingEnabled = false; - public resolveModuleNames: ((moduleName: string[], containingFile: string) => (ts.ResolvedModuleFull | undefined)[]) | undefined; - public resolveTypeReferenceDirectives: ((typeDirectiveNames: string[] | readonly ts.FileReference[], containingFile: string) => (ts.ResolvedTypeReferenceDirective | undefined)[]) | undefined; + public resolveModuleNames: ((moduleName: string[], containingFile: string) => (ResolvedModuleFull | undefined)[]) | undefined; + public resolveTypeReferenceDirectives: ((typeDirectiveNames: string[] | readonly FileReference[], containingFile: string) => (ResolvedTypeReferenceDirective | undefined)[]) | undefined; public directoryExists: ((directoryName: string) => boolean) | undefined; constructor(private shimHost: LanguageServiceShimHost) { @@ -370,10 +383,10 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { // 'in' does not have this effect. if ("getModuleResolutionsForFile" in this.shimHost) { this.resolveModuleNames = (moduleNames, containingFile) => { - const resolutionsInFile = JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)) as ts.MapLike; // TODO: GH#18217 - return ts.map(moduleNames, name => { - const result = ts.getProperty(resolutionsInFile, name); - return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined; + const resolutionsInFile = JSON.parse(this.shimHost.getModuleResolutionsForFile!(containingFile)) as MapLike; // TODO: GH#18217 + return map(moduleNames, name => { + const result = getProperty(resolutionsInFile, name); + return result ? { resolvedFileName: result, extension: extensionFromPath(result), isExternalLibraryImport: false } : undefined; }); }; } @@ -382,8 +395,8 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { } if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) { this.resolveTypeReferenceDirectives = (typeDirectiveNames, containingFile) => { - const typeDirectivesForFile = JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile)) as ts.MapLike; // TODO: GH#18217 - return ts.map(typeDirectiveNames as (string | ts.FileReference)[], name => ts.getProperty(typeDirectivesForFile, ts.isString(name) ? name : name.fileName.toLowerCase())); + const typeDirectivesForFile = JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile!(containingFile)) as MapLike; // TODO: GH#18217 + return map(typeDirectiveNames as (string | FileReference)[], name => getProperty(typeDirectivesForFile, isString(name) ? name : name.fileName.toLowerCase())); }; } } @@ -424,13 +437,13 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false; } - public getCompilationSettings(): ts.CompilerOptions { + public getCompilationSettings(): CompilerOptions { const settingsJson = this.shimHost.getCompilationSettings(); // eslint-disable-next-line no-null/no-null if (settingsJson === null || settingsJson === "") { throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings"); } - const compilerOptions = JSON.parse(settingsJson) as ts.CompilerOptions; + const compilerOptions = JSON.parse(settingsJson) as CompilerOptions; // permit language service to handle all files (filtering should be performed on the host side) compilerOptions.allowNonTsExtensions = true; return compilerOptions; @@ -441,17 +454,17 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { return JSON.parse(encoded); } - public getScriptSnapshot(fileName: string): ts.IScriptSnapshot | undefined { + public getScriptSnapshot(fileName: string): IScriptSnapshot | undefined { const scriptSnapshot = this.shimHost.getScriptSnapshot(fileName); return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot); } - public getScriptKind(fileName: string): ts.ScriptKind { + public getScriptKind(fileName: string): ScriptKind { if ("getScriptKind" in this.shimHost) { return this.shimHost.getScriptKind!(fileName); // TODO: GH#18217 } else { - return ts.ScriptKind.Unknown; + return ScriptKind.Unknown; } } @@ -476,9 +489,9 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { /* eslint-enable no-null/no-null */ } - public getCancellationToken(): ts.HostCancellationToken { + public getCancellationToken(): HostCancellationToken { const hostCancellationToken = this.shimHost.getCancellationToken(); - return new ts.ThrottledCancellationToken(hostCancellationToken); + return new ThrottledCancellationToken(hostCancellationToken); } public getCurrentDirectory(): string { @@ -489,12 +502,12 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { return JSON.parse(this.shimHost.getDirectories(path)); } - public getDefaultLibFileName(options: ts.CompilerOptions): string { + public getDefaultLibFileName(options: CompilerOptions): string { return this.shimHost.getDefaultLibFileName(JSON.stringify(options)); } public readDirectory(path: string, extensions?: readonly string[], exclude?: string[], include?: string[], depth?: number): string[] { - const pattern = ts.getFileMatcherPatterns(path, exclude, include, + const pattern = getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( path, @@ -517,7 +530,7 @@ export class LanguageServiceShimHostAdapter implements ts.LanguageServiceHost { } /** @internal */ -export class CoreServicesShimHostAdapter implements ts.ParseConfigHost, ts.ModuleResolutionHost, ts.JsTyping.TypingResolutionHost { +export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost, JsTyping.TypingResolutionHost { public directoryExists: (directoryName: string) => boolean; public realpath: (path: string) => string; @@ -540,7 +553,7 @@ export class CoreServicesShimHostAdapter implements ts.ParseConfigHost, ts.Modul } public readDirectory(rootDir: string, extensions: readonly string[], exclude: readonly string[], include: readonly string[], depth?: number): string[] { - const pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, + const pattern = getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames!(), this.shimHost.getCurrentDirectory()); // TODO: GH#18217 return JSON.parse(this.shimHost.readDirectory( rootDir, @@ -570,15 +583,15 @@ function simpleForwardCall(logger: Logger, actionDescription: string, action: () let start: number | undefined; if (logPerformance) { logger.log(actionDescription); - start = ts.timestamp(); + start = timestamp(); } const result = action(); if (logPerformance) { - const end = ts.timestamp(); + const end = timestamp(); logger.log(`${actionDescription} completed in ${end - start!} msec`); - if (ts.isString(result)) { + if (isString(result)) { let str = result; if (str.length > 128) { str = str.substring(0, 128) + "..."; @@ -600,7 +613,7 @@ function forwardCall(logger: Logger, actionDescription: string, returnJson: b return returnJson ? JSON.stringify({ result }) : result as T; } catch (err) { - if (err instanceof ts.OperationCanceledException) { + if (err instanceof OperationCanceledException) { return JSON.stringify({ canceled: true }); } logInternalError(logger, err); @@ -630,16 +643,16 @@ export interface RealizedDiagnostic { reportsDeprecated?: {}; } /** @internal */ -export function realizeDiagnostics(diagnostics: readonly ts.Diagnostic[], newLine: string): RealizedDiagnostic[] { +export function realizeDiagnostics(diagnostics: readonly Diagnostic[], newLine: string): RealizedDiagnostic[] { return diagnostics.map(d => realizeDiagnostic(d, newLine)); } -function realizeDiagnostic(diagnostic: ts.Diagnostic, newLine: string): RealizedDiagnostic { +function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): RealizedDiagnostic { return { - message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine), + message: flattenDiagnosticMessageText(diagnostic.messageText, newLine), start: diagnostic.start!, // TODO: GH#18217 length: diagnostic.length!, // TODO: GH#18217 - category: ts.diagnosticCategoryName(diagnostic), + category: diagnosticCategoryName(diagnostic), code: diagnostic.code, reportsUnnecessary: diagnostic.reportsUnnecessary, reportsDeprecated: diagnostic.reportsDeprecated @@ -652,7 +665,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim constructor(factory: ShimFactory, private host: LanguageServiceShimHost, - public languageService: ts.LanguageService) { + public languageService: LanguageService) { super(factory); this.logger = this.host; } @@ -704,22 +717,22 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim }); } - private realizeDiagnostics(diagnostics: readonly ts.Diagnostic[]): { message: string; start: number; length: number; category: string; }[] { - const newLine = ts.getNewLineOrDefaultFromHost(this.host); + private realizeDiagnostics(diagnostics: readonly Diagnostic[]): { message: string; start: number; length: number; category: string; }[] { + const newLine = getNewLineOrDefaultFromHost(this.host); return realizeDiagnostics(diagnostics, newLine); } public getSyntacticClassifications(fileName: string, start: number, length: number): string { return this.forwardJSONCall( `getSyntacticClassifications('${fileName}', ${start}, ${length})`, - () => this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length)) + () => this.languageService.getSyntacticClassifications(fileName, createTextSpan(start, length)) ); } public getSemanticClassifications(fileName: string, start: number, length: number): string { return this.forwardJSONCall( `getSemanticClassifications('${fileName}', ${start}, ${length})`, - () => this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length)) + () => this.languageService.getSemanticClassifications(fileName, createTextSpan(start, length)) ); } @@ -728,7 +741,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim `getEncodedSyntacticClassifications('${fileName}', ${start}, ${length})`, // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. - () => convertClassifications(this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))) + () => convertClassifications(this.languageService.getEncodedSyntacticClassifications(fileName, createTextSpan(start, length))) ); } @@ -737,7 +750,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim `getEncodedSemanticClassifications('${fileName}', ${start}, ${length})`, // directly serialize the spans out to a string. This is much faster to decode // on the managed side versus a full JSON array. - () => convertClassifications(this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))) + () => convertClassifications(this.languageService.getEncodedSemanticClassifications(fileName, createTextSpan(start, length))) ); } @@ -812,7 +825,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim /// SIGNATUREHELP - public getSignatureHelpItems(fileName: string, position: number, options: ts.SignatureHelpItemsOptions | undefined): string { + public getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): string { return this.forwardJSONCall( `getSignatureHelpItems('${fileName}', ${position})`, () => this.languageService.getSignatureHelpItems(fileName, position, options) @@ -869,7 +882,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public getRenameInfo(fileName: string, position: number, preferences: ts.UserPreferences): string { + public getRenameInfo(fileName: string, position: number, preferences: UserPreferences): string { return this.forwardJSONCall( `getRenameInfo('${fileName}', ${position})`, () => this.languageService.getRenameInfo(fileName, position, preferences) @@ -917,7 +930,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim return this.forwardJSONCall( `getIndentationAtPosition('${fileName}', ${position})`, () => { - const localOptions: ts.EditorOptions = JSON.parse(options); + const localOptions: EditorOptions = JSON.parse(options); return this.languageService.getIndentationAtPosition(fileName, position, localOptions); }); } @@ -958,8 +971,8 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim () => { const results = this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch)); // workaround for VS document highlighting issue - keep only items from the initial file - const normalizedName = ts.toFileNameLowerCase(ts.normalizeSlashes(fileName)); - return ts.filter(results, r => ts.toFileNameLowerCase(ts.normalizeSlashes(r.fileName)) === normalizedName); + const normalizedName = toFileNameLowerCase(normalizeSlashes(fileName)); + return filter(results, r => toFileNameLowerCase(normalizeSlashes(r.fileName)) === normalizedName); }); } @@ -970,7 +983,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim * to provide at the given source position and providing a member completion * list if requested. */ - public getCompletionsAtPosition(fileName: string, position: number, preferences: ts.GetCompletionsAtPositionOptions | undefined, formattingSettings: ts.FormatCodeSettings | undefined) { + public getCompletionsAtPosition(fileName: string, position: number, preferences: GetCompletionsAtPositionOptions | undefined, formattingSettings: FormatCodeSettings | undefined) { return this.forwardJSONCall( `getCompletionsAtPosition('${fileName}', ${position}, ${preferences}, ${formattingSettings})`, () => this.languageService.getCompletionsAtPosition(fileName, position, preferences, formattingSettings) @@ -978,11 +991,11 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim } /** Get a string based representation of a completion list entry details */ - public getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: ts.UserPreferences | undefined, data: ts.CompletionEntryData | undefined) { + public getCompletionEntryDetails(fileName: string, position: number, entryName: string, formatOptions: string/*Services.FormatCodeOptions*/ | undefined, source: string | undefined, preferences: UserPreferences | undefined, data: CompletionEntryData | undefined) { return this.forwardJSONCall( `getCompletionEntryDetails('${fileName}', ${position}, '${entryName}')`, () => { - const localOptions: ts.FormatCodeOptions = formatOptions === undefined ? undefined : JSON.parse(formatOptions); + const localOptions: FormatCodeOptions = formatOptions === undefined ? undefined : JSON.parse(formatOptions); return this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source, preferences, data); } ); @@ -992,7 +1005,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim return this.forwardJSONCall( `getFormattingEditsForRange('${fileName}', ${start}, ${end})`, () => { - const localOptions: ts.FormatCodeOptions = JSON.parse(options); + const localOptions: FormatCodeOptions = JSON.parse(options); return this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions); }); } @@ -1001,7 +1014,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim return this.forwardJSONCall( `getFormattingEditsForDocument('${fileName}')`, () => { - const localOptions: ts.FormatCodeOptions = JSON.parse(options); + const localOptions: FormatCodeOptions = JSON.parse(options); return this.languageService.getFormattingEditsForDocument(fileName, localOptions); }); } @@ -1010,12 +1023,12 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim return this.forwardJSONCall( `getFormattingEditsAfterKeystroke('${fileName}', ${position}, '${key}')`, () => { - const localOptions: ts.FormatCodeOptions = JSON.parse(options); + const localOptions: FormatCodeOptions = JSON.parse(options); return this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions); }); } - public getDocCommentTemplateAtPosition(fileName: string, position: number, options?: ts.DocCommentTemplateOptions): string { + public getDocCommentTemplateAtPosition(fileName: string, position: number, options?: DocCommentTemplateOptions): string { return this.forwardJSONCall( `getDocCommentTemplateAtPosition('${fileName}', ${position})`, () => this.languageService.getDocCommentTemplateAtPosition(fileName, position, options) @@ -1083,7 +1096,7 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public provideInlayHints(fileName: string, span: ts.TextSpan, preference: ts.UserPreferences | undefined): string { + public provideInlayHints(fileName: string, span: TextSpan, preference: UserPreferences | undefined): string { return this.forwardJSONCall( `provideInlayHints('${fileName}', '${JSON.stringify(span)}', ${JSON.stringify(preference)})`, () => this.languageService.provideInlayHints(fileName, span, preference) @@ -1101,37 +1114,37 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim ); } - public getEmitOutputObject(fileName: string): ts.EmitOutput { + public getEmitOutputObject(fileName: string): EmitOutput { return forwardCall( this.logger, `getEmitOutput('${fileName}')`, /*returnJson*/ false, () => this.languageService.getEmitOutput(fileName), - this.logPerformance) as ts.EmitOutput; + this.logPerformance) as EmitOutput; } - public toggleLineComment(fileName: string, textRange: ts.TextRange): string { + public toggleLineComment(fileName: string, textRange: TextRange): string { return this.forwardJSONCall( `toggleLineComment('${fileName}', '${JSON.stringify(textRange)}')`, () => this.languageService.toggleLineComment(fileName, textRange) ); } - public toggleMultilineComment(fileName: string, textRange: ts.TextRange): string { + public toggleMultilineComment(fileName: string, textRange: TextRange): string { return this.forwardJSONCall( `toggleMultilineComment('${fileName}', '${JSON.stringify(textRange)}')`, () => this.languageService.toggleMultilineComment(fileName, textRange) ); } - public commentSelection(fileName: string, textRange: ts.TextRange): string { + public commentSelection(fileName: string, textRange: TextRange): string { return this.forwardJSONCall( `commentSelection('${fileName}', '${JSON.stringify(textRange)}')`, () => this.languageService.commentSelection(fileName, textRange) ); } - public uncommentSelection(fileName: string, textRange: ts.TextRange): string { + public uncommentSelection(fileName: string, textRange: TextRange): string { return this.forwardJSONCall( `uncommentSelection('${fileName}', '${JSON.stringify(textRange)}')`, () => this.languageService.uncommentSelection(fileName, textRange) @@ -1139,27 +1152,27 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim } } -function convertClassifications(classifications: ts.Classifications): { spans: string, endOfLineState: ts.EndOfLineState } { +function convertClassifications(classifications: Classifications): { spans: string, endOfLineState: EndOfLineState } { return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState }; } class ClassifierShimObject extends ShimBase implements ClassifierShim { - public classifier: ts.Classifier; + public classifier: Classifier; private logPerformance = false; constructor(factory: ShimFactory, private logger: Logger) { super(factory); - this.classifier = ts.createClassifier(); + this.classifier = createClassifier(); } - public getEncodedLexicalClassifications(text: string, lexState: ts.EndOfLineState, syntacticClassifierAbsent = false): string { + public getEncodedLexicalClassifications(text: string, lexState: EndOfLineState, syntacticClassifierAbsent = false): string { return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", () => convertClassifications(this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)), this.logPerformance); } /// COLORIZATION - public getClassificationsForLine(text: string, lexState: ts.EndOfLineState, classifyKeywordsInGenerics = false): string { + public getClassificationsForLine(text: string, lexState: EndOfLineState, classifyKeywordsInGenerics = false): string { const classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics); let result = ""; for (const item of classification.entries) { @@ -1173,7 +1186,7 @@ class ClassifierShimObject extends ShimBase implements ClassifierShim { class CoreServicesShimObject extends ShimBase implements CoreServicesShim { private logPerformance = false; - private safeList: ts.JsTyping.SafeList | undefined; + private safeList: JsTyping.SafeList | undefined; constructor(factory: ShimFactory, public readonly logger: Logger, private readonly host: CoreServicesShimHostAdapter) { super(factory); @@ -1185,10 +1198,10 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { public resolveModuleName(fileName: string, moduleName: string, compilerOptionsJson: string): string { return this.forwardJSONCall(`resolveModuleName('${fileName}')`, () => { - const compilerOptions = JSON.parse(compilerOptionsJson) as ts.CompilerOptions; - const result = ts.resolveModuleName(moduleName, ts.normalizeSlashes(fileName), compilerOptions, this.host); + const compilerOptions = JSON.parse(compilerOptionsJson) as CompilerOptions; + const result = resolveModuleName(moduleName, normalizeSlashes(fileName), compilerOptions, this.host); let resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined; - if (result.resolvedModule && result.resolvedModule.extension !== ts.Extension.Ts && result.resolvedModule.extension !== ts.Extension.Tsx && result.resolvedModule.extension !== ts.Extension.Dts) { + if (result.resolvedModule && result.resolvedModule.extension !== Extension.Ts && result.resolvedModule.extension !== Extension.Tsx && result.resolvedModule.extension !== Extension.Dts) { resolvedFileName = undefined; } @@ -1202,8 +1215,8 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { public resolveTypeReferenceDirective(fileName: string, typeReferenceDirective: string, compilerOptionsJson: string): string { return this.forwardJSONCall(`resolveTypeReferenceDirective(${fileName})`, () => { - const compilerOptions = JSON.parse(compilerOptionsJson) as ts.CompilerOptions; - const result = ts.resolveTypeReferenceDirective(typeReferenceDirective, ts.normalizeSlashes(fileName), compilerOptions, this.host); + const compilerOptions = JSON.parse(compilerOptionsJson) as CompilerOptions; + const result = resolveTypeReferenceDirective(typeReferenceDirective, normalizeSlashes(fileName), compilerOptions, this.host); return { resolvedFileName: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.resolvedFileName : undefined, primary: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.primary : true, @@ -1212,12 +1225,12 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { }); } - public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: ts.IScriptSnapshot): string { + public getPreProcessedFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string { return this.forwardJSONCall( `getPreProcessedFileInfo('${fileName}')`, () => { // for now treat files as JavaScript - const result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true); + const result = preProcessFile(getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true); return { referencedFiles: this.convertFileReferences(result.referencedFiles), importedFiles: this.convertFileReferences(result.importedFiles), @@ -1233,20 +1246,20 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { return this.forwardJSONCall( `getAutomaticTypeDirectiveNames('${compilerOptionsJson}')`, () => { - const compilerOptions = JSON.parse(compilerOptionsJson) as ts.CompilerOptions; - return ts.getAutomaticTypeDirectiveNames(compilerOptions, this.host); + const compilerOptions = JSON.parse(compilerOptionsJson) as CompilerOptions; + return getAutomaticTypeDirectiveNames(compilerOptions, this.host); } ); } - private convertFileReferences(refs: ts.FileReference[]): ShimsFileReference[] | undefined { + private convertFileReferences(refs: FileReference[]): ShimsFileReference[] | undefined { if (!refs) { return undefined; } const result: ShimsFileReference[] = []; for (const ref of refs) { result.push({ - path: ts.normalizeSlashes(ref.fileName), + path: normalizeSlashes(ref.fileName), position: ref.pos, length: ref.end - ref.pos }); @@ -1254,13 +1267,13 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { return result; } - public getTSConfigFileInfo(fileName: string, sourceTextSnapshot: ts.IScriptSnapshot): string { + public getTSConfigFileInfo(fileName: string, sourceTextSnapshot: IScriptSnapshot): string { return this.forwardJSONCall( `getTSConfigFileInfo('${fileName}')`, () => { - const result = ts.parseJsonText(fileName, ts.getSnapshotText(sourceTextSnapshot)); - const normalizedFileName = ts.normalizeSlashes(fileName); - const configFile = ts.parseJsonSourceFileConfigFileContent(result, this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); + const result = parseJsonText(fileName, getSnapshotText(sourceTextSnapshot)); + const normalizedFileName = normalizeSlashes(fileName); + const configFile = parseJsonSourceFileConfigFileContent(result, this.host, getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName); return { options: configFile.options, @@ -1275,28 +1288,28 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { public getDefaultCompilationSettings(): string { return this.forwardJSONCall( "getDefaultCompilationSettings()", - () => ts.getDefaultCompilerOptions() + () => getDefaultCompilerOptions() ); } public discoverTypings(discoverTypingsJson: string): string { - const getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); + const getCanonicalFileName = createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false); return this.forwardJSONCall("discoverTypings()", () => { const info = JSON.parse(discoverTypingsJson) as DiscoverTypingsInfo; if (this.safeList === undefined) { - this.safeList = ts.JsTyping.loadSafeList(this.host, ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName)); + this.safeList = JsTyping.loadSafeList(this.host, toPath(info.safeListPath, info.safeListPath, getCanonicalFileName)); } - return ts.JsTyping.discoverTypings( + return JsTyping.discoverTypings( this.host, msg => this.logger.log(msg), info.fileNames, - ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), + toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), this.safeList, info.packageNameToTypingLocation, info.typeAcquisition, info.unresolvedImports, info.typesRegistry, - ts.emptyOptions); + emptyOptions); }); } } @@ -1304,22 +1317,22 @@ class CoreServicesShimObject extends ShimBase implements CoreServicesShim { /** @internal */ export class TypeScriptServicesFactory implements ShimFactory { private _shims: Shim[] = []; - private documentRegistry: ts.DocumentRegistry | undefined; + private documentRegistry: DocumentRegistry | undefined; /* * Returns script API version. */ public getServicesVersion(): string { - return ts.servicesVersion; + return servicesVersion; } public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { try { if (this.documentRegistry === undefined) { - this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); + this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); } const hostAdapter = new LanguageServiceShimHostAdapter(host); - const languageService = ts.createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnly*/ false); + const languageService = createLanguageService(hostAdapter, this.documentRegistry, /*syntaxOnly*/ false); return new LanguageServiceShimObject(this, host, languageService); } catch (err) { @@ -1351,7 +1364,7 @@ export class TypeScriptServicesFactory implements ShimFactory { public close(): void { // Forget all the registered shims - ts.clear(this._shims); + clear(this._shims); this.documentRegistry = undefined; } diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 70d33a34a5478..cf672d0699634 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -1,31 +1,45 @@ -import * as ts from "./_namespaces/ts"; +import { + ArrowFunction, BinaryExpression, CallLikeExpression, CancellationToken, CheckFlags, contains, countWhere, + createPrinter, createTextSpan, createTextSpanFromBounds, createTextSpanFromNode, Debug, EmitHint, emptyArray, + Expression, factory, findContainingList, findIndex, findPrecedingToken, findTokenOnLeftOfPosition, first, + firstDefined, flatMapToMutable, FunctionExpression, getInvokedExpression, getPossibleGenericSignatures, + getPossibleTypeArgumentsInfo, Identifier, identity, InternalSymbolName, isBinaryExpression, isBlock, + isCallOrNewExpression, isFunctionTypeNode, isIdentifier, isInComment, isInsideTemplateLiteral, isInString, + isJsxOpeningLikeElement, isMethodDeclaration, isNoSubstitutionTemplateLiteral, isPropertyAccessExpression, + isSourceFile, isSourceFileJS, isTaggedTemplateExpression, isTemplateHead, isTemplateLiteralToken, isTemplateSpan, + isTemplateTail, last, lastOrUndefined, ListFormat, map, mapToDisplayParts, Node, NodeBuilderFlags, + ParameterDeclaration, ParenthesizedExpression, Printer, Program, punctuationPart, rangeContainsRange, Signature, + SignatureHelpItem, SignatureHelpItems, SignatureHelpParameter, SignatureHelpTriggerReason, skipTrivia, SourceFile, + spacePart, Symbol, SymbolDisplayPart, symbolToDisplayParts, SyntaxKind, TaggedTemplateExpression, + TemplateExpression, TextSpan, TransientSymbol, Type, TypeChecker, TypeParameter, +} from "./_namespaces/ts"; const enum InvocationKind { Call, TypeArgs, Contextual } -interface CallInvocation { readonly kind: InvocationKind.Call; readonly node: ts.CallLikeExpression; } -interface TypeArgsInvocation { readonly kind: InvocationKind.TypeArgs; readonly called: ts.Identifier; } +interface CallInvocation { readonly kind: InvocationKind.Call; readonly node: CallLikeExpression; } +interface TypeArgsInvocation { readonly kind: InvocationKind.TypeArgs; readonly called: Identifier; } interface ContextualInvocation { readonly kind: InvocationKind.Contextual; - readonly signature: ts.Signature; - readonly node: ts.Node; // Just for enclosingDeclaration for printing types - readonly symbol: ts.Symbol; + readonly signature: Signature; + readonly node: Node; // Just for enclosingDeclaration for printing types + readonly symbol: Symbol; } type Invocation = CallInvocation | TypeArgsInvocation | ContextualInvocation; interface ArgumentListInfo { readonly isTypeParameterList: boolean; readonly invocation: Invocation; - readonly argumentsSpan: ts.TextSpan; + readonly argumentsSpan: TextSpan; readonly argumentIndex: number; /** argumentCount is the *apparent* number of arguments. */ readonly argumentCount: number; } /** @internal */ -export function getSignatureHelpItems(program: ts.Program, sourceFile: ts.SourceFile, position: number, triggerReason: ts.SignatureHelpTriggerReason | undefined, cancellationToken: ts.CancellationToken): ts.SignatureHelpItems | undefined { +export function getSignatureHelpItems(program: Program, sourceFile: SourceFile, position: number, triggerReason: SignatureHelpTriggerReason | undefined, cancellationToken: CancellationToken): SignatureHelpItems | undefined { const typeChecker = program.getTypeChecker(); // Decide whether to show signature help - const startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position); + const startingToken = findTokenOnLeftOfPosition(sourceFile, position); if (!startingToken) { // We are at the beginning of the file return undefined; @@ -35,7 +49,7 @@ export function getSignatureHelpItems(program: ts.Program, sourceFile: ts.Source const onlyUseSyntacticOwners = !!triggerReason && triggerReason.kind === "characterTyped"; // Bail out quickly in the middle of a string or comment, don't provide signature help unless the user explicitly requested it. - if (onlyUseSyntacticOwners && (ts.isInString(sourceFile, position, startingToken) || ts.isInComment(sourceFile, position))) { + if (onlyUseSyntacticOwners && (isInString(sourceFile, position, startingToken) || isInComment(sourceFile, position))) { return undefined; } @@ -52,7 +66,7 @@ export function getSignatureHelpItems(program: ts.Program, sourceFile: ts.Source if (!candidateInfo) { // We didn't have any sig help items produced by the TS compiler. If this is a JS // file, then see if we can figure out anything better. - return ts.isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; + return isSourceFileJS(sourceFile) ? createJSSignatureHelpItems(argumentInfo, program, cancellationToken) : undefined; } return typeChecker.runWithCancellationToken(cancellationToken, typeChecker => @@ -64,31 +78,31 @@ export function getSignatureHelpItems(program: ts.Program, sourceFile: ts.Source const enum CandidateOrTypeKind { Candidate, Type } interface CandidateInfo { readonly kind: CandidateOrTypeKind.Candidate; - readonly candidates: readonly ts.Signature[]; - readonly resolvedSignature: ts.Signature; + readonly candidates: readonly Signature[]; + readonly resolvedSignature: Signature; } interface TypeInfo { readonly kind: CandidateOrTypeKind.Type; - readonly symbol: ts.Symbol; + readonly symbol: Symbol; } -function getCandidateOrTypeInfo({ invocation, argumentCount }: ArgumentListInfo, checker: ts.TypeChecker, sourceFile: ts.SourceFile, startingToken: ts.Node, onlyUseSyntacticOwners: boolean): CandidateInfo | TypeInfo | undefined { +function getCandidateOrTypeInfo({ invocation, argumentCount }: ArgumentListInfo, checker: TypeChecker, sourceFile: SourceFile, startingToken: Node, onlyUseSyntacticOwners: boolean): CandidateInfo | TypeInfo | undefined { switch (invocation.kind) { case InvocationKind.Call: { if (onlyUseSyntacticOwners && !isSyntacticOwner(startingToken, invocation.node, sourceFile)) { return undefined; } - const candidates: ts.Signature[] = []; + const candidates: Signature[] = []; const resolvedSignature = checker.getResolvedSignatureForSignatureHelp(invocation.node, candidates, argumentCount)!; // TODO: GH#18217 return candidates.length === 0 ? undefined : { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature }; } case InvocationKind.TypeArgs: { const { called } = invocation; - if (onlyUseSyntacticOwners && !containsPrecedingToken(startingToken, sourceFile, ts.isIdentifier(called) ? called.parent : called)) { + if (onlyUseSyntacticOwners && !containsPrecedingToken(startingToken, sourceFile, isIdentifier(called) ? called.parent : called)) { return undefined; } - const candidates = ts.getPossibleGenericSignatures(called, argumentCount, checker); - if (candidates.length !== 0) return { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature: ts.first(candidates) }; + const candidates = getPossibleGenericSignatures(called, argumentCount, checker); + if (candidates.length !== 0) return { kind: CandidateOrTypeKind.Candidate, candidates, resolvedSignature: first(candidates) }; const symbol = checker.getSymbolAtLocation(called); return symbol && { kind: CandidateOrTypeKind.Type, symbol }; @@ -96,35 +110,35 @@ function getCandidateOrTypeInfo({ invocation, argumentCount }: ArgumentListInfo, case InvocationKind.Contextual: return { kind: CandidateOrTypeKind.Candidate, candidates: [invocation.signature], resolvedSignature: invocation.signature }; default: - return ts.Debug.assertNever(invocation); + return Debug.assertNever(invocation); } } -function isSyntacticOwner(startingToken: ts.Node, node: ts.CallLikeExpression, sourceFile: ts.SourceFile): boolean { - if (!ts.isCallOrNewExpression(node)) return false; +function isSyntacticOwner(startingToken: Node, node: CallLikeExpression, sourceFile: SourceFile): boolean { + if (!isCallOrNewExpression(node)) return false; const invocationChildren = node.getChildren(sourceFile); switch (startingToken.kind) { - case ts.SyntaxKind.OpenParenToken: - return ts.contains(invocationChildren, startingToken); - case ts.SyntaxKind.CommaToken: { - const containingList = ts.findContainingList(startingToken); - return !!containingList && ts.contains(invocationChildren, containingList); + case SyntaxKind.OpenParenToken: + return contains(invocationChildren, startingToken); + case SyntaxKind.CommaToken: { + const containingList = findContainingList(startingToken); + return !!containingList && contains(invocationChildren, containingList); } - case ts.SyntaxKind.LessThanToken: + case SyntaxKind.LessThanToken: return containsPrecedingToken(startingToken, sourceFile, node.expression); default: return false; } } -function createJSSignatureHelpItems(argumentInfo: ArgumentListInfo, program: ts.Program, cancellationToken: ts.CancellationToken): ts.SignatureHelpItems | undefined { +function createJSSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined { if (argumentInfo.invocation.kind === InvocationKind.Contextual) return undefined; // See if we can find some symbol with the call expression name that has call signatures. const expression = getExpressionFromInvocation(argumentInfo.invocation); - const name = ts.isPropertyAccessExpression(expression) ? expression.name.text : undefined; + const name = isPropertyAccessExpression(expression) ? expression.name.text : undefined; const typeChecker = program.getTypeChecker(); - return name === undefined ? undefined : ts.firstDefined(program.getSourceFiles(), sourceFile => - ts.firstDefined(sourceFile.getNamedDeclarations().get(name), declaration => { + return name === undefined ? undefined : firstDefined(program.getSourceFiles(), sourceFile => + firstDefined(sourceFile.getNamedDeclarations().get(name), declaration => { const type = declaration.symbol && typeChecker.getTypeOfSymbolAtLocation(declaration.symbol, declaration); const callSignatures = type && type.getCallSignatures(); if (callSignatures && callSignatures.length) { @@ -141,51 +155,51 @@ function createJSSignatureHelpItems(argumentInfo: ArgumentListInfo, program: ts. })); } -function containsPrecedingToken(startingToken: ts.Node, sourceFile: ts.SourceFile, container: ts.Node) { +function containsPrecedingToken(startingToken: Node, sourceFile: SourceFile, container: Node) { const pos = startingToken.getFullStart(); // There’s a possibility that `startingToken.parent` contains only `startingToken` and // missing nodes, none of which are valid to be returned by `findPrecedingToken`. In that // case, the preceding token we want is actually higher up the tree—almost definitely the // next parent, but theoretically the situation with missing nodes might be happening on // multiple nested levels. - let currentParent: ts.Node | undefined = startingToken.parent; + let currentParent: Node | undefined = startingToken.parent; while (currentParent) { - const precedingToken = ts.findPrecedingToken(pos, sourceFile, currentParent, /*excludeJsdoc*/ true); + const precedingToken = findPrecedingToken(pos, sourceFile, currentParent, /*excludeJsdoc*/ true); if (precedingToken) { - return ts.rangeContainsRange(container, precedingToken); + return rangeContainsRange(container, precedingToken); } currentParent = currentParent.parent; } - return ts.Debug.fail("Could not find preceding token"); + return Debug.fail("Could not find preceding token"); } /** @internal */ export interface ArgumentInfoForCompletions { - readonly invocation: ts.CallLikeExpression; + readonly invocation: CallLikeExpression; readonly argumentIndex: number; readonly argumentCount: number; } /** @internal */ -export function getArgumentInfoForCompletions(node: ts.Node, position: number, sourceFile: ts.SourceFile): ArgumentInfoForCompletions | undefined { +export function getArgumentInfoForCompletions(node: Node, position: number, sourceFile: SourceFile): ArgumentInfoForCompletions | undefined { const info = getImmediatelyContainingArgumentInfo(node, position, sourceFile); return !info || info.isTypeParameterList || info.invocation.kind !== InvocationKind.Call ? undefined : { invocation: info.invocation.node, argumentCount: info.argumentCount, argumentIndex: info.argumentIndex }; } -function getArgumentOrParameterListInfo(node: ts.Node, position: number, sourceFile: ts.SourceFile): { readonly list: ts.Node, readonly argumentIndex: number, readonly argumentCount: number, readonly argumentsSpan: ts.TextSpan } | undefined { +function getArgumentOrParameterListInfo(node: Node, position: number, sourceFile: SourceFile): { readonly list: Node, readonly argumentIndex: number, readonly argumentCount: number, readonly argumentsSpan: TextSpan } | undefined { const info = getArgumentOrParameterListAndIndex(node, sourceFile); if (!info) return undefined; const { list, argumentIndex } = info; - const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ ts.isInString(sourceFile, position, node)); + const argumentCount = getArgumentCount(list, /*ignoreTrailingComma*/ isInString(sourceFile, position, node)); if (argumentIndex !== 0) { - ts.Debug.assertLessThan(argumentIndex, argumentCount); + Debug.assertLessThan(argumentIndex, argumentCount); } const argumentsSpan = getApplicableSpanForArguments(list, sourceFile); return { list, argumentIndex, argumentCount, argumentsSpan }; } -function getArgumentOrParameterListAndIndex(node: ts.Node, sourceFile: ts.SourceFile): { readonly list: ts.Node, readonly argumentIndex: number } | undefined { - if (node.kind === ts.SyntaxKind.LessThanToken || node.kind === ts.SyntaxKind.OpenParenToken) { +function getArgumentOrParameterListAndIndex(node: Node, sourceFile: SourceFile): { readonly list: Node, readonly argumentIndex: number } | undefined { + if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) { // Find the list that starts right *after* the < or ( token. // If the user has just opened a list, consider this item 0. return { list: getChildListThatStartsWithOpenerToken(node.parent, node, sourceFile), argumentIndex: 0 }; @@ -197,7 +211,7 @@ function getArgumentOrParameterListAndIndex(node: ts.Node, sourceFile: ts.Source // - Between the type arguments and the arguments (greater than token) // - On the target of the call (parent.func) // - On the 'new' keyword in a 'new' expression - const list = ts.findContainingList(node); + const list = findContainingList(node); return list && { list, argumentIndex: getArgumentIndex(list, node) }; } } @@ -206,9 +220,9 @@ function getArgumentOrParameterListAndIndex(node: ts.Node, sourceFile: ts.Source * Returns relevant information for the argument list and the current argument if we are * in the argument of an invocation; returns undefined otherwise. */ -function getImmediatelyContainingArgumentInfo(node: ts.Node, position: number, sourceFile: ts.SourceFile): ArgumentListInfo | undefined { +function getImmediatelyContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile): ArgumentListInfo | undefined { const { parent } = node; - if (ts.isCallOrNewExpression(parent)) { + if (isCallOrNewExpression(parent)) { const invocation = parent; // There are 3 cases to handle: @@ -231,29 +245,29 @@ function getImmediatelyContainingArgumentInfo(node: ts.Node, position: number, s const isTypeParameterList = !!parent.typeArguments && parent.typeArguments.pos === list.pos; return { isTypeParameterList, invocation: { kind: InvocationKind.Call, node: invocation }, argumentsSpan, argumentIndex, argumentCount }; } - else if (ts.isNoSubstitutionTemplateLiteral(node) && ts.isTaggedTemplateExpression(parent)) { + else if (isNoSubstitutionTemplateLiteral(node) && isTaggedTemplateExpression(parent)) { // Check if we're actually inside the template; // otherwise we'll fall out and return undefined. - if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { + if (isInsideTemplateLiteral(node, position, sourceFile)) { return getArgumentListInfoForTemplate(parent, /*argumentIndex*/ 0, sourceFile); } return undefined; } - else if (ts.isTemplateHead(node) && parent.parent.kind === ts.SyntaxKind.TaggedTemplateExpression) { - const templateExpression = parent as ts.TemplateExpression; - const tagExpression = templateExpression.parent as ts.TaggedTemplateExpression; - ts.Debug.assert(templateExpression.kind === ts.SyntaxKind.TemplateExpression); + else if (isTemplateHead(node) && parent.parent.kind === SyntaxKind.TaggedTemplateExpression) { + const templateExpression = parent as TemplateExpression; + const tagExpression = templateExpression.parent as TaggedTemplateExpression; + Debug.assert(templateExpression.kind === SyntaxKind.TemplateExpression); - const argumentIndex = ts.isInsideTemplateLiteral(node, position, sourceFile) ? 0 : 1; + const argumentIndex = isInsideTemplateLiteral(node, position, sourceFile) ? 0 : 1; return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } - else if (ts.isTemplateSpan(parent) && ts.isTaggedTemplateExpression(parent.parent.parent)) { + else if (isTemplateSpan(parent) && isTaggedTemplateExpression(parent.parent.parent)) { const templateSpan = parent; const tagExpression = parent.parent.parent; // If we're just after a template tail, don't show signature help. - if (ts.isTemplateTail(node) && !ts.isInsideTemplateLiteral(node, position, sourceFile)) { + if (isTemplateTail(node) && !isInsideTemplateLiteral(node, position, sourceFile)) { return undefined; } @@ -262,47 +276,47 @@ function getImmediatelyContainingArgumentInfo(node: ts.Node, position: number, s return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile); } - else if (ts.isJsxOpeningLikeElement(parent)) { + else if (isJsxOpeningLikeElement(parent)) { // Provide a signature help for JSX opening element or JSX self-closing element. // This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems") // i.e // export function MainButton(props: ButtonProps, context: any): JSX.Element { ... } // ts.isFunctionTypeNode(d) ? d.parent.symbol : undefined) || s +function chooseBetterSymbol(s: Symbol): Symbol { + return s.name === InternalSymbolName.Type + ? firstDefined(s.declarations, d => isFunctionTypeNode(d) ? d.parent.symbol : undefined) || s : s; } -function getArgumentIndex(argumentsList: ts.Node, node: ts.Node) { +function getArgumentIndex(argumentsList: Node, node: Node) { // The list we got back can include commas. In the presence of errors it may // also just have nodes without commas. For example "Foo(a b c)" will have 3 // args without commas. We want to find what index we're at. So we count @@ -370,7 +384,7 @@ function getArgumentIndex(argumentsList: ts.Node, node: ts.Node) { if (child === node) { break; } - if (child.kind !== ts.SyntaxKind.CommaToken) { + if (child.kind !== SyntaxKind.CommaToken) { argumentIndex++; } } @@ -378,7 +392,7 @@ function getArgumentIndex(argumentsList: ts.Node, node: ts.Node) { return argumentIndex; } -function getArgumentCount(argumentsList: ts.Node, ignoreTrailingComma: boolean) { +function getArgumentCount(argumentsList: Node, ignoreTrailingComma: boolean) { // The argument count for a list is normally the number of non-comma children it has. // For example, if you have "Foo(a,b)" then there will be three children of the arg // list 'a' '' 'b'. So, in this case the arg count will be 2. However, there @@ -392,8 +406,8 @@ function getArgumentCount(argumentsList: ts.Node, ignoreTrailingComma: boolean) // arg count of 3. const listChildren = argumentsList.getChildren(); - let argumentCount = ts.countWhere(listChildren, arg => arg.kind !== ts.SyntaxKind.CommaToken); - if (!ignoreTrailingComma && listChildren.length > 0 && ts.last(listChildren).kind === ts.SyntaxKind.CommaToken) { + let argumentCount = countWhere(listChildren, arg => arg.kind !== SyntaxKind.CommaToken); + if (!ignoreTrailingComma && listChildren.length > 0 && last(listChildren).kind === SyntaxKind.CommaToken) { argumentCount++; } return argumentCount; @@ -401,7 +415,7 @@ function getArgumentCount(argumentsList: ts.Node, ignoreTrailingComma: boolean) // spanIndex is either the index for a given template span. // This does not give appropriate results for a NoSubstitutionTemplateLiteral -function getArgumentIndexForTemplatePiece(spanIndex: number, node: ts.Node, position: number, sourceFile: ts.SourceFile): number { +function getArgumentIndexForTemplatePiece(spanIndex: number, node: Node, position: number, sourceFile: SourceFile): number { // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1. // There are three cases we can encounter: // 1. We are precisely in the template literal (argIndex = 0). @@ -415,9 +429,9 @@ function getArgumentIndexForTemplatePiece(spanIndex: number, node: ts.Node, posi // ^ ^ ^ ^ ^ ^ ^ ^ ^ // Case: 1 1 3 2 1 3 2 2 1 /* eslint-enable local/no-double-space */ - ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); - if (ts.isTemplateLiteralToken(node)) { - if (ts.isInsideTemplateLiteral(node, position, sourceFile)) { + Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node."); + if (isTemplateLiteralToken(node)) { + if (isInsideTemplateLiteral(node, position, sourceFile)) { return 0; } return spanIndex + 2; @@ -425,11 +439,11 @@ function getArgumentIndexForTemplatePiece(spanIndex: number, node: ts.Node, posi return spanIndex + 1; } -function getArgumentListInfoForTemplate(tagExpression: ts.TaggedTemplateExpression, argumentIndex: number, sourceFile: ts.SourceFile): ArgumentListInfo { +function getArgumentListInfoForTemplate(tagExpression: TaggedTemplateExpression, argumentIndex: number, sourceFile: SourceFile): ArgumentListInfo { // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument. - const argumentCount = ts.isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1; + const argumentCount = isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1; if (argumentIndex !== 0) { - ts.Debug.assertLessThan(argumentIndex, argumentCount); + Debug.assertLessThan(argumentIndex, argumentCount); } return { isTypeParameterList: false, @@ -440,7 +454,7 @@ function getArgumentListInfoForTemplate(tagExpression: ts.TaggedTemplateExpressi }; } -function getApplicableSpanForArguments(argumentsList: ts.Node, sourceFile: ts.SourceFile): ts.TextSpan { +function getApplicableSpanForArguments(argumentsList: Node, sourceFile: SourceFile): TextSpan { // We use full start and skip trivia on the end because we want to include trivia on // both sides. For example, // @@ -450,11 +464,11 @@ function getApplicableSpanForArguments(argumentsList: ts.Node, sourceFile: ts.So // The applicable span is from the first bar to the second bar (inclusive, // but not including parentheses) const applicableSpanStart = argumentsList.getFullStart(); - const applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + const applicableSpanEnd = skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false); + return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } -function getApplicableSpanForTaggedTemplate(taggedTemplate: ts.TaggedTemplateExpression, sourceFile: ts.SourceFile): ts.TextSpan { +function getApplicableSpanForTaggedTemplate(taggedTemplate: TaggedTemplateExpression, sourceFile: SourceFile): TextSpan { const template = taggedTemplate.template; const applicableSpanStart = template.getStart(); let applicableSpanEnd = template.getEnd(); @@ -467,21 +481,21 @@ function getApplicableSpanForTaggedTemplate(taggedTemplate: ts.TaggedTemplateExp // | | // This is because a Missing node has no width. However, what we actually want is to include trivia // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail. - if (template.kind === ts.SyntaxKind.TemplateExpression) { - const lastSpan = ts.last(template.templateSpans); + if (template.kind === SyntaxKind.TemplateExpression) { + const lastSpan = last(template.templateSpans); if (lastSpan.literal.getFullWidth() === 0) { - applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); + applicableSpanEnd = skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false); } } - return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); + return createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart); } -function getContainingArgumentInfo(node: ts.Node, position: number, sourceFile: ts.SourceFile, checker: ts.TypeChecker, isManuallyInvoked: boolean): ArgumentListInfo | undefined { - for (let n = node; !ts.isSourceFile(n) && (isManuallyInvoked || !ts.isBlock(n)); n = n.parent) { +function getContainingArgumentInfo(node: Node, position: number, sourceFile: SourceFile, checker: TypeChecker, isManuallyInvoked: boolean): ArgumentListInfo | undefined { + for (let n = node; !isSourceFile(n) && (isManuallyInvoked || !isBlock(n)); n = n.parent) { // If the node is not a subspan of its parent, this is a big problem. // There have been crashes that might be caused by this violation. - ts.Debug.assert(ts.rangeContainsRange(n.parent, n), "Not a subspan", () => `Child: ${ts.Debug.formatSyntaxKind(n.kind)}, parent: ${ts.Debug.formatSyntaxKind(n.parent.kind)}`); + Debug.assert(rangeContainsRange(n.parent, n), "Not a subspan", () => `Child: ${Debug.formatSyntaxKind(n.kind)}, parent: ${Debug.formatSyntaxKind(n.parent.kind)}`); const argumentInfo = getImmediatelyContainingArgumentOrContextualParameterInfo(n, position, sourceFile, checker); if (argumentInfo) { return argumentInfo; @@ -490,37 +504,37 @@ function getContainingArgumentInfo(node: ts.Node, position: number, sourceFile: return undefined; } -function getChildListThatStartsWithOpenerToken(parent: ts.Node, openerToken: ts.Node, sourceFile: ts.SourceFile): ts.Node { +function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node { const children = parent.getChildren(sourceFile); const indexOfOpenerToken = children.indexOf(openerToken); - ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); + Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1); return children[indexOfOpenerToken + 1]; } -function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): ts.Expression { - return invocation.kind === InvocationKind.Call ? ts.getInvokedExpression(invocation.node) : invocation.called; +function getExpressionFromInvocation(invocation: CallInvocation | TypeArgsInvocation): Expression { + return invocation.kind === InvocationKind.Call ? getInvokedExpression(invocation.node) : invocation.called; } -function getEnclosingDeclarationFromInvocation(invocation: Invocation): ts.Node { +function getEnclosingDeclarationFromInvocation(invocation: Invocation): Node { return invocation.kind === InvocationKind.Call ? invocation.node : invocation.kind === InvocationKind.TypeArgs ? invocation.called : invocation.node; } -const signatureHelpNodeBuilderFlags = ts.NodeBuilderFlags.OmitParameterModifiers | ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; +const signatureHelpNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; function createSignatureHelpItems( - candidates: readonly ts.Signature[], - resolvedSignature: ts.Signature, + candidates: readonly Signature[], + resolvedSignature: Signature, { isTypeParameterList, argumentCount, argumentsSpan: applicableSpan, invocation, argumentIndex }: ArgumentListInfo, - sourceFile: ts.SourceFile, - typeChecker: ts.TypeChecker, + sourceFile: SourceFile, + typeChecker: TypeChecker, useFullPrefix?: boolean, -): ts.SignatureHelpItems { +): SignatureHelpItems { const enclosingDeclaration = getEnclosingDeclarationFromInvocation(invocation); const callTargetSymbol = invocation.kind === InvocationKind.Contextual ? invocation.symbol : (typeChecker.getSymbolAtLocation(getExpressionFromInvocation(invocation)) || useFullPrefix && resolvedSignature.declaration?.symbol); - const callTargetDisplayParts = callTargetSymbol ? ts.symbolToDisplayParts(typeChecker, callTargetSymbol, useFullPrefix ? sourceFile : undefined, /*meaning*/ undefined) : ts.emptyArray; - const items = ts.map(candidates, candidateSignature => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile)); + const callTargetDisplayParts = callTargetSymbol ? symbolToDisplayParts(typeChecker, callTargetSymbol, useFullPrefix ? sourceFile : undefined, /*meaning*/ undefined) : emptyArray; + const items = map(candidates, candidateSignature => getSignatureHelpItem(candidateSignature, callTargetDisplayParts, isTypeParameterList, typeChecker, enclosingDeclaration, sourceFile)); if (argumentIndex !== 0) { - ts.Debug.assertLessThan(argumentIndex, argumentCount); + Debug.assertLessThan(argumentIndex, argumentCount); } let selectedItemIndex = 0; let itemsSeen = 0; @@ -544,11 +558,11 @@ function createSignatureHelpItems( itemsSeen += item.length; } - ts.Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. - const help = { items: ts.flatMapToMutable(items, ts.identity), applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; + Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function. + const help = { items: flatMapToMutable(items, identity), applicableSpan, selectedItemIndex, argumentIndex, argumentCount }; const selected = help.items[selectedItemIndex]; if (selected.isVariadic) { - const firstRest = ts.findIndex(selected.parameters, p => !!p.isRest); + const firstRest = findIndex(selected.parameters, p => !!p.isRest); if (-1 < firstRest && firstRest < selected.parameters.length - 1) { // We don't have any code to get this correct; instead, don't highlight a current parameter AT ALL help.argumentIndex = selected.parameters.length; @@ -561,34 +575,34 @@ function createSignatureHelpItems( } function createTypeHelpItems( - symbol: ts.Symbol, + symbol: Symbol, { argumentCount, argumentsSpan: applicableSpan, invocation, argumentIndex }: ArgumentListInfo, - sourceFile: ts.SourceFile, - checker: ts.TypeChecker -): ts.SignatureHelpItems | undefined { + sourceFile: SourceFile, + checker: TypeChecker +): SignatureHelpItems | undefined { const typeParameters = checker.getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol); if (!typeParameters) return undefined; const items = [getTypeHelpItem(symbol, typeParameters, checker, getEnclosingDeclarationFromInvocation(invocation), sourceFile)]; return { items, applicableSpan, selectedItemIndex: 0, argumentIndex, argumentCount }; } -function getTypeHelpItem(symbol: ts.Symbol, typeParameters: readonly ts.TypeParameter[], checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile): ts.SignatureHelpItem { - const typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol); +function getTypeHelpItem(symbol: Symbol, typeParameters: readonly TypeParameter[], checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem { + const typeSymbolDisplay = symbolToDisplayParts(checker, symbol); - const printer = ts.createPrinter({ removeComments: true }); + const printer = createPrinter({ removeComments: true }); const parameters = typeParameters.map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const documentation = symbol.getDocumentationComment(checker); const tags = symbol.getJsDocTags(checker); - const prefixDisplayParts = [...typeSymbolDisplay, ts.punctuationPart(ts.SyntaxKind.LessThanToken)]; - return { isVariadic: false, prefixDisplayParts, suffixDisplayParts: [ts.punctuationPart(ts.SyntaxKind.GreaterThanToken)], separatorDisplayParts, parameters, documentation, tags }; + const prefixDisplayParts = [...typeSymbolDisplay, punctuationPart(SyntaxKind.LessThanToken)]; + return { isVariadic: false, prefixDisplayParts, suffixDisplayParts: [punctuationPart(SyntaxKind.GreaterThanToken)], separatorDisplayParts, parameters, documentation, tags }; } -const separatorDisplayParts: ts.SymbolDisplayPart[] = [ts.punctuationPart(ts.SyntaxKind.CommaToken), ts.spacePart()]; +const separatorDisplayParts: SymbolDisplayPart[] = [punctuationPart(SyntaxKind.CommaToken), spacePart()]; -function getSignatureHelpItem(candidateSignature: ts.Signature, callTargetDisplayParts: readonly ts.SymbolDisplayPart[], isTypeParameterList: boolean, checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile): ts.SignatureHelpItem[] { +function getSignatureHelpItem(candidateSignature: Signature, callTargetDisplayParts: readonly SymbolDisplayPart[], isTypeParameterList: boolean, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem[] { const infos = (isTypeParameterList ? itemInfoForTypeParameters : itemInfoForParameters)(candidateSignature, checker, enclosingDeclaration, sourceFile); - return ts.map(infos, ({ isVariadic, parameters, prefix, suffix }) => { + return map(infos, ({ isVariadic, parameters, prefix, suffix }) => { const prefixDisplayParts = [...callTargetDisplayParts, ...prefix]; const suffixDisplayParts = [...suffix, ...returnTypeToDisplayParts(candidateSignature, enclosingDeclaration, checker)]; const documentation = candidateSignature.getDocumentationComment(checker); @@ -597,8 +611,8 @@ function getSignatureHelpItem(candidateSignature: ts.Signature, callTargetDispla }); } -function returnTypeToDisplayParts(candidateSignature: ts.Signature, enclosingDeclaration: ts.Node, checker: ts.TypeChecker): readonly ts.SymbolDisplayPart[] { - return ts.mapToDisplayParts(writer => { +function returnTypeToDisplayParts(candidateSignature: Signature, enclosingDeclaration: Node, checker: TypeChecker): readonly SymbolDisplayPart[] { + return mapToDisplayParts(writer => { writer.writePunctuation(":"); writer.writeSpace(" "); const predicate = checker.getTypePredicateOfSignature(candidateSignature); @@ -611,58 +625,58 @@ function returnTypeToDisplayParts(candidateSignature: ts.Signature, enclosingDec }); } -interface SignatureHelpItemInfo { readonly isVariadic: boolean; readonly parameters: ts.SignatureHelpParameter[]; readonly prefix: readonly ts.SymbolDisplayPart[]; readonly suffix: readonly ts.SymbolDisplayPart[]; } +interface SignatureHelpItemInfo { readonly isVariadic: boolean; readonly parameters: SignatureHelpParameter[]; readonly prefix: readonly SymbolDisplayPart[]; readonly suffix: readonly SymbolDisplayPart[]; } -function itemInfoForTypeParameters(candidateSignature: ts.Signature, checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile): SignatureHelpItemInfo[] { +function itemInfoForTypeParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { const typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - const printer = ts.createPrinter({ removeComments: true }); - const parameters = (typeParameters || ts.emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); + const printer = createPrinter({ removeComments: true }); + const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : []; return checker.getExpandedParameters(candidateSignature).map(paramList => { - const params = ts.factory.createNodeArray([...thisParameter, ...ts.map(paramList, param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); - const parameterParts = ts.mapToDisplayParts(writer => { - printer.writeList(ts.ListFormat.CallExpressionArguments, params, sourceFile, writer); + const params = factory.createNodeArray([...thisParameter, ...map(paramList, param => checker.symbolToParameterDeclaration(param, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)]); + const parameterParts = mapToDisplayParts(writer => { + printer.writeList(ListFormat.CallExpressionArguments, params, sourceFile, writer); }); - return { isVariadic: false, parameters, prefix: [ts.punctuationPart(ts.SyntaxKind.LessThanToken)], suffix: [ts.punctuationPart(ts.SyntaxKind.GreaterThanToken), ...parameterParts] }; + return { isVariadic: false, parameters, prefix: [punctuationPart(SyntaxKind.LessThanToken)], suffix: [punctuationPart(SyntaxKind.GreaterThanToken), ...parameterParts] }; }); } -function itemInfoForParameters(candidateSignature: ts.Signature, checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile): SignatureHelpItemInfo[] { - const printer = ts.createPrinter({ removeComments: true }); - const typeParameterParts = ts.mapToDisplayParts(writer => { +function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { + const printer = createPrinter({ removeComments: true }); + const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { - const args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)); - printer.writeList(ts.ListFormat.TypeParameters, args, sourceFile, writer); + const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)); + printer.writeList(ListFormat.TypeParameters, args, sourceFile, writer); } }); const lists = checker.getExpandedParameters(candidateSignature); - const isVariadic: (parameterList: readonly ts.Symbol[]) => boolean = + const isVariadic: (parameterList: readonly Symbol[]) => boolean = !checker.hasEffectiveRestParameter(candidateSignature) ? _ => false : lists.length === 1 ? _ => true - : pList => !!(pList.length && (pList[pList.length - 1] as ts.TransientSymbol).checkFlags & ts.CheckFlags.RestParameter); + : pList => !!(pList.length && (pList[pList.length - 1] as TransientSymbol).checkFlags & CheckFlags.RestParameter); return lists.map(parameterList => ({ isVariadic: isVariadic(parameterList), parameters: parameterList.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)), - prefix: [...typeParameterParts, ts.punctuationPart(ts.SyntaxKind.OpenParenToken)], - suffix: [ts.punctuationPart(ts.SyntaxKind.CloseParenToken)] + prefix: [...typeParameterParts, punctuationPart(SyntaxKind.OpenParenToken)], + suffix: [punctuationPart(SyntaxKind.CloseParenToken)] })); } -function createSignatureHelpParameterForParameter(parameter: ts.Symbol, checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile, printer: ts.Printer): ts.SignatureHelpParameter { - const displayParts = ts.mapToDisplayParts(writer => { +function createSignatureHelpParameterForParameter(parameter: Symbol, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter { + const displayParts = mapToDisplayParts(writer => { const param = checker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!; - printer.writeNode(ts.EmitHint.Unspecified, param, sourceFile, writer); + printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer); }); - const isOptional = checker.isOptionalParameter(parameter.valueDeclaration as ts.ParameterDeclaration); - const isRest = !!((parameter as ts.TransientSymbol).checkFlags & ts.CheckFlags.RestParameter); + const isOptional = checker.isOptionalParameter(parameter.valueDeclaration as ParameterDeclaration); + const isRest = !!((parameter as TransientSymbol).checkFlags & CheckFlags.RestParameter); return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts, isOptional, isRest }; } -function createSignatureHelpParameterForTypeParameter(typeParameter: ts.TypeParameter, checker: ts.TypeChecker, enclosingDeclaration: ts.Node, sourceFile: ts.SourceFile, printer: ts.Printer): ts.SignatureHelpParameter { - const displayParts = ts.mapToDisplayParts(writer => { +function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter { + const displayParts = mapToDisplayParts(writer => { const param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!; - printer.writeNode(ts.EmitHint.Unspecified, param, sourceFile, writer); + printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer); }); return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false, isRest: false }; } diff --git a/src/services/smartSelection.ts b/src/services/smartSelection.ts index d1476ecb36b4e..04ffc73c4b10a 100644 --- a/src/services/smartSelection.ts +++ b/src/services/smartSelection.ts @@ -1,32 +1,41 @@ -import * as ts from "./_namespaces/ts"; +import { + CharacterCodes, compact, contains, createTextSpanFromBounds, Debug, findIndex, first, getTokenPosOfNode, + getTouchingPropertyName, getTrailingCommentRanges, hasJSDocNodes, isBindingElement, isBlock, isFunctionBody, + isFunctionLikeDeclaration, isImportDeclaration, isImportEqualsDeclaration, isJSDocSignature, isJSDocTypeExpression, + isJSDocTypeLiteral, isMappedTypeNode, isParameter, isPropertySignature, isSourceFile, isStringLiteral, isSyntaxList, + isTemplateHead, isTemplateLiteral, isTemplateMiddleOrTemplateTail, isTemplateSpan, isTemplateTail, + isVariableDeclaration, isVariableDeclarationList, isVariableStatement, last, Node, or, parseNodeFactory, + positionsAreOnSameLine, SelectionRange, setTextRangePosEnd, singleOrUndefined, SourceFile, SyntaxKind, SyntaxList, + textSpanIntersectsWithPosition, textSpansEqual, +} from "./_namespaces/ts"; /** @internal */ -export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): ts.SelectionRange { - let selectionRange: ts.SelectionRange = { - textSpan: ts.createTextSpanFromBounds(sourceFile.getFullStart(), sourceFile.getEnd()) +export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): SelectionRange { + let selectionRange: SelectionRange = { + textSpan: createTextSpanFromBounds(sourceFile.getFullStart(), sourceFile.getEnd()) }; - let parentNode: ts.Node = sourceFile; + let parentNode: Node = sourceFile; outer: while (true) { const children = getSelectionChildren(parentNode); if (!children.length) break; for (let i = 0; i < children.length; i++) { - const prevNode: ts.Node | undefined = children[i - 1]; - const node: ts.Node = children[i]; - const nextNode: ts.Node | undefined = children[i + 1]; + const prevNode: Node | undefined = children[i - 1]; + const node: Node = children[i]; + const nextNode: Node | undefined = children[i + 1]; - if (ts.getTokenPosOfNode(node, sourceFile, /*includeJsDoc*/ true) > pos) { + if (getTokenPosOfNode(node, sourceFile, /*includeJsDoc*/ true) > pos) { break outer; } - const comment = ts.singleOrUndefined(ts.getTrailingCommentRanges(sourceFile.text, node.end)); - if (comment && comment.kind === ts.SyntaxKind.SingleLineCommentTrivia) { + const comment = singleOrUndefined(getTrailingCommentRanges(sourceFile.text, node.end)); + if (comment && comment.kind === SyntaxKind.SingleLineCommentTrivia) { pushSelectionCommentRange(comment.pos, comment.end); } if (positionShouldSnapToNode(sourceFile, pos, node)) { - if (ts.isFunctionBody(node) - && ts.isFunctionLikeDeclaration(parentNode) && !ts.positionsAreOnSameLine(node.getStart(sourceFile), node.getEnd(), sourceFile)) { + if (isFunctionBody(node) + && isFunctionLikeDeclaration(parentNode) && !positionsAreOnSameLine(node.getStart(sourceFile), node.getEnd(), sourceFile)) { pushSelectionRange(node.getStart(sourceFile), node.getEnd()); } @@ -36,19 +45,19 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): // 3. A VariableStatement’s children are just a VaraiableDeclarationList and a semicolon. // 4. A lone VariableDeclaration in a VaraibleDeclaration feels redundant with the VariableStatement. // Dive in without pushing a selection range. - if (ts.isBlock(node) - || ts.isTemplateSpan(node) || ts.isTemplateHead(node) || ts.isTemplateTail(node) - || prevNode && ts.isTemplateHead(prevNode) - || ts.isVariableDeclarationList(node) && ts.isVariableStatement(parentNode) - || ts.isSyntaxList(node) && ts.isVariableDeclarationList(parentNode) - || ts.isVariableDeclaration(node) && ts.isSyntaxList(parentNode) && children.length === 1 - || ts.isJSDocTypeExpression(node) || ts.isJSDocSignature(node) || ts.isJSDocTypeLiteral(node)) { + if (isBlock(node) + || isTemplateSpan(node) || isTemplateHead(node) || isTemplateTail(node) + || prevNode && isTemplateHead(prevNode) + || isVariableDeclarationList(node) && isVariableStatement(parentNode) + || isSyntaxList(node) && isVariableDeclarationList(parentNode) + || isVariableDeclaration(node) && isSyntaxList(parentNode) && children.length === 1 + || isJSDocTypeExpression(node) || isJSDocSignature(node) || isJSDocTypeLiteral(node)) { parentNode = node; break; } // Synthesize a stop for '${ ... }' since '${' and '}' actually belong to siblings. - if (ts.isTemplateSpan(parentNode) && nextNode && ts.isTemplateMiddleOrTemplateTail(nextNode)) { + if (isTemplateSpan(parentNode) && nextNode && isTemplateMiddleOrTemplateTail(nextNode)) { const start = node.getFullStart() - "${".length; const end = nextNode.getStart() + "}".length; pushSelectionRange(start, end); @@ -56,13 +65,13 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): // Blocks with braces, brackets, parens, or JSX tags on separate lines should be // selected from open to close, including whitespace but not including the braces/etc. themselves. - const isBetweenMultiLineBookends = ts.isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode) - && !ts.positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile); + const isBetweenMultiLineBookends = isSyntaxList(node) && isListOpener(prevNode) && isListCloser(nextNode) + && !positionsAreOnSameLine(prevNode.getStart(), nextNode.getStart(), sourceFile); let start = isBetweenMultiLineBookends ? prevNode.getEnd() : node.getStart(); const end = isBetweenMultiLineBookends ? nextNode.getStart() : getEndPos(sourceFile, node); - if (ts.hasJSDocNodes(node) && node.jsDoc?.length) { - pushSelectionRange(ts.first(node.jsDoc).getStart(), end); + if (hasJSDocNodes(node) && node.jsDoc?.length) { + pushSelectionRange(first(node.jsDoc).getStart(), end); } // (#39618 & #49807) @@ -70,16 +79,16 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): // `start` (which usually is the result of calling `node.getStart()`) points to the first // token after the JSDoc comment. So, we have to make sure we'd pushed the selection // covering the JSDoc comment before diving further. - if (ts.isSyntaxList(node)) { + if (isSyntaxList(node)) { const firstChild = node.getChildren()[0]; - if (firstChild && ts.hasJSDocNodes(firstChild) && firstChild.jsDoc?.length && firstChild.getStart() !== node.pos) { - start = Math.min(start, ts.first(firstChild.jsDoc).getStart()); + if (firstChild && hasJSDocNodes(firstChild) && firstChild.jsDoc?.length && firstChild.getStart() !== node.pos) { + start = Math.min(start, first(firstChild.jsDoc).getStart()); } } pushSelectionRange(start, end); // String literals should have a stop both inside and outside their quotes. - if (ts.isStringLiteral(node) || ts.isTemplateLiteral(node)) { + if (isStringLiteral(node) || isTemplateLiteral(node)) { pushSelectionRange(start + 1, end - 1); } @@ -101,12 +110,12 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): function pushSelectionRange(start: number, end: number): void { // Skip empty ranges if (start !== end) { - const textSpan = ts.createTextSpanFromBounds(start, end); + const textSpan = createTextSpanFromBounds(start, end); if (!selectionRange || ( // Skip ranges that are identical to the parent - !ts.textSpansEqual(textSpan, selectionRange.textSpan) && + !textSpansEqual(textSpan, selectionRange.textSpan) && // Skip ranges that don’t contain the original position - ts.textSpanIntersectsWithPosition(textSpan, pos) + textSpanIntersectsWithPosition(textSpan, pos) )) { selectionRange = { textSpan, ...selectionRange && { parent: selectionRange } }; } @@ -117,7 +126,7 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): pushSelectionRange(start, end); let pos = start; - while (sourceFile.text.charCodeAt(pos) === ts.CharacterCodes.slash) { + while (sourceFile.text.charCodeAt(pos) === CharacterCodes.slash) { pos++; } pushSelectionRange(pos, end); @@ -133,22 +142,22 @@ export function getSmartSelectionRange(pos: number, sourceFile: ts.SourceFile): * @param pos The position to check. * @param node The candidate node to snap to. */ -function positionShouldSnapToNode(sourceFile: ts.SourceFile, pos: number, node: ts.Node) { +function positionShouldSnapToNode(sourceFile: SourceFile, pos: number, node: Node) { // Can’t use 'ts.positionBelongsToNode()' here because it cleverly accounts // for missing nodes, which can’t really be considered when deciding what // to select. - ts.Debug.assert(node.pos <= pos); + Debug.assert(node.pos <= pos); if (pos < node.end) { return true; } const nodeEnd = node.getEnd(); if (nodeEnd === pos) { - return ts.getTouchingPropertyName(sourceFile, pos).pos < node.end; + return getTouchingPropertyName(sourceFile, pos).pos < node.end; } return false; } -const isImport = ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration); +const isImport = or(isImportDeclaration, isImportEqualsDeclaration); /** * Gets the children of a node to be considered for selection ranging, @@ -158,9 +167,9 @@ const isImport = ts.or(ts.isImportDeclaration, ts.isImportEqualsDeclaration); * selected all together, even though in the AST they’re just siblings of each * other as well as of other top-level statements and declarations. */ -function getSelectionChildren(node: ts.Node): readonly ts.Node[] { +function getSelectionChildren(node: Node): readonly Node[] { // Group top-level imports - if (ts.isSourceFile(node)) { + if (isSourceFile(node)) { return groupChildren(node.getChildAt(0).getChildren(), isImport); } @@ -174,51 +183,51 @@ function getSelectionChildren(node: ts.Node): readonly ts.Node[] { // around the “key/value” pair not because there’s a node there, but // because it allows the mapped type to become an object type with a // few keystrokes. - if (ts.isMappedTypeNode(node)) { + if (isMappedTypeNode(node)) { const [openBraceToken, ...children] = node.getChildren(); - const closeBraceToken = ts.Debug.checkDefined(children.pop()); - ts.Debug.assertEqual(openBraceToken.kind, ts.SyntaxKind.OpenBraceToken); - ts.Debug.assertEqual(closeBraceToken.kind, ts.SyntaxKind.CloseBraceToken); + const closeBraceToken = Debug.checkDefined(children.pop()); + Debug.assertEqual(openBraceToken.kind, SyntaxKind.OpenBraceToken); + Debug.assertEqual(closeBraceToken.kind, SyntaxKind.CloseBraceToken); // Group `-/+readonly` and `-/+?` const groupedWithPlusMinusTokens = groupChildren(children, child => - child === node.readonlyToken || child.kind === ts.SyntaxKind.ReadonlyKeyword || - child === node.questionToken || child.kind === ts.SyntaxKind.QuestionToken); + child === node.readonlyToken || child.kind === SyntaxKind.ReadonlyKeyword || + child === node.questionToken || child.kind === SyntaxKind.QuestionToken); // Group type parameter with surrounding brackets const groupedWithBrackets = groupChildren(groupedWithPlusMinusTokens, ({ kind }) => - kind === ts.SyntaxKind.OpenBracketToken || - kind === ts.SyntaxKind.TypeParameter || - kind === ts.SyntaxKind.CloseBracketToken + kind === SyntaxKind.OpenBracketToken || + kind === SyntaxKind.TypeParameter || + kind === SyntaxKind.CloseBracketToken ); return [ openBraceToken, // Pivot on `:` - createSyntaxList(splitChildren(groupedWithBrackets, ({ kind }) => kind === ts.SyntaxKind.ColonToken)), + createSyntaxList(splitChildren(groupedWithBrackets, ({ kind }) => kind === SyntaxKind.ColonToken)), closeBraceToken, ]; } // Group modifiers and property name, then pivot on `:`. - if (ts.isPropertySignature(node)) { + if (isPropertySignature(node)) { const children = groupChildren(node.getChildren(), child => - child === node.name || ts.contains(node.modifiers, child)); - const firstJSDocChild = children[0]?.kind === ts.SyntaxKind.JSDoc ? children[0] : undefined; + child === node.name || contains(node.modifiers, child)); + const firstJSDocChild = children[0]?.kind === SyntaxKind.JSDoc ? children[0] : undefined; const withJSDocSeparated = firstJSDocChild? children.slice(1) : children; - const splittedChildren = splitChildren(withJSDocSeparated, ({ kind }) => kind === ts.SyntaxKind.ColonToken); + const splittedChildren = splitChildren(withJSDocSeparated, ({ kind }) => kind === SyntaxKind.ColonToken); return firstJSDocChild? [firstJSDocChild, createSyntaxList(splittedChildren)] : splittedChildren; } // Group the parameter name with its `...`, then that group with its `?`, then pivot on `=`. - if (ts.isParameter(node)) { + if (isParameter(node)) { const groupedDotDotDotAndName = groupChildren(node.getChildren(), child => child === node.dotDotDotToken || child === node.name); const groupedWithQuestionToken = groupChildren(groupedDotDotDotAndName, child => child === groupedDotDotDotAndName[0] || child === node.questionToken); - return splitChildren(groupedWithQuestionToken, ({ kind }) => kind === ts.SyntaxKind.EqualsToken); + return splitChildren(groupedWithQuestionToken, ({ kind }) => kind === SyntaxKind.EqualsToken); } // Pivot on '=' - if (ts.isBindingElement(node)) { - return splitChildren(node.getChildren(), ({ kind }) => kind === ts.SyntaxKind.EqualsToken); + if (isBindingElement(node)) { + return splitChildren(node.getChildren(), ({ kind }) => kind === SyntaxKind.EqualsToken); } return node.getChildren(); @@ -228,9 +237,9 @@ function getSelectionChildren(node: ts.Node): readonly ts.Node[] { * Groups sibling nodes together into their own SyntaxList if they * a) are adjacent, AND b) match a predicate function. */ -function groupChildren(children: ts.Node[], groupOn: (child: ts.Node) => boolean): ts.Node[] { - const result: ts.Node[] = []; - let group: ts.Node[] | undefined; +function groupChildren(children: Node[], groupOn: (child: Node) => boolean): Node[] { + const result: Node[] = []; + let group: Node[] | undefined; for (const child of children) { if (groupOn(child)) { group = group || []; @@ -264,20 +273,20 @@ function groupChildren(children: ts.Node[], groupOn: (child: ts.Node) => boolean * @param separateTrailingSemicolon If the last token is a semicolon, it will be returned as a separate * child rather than be included in the right-hand group. */ -function splitChildren(children: ts.Node[], pivotOn: (child: ts.Node) => boolean, separateTrailingSemicolon = true): ts.Node[] { +function splitChildren(children: Node[], pivotOn: (child: Node) => boolean, separateTrailingSemicolon = true): Node[] { if (children.length < 2) { return children; } - const splitTokenIndex = ts.findIndex(children, pivotOn); + const splitTokenIndex = findIndex(children, pivotOn); if (splitTokenIndex === -1) { return children; } const leftChildren = children.slice(0, splitTokenIndex); const splitToken = children[splitTokenIndex]; - const lastToken = ts.last(children); - const separateLastToken = separateTrailingSemicolon && lastToken.kind === ts.SyntaxKind.SemicolonToken; + const lastToken = last(children); + const separateLastToken = separateTrailingSemicolon && lastToken.kind === SyntaxKind.SemicolonToken; const rightChildren = children.slice(splitTokenIndex + 1, separateLastToken ? children.length - 1 : undefined); - const result = ts.compact([ + const result = compact([ leftChildren.length ? createSyntaxList(leftChildren) : undefined, splitToken, rightChildren.length ? createSyntaxList(rightChildren) : undefined, @@ -285,34 +294,34 @@ function splitChildren(children: ts.Node[], pivotOn: (child: ts.Node) => boolean return separateLastToken ? result.concat(lastToken) : result; } -function createSyntaxList(children: ts.Node[]): ts.SyntaxList { - ts.Debug.assertGreaterThanOrEqual(children.length, 1); - return ts.setTextRangePosEnd(ts.parseNodeFactory.createSyntaxList(children), children[0].pos, ts.last(children).end); +function createSyntaxList(children: Node[]): SyntaxList { + Debug.assertGreaterThanOrEqual(children.length, 1); + return setTextRangePosEnd(parseNodeFactory.createSyntaxList(children), children[0].pos, last(children).end); } -function isListOpener(token: ts.Node | undefined): token is ts.Node { +function isListOpener(token: Node | undefined): token is Node { const kind = token && token.kind; - return kind === ts.SyntaxKind.OpenBraceToken - || kind === ts.SyntaxKind.OpenBracketToken - || kind === ts.SyntaxKind.OpenParenToken - || kind === ts.SyntaxKind.JsxOpeningElement; + return kind === SyntaxKind.OpenBraceToken + || kind === SyntaxKind.OpenBracketToken + || kind === SyntaxKind.OpenParenToken + || kind === SyntaxKind.JsxOpeningElement; } -function isListCloser(token: ts.Node | undefined): token is ts.Node { +function isListCloser(token: Node | undefined): token is Node { const kind = token && token.kind; - return kind === ts.SyntaxKind.CloseBraceToken - || kind === ts.SyntaxKind.CloseBracketToken - || kind === ts.SyntaxKind.CloseParenToken - || kind === ts.SyntaxKind.JsxClosingElement; + return kind === SyntaxKind.CloseBraceToken + || kind === SyntaxKind.CloseBracketToken + || kind === SyntaxKind.CloseParenToken + || kind === SyntaxKind.JsxClosingElement; } -function getEndPos(sourceFile: ts.SourceFile, node: ts.Node): number { +function getEndPos(sourceFile: SourceFile, node: Node): number { switch (node.kind) { - case ts.SyntaxKind.JSDocParameterTag: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocPropertyTag: - case ts.SyntaxKind.JSDocTypedefTag: - case ts.SyntaxKind.JSDocThisTag: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocThisTag: return sourceFile.getLineEndOfPosition(node.getStart()); default: return node.getEnd(); diff --git a/src/services/sourcemaps.ts b/src/services/sourcemaps.ts index 1a88018867a95..f954eea53b8ff 100644 --- a/src/services/sourcemaps.ts +++ b/src/services/sourcemaps.ts @@ -1,12 +1,19 @@ import * as ts from "./_namespaces/ts"; +import { + base64decode, computeLineAndCharacterOfPosition, createDocumentPositionMapper, createGetCanonicalFileName, + DocumentPosition, DocumentPositionMapper, DocumentPositionMapperHost, Extension, + getDeclarationEmitOutputFilePathWorker, getDirectoryPath, getLineInfo, getLineStarts, getNormalizedAbsolutePath, + identitySourceMapConsumer, isDeclarationFileName, isString, LineAndCharacter, LineInfo, Map, outFile, Program, + removeFileExtension, SourceFileLike, sys, tryGetSourceMappingURL, tryParseRawSourceMap, +} from "./_namespaces/ts"; const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+\/=]+)$)?/; /** @internal */ export interface SourceMapper { - toLineColumnOffset(fileName: string, position: number): ts.LineAndCharacter; - tryGetSourcePosition(info: ts.DocumentPosition): ts.DocumentPosition | undefined; - tryGetGeneratedPosition(info: ts.DocumentPosition): ts.DocumentPosition | undefined; + toLineColumnOffset(fileName: string, position: number): LineAndCharacter; + tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined; + tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined; clearCache(): void; } @@ -14,20 +21,20 @@ export interface SourceMapper { export interface SourceMapperHost { useCaseSensitiveFileNames(): boolean; getCurrentDirectory(): string; - getProgram(): ts.Program | undefined; + getProgram(): Program | undefined; fileExists?(path: string): boolean; readFile?(path: string, encoding?: string): string | undefined; - getSourceFileLike?(fileName: string): ts.SourceFileLike | undefined; - getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): ts.DocumentPositionMapper | undefined; + getSourceFileLike?(fileName: string): SourceFileLike | undefined; + getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined; log(s: string): void; } /** @internal */ export function getSourceMapper(host: SourceMapperHost): SourceMapper { - const getCanonicalFileName = ts.createGetCanonicalFileName(host.useCaseSensitiveFileNames()); + const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames()); const currentDirectory = host.getCurrentDirectory(); - const sourceFileLike = new ts.Map(); - const documentPositionMappers = new ts.Map(); + const sourceFileLike = new Map(); + const documentPositionMappers = new Map(); return { tryGetSourcePosition, tryGetGeneratedPosition, toLineColumnOffset, clearCache }; function toPath(fileName: string) { @@ -39,7 +46,7 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { const value = documentPositionMappers.get(path); if (value) return value; - let mapper: ts.DocumentPositionMapper | undefined; + let mapper: DocumentPositionMapper | undefined; if (host.getDocumentPositionMapper) { mapper = host.getDocumentPositionMapper(generatedFileName, sourceFileName); } @@ -48,16 +55,16 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { mapper = file && ts.getDocumentPositionMapper( { getSourceFileLike, getCanonicalFileName, log: s => host.log(s) }, generatedFileName, - ts.getLineInfo(file.text, ts.getLineStarts(file)), + getLineInfo(file.text, getLineStarts(file)), f => !host.fileExists || host.fileExists(f) ? host.readFile!(f) : undefined ); } - documentPositionMappers.set(path, mapper || ts.identitySourceMapConsumer); - return mapper || ts.identitySourceMapConsumer; + documentPositionMappers.set(path, mapper || identitySourceMapConsumer); + return mapper || identitySourceMapConsumer; } - function tryGetSourcePosition(info: ts.DocumentPosition): ts.DocumentPosition | undefined { - if (!ts.isDeclarationFileName(info.fileName)) return undefined; + function tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined { + if (!isDeclarationFileName(info.fileName)) return undefined; const file = getSourceFile(info.fileName); if (!file) return undefined; @@ -66,8 +73,8 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { return !newLoc || newLoc === info ? undefined : tryGetSourcePosition(newLoc) || newLoc; } - function tryGetGeneratedPosition(info: ts.DocumentPosition): ts.DocumentPosition | undefined { - if (ts.isDeclarationFileName(info.fileName)) return undefined; + function tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined { + if (isDeclarationFileName(info.fileName)) return undefined; const sourceFile = getSourceFile(info.fileName); if (!sourceFile) return undefined; @@ -79,11 +86,11 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { } const options = program.getCompilerOptions(); - const outPath = ts.outFile(options); + const outPath = outFile(options); const declarationPath = outPath ? - ts.removeFileExtension(outPath) + ts.Extension.Dts : - ts.getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName); + removeFileExtension(outPath) + Extension.Dts : + getDeclarationEmitOutputFilePathWorker(info.fileName, program.getCompilerOptions(), currentDirectory, program.getCommonSourceDirectory(), getCanonicalFileName); if (declarationPath === undefined) return undefined; const newLoc = getDocumentPositionMapper(declarationPath, info.fileName).getGeneratedPosition(info); @@ -100,7 +107,7 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { return file && file.resolvedPath === path ? file : undefined; } - function getOrCreateSourceFileLike(fileName: string): ts.SourceFileLike | undefined { + function getOrCreateSourceFileLike(fileName: string): SourceFileLike | undefined { const path = toPath(fileName); const fileFromCache = sourceFileLike.get(path); if (fileFromCache !== undefined) return fileFromCache ? fileFromCache : undefined; @@ -124,7 +131,7 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { host.getSourceFileLike(fileName); } - function toLineColumnOffset(fileName: string, position: number): ts.LineAndCharacter { + function toLineColumnOffset(fileName: string, position: number): LineAndCharacter { const file = getSourceFileLike(fileName)!; // TODO: GH#18217 return file.getLineAndCharacterOfPosition(position); } @@ -140,21 +147,21 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper { * string | undefined to contents of map file to create DocumentPositionMapper from it * DocumentPositionMapper | false to give back cached DocumentPositionMapper */ -export type ReadMapFile = (mapFileName: string, mapFileNameFromDts: string | undefined) => string | undefined | ts.DocumentPositionMapper | false; +export type ReadMapFile = (mapFileName: string, mapFileNameFromDts: string | undefined) => string | undefined | DocumentPositionMapper | false; /** @internal */ export function getDocumentPositionMapper( - host: ts.DocumentPositionMapperHost, + host: DocumentPositionMapperHost, generatedFileName: string, - generatedFileLineInfo: ts.LineInfo, + generatedFileLineInfo: LineInfo, readMapFile: ReadMapFile) { - let mapFileName = ts.tryGetSourceMappingURL(generatedFileLineInfo); + let mapFileName = tryGetSourceMappingURL(generatedFileLineInfo); if (mapFileName) { const match = base64UrlRegExp.exec(mapFileName); if (match) { if (match[1]) { const base64Object = match[1]; - return convertDocumentToSourceMapper(host, ts.base64decode(ts.sys, base64Object), generatedFileName); + return convertDocumentToSourceMapper(host, base64decode(sys, base64Object), generatedFileName); } // Not a data URL we can parse, skip it mapFileName = undefined; @@ -165,11 +172,11 @@ export function getDocumentPositionMapper( possibleMapLocations.push(mapFileName); } possibleMapLocations.push(generatedFileName + ".map"); - const originalMapFileName = mapFileName && ts.getNormalizedAbsolutePath(mapFileName, ts.getDirectoryPath(generatedFileName)); + const originalMapFileName = mapFileName && getNormalizedAbsolutePath(mapFileName, getDirectoryPath(generatedFileName)); for (const location of possibleMapLocations) { - const mapFileName = ts.getNormalizedAbsolutePath(location, ts.getDirectoryPath(generatedFileName)); + const mapFileName = getNormalizedAbsolutePath(location, getDirectoryPath(generatedFileName)); const mapFileContents = readMapFile(mapFileName, originalMapFileName); - if (ts.isString(mapFileContents)) { + if (isString(mapFileContents)) { return convertDocumentToSourceMapper(host, mapFileContents, mapFileName); } if (mapFileContents !== undefined) { @@ -179,25 +186,25 @@ export function getDocumentPositionMapper( return undefined; } -function convertDocumentToSourceMapper(host: ts.DocumentPositionMapperHost, contents: string, mapFileName: string) { - const map = ts.tryParseRawSourceMap(contents); +function convertDocumentToSourceMapper(host: DocumentPositionMapperHost, contents: string, mapFileName: string) { + const map = tryParseRawSourceMap(contents); if (!map || !map.sources || !map.file || !map.mappings) { // obviously invalid map return undefined; } // Dont support sourcemaps that contain inlined sources - if (map.sourcesContent && map.sourcesContent.some(ts.isString)) return undefined; + if (map.sourcesContent && map.sourcesContent.some(isString)) return undefined; - return ts.createDocumentPositionMapper(host, map, mapFileName); + return createDocumentPositionMapper(host, map, mapFileName); } -function createSourceFileLike(text: string, lineMap?: ts.SourceFileLike["lineMap"]): ts.SourceFileLike { +function createSourceFileLike(text: string, lineMap?: SourceFileLike["lineMap"]): SourceFileLike { return { text, lineMap, getLineAndCharacterOfPosition(pos: number) { - return ts.computeLineAndCharacterOfPosition(ts.getLineStarts(this), pos); + return computeLineAndCharacterOfPosition(getLineStarts(this), pos); } }; } diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index acaed2f724190..15117e0ce76f0 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -1,17 +1,46 @@ -import * as ts from "./_namespaces/ts"; +import { + addToSeen, altDirectorySeparator, arrayFrom, CallLikeExpression, CancellationToken, changeExtension, CharacterCodes, + combinePaths, comparePaths, comparePatternKeys, compareStringsCaseSensitive, compareValues, Comparison, + CompilerOptions, CompletionEntry, CompletionEntryDetails, CompletionInfo, contains, containsPath, ContextFlags, + createSortedArray, createTextSpan, createTextSpanFromStringLiteralLikeContent, Debug, deduplicate, + directorySeparator, ElementAccessExpression, emptyArray, endsWith, ensureTrailingDirectorySeparator, + equateStringsCaseSensitive, Extension, fileExtensionIsOneOf, filter, find, findAncestor, findPackageJson, + findPackageJsons, firstDefined, firstOrUndefined, flatMap, flatten, forEachAncestorDirectory, getBaseFileName, + getContextualTypeFromParent, getDirectoryPath, getEffectiveTypeRoots, getEmitModuleResolutionKind, + getLeadingCommentRanges, getModeForUsageLocation, getOwnKeys, getPackageJsonTypesVersionsPaths, getPathComponents, + getReplacementSpanForContextToken, getSupportedExtensions, getSupportedExtensionsWithJsonIfResolveJsonModule, + getTokenAtPosition, hasIndexSignature, hasProperty, hasTrailingDirectorySeparator, hostGetCanonicalFileName, + IndexedAccessTypeNode, isApplicableVersionedTypesKey, isArray, isCallExpression, isIdentifier, isIdentifierText, + isImportCall, isInReferenceComment, isInString, isJsxAttribute, isJsxOpeningLikeElement, isLiteralTypeNode, + isObjectLiteralExpression, isPatternMatch, isPrivateIdentifierClassElementDeclaration, isRootedDiskPath, isString, + isStringLiteral, isStringLiteralLike, isTypeReferenceNode, isUrl, Iterator, JsxAttribute, LanguageServiceHost, + length, LiteralExpression, LiteralTypeNode, Map, mapDefined, MapLike, ModuleKind, ModuleResolutionKind, + moduleSpecifiers, Node, normalizePath, normalizeSlashes, ObjectLiteralExpression, Path, Program, PropertyAssignment, + rangeContainsPosition, readJson, removeFileExtension, removePrefix, removeTrailingDirectorySeparator, resolvePath, + ScriptElementKind, ScriptElementKindModifier, ScriptTarget, Signature, signatureHasRestParameter, SignatureHelp, + singleElementArray, skipConstraint, skipParentheses, SourceFile, startsWith, stringContains, StringLiteralLike, + StringLiteralType, stripQuotes, Symbol, SyntaxKind, textPart, TextSpan, tryAndIgnoreErrors, tryDirectoryExists, + tryFileExists, tryGetDirectories, tryGetExtensionFromPath, tryParsePattern, tryReadDirectory, + tryRemoveDirectoryPrefix, tryRemovePrefix, Type, TypeChecker, TypeFlags, UnionTypeNode, unmangleScopedPackageName, + UserPreferences, walkUpParenthesizedExpressions, walkUpParenthesizedTypes, +} from "./_namespaces/ts"; +import { + CompletionKind, createCompletionDetails, createCompletionDetailsForSymbol, getCompletionEntriesFromSymbols, + getPropertiesForObjectExpression, Log, SortText, +} from "./_namespaces/ts.Completions"; interface NameAndKindSet { add(value: NameAndKind): void; has(name: string): boolean; - values(): ts.Iterator; + values(): Iterator; } const kindPrecedence = { - [ts.ScriptElementKind.directory]: 0, - [ts.ScriptElementKind.scriptElement]: 1, - [ts.ScriptElementKind.externalModuleName]: 2, + [ScriptElementKind.directory]: 0, + [ScriptElementKind.scriptElement]: 1, + [ScriptElementKind.externalModuleName]: 2, }; function createNameAndKindSet(): NameAndKindSet { - const map = new ts.Map(); + const map = new Map(); function add(value: NameAndKind) { const existing = map.get(value.name); if (!existing || kindPrecedence[existing.kind] < kindPrecedence[value.kind]) { @@ -27,20 +56,20 @@ function createNameAndKindSet(): NameAndKindSet { /** @internal */ export function getStringLiteralCompletions( - sourceFile: ts.SourceFile, + sourceFile: SourceFile, position: number, - contextToken: ts.Node | undefined, - options: ts.CompilerOptions, - host: ts.LanguageServiceHost, - program: ts.Program, - log: ts.Completions.Log, - preferences: ts.UserPreferences): ts.CompletionInfo | undefined { - if (ts.isInReferenceComment(sourceFile, position)) { + contextToken: Node | undefined, + options: CompilerOptions, + host: LanguageServiceHost, + program: Program, + log: Log, + preferences: UserPreferences): CompletionInfo | undefined { + if (isInReferenceComment(sourceFile, position)) { const entries = getTripleSlashReferenceCompletion(sourceFile, position, options, host); return entries && convertPathCompletions(entries); } - if (ts.isInString(sourceFile, position, contextToken)) { - if (!contextToken || !ts.isStringLiteralLike(contextToken)) return undefined; + if (isInString(sourceFile, position, contextToken)) { + if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; const entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, program.getTypeChecker(), options, host, preferences); return convertStringLiteralCompletions(entries, contextToken, sourceFile, host, program, log, options, preferences); } @@ -48,25 +77,25 @@ export function getStringLiteralCompletions( function convertStringLiteralCompletions( completion: StringLiteralCompletion | undefined, - contextToken: ts.StringLiteralLike, - sourceFile: ts.SourceFile, - host: ts.LanguageServiceHost, - program: ts.Program, - log: ts.Completions.Log, - options: ts.CompilerOptions, - preferences: ts.UserPreferences, -): ts.CompletionInfo | undefined { + contextToken: StringLiteralLike, + sourceFile: SourceFile, + host: LanguageServiceHost, + program: Program, + log: Log, + options: CompilerOptions, + preferences: UserPreferences, +): CompletionInfo | undefined { if (completion === undefined) { return undefined; } - const optionalReplacementSpan = ts.createTextSpanFromStringLiteralLikeContent(contextToken); + const optionalReplacementSpan = createTextSpanFromStringLiteralLikeContent(contextToken); switch (completion.kind) { case StringLiteralCompletionKind.Paths: return convertPathCompletions(completion.paths); case StringLiteralCompletionKind.Properties: { - const entries = ts.createSortedArray(); - ts.Completions.getCompletionEntriesFromSymbols( + const entries = createSortedArray(); + getCompletionEntriesFromSymbols( completion.symbols, entries, contextToken, @@ -75,9 +104,9 @@ function convertStringLiteralCompletions( sourceFile, host, program, - ts.ScriptTarget.ESNext, + ScriptTarget.ESNext, log, - ts.Completions.CompletionKind.String, + CompletionKind.String, preferences, options, /*formatContext*/ undefined, @@ -87,124 +116,124 @@ function convertStringLiteralCompletions( case StringLiteralCompletionKind.Types: { const entries = completion.types.map(type => ({ name: type.value, - kindModifiers: ts.ScriptElementKindModifier.none, - kind: ts.ScriptElementKind.string, - sortText: ts.Completions.SortText.LocationPriority, - replacementSpan: ts.getReplacementSpanForContextToken(contextToken) + kindModifiers: ScriptElementKindModifier.none, + kind: ScriptElementKind.string, + sortText: SortText.LocationPriority, + replacementSpan: getReplacementSpanForContextToken(contextToken) })); return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, optionalReplacementSpan, entries }; } default: - return ts.Debug.assertNever(completion); + return Debug.assertNever(completion); } } /** @internal */ -export function getStringLiteralCompletionDetails(name: string, sourceFile: ts.SourceFile, position: number, contextToken: ts.Node | undefined, checker: ts.TypeChecker, options: ts.CompilerOptions, host: ts.LanguageServiceHost, cancellationToken: ts.CancellationToken, preferences: ts.UserPreferences) { - if (!contextToken || !ts.isStringLiteralLike(contextToken)) return undefined; +export function getStringLiteralCompletionDetails(name: string, sourceFile: SourceFile, position: number, contextToken: Node | undefined, checker: TypeChecker, options: CompilerOptions, host: LanguageServiceHost, cancellationToken: CancellationToken, preferences: UserPreferences) { + if (!contextToken || !isStringLiteralLike(contextToken)) return undefined; const completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host, preferences); return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, checker, cancellationToken); } -function stringLiteralCompletionDetails(name: string, location: ts.Node, completion: StringLiteralCompletion, sourceFile: ts.SourceFile, checker: ts.TypeChecker, cancellationToken: ts.CancellationToken): ts.CompletionEntryDetails | undefined { +function stringLiteralCompletionDetails(name: string, location: Node, completion: StringLiteralCompletion, sourceFile: SourceFile, checker: TypeChecker, cancellationToken: CancellationToken): CompletionEntryDetails | undefined { switch (completion.kind) { case StringLiteralCompletionKind.Paths: { - const match = ts.find(completion.paths, p => p.name === name); - return match && ts.Completions.createCompletionDetails(name, kindModifiersFromExtension(match.extension), match.kind, [ts.textPart(name)]); + const match = find(completion.paths, p => p.name === name); + return match && createCompletionDetails(name, kindModifiersFromExtension(match.extension), match.kind, [textPart(name)]); } case StringLiteralCompletionKind.Properties: { - const match = ts.find(completion.symbols, s => s.name === name); - return match && ts.Completions.createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken); + const match = find(completion.symbols, s => s.name === name); + return match && createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken); } case StringLiteralCompletionKind.Types: - return ts.find(completion.types, t => t.value === name) ? ts.Completions.createCompletionDetails(name, ts.ScriptElementKindModifier.none, ts.ScriptElementKind.typeElement, [ts.textPart(name)]) : undefined; + return find(completion.types, t => t.value === name) ? createCompletionDetails(name, ScriptElementKindModifier.none, ScriptElementKind.typeElement, [textPart(name)]) : undefined; default: - return ts.Debug.assertNever(completion); + return Debug.assertNever(completion); } } -function convertPathCompletions(pathCompletions: readonly PathCompletion[]): ts.CompletionInfo { +function convertPathCompletions(pathCompletions: readonly PathCompletion[]): CompletionInfo { const isGlobalCompletion = false; // We don't want the editor to offer any other completions, such as snippets, inside a comment. const isNewIdentifierLocation = true; // The user may type in a path that doesn't yet exist, creating a "new identifier" with respect to the collection of identifiers the server is aware of. - const entries = pathCompletions.map(({ name, kind, span, extension }): ts.CompletionEntry => - ({ name, kind, kindModifiers: kindModifiersFromExtension(extension), sortText: ts.Completions.SortText.LocationPriority, replacementSpan: span })); + const entries = pathCompletions.map(({ name, kind, span, extension }): CompletionEntry => + ({ name, kind, kindModifiers: kindModifiersFromExtension(extension), sortText: SortText.LocationPriority, replacementSpan: span })); return { isGlobalCompletion, isMemberCompletion: false, isNewIdentifierLocation, entries }; } -function kindModifiersFromExtension(extension: ts.Extension | undefined): ts.ScriptElementKindModifier { +function kindModifiersFromExtension(extension: Extension | undefined): ScriptElementKindModifier { switch (extension) { - case ts.Extension.Dts: return ts.ScriptElementKindModifier.dtsModifier; - case ts.Extension.Js: return ts.ScriptElementKindModifier.jsModifier; - case ts.Extension.Json: return ts.ScriptElementKindModifier.jsonModifier; - case ts.Extension.Jsx: return ts.ScriptElementKindModifier.jsxModifier; - case ts.Extension.Ts: return ts.ScriptElementKindModifier.tsModifier; - case ts.Extension.Tsx: return ts.ScriptElementKindModifier.tsxModifier; - case ts.Extension.Dmts: return ts.ScriptElementKindModifier.dmtsModifier; - case ts.Extension.Mjs: return ts.ScriptElementKindModifier.mjsModifier; - case ts.Extension.Mts: return ts.ScriptElementKindModifier.mtsModifier; - case ts.Extension.Dcts: return ts.ScriptElementKindModifier.dctsModifier; - case ts.Extension.Cjs: return ts.ScriptElementKindModifier.cjsModifier; - case ts.Extension.Cts: return ts.ScriptElementKindModifier.ctsModifier; - case ts.Extension.TsBuildInfo: return ts.Debug.fail(`Extension ${ts.Extension.TsBuildInfo} is unsupported.`); - case undefined: return ts.ScriptElementKindModifier.none; + case Extension.Dts: return ScriptElementKindModifier.dtsModifier; + case Extension.Js: return ScriptElementKindModifier.jsModifier; + case Extension.Json: return ScriptElementKindModifier.jsonModifier; + case Extension.Jsx: return ScriptElementKindModifier.jsxModifier; + case Extension.Ts: return ScriptElementKindModifier.tsModifier; + case Extension.Tsx: return ScriptElementKindModifier.tsxModifier; + case Extension.Dmts: return ScriptElementKindModifier.dmtsModifier; + case Extension.Mjs: return ScriptElementKindModifier.mjsModifier; + case Extension.Mts: return ScriptElementKindModifier.mtsModifier; + case Extension.Dcts: return ScriptElementKindModifier.dctsModifier; + case Extension.Cjs: return ScriptElementKindModifier.cjsModifier; + case Extension.Cts: return ScriptElementKindModifier.ctsModifier; + case Extension.TsBuildInfo: return Debug.fail(`Extension ${Extension.TsBuildInfo} is unsupported.`); + case undefined: return ScriptElementKindModifier.none; default: - return ts.Debug.assertNever(extension); + return Debug.assertNever(extension); } } const enum StringLiteralCompletionKind { Paths, Properties, Types } interface StringLiteralCompletionsFromProperties { readonly kind: StringLiteralCompletionKind.Properties; - readonly symbols: readonly ts.Symbol[]; + readonly symbols: readonly Symbol[]; readonly hasIndexSignature: boolean; } interface StringLiteralCompletionsFromTypes { readonly kind: StringLiteralCompletionKind.Types; - readonly types: readonly ts.StringLiteralType[]; + readonly types: readonly StringLiteralType[]; readonly isNewIdentifier: boolean; } type StringLiteralCompletion = { readonly kind: StringLiteralCompletionKind.Paths, readonly paths: readonly PathCompletion[] } | StringLiteralCompletionsFromProperties | StringLiteralCompletionsFromTypes; -function getStringLiteralCompletionEntries(sourceFile: ts.SourceFile, node: ts.StringLiteralLike, position: number, typeChecker: ts.TypeChecker, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, preferences: ts.UserPreferences): StringLiteralCompletion | undefined { +function getStringLiteralCompletionEntries(sourceFile: SourceFile, node: StringLiteralLike, position: number, typeChecker: TypeChecker, compilerOptions: CompilerOptions, host: LanguageServiceHost, preferences: UserPreferences): StringLiteralCompletion | undefined { const parent = walkUpParentheses(node.parent); switch (parent.kind) { - case ts.SyntaxKind.LiteralType: { + case SyntaxKind.LiteralType: { const grandParent = walkUpParentheses(parent.parent); switch (grandParent.kind) { - case ts.SyntaxKind.ExpressionWithTypeArguments: - case ts.SyntaxKind.TypeReference: { - const typeArgument = ts.findAncestor(parent, n => n.parent === grandParent) as ts.LiteralTypeNode; + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.TypeReference: { + const typeArgument = findAncestor(parent, n => n.parent === grandParent) as LiteralTypeNode; if (typeArgument) { return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(typeArgument)), isNewIdentifier: false }; } return undefined; } - case ts.SyntaxKind.IndexedAccessType: + case SyntaxKind.IndexedAccessType: // Get all apparent property names // i.e. interface Foo { // foo: string; // bar: string; // } // let x: Foo["/*completion position*/"] - const { indexType, objectType } = grandParent as ts.IndexedAccessTypeNode; - if (!ts.rangeContainsPosition(indexType, position)) { + const { indexType, objectType } = grandParent as IndexedAccessTypeNode; + if (!rangeContainsPosition(indexType, position)) { return undefined; } return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(objectType)); - case ts.SyntaxKind.ImportType: + case SyntaxKind.ImportType: return { kind: StringLiteralCompletionKind.Paths, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker, preferences) }; - case ts.SyntaxKind.UnionType: { - if (!ts.isTypeReferenceNode(grandParent.parent)) { + case SyntaxKind.UnionType: { + if (!isTypeReferenceNode(grandParent.parent)) { return undefined; } - const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion(grandParent as ts.UnionTypeNode, parent as ts.LiteralTypeNode); - const types = getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(grandParent as ts.UnionTypeNode)).filter(t => !ts.contains(alreadyUsedTypes, t.value)); + const alreadyUsedTypes = getAlreadyUsedTypesInStringLiteralUnion(grandParent as UnionTypeNode, parent as LiteralTypeNode); + const types = getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(grandParent as UnionTypeNode)).filter(t => !contains(alreadyUsedTypes, t.value)); return { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier: false }; } default: return undefined; } } - case ts.SyntaxKind.PropertyAssignment: - if (ts.isObjectLiteralExpression(parent.parent) && (parent as ts.PropertyAssignment).name === node) { + case SyntaxKind.PropertyAssignment: + if (isObjectLiteralExpression(parent.parent) && (parent as PropertyAssignment).name === node) { // Get quoted name of properties of the object literal expression // i.e. interface ConfigFiles { // 'jspm:dev': string @@ -221,9 +250,9 @@ function getStringLiteralCompletionEntries(sourceFile: ts.SourceFile, node: ts.S } return fromContextualType(); - case ts.SyntaxKind.ElementAccessExpression: { - const { expression, argumentExpression } = parent as ts.ElementAccessExpression; - if (node === ts.skipParentheses(argumentExpression)) { + case SyntaxKind.ElementAccessExpression: { + const { expression, argumentExpression } = parent as ElementAccessExpression; + if (node === skipParentheses(argumentExpression)) { // Get all names of properties on the expression // i.e. interface A { // 'prop1': string @@ -235,11 +264,11 @@ function getStringLiteralCompletionEntries(sourceFile: ts.SourceFile, node: ts.S return undefined; } - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.NewExpression: - case ts.SyntaxKind.JsxAttribute: - if (!isRequireCallArgument(node) && !ts.isImportCall(parent)) { - const argumentInfo = ts.SignatureHelp.getArgumentInfoForCompletions(parent.kind === ts.SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile); + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.JsxAttribute: + if (!isRequireCallArgument(node) && !isImportCall(parent)) { + const argumentInfo = SignatureHelp.getArgumentInfoForCompletions(parent.kind === SyntaxKind.JsxAttribute ? parent.parent : node, position, sourceFile); // Get string literal completions from specialized signatures of the target // i.e. declare function f(a: 'A'); // f("/*completion position*/") @@ -247,9 +276,9 @@ function getStringLiteralCompletionEntries(sourceFile: ts.SourceFile, node: ts.S } // falls through (is `require("")` or `require(""` or `import("")`) - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ExternalModuleReference: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExternalModuleReference: // Get all known external module names or complete a path to a module // i.e. import * as ns from "/*completion position*/"; // var y = import("/*completion position*/"); @@ -265,61 +294,61 @@ function getStringLiteralCompletionEntries(sourceFile: ts.SourceFile, node: ts.S function fromContextualType(): StringLiteralCompletion { // Get completion for string literal from string literal type // i.e. var x: "hi" | "hello" = "/*completion position*/" - return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(ts.getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; + return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false }; } } -function walkUpParentheses(node: ts.Node) { +function walkUpParentheses(node: Node) { switch (node.kind) { - case ts.SyntaxKind.ParenthesizedType: - return ts.walkUpParenthesizedTypes(node); - case ts.SyntaxKind.ParenthesizedExpression: - return ts.walkUpParenthesizedExpressions(node); + case SyntaxKind.ParenthesizedType: + return walkUpParenthesizedTypes(node); + case SyntaxKind.ParenthesizedExpression: + return walkUpParenthesizedExpressions(node); default: return node; } } -function getAlreadyUsedTypesInStringLiteralUnion(union: ts.UnionTypeNode, current: ts.LiteralTypeNode): readonly string[] { - return ts.mapDefined(union.types, type => - type !== current && ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal) ? type.literal.text : undefined); +function getAlreadyUsedTypesInStringLiteralUnion(union: UnionTypeNode, current: LiteralTypeNode): readonly string[] { + return mapDefined(union.types, type => + type !== current && isLiteralTypeNode(type) && isStringLiteral(type.literal) ? type.literal.text : undefined); } -function getStringLiteralCompletionsFromSignature(call: ts.CallLikeExpression, arg: ts.StringLiteralLike, argumentInfo: ts.SignatureHelp.ArgumentInfoForCompletions, checker: ts.TypeChecker): StringLiteralCompletionsFromTypes | undefined { +function getStringLiteralCompletionsFromSignature(call: CallLikeExpression, arg: StringLiteralLike, argumentInfo: SignatureHelp.ArgumentInfoForCompletions, checker: TypeChecker): StringLiteralCompletionsFromTypes | undefined { let isNewIdentifier = false; - const uniques = new ts.Map(); - const candidates: ts.Signature[] = []; - const editingArgument = ts.isJsxOpeningLikeElement(call) ? ts.Debug.checkDefined(ts.findAncestor(arg.parent, ts.isJsxAttribute)) : arg; + const uniques = new Map(); + const candidates: Signature[] = []; + const editingArgument = isJsxOpeningLikeElement(call) ? Debug.checkDefined(findAncestor(arg.parent, isJsxAttribute)) : arg; checker.getResolvedSignatureForStringLiteralCompletions(call, editingArgument, candidates); - const types = ts.flatMap(candidates, candidate => { - if (!ts.signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length) return; + const types = flatMap(candidates, candidate => { + if (!signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length) return; let type = candidate.getTypeParameterAtPosition(argumentInfo.argumentIndex); - if (ts.isJsxOpeningLikeElement(call)) { - const propType = checker.getTypeOfPropertyOfType(type, (editingArgument as ts.JsxAttribute).name.text); + if (isJsxOpeningLikeElement(call)) { + const propType = checker.getTypeOfPropertyOfType(type, (editingArgument as JsxAttribute).name.text); if (propType) { type = propType; } } - isNewIdentifier = isNewIdentifier || !!(type.flags & ts.TypeFlags.String); + isNewIdentifier = isNewIdentifier || !!(type.flags & TypeFlags.String); return getStringLiteralTypes(type, uniques); }); - return ts.length(types) ? { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier } : undefined; + return length(types) ? { kind: StringLiteralCompletionKind.Types, types, isNewIdentifier } : undefined; } -function stringLiteralCompletionsFromProperties(type: ts.Type | undefined): StringLiteralCompletionsFromProperties | undefined { +function stringLiteralCompletionsFromProperties(type: Type | undefined): StringLiteralCompletionsFromProperties | undefined { return type && { kind: StringLiteralCompletionKind.Properties, - symbols: ts.filter(type.getApparentProperties(), prop => !(prop.valueDeclaration && ts.isPrivateIdentifierClassElementDeclaration(prop.valueDeclaration))), - hasIndexSignature: ts.hasIndexSignature(type) + symbols: filter(type.getApparentProperties(), prop => !(prop.valueDeclaration && isPrivateIdentifierClassElementDeclaration(prop.valueDeclaration))), + hasIndexSignature: hasIndexSignature(type) }; } -function stringLiteralCompletionsForObjectLiteral(checker: ts.TypeChecker, objectLiteralExpression: ts.ObjectLiteralExpression): StringLiteralCompletionsFromProperties | undefined { +function stringLiteralCompletionsForObjectLiteral(checker: TypeChecker, objectLiteralExpression: ObjectLiteralExpression): StringLiteralCompletionsFromProperties | undefined { const contextualType = checker.getContextualType(objectLiteralExpression); if (!contextualType) return undefined; - const completionsType = checker.getContextualType(objectLiteralExpression, ts.ContextFlags.Completions); - const symbols = ts.Completions.getPropertiesForObjectExpression( + const completionsType = checker.getContextualType(objectLiteralExpression, ContextFlags.Completions); + const symbols = getPropertiesForObjectExpression( contextualType, completionsType, objectLiteralExpression, @@ -329,94 +358,94 @@ function stringLiteralCompletionsForObjectLiteral(checker: ts.TypeChecker, objec return { kind: StringLiteralCompletionKind.Properties, symbols, - hasIndexSignature: ts.hasIndexSignature(contextualType) + hasIndexSignature: hasIndexSignature(contextualType) }; } -function getStringLiteralTypes(type: ts.Type | undefined, uniques = new ts.Map()): readonly ts.StringLiteralType[] { - if (!type) return ts.emptyArray; - type = ts.skipConstraint(type); - return type.isUnion() ? ts.flatMap(type.types, t => getStringLiteralTypes(t, uniques)) : - type.isStringLiteral() && !(type.flags & ts.TypeFlags.EnumLiteral) && ts.addToSeen(uniques, type.value) ? [type] : ts.emptyArray; +function getStringLiteralTypes(type: Type | undefined, uniques = new Map()): readonly StringLiteralType[] { + if (!type) return emptyArray; + type = skipConstraint(type); + return type.isUnion() ? flatMap(type.types, t => getStringLiteralTypes(t, uniques)) : + type.isStringLiteral() && !(type.flags & TypeFlags.EnumLiteral) && addToSeen(uniques, type.value) ? [type] : emptyArray; } interface NameAndKind { readonly name: string; - readonly kind: ts.ScriptElementKind.scriptElement | ts.ScriptElementKind.directory | ts.ScriptElementKind.externalModuleName; - readonly extension: ts.Extension | undefined; + readonly kind: ScriptElementKind.scriptElement | ScriptElementKind.directory | ScriptElementKind.externalModuleName; + readonly extension: Extension | undefined; } interface PathCompletion extends NameAndKind { - readonly span: ts.TextSpan | undefined; + readonly span: TextSpan | undefined; } -function nameAndKind(name: string, kind: NameAndKind["kind"], extension: ts.Extension | undefined): NameAndKind { +function nameAndKind(name: string, kind: NameAndKind["kind"], extension: Extension | undefined): NameAndKind { return { name, kind, extension }; } function directoryResult(name: string): NameAndKind { - return nameAndKind(name, ts.ScriptElementKind.directory, /*extension*/ undefined); + return nameAndKind(name, ScriptElementKind.directory, /*extension*/ undefined); } function addReplacementSpans(text: string, textStart: number, names: readonly NameAndKind[]): readonly PathCompletion[] { const span = getDirectoryFragmentTextSpan(text, textStart); - const wholeSpan = text.length === 0 ? undefined : ts.createTextSpan(textStart, text.length); + const wholeSpan = text.length === 0 ? undefined : createTextSpan(textStart, text.length); return names.map(({ name, kind, extension }): PathCompletion => - Math.max(name.indexOf(ts.directorySeparator), name.indexOf(ts.altDirectorySeparator)) !== -1 ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span }); + Math.max(name.indexOf(directorySeparator), name.indexOf(altDirectorySeparator)) !== -1 ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span }); } -function getStringLiteralCompletionsFromModuleNames(sourceFile: ts.SourceFile, node: ts.LiteralExpression, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, typeChecker: ts.TypeChecker, preferences: ts.UserPreferences): readonly PathCompletion[] { +function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly PathCompletion[] { return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker, preferences)); } -function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: ts.SourceFile, node: ts.LiteralExpression, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, typeChecker: ts.TypeChecker, preferences: ts.UserPreferences): readonly NameAndKind[] { - const literalValue = ts.normalizeSlashes(node.text); - const mode = ts.isStringLiteralLike(node) ? ts.getModeForUsageLocation(sourceFile, node) : undefined; +function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker, preferences: UserPreferences): readonly NameAndKind[] { + const literalValue = normalizeSlashes(node.text); + const mode = isStringLiteralLike(node) ? getModeForUsageLocation(sourceFile, node) : undefined; const scriptPath = sourceFile.path; - const scriptDirectory = ts.getDirectoryPath(scriptPath); + const scriptDirectory = getDirectoryPath(scriptPath); - return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (ts.isRootedDiskPath(literalValue) || ts.isUrl(literalValue)) + return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (isRootedDiskPath(literalValue) || isUrl(literalValue)) ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath, getIncludeExtensionOption()) : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, mode, compilerOptions, host, getIncludeExtensionOption(), typeChecker); function getIncludeExtensionOption() { - const mode = ts.isStringLiteralLike(node) ? ts.getModeForUsageLocation(sourceFile, node) : undefined; - return preferences.importModuleSpecifierEnding === "js" || mode === ts.ModuleKind.ESNext ? IncludeExtensionsOption.ModuleSpecifierCompletion : IncludeExtensionsOption.Exclude; + const mode = isStringLiteralLike(node) ? getModeForUsageLocation(sourceFile, node) : undefined; + return preferences.importModuleSpecifierEnding === "js" || mode === ModuleKind.ESNext ? IncludeExtensionsOption.ModuleSpecifierCompletion : IncludeExtensionsOption.Exclude; } } interface ExtensionOptions { - readonly extensions: readonly ts.Extension[]; + readonly extensions: readonly Extension[]; readonly includeExtensionsOption: IncludeExtensionsOption; } -function getExtensionOptions(compilerOptions: ts.CompilerOptions, includeExtensionsOption = IncludeExtensionsOption.Exclude): ExtensionOptions { - return { extensions: ts.flatten(getSupportedExtensionsForModuleResolution(compilerOptions)), includeExtensionsOption }; +function getExtensionOptions(compilerOptions: CompilerOptions, includeExtensionsOption = IncludeExtensionsOption.Exclude): ExtensionOptions { + return { extensions: flatten(getSupportedExtensionsForModuleResolution(compilerOptions)), includeExtensionsOption }; } -function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, scriptPath: ts.Path, includeExtensions: IncludeExtensionsOption) { +function getCompletionEntriesForRelativeModules(literalValue: string, scriptDirectory: string, compilerOptions: CompilerOptions, host: LanguageServiceHost, scriptPath: Path, includeExtensions: IncludeExtensionsOption) { const extensionOptions = getExtensionOptions(compilerOptions, includeExtensions); if (compilerOptions.rootDirs) { return getCompletionEntriesForDirectoryFragmentWithRootDirs( compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath); } else { - return ts.arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, scriptPath).values()); + return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, scriptPath).values()); } } -function isEmitResolutionKindUsingNodeModules(compilerOptions: ts.CompilerOptions): boolean { - return ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs || - ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Node16 || - ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeNext; +function isEmitResolutionKindUsingNodeModules(compilerOptions: CompilerOptions): boolean { + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeJs || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext; } -function isEmitModuleResolutionRespectingExportMaps(compilerOptions: ts.CompilerOptions) { - return ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.Node16 || - ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeNext; +function isEmitModuleResolutionRespectingExportMaps(compilerOptions: CompilerOptions) { + return getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || + getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext; } -function getSupportedExtensionsForModuleResolution(compilerOptions: ts.CompilerOptions): readonly ts.Extension[][] { - const extensions = ts.getSupportedExtensions(compilerOptions); +function getSupportedExtensionsForModuleResolution(compilerOptions: CompilerOptions): readonly Extension[][] { + const extensions = getSupportedExtensions(compilerOptions); return isEmitResolutionKindUsingNodeModules(compilerOptions) ? - ts.getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) : + getSupportedExtensionsWithJsonIfResolveJsonModule(compilerOptions, extensions) : extensions; } @@ -426,24 +455,24 @@ function getSupportedExtensionsForModuleResolution(compilerOptions: ts.CompilerO */ function getBaseDirectoriesFromRootDirs(rootDirs: string[], basePath: string, scriptDirectory: string, ignoreCase: boolean): readonly string[] { // Make all paths absolute/normalized if they are not already - rootDirs = rootDirs.map(rootDirectory => ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory))); + rootDirs = rootDirs.map(rootDirectory => normalizePath(isRootedDiskPath(rootDirectory) ? rootDirectory : combinePaths(basePath, rootDirectory))); // Determine the path to the directory containing the script relative to the root directory it is contained within - const relativeDirectory = ts.firstDefined(rootDirs, rootDirectory => - ts.containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) ? scriptDirectory.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217 + const relativeDirectory = firstDefined(rootDirs, rootDirectory => + containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) ? scriptDirectory.substr(rootDirectory.length) : undefined)!; // TODO: GH#18217 // Now find a path for each potential directory that is to be merged with the one containing the script - return ts.deduplicate( - [...rootDirs.map(rootDirectory => ts.combinePaths(rootDirectory, relativeDirectory)), scriptDirectory], - ts.equateStringsCaseSensitive, - ts.compareStringsCaseSensitive); + return deduplicate( + [...rootDirs.map(rootDirectory => combinePaths(rootDirectory, relativeDirectory)), scriptDirectory], + equateStringsCaseSensitive, + compareStringsCaseSensitive); } -function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost, exclude: string): readonly NameAndKind[] { +function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[], fragment: string, scriptDirectory: string, extensionOptions: ExtensionOptions, compilerOptions: CompilerOptions, host: LanguageServiceHost, exclude: string): readonly NameAndKind[] { const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); - return ts.flatMap(baseDirectories, baseDirectory => ts.arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude).values())); + return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude).values())); } const enum IncludeExtensionsOption { @@ -458,7 +487,7 @@ function getCompletionEntriesForDirectoryFragment( fragment: string, scriptPath: string, extensionOptions: ExtensionOptions, - host: ts.LanguageServiceHost, + host: LanguageServiceHost, exclude?: string, result = createNameAndKindSet() ): NameAndKindSet { @@ -466,35 +495,35 @@ function getCompletionEntriesForDirectoryFragment( fragment = ""; } - fragment = ts.normalizeSlashes(fragment); + fragment = normalizeSlashes(fragment); /** * Remove the basename from the path. Note that we don't use the basename to filter completions; * the client is responsible for refining completions. */ - if (!ts.hasTrailingDirectorySeparator(fragment)) { - fragment = ts.getDirectoryPath(fragment); + if (!hasTrailingDirectorySeparator(fragment)) { + fragment = getDirectoryPath(fragment); } if (fragment === "") { - fragment = "." + ts.directorySeparator; + fragment = "." + directorySeparator; } - fragment = ts.ensureTrailingDirectorySeparator(fragment); + fragment = ensureTrailingDirectorySeparator(fragment); - const absolutePath = ts.resolvePath(scriptPath, fragment); - const baseDirectory = ts.hasTrailingDirectorySeparator(absolutePath) ? absolutePath : ts.getDirectoryPath(absolutePath); + const absolutePath = resolvePath(scriptPath, fragment); + const baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath); // check for a version redirect - const packageJsonPath = ts.findPackageJson(baseDirectory, host); + const packageJsonPath = findPackageJson(baseDirectory, host); if (packageJsonPath) { - const packageJson = ts.readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined }); + const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined }); const typesVersions = (packageJson as any).typesVersions; if (typeof typesVersions === "object") { - const versionPaths = ts.getPackageJsonTypesVersionsPaths(typesVersions)?.paths; + const versionPaths = getPackageJsonTypesVersionsPaths(typesVersions)?.paths; if (versionPaths) { - const packageDirectory = ts.getDirectoryPath(packageJsonPath); - const pathInPackage = absolutePath.slice(ts.ensureTrailingDirectorySeparator(packageDirectory).length); + const packageDirectory = getDirectoryPath(packageJsonPath); + const pathInPackage = absolutePath.slice(ensureTrailingDirectorySeparator(packageDirectory).length); if (addCompletionEntriesFromPaths(result, pathInPackage, packageDirectory, extensionOptions, host, versionPaths)) { // A true result means one of the `versionPaths` was matched, which will block relative resolution // to files and folders from here. All reachable paths given the pattern match are already added. @@ -505,29 +534,29 @@ function getCompletionEntriesForDirectoryFragment( } const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); - if (!ts.tryDirectoryExists(host, baseDirectory)) return result; + if (!tryDirectoryExists(host, baseDirectory)) return result; // Enumerate the available files if possible - const files = ts.tryReadDirectory(host, baseDirectory, extensionOptions.extensions, /*exclude*/ undefined, /*include*/ ["./*"]); + const files = tryReadDirectory(host, baseDirectory, extensionOptions.extensions, /*exclude*/ undefined, /*include*/ ["./*"]); if (files) { for (let filePath of files) { - filePath = ts.normalizePath(filePath); - if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === ts.Comparison.EqualTo) { + filePath = normalizePath(filePath); + if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) { continue; } - const { name, extension } = getFilenameWithExtensionOption(ts.getBaseFileName(filePath), host.getCompilationSettings(), extensionOptions.includeExtensionsOption); - result.add(nameAndKind(name, ts.ScriptElementKind.scriptElement, extension)); + const { name, extension } = getFilenameWithExtensionOption(getBaseFileName(filePath), host.getCompilationSettings(), extensionOptions.includeExtensionsOption); + result.add(nameAndKind(name, ScriptElementKind.scriptElement, extension)); } } // If possible, get folder completion as well - const directories = ts.tryGetDirectories(host, baseDirectory); + const directories = tryGetDirectories(host, baseDirectory); if (directories) { for (const directory of directories) { - const directoryName = ts.getBaseFileName(ts.normalizePath(directory)); + const directoryName = getBaseFileName(normalizePath(directory)); if (directoryName !== "@types") { result.add(directoryResult(directoryName)); } @@ -537,16 +566,16 @@ function getCompletionEntriesForDirectoryFragment( return result; } -function getFilenameWithExtensionOption(name: string, compilerOptions: ts.CompilerOptions, includeExtensionsOption: IncludeExtensionsOption): { name: string, extension: ts.Extension | undefined } { - const outputExtension = ts.moduleSpecifiers.tryGetJSExtensionForFile(name, compilerOptions); - if (includeExtensionsOption === IncludeExtensionsOption.Exclude && !ts.fileExtensionIsOneOf(name, [ts.Extension.Json, ts.Extension.Mts, ts.Extension.Cts, ts.Extension.Dmts, ts.Extension.Dcts, ts.Extension.Mjs, ts.Extension.Cjs])) { - return { name: ts.removeFileExtension(name), extension: ts.tryGetExtensionFromPath(name) }; +function getFilenameWithExtensionOption(name: string, compilerOptions: CompilerOptions, includeExtensionsOption: IncludeExtensionsOption): { name: string, extension: Extension | undefined } { + const outputExtension = moduleSpecifiers.tryGetJSExtensionForFile(name, compilerOptions); + if (includeExtensionsOption === IncludeExtensionsOption.Exclude && !fileExtensionIsOneOf(name, [Extension.Json, Extension.Mts, Extension.Cts, Extension.Dmts, Extension.Dcts, Extension.Mjs, Extension.Cjs])) { + return { name: removeFileExtension(name), extension: tryGetExtensionFromPath(name) }; } - else if ((ts.fileExtensionIsOneOf(name, [ts.Extension.Mts, ts.Extension.Cts, ts.Extension.Dmts, ts.Extension.Dcts, ts.Extension.Mjs, ts.Extension.Cjs]) || includeExtensionsOption === IncludeExtensionsOption.ModuleSpecifierCompletion) && outputExtension) { - return { name: ts.changeExtension(name, outputExtension), extension: outputExtension }; + else if ((fileExtensionIsOneOf(name, [Extension.Mts, Extension.Cts, Extension.Dmts, Extension.Dcts, Extension.Mjs, Extension.Cjs]) || includeExtensionsOption === IncludeExtensionsOption.ModuleSpecifierCompletion) && outputExtension) { + return { name: changeExtension(name, outputExtension), extension: outputExtension }; } else { - return { name, extension: ts.tryGetExtensionFromPath(name) }; + return { name, extension: tryGetExtensionFromPath(name) }; } } @@ -556,18 +585,18 @@ function addCompletionEntriesFromPaths( fragment: string, baseDirectory: string, extensionOptions: ExtensionOptions, - host: ts.LanguageServiceHost, - paths: ts.MapLike + host: LanguageServiceHost, + paths: MapLike ) { const getPatternsForKey = (key: string) => paths[key]; - const comparePaths = (a: string, b: string): ts.Comparison => { - const patternA = ts.tryParsePattern(a); - const patternB = ts.tryParsePattern(b); + const comparePaths = (a: string, b: string): Comparison => { + const patternA = tryParsePattern(a); + const patternB = tryParsePattern(b); const lengthA = typeof patternA === "object" ? patternA.prefix.length : a.length; const lengthB = typeof patternB === "object" ? patternB.prefix.length : b.length; - return ts.compareValues(lengthB, lengthA); + return compareValues(lengthB, lengthA); }; - return addCompletionEntriesFromPathsOrExports(result, fragment, baseDirectory, extensionOptions, host, ts.getOwnKeys(paths), getPatternsForKey, comparePaths); + return addCompletionEntriesFromPathsOrExports(result, fragment, baseDirectory, extensionOptions, host, getOwnKeys(paths), getPatternsForKey, comparePaths); } /** @returns whether `fragment` was a match for any `paths` (which should indicate whether any other path completions should be offered) */ @@ -576,10 +605,10 @@ function addCompletionEntriesFromPathsOrExports( fragment: string, baseDirectory: string, extensionOptions: ExtensionOptions, - host: ts.LanguageServiceHost, + host: LanguageServiceHost, keys: readonly string[], getPatternsForKey: (key: string) => string[] | undefined, - comparePaths: (a: string, b: string) => ts.Comparison, + comparePaths: (a: string, b: string) => Comparison, ) { let pathResults: { results: NameAndKind[], matchedPattern: boolean }[] = []; let matchedPath: string | undefined; @@ -588,10 +617,10 @@ function addCompletionEntriesFromPathsOrExports( const keyWithoutLeadingDotSlash = key.replace(/^\.\//, ""); // remove leading "./" const patterns = getPatternsForKey(key); if (patterns) { - const pathPattern = ts.tryParsePattern(keyWithoutLeadingDotSlash); + const pathPattern = tryParsePattern(keyWithoutLeadingDotSlash); if (!pathPattern) continue; - const isMatch = typeof pathPattern === "object" && ts.isPatternMatch(pathPattern, fragment); - const isLongestMatch = isMatch && (matchedPath === undefined || comparePaths(key, matchedPath) === ts.Comparison.LessThan); + const isMatch = typeof pathPattern === "object" && isPatternMatch(pathPattern, fragment); + const isLongestMatch = isMatch && (matchedPath === undefined || comparePaths(key, matchedPath) === Comparison.LessThan); if (isLongestMatch) { // If this is a higher priority match than anything we've seen so far, previous results from matches are invalid, e.g. // for `import {} from "some-package/|"` with a typesVersions: @@ -607,7 +636,7 @@ function addCompletionEntriesFromPathsOrExports( matchedPath = key; pathResults = pathResults.filter(r => !r.matchedPattern); } - if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths(key, matchedPath) !== ts.Comparison.GreaterThan) { + if (typeof pathPattern === "string" || matchedPath === undefined || comparePaths(key, matchedPath) !== Comparison.GreaterThan) { pathResults.push({ matchedPattern: isMatch, results: getCompletionsForPathMapping(keyWithoutLeadingDotSlash, patterns, fragment, baseDirectory, extensionOptions, host) @@ -631,11 +660,11 @@ function addCompletionEntriesFromPathsOrExports( function getCompletionEntriesForNonRelativeModules( fragment: string, scriptPath: string, - mode: ts.SourceFile["impliedNodeFormat"], - compilerOptions: ts.CompilerOptions, - host: ts.LanguageServiceHost, + mode: SourceFile["impliedNodeFormat"], + compilerOptions: CompilerOptions, + host: LanguageServiceHost, includeExtensionsOption: IncludeExtensionsOption, - typeChecker: ts.TypeChecker, + typeChecker: TypeChecker, ): readonly NameAndKind[] { const { baseUrl, paths } = compilerOptions; @@ -643,7 +672,7 @@ function getCompletionEntriesForNonRelativeModules( const extensionOptions = getExtensionOptions(compilerOptions, includeExtensionsOption); if (baseUrl) { const projectDir = compilerOptions.project || host.getCurrentDirectory(); - const absolute = ts.normalizePath(ts.combinePaths(projectDir, baseUrl)); + const absolute = normalizePath(combinePaths(projectDir, baseUrl)); getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*exclude*/ undefined, result); if (paths) { addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions, host, paths); @@ -652,7 +681,7 @@ function getCompletionEntriesForNonRelativeModules( const fragmentDirectory = getFragmentDirectory(fragment); for (const ambientName of getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker)) { - result.add(nameAndKind(ambientName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.add(nameAndKind(ambientName, ScriptElementKind.externalModuleName, /*extension*/ undefined)); } getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result); @@ -663,7 +692,7 @@ function getCompletionEntriesForNonRelativeModules( let foundGlobal = false; if (fragmentDirectory === undefined) { for (const moduleName of enumerateNodeModulesVisibleToScript(host, scriptPath)) { - const moduleResult = nameAndKind(moduleName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined); + const moduleResult = nameAndKind(moduleName, ScriptElementKind.externalModuleName, /*extension*/ undefined); if (!result.has(moduleResult.name)) { foundGlobal = true; result.add(moduleResult); @@ -672,39 +701,39 @@ function getCompletionEntriesForNonRelativeModules( } if (!foundGlobal) { let ancestorLookup: (directory: string) => void | undefined = ancestor => { - const nodeModules = ts.combinePaths(ancestor, "node_modules"); - if (ts.tryDirectoryExists(host, nodeModules)) { + const nodeModules = combinePaths(ancestor, "node_modules"); + if (tryDirectoryExists(host, nodeModules)) { getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result); } }; if (fragmentDirectory && isEmitModuleResolutionRespectingExportMaps(compilerOptions)) { const nodeModulesDirectoryLookup = ancestorLookup; ancestorLookup = ancestor => { - const components = ts.getPathComponents(fragment); + const components = getPathComponents(fragment); components.shift(); // shift off empty root let packagePath = components.shift(); if (!packagePath) { return nodeModulesDirectoryLookup(ancestor); } - if (ts.startsWith(packagePath, "@")) { + if (startsWith(packagePath, "@")) { const subName = components.shift(); if (!subName) { return nodeModulesDirectoryLookup(ancestor); } - packagePath = ts.combinePaths(packagePath, subName); + packagePath = combinePaths(packagePath, subName); } - const packageDirectory = ts.combinePaths(ancestor, "node_modules", packagePath); - const packageFile = ts.combinePaths(packageDirectory, "package.json"); - if (ts.tryFileExists(host, packageFile)) { - const packageJson = ts.readJson(packageFile, host); + const packageDirectory = combinePaths(ancestor, "node_modules", packagePath); + const packageFile = combinePaths(packageDirectory, "package.json"); + if (tryFileExists(host, packageFile)) { + const packageJson = readJson(packageFile, host); const exports = (packageJson as any).exports; if (exports) { if (typeof exports !== "object" || exports === null) { // eslint-disable-line no-null/no-null return; // null exports or entrypoint only, no sub-modules available } - const keys = ts.getOwnKeys(exports); - const fragmentSubpath = components.join("/") + (components.length && ts.hasTrailingDirectorySeparator(fragment) ? "/" : ""); - const conditions = mode === ts.ModuleKind.ESNext ? ["node", "import", "types"] : ["node", "require", "types"]; + const keys = getOwnKeys(exports); + const fragmentSubpath = components.join("/") + (components.length && hasTrailingDirectorySeparator(fragment) ? "/" : ""); + const conditions = mode === ModuleKind.ESNext ? ["node", "import", "types"] : ["node", "require", "types"]; addCompletionEntriesFromPathsOrExports( result, fragmentSubpath, @@ -712,29 +741,29 @@ function getCompletionEntriesForNonRelativeModules( extensionOptions, host, keys, - key => ts.singleElementArray(getPatternFromFirstMatchingCondition(exports[key], conditions)), - ts.comparePatternKeys); + key => singleElementArray(getPatternFromFirstMatchingCondition(exports[key], conditions)), + comparePatternKeys); return; } } return nodeModulesDirectoryLookup(ancestor); }; } - ts.forEachAncestorDirectory(scriptPath, ancestorLookup); + forEachAncestorDirectory(scriptPath, ancestorLookup); } } - return ts.arrayFrom(result.values()); + return arrayFrom(result.values()); } function getPatternFromFirstMatchingCondition(target: unknown, conditions: readonly string[]): string | undefined { if (typeof target === "string") { return target; } - if (target && typeof target === "object" && !ts.isArray(target)) { + if (target && typeof target === "object" && !isArray(target)) { for (const condition in target) { - if (condition === "default" || conditions.indexOf(condition) > -1 || ts.isApplicableVersionedTypesKey(conditions, condition)) { - const pattern = (target as ts.MapLike)[condition]; + if (condition === "default" || conditions.indexOf(condition) > -1 || isApplicableVersionedTypesKey(conditions, condition)) { + const pattern = (target as MapLike)[condition]; return getPatternFromFirstMatchingCondition(pattern, conditions); } } @@ -742,7 +771,7 @@ function getPatternFromFirstMatchingCondition(target: unknown, conditions: reado } function getFragmentDirectory(fragment: string): string | undefined { - return containsSlash(fragment) ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; + return containsSlash(fragment) ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined; } function getCompletionsForPathMapping( @@ -751,24 +780,24 @@ function getCompletionsForPathMapping( fragment: string, packageDirectory: string, extensionOptions: ExtensionOptions, - host: ts.LanguageServiceHost, + host: LanguageServiceHost, ): readonly NameAndKind[] { - if (!ts.endsWith(path, "*")) { + if (!endsWith(path, "*")) { // For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion. - return !ts.stringContains(path, "*") ? justPathMappingName(path, ts.ScriptElementKind.scriptElement) : ts.emptyArray; + return !stringContains(path, "*") ? justPathMappingName(path, ScriptElementKind.scriptElement) : emptyArray; } const pathPrefix = path.slice(0, path.length - 1); - const remainingFragment = ts.tryRemovePrefix(fragment, pathPrefix); + const remainingFragment = tryRemovePrefix(fragment, pathPrefix); if (remainingFragment === undefined) { const starIsFullPathComponent = path[path.length - 2] === "/"; - return starIsFullPathComponent ? justPathMappingName(pathPrefix, ts.ScriptElementKind.directory) : ts.flatMap(patterns, pattern => + return starIsFullPathComponent ? justPathMappingName(pathPrefix, ScriptElementKind.directory) : flatMap(patterns, pattern => getModulesForPathsPattern("", packageDirectory, pattern, extensionOptions, host)?.map(({ name, ...rest }) => ({ name: pathPrefix + name, ...rest }))); } - return ts.flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, host)); + return flatMap(patterns, pattern => getModulesForPathsPattern(remainingFragment, packageDirectory, pattern, extensionOptions, host)); - function justPathMappingName(name: string, kind: ts.ScriptElementKind.directory | ts.ScriptElementKind.scriptElement): readonly NameAndKind[] { - return ts.startsWith(name, fragment) ? [{ name: ts.removeTrailingDirectorySeparator(name), kind, extension: undefined }] : ts.emptyArray; + function justPathMappingName(name: string, kind: ScriptElementKind.directory | ScriptElementKind.scriptElement): readonly NameAndKind[] { + return startsWith(name, fragment) ? [{ name: removeTrailingDirectorySeparator(name), kind, extension: undefined }] : emptyArray; } } @@ -777,33 +806,33 @@ function getModulesForPathsPattern( packageDirectory: string, pattern: string, extensionOptions: ExtensionOptions, - host: ts.LanguageServiceHost, + host: LanguageServiceHost, ): readonly NameAndKind[] | undefined { if (!host.readDirectory) { return undefined; } - const parsed = ts.tryParsePattern(pattern); - if (parsed === undefined || ts.isString(parsed)) { + const parsed = tryParsePattern(pattern); + if (parsed === undefined || isString(parsed)) { return undefined; } // The prefix has two effective parts: the directory path and the base component after the filepath that is not a // full directory component. For example: directory/path/of/prefix/base* - const normalizedPrefix = ts.resolvePath(parsed.prefix); - const normalizedPrefixDirectory = ts.hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : ts.getDirectoryPath(normalizedPrefix); - const normalizedPrefixBase = ts.hasTrailingDirectorySeparator(parsed.prefix) ? "" : ts.getBaseFileName(normalizedPrefix); + const normalizedPrefix = resolvePath(parsed.prefix); + const normalizedPrefixDirectory = hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : getDirectoryPath(normalizedPrefix); + const normalizedPrefixBase = hasTrailingDirectorySeparator(parsed.prefix) ? "" : getBaseFileName(normalizedPrefix); const fragmentHasPath = containsSlash(fragment); - const fragmentDirectory = fragmentHasPath ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined; + const fragmentDirectory = fragmentHasPath ? hasTrailingDirectorySeparator(fragment) ? fragment : getDirectoryPath(fragment) : undefined; // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call - const expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; + const expandedPrefixDirectory = fragmentHasPath ? combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory; - const normalizedSuffix = ts.normalizePath(parsed.suffix); + const normalizedSuffix = normalizePath(parsed.suffix); // Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b". - const baseDirectory = ts.normalizePath(ts.combinePaths(packageDirectory, expandedPrefixDirectory)); - const completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; + const baseDirectory = normalizePath(combinePaths(packageDirectory, expandedPrefixDirectory)); + const completePrefix = fragmentHasPath ? baseDirectory : ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase; // If we have a suffix, then we read the directory all the way down to avoid returning completions for // directories that don't contain files that would match the suffix. A previous comment here was concerned @@ -815,14 +844,14 @@ function getModulesForPathsPattern( // done. const includeGlob = normalizedSuffix ? "**/*" + normalizedSuffix : "./*"; - const matches = ts.mapDefined(ts.tryReadDirectory(host, baseDirectory, extensionOptions.extensions, /*exclude*/ undefined, [includeGlob]), match => { + const matches = mapDefined(tryReadDirectory(host, baseDirectory, extensionOptions.extensions, /*exclude*/ undefined, [includeGlob]), match => { const trimmedWithPattern = trimPrefixAndSuffix(match); if (trimmedWithPattern) { if (containsSlash(trimmedWithPattern)) { - return directoryResult(ts.getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); + return directoryResult(getPathComponents(removeLeadingDirectorySeparator(trimmedWithPattern))[1]); } const { name, extension } = getFilenameWithExtensionOption(trimmedWithPattern, host.getCompilationSettings(), extensionOptions.includeExtensionsOption); - return nameAndKind(name, ts.ScriptElementKind.scriptElement, extension); + return nameAndKind(name, ScriptElementKind.scriptElement, extension); } }); @@ -830,43 +859,43 @@ function getModulesForPathsPattern( // it and returned the directories leading to those files. Otherwise, assume any directory could // have something valid to import. const directories = normalizedSuffix - ? ts.emptyArray - : ts.mapDefined(ts.tryGetDirectories(host, baseDirectory), dir => dir === "node_modules" ? undefined : directoryResult(dir)); + ? emptyArray + : mapDefined(tryGetDirectories(host, baseDirectory), dir => dir === "node_modules" ? undefined : directoryResult(dir)); return [...matches, ...directories]; function trimPrefixAndSuffix(path: string): string | undefined { - const inner = withoutStartAndEnd(ts.normalizePath(path), completePrefix, normalizedSuffix); + const inner = withoutStartAndEnd(normalizePath(path), completePrefix, normalizedSuffix); return inner === undefined ? undefined : removeLeadingDirectorySeparator(inner); } } function withoutStartAndEnd(s: string, start: string, end: string): string | undefined { - return ts.startsWith(s, start) && ts.endsWith(s, end) ? s.slice(start.length, s.length - end.length) : undefined; + return startsWith(s, start) && endsWith(s, end) ? s.slice(start.length, s.length - end.length) : undefined; } function removeLeadingDirectorySeparator(path: string): string { - return path[0] === ts.directorySeparator ? path.slice(1) : path; + return path[0] === directorySeparator ? path.slice(1) : path; } -function getAmbientModuleCompletions(fragment: string, fragmentDirectory: string | undefined, checker: ts.TypeChecker): readonly string[] { +function getAmbientModuleCompletions(fragment: string, fragmentDirectory: string | undefined, checker: TypeChecker): readonly string[] { // Get modules that the type checker picked up - const ambientModules = checker.getAmbientModules().map(sym => ts.stripQuotes(sym.name)); - const nonRelativeModuleNames = ambientModules.filter(moduleName => ts.startsWith(moduleName, fragment)); + const ambientModules = checker.getAmbientModules().map(sym => stripQuotes(sym.name)); + const nonRelativeModuleNames = ambientModules.filter(moduleName => startsWith(moduleName, fragment)); // Nested modules of the form "module-name/sub" need to be adjusted to only return the string // after the last '/' that appears in the fragment because that's where the replacement span // starts if (fragmentDirectory !== undefined) { - const moduleNameWithSeparator = ts.ensureTrailingDirectorySeparator(fragmentDirectory); - return nonRelativeModuleNames.map(nonRelativeModuleName => ts.removePrefix(nonRelativeModuleName, moduleNameWithSeparator)); + const moduleNameWithSeparator = ensureTrailingDirectorySeparator(fragmentDirectory); + return nonRelativeModuleNames.map(nonRelativeModuleName => removePrefix(nonRelativeModuleName, moduleNameWithSeparator)); } return nonRelativeModuleNames; } -function getTripleSlashReferenceCompletion(sourceFile: ts.SourceFile, position: number, compilerOptions: ts.CompilerOptions, host: ts.LanguageServiceHost): readonly PathCompletion[] | undefined { - const token = ts.getTokenAtPosition(sourceFile, position); - const commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos); - const range = commentRanges && ts.find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end); +function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): readonly PathCompletion[] | undefined { + const token = getTokenAtPosition(sourceFile, position); + const commentRanges = getLeadingCommentRanges(sourceFile.text, token.pos); + const range = commentRanges && find(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end); if (!range) { return undefined; } @@ -877,47 +906,47 @@ function getTripleSlashReferenceCompletion(sourceFile: ts.SourceFile, position: } const [, prefix, kind, toComplete] = match; - const scriptPath = ts.getDirectoryPath(sourceFile.path); + const scriptPath = getDirectoryPath(sourceFile.path); const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, IncludeExtensionsOption.Include), host, sourceFile.path) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions)) - : ts.Debug.fail(); - return addReplacementSpans(toComplete, range.pos + prefix.length, ts.arrayFrom(names.values())); + : Debug.fail(); + return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); } -function getCompletionEntriesFromTypings(host: ts.LanguageServiceHost, options: ts.CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { +function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { // Check for typings specified in compiler options - const seen = new ts.Map(); + const seen = new Map(); - const typeRoots = ts.tryAndIgnoreErrors(() => ts.getEffectiveTypeRoots(options, host)) || ts.emptyArray; + const typeRoots = tryAndIgnoreErrors(() => getEffectiveTypeRoots(options, host)) || emptyArray; for (const root of typeRoots) { getCompletionEntriesFromDirectories(root); } // Also get all @types typings installed in visible node_modules directories - for (const packageJson of ts.findPackageJsons(scriptPath, host)) { - const typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types"); + for (const packageJson of findPackageJsons(scriptPath, host)) { + const typesDir = combinePaths(getDirectoryPath(packageJson), "node_modules/@types"); getCompletionEntriesFromDirectories(typesDir); } return result; function getCompletionEntriesFromDirectories(directory: string): void { - if (!ts.tryDirectoryExists(host, directory)) return; + if (!tryDirectoryExists(host, directory)) return; - for (const typeDirectoryName of ts.tryGetDirectories(host, directory)) { - const packageName = ts.unmangleScopedPackageName(typeDirectoryName); - if (options.types && !ts.contains(options.types, packageName)) continue; + for (const typeDirectoryName of tryGetDirectories(host, directory)) { + const packageName = unmangleScopedPackageName(typeDirectoryName); + if (options.types && !contains(options.types, packageName)) continue; if (fragmentDirectory === undefined) { if (!seen.has(packageName)) { - result.add(nameAndKind(packageName, ts.ScriptElementKind.externalModuleName, /*extension*/ undefined)); + result.add(nameAndKind(packageName, ScriptElementKind.externalModuleName, /*extension*/ undefined)); seen.set(packageName, true); } } else { - const baseDirectory = ts.combinePaths(directory, typeDirectoryName); - const remainingFragment = ts.tryRemoveDirectoryPrefix(fragmentDirectory, packageName, ts.hostGetCanonicalFileName(host)); + const baseDirectory = combinePaths(directory, typeDirectoryName); + const remainingFragment = tryRemoveDirectoryPrefix(fragmentDirectory, packageName, hostGetCanonicalFileName(host)); if (remainingFragment !== undefined) { getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*exclude*/ undefined, result); } @@ -926,18 +955,18 @@ function getCompletionEntriesFromTypings(host: ts.LanguageServiceHost, options: } } -function enumerateNodeModulesVisibleToScript(host: ts.LanguageServiceHost, scriptPath: string): readonly string[] { - if (!host.readFile || !host.fileExists) return ts.emptyArray; +function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string): readonly string[] { + if (!host.readFile || !host.fileExists) return emptyArray; const result: string[] = []; - for (const packageJson of ts.findPackageJsons(scriptPath, host)) { - const contents = ts.readJson(packageJson, host as { readFile: (filename: string) => string | undefined }); // Cast to assert that readFile is defined + for (const packageJson of findPackageJsons(scriptPath, host)) { + const contents = readJson(packageJson, host as { readFile: (filename: string) => string | undefined }); // Cast to assert that readFile is defined // Provide completions for all non @types dependencies for (const key of nodeModulesDependencyKeys) { const dependencies: object | undefined = (contents as any)[key]; if (!dependencies) continue; for (const dep in dependencies) { - if (ts.hasProperty(dependencies, dep) && !ts.startsWith(dep, "@types/")) { + if (hasProperty(dependencies, dep) && !startsWith(dep, "@types/")) { result.push(dep); } } @@ -947,20 +976,20 @@ function enumerateNodeModulesVisibleToScript(host: ts.LanguageServiceHost, scrip } // Replace everything after the last directory separator that appears -function getDirectoryFragmentTextSpan(text: string, textStart: number): ts.TextSpan | undefined { - const index = Math.max(text.lastIndexOf(ts.directorySeparator), text.lastIndexOf(ts.altDirectorySeparator)); +function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan | undefined { + const index = Math.max(text.lastIndexOf(directorySeparator), text.lastIndexOf(altDirectorySeparator)); const offset = index !== -1 ? index + 1 : 0; // If the range is an identifier, span is unnecessary. const length = text.length - offset; - return length === 0 || ts.isIdentifierText(text.substr(offset, length), ts.ScriptTarget.ESNext) ? undefined : ts.createTextSpan(textStart + offset, length); + return length === 0 || isIdentifierText(text.substr(offset, length), ScriptTarget.ESNext) ? undefined : createTextSpan(textStart + offset, length); } // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..) function isPathRelativeToScript(path: string) { - if (path && path.length >= 2 && path.charCodeAt(0) === ts.CharacterCodes.dot) { - const slashIndex = path.length >= 3 && path.charCodeAt(1) === ts.CharacterCodes.dot ? 2 : 1; + if (path && path.length >= 2 && path.charCodeAt(0) === CharacterCodes.dot) { + const slashIndex = path.length >= 3 && path.charCodeAt(1) === CharacterCodes.dot ? 2 : 1; const slashCharCode = path.charCodeAt(slashIndex); - return slashCharCode === ts.CharacterCodes.slash || slashCharCode === ts.CharacterCodes.backslash; + return slashCharCode === CharacterCodes.slash || slashCharCode === CharacterCodes.backslash; } return false; } @@ -982,7 +1011,7 @@ const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*(); +const visitedNestedConvertibleFunctions = new Map(); /** @internal */ -export function computeSuggestionDiagnostics(sourceFile: ts.SourceFile, program: ts.Program, cancellationToken: ts.CancellationToken): ts.DiagnosticWithLocation[] { +export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken): DiagnosticWithLocation[] { program.getSemanticDiagnostics(sourceFile, cancellationToken); - const diags: ts.DiagnosticWithLocation[] = []; + const diags: DiagnosticWithLocation[] = []; const checker = program.getTypeChecker(); - const isCommonJSFile = sourceFile.impliedNodeFormat === ts.ModuleKind.CommonJS || ts.fileExtensionIsOneOf(sourceFile.fileName, [ts.Extension.Cts, ts.Extension.Cjs]) ; + const isCommonJSFile = sourceFile.impliedNodeFormat === ModuleKind.CommonJS || fileExtensionIsOneOf(sourceFile.fileName, [Extension.Cts, Extension.Cjs]) ; if (!isCommonJSFile && sourceFile.commonJsModuleIndicator && - (ts.programContainsEsModules(program) || ts.compilerOptionsIndicateEsModules(program.getCompilerOptions())) && + (programContainsEsModules(program) || compilerOptionsIndicateEsModules(program.getCompilerOptions())) && containsTopLevelCommonjs(sourceFile)) { - diags.push(ts.createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_module)); + diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES_module)); } - const isJsFile = ts.isSourceFileJS(sourceFile); + const isJsFile = isSourceFileJS(sourceFile); visitedNestedConvertibleFunctions.clear(); check(sourceFile); - if (ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())) { + if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) { for (const moduleSpecifier of sourceFile.imports) { - const importNode = ts.importFromModuleSpecifier(moduleSpecifier); + const importNode = importFromModuleSpecifier(moduleSpecifier); const name = importNameForConvertToDefaultImport(importNode); if (!name) continue; - const module = ts.getResolvedModule(sourceFile, moduleSpecifier.text, ts.getModeForUsageLocation(sourceFile, moduleSpecifier)); + const module = getResolvedModule(sourceFile, moduleSpecifier.text, getModeForUsageLocation(sourceFile, moduleSpecifier)); const resolvedFile = module && program.getSourceFile(module.resolvedFileName); - if (resolvedFile && resolvedFile.externalModuleIndicator && resolvedFile.externalModuleIndicator !== true && ts.isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) { - diags.push(ts.createDiagnosticForNode(name, ts.Diagnostics.Import_may_be_converted_to_a_default_import)); + if (resolvedFile && resolvedFile.externalModuleIndicator && resolvedFile.externalModuleIndicator !== true && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) { + diags.push(createDiagnosticForNode(name, Diagnostics.Import_may_be_converted_to_a_default_import)); } } } - ts.addRange(diags, sourceFile.bindSuggestionDiagnostics); - ts.addRange(diags, program.getSuggestionDiagnostics(sourceFile, cancellationToken)); + addRange(diags, sourceFile.bindSuggestionDiagnostics); + addRange(diags, program.getSuggestionDiagnostics(sourceFile, cancellationToken)); return diags.sort((d1, d2) => d1.start - d2.start); - function check(node: ts.Node) { + function check(node: Node) { if (isJsFile) { if (canBeConvertedToClass(node, checker)) { - diags.push(ts.createDiagnosticForNode(ts.isVariableDeclaration(node.parent) ? node.parent.name : node, ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); + diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration)); } } else { - if (ts.isVariableStatement(node) && + if (isVariableStatement(node) && node.parent === sourceFile && - node.declarationList.flags & ts.NodeFlags.Const && + node.declarationList.flags & NodeFlags.Const && node.declarationList.declarations.length === 1) { const init = node.declarationList.declarations[0].initializer; - if (init && ts.isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) { - diags.push(ts.createDiagnosticForNode(init, ts.Diagnostics.require_call_may_be_converted_to_an_import)); + if (init && isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) { + diags.push(createDiagnosticForNode(init, Diagnostics.require_call_may_be_converted_to_an_import)); } } - if (ts.codefix.parameterShouldGetTypeFromJSDoc(node)) { - diags.push(ts.createDiagnosticForNode(node.name || node, ts.Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types)); + if (codefix.parameterShouldGetTypeFromJSDoc(node)) { + diags.push(createDiagnosticForNode(node.name || node, Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types)); } } @@ -68,17 +79,17 @@ export function computeSuggestionDiagnostics(sourceFile: ts.SourceFile, program: } // convertToEsModule only works on top-level, so don't trigger it if commonjs code only appears in nested scopes. -function containsTopLevelCommonjs(sourceFile: ts.SourceFile): boolean { +function containsTopLevelCommonjs(sourceFile: SourceFile): boolean { return sourceFile.statements.some(statement => { switch (statement.kind) { - case ts.SyntaxKind.VariableStatement: - return (statement as ts.VariableStatement).declarationList.declarations.some(decl => - !!decl.initializer && ts.isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true)); - case ts.SyntaxKind.ExpressionStatement: { - const { expression } = statement as ts.ExpressionStatement; - if (!ts.isBinaryExpression(expression)) return ts.isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); - const kind = ts.getAssignmentDeclarationKind(expression); - return kind === ts.AssignmentDeclarationKind.ExportsProperty || kind === ts.AssignmentDeclarationKind.ModuleExports; + case SyntaxKind.VariableStatement: + return (statement as VariableStatement).declarationList.declarations.some(decl => + !!decl.initializer && isRequireCall(propertyAccessLeftHandSide(decl.initializer), /*checkArgumentIsStringLiteralLike*/ true)); + case SyntaxKind.ExpressionStatement: { + const { expression } = statement as ExpressionStatement; + if (!isBinaryExpression(expression)) return isRequireCall(expression, /*checkArgumentIsStringLiteralLike*/ true); + const kind = getAssignmentDeclarationKind(expression); + return kind === AssignmentDeclarationKind.ExportsProperty || kind === AssignmentDeclarationKind.ModuleExports; } default: return false; @@ -86,64 +97,64 @@ function containsTopLevelCommonjs(sourceFile: ts.SourceFile): boolean { }); } -function propertyAccessLeftHandSide(node: ts.Expression): ts.Expression { - return ts.isPropertyAccessExpression(node) ? propertyAccessLeftHandSide(node.expression) : node; +function propertyAccessLeftHandSide(node: Expression): Expression { + return isPropertyAccessExpression(node) ? propertyAccessLeftHandSide(node.expression) : node; } -function importNameForConvertToDefaultImport(node: ts.AnyValidImportOrReExport): ts.Identifier | undefined { +function importNameForConvertToDefaultImport(node: AnyValidImportOrReExport): Identifier | undefined { switch (node.kind) { - case ts.SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportDeclaration: const { importClause, moduleSpecifier } = node; - return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport && ts.isStringLiteral(moduleSpecifier) + return importClause && !importClause.name && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier) ? importClause.namedBindings.name : undefined; - case ts.SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportEqualsDeclaration: return node.name; default: return undefined; } } -function addConvertToAsyncFunctionDiagnostics(node: ts.FunctionLikeDeclaration, checker: ts.TypeChecker, diags: ts.Push): void { +function addConvertToAsyncFunctionDiagnostics(node: FunctionLikeDeclaration, checker: TypeChecker, diags: Push): void { // need to check function before checking map so that deeper levels of nested callbacks are checked if (isConvertibleFunction(node, checker) && !visitedNestedConvertibleFunctions.has(getKeyFromNode(node))) { - diags.push(ts.createDiagnosticForNode( - !node.name && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name) ? node.parent.name : node, - ts.Diagnostics.This_may_be_converted_to_an_async_function)); + diags.push(createDiagnosticForNode( + !node.name && isVariableDeclaration(node.parent) && isIdentifier(node.parent.name) ? node.parent.name : node, + Diagnostics.This_may_be_converted_to_an_async_function)); } } -function isConvertibleFunction(node: ts.FunctionLikeDeclaration, checker: ts.TypeChecker) { - return !ts.isAsyncFunction(node) && +function isConvertibleFunction(node: FunctionLikeDeclaration, checker: TypeChecker) { + return !isAsyncFunction(node) && node.body && - ts.isBlock(node.body) && + isBlock(node.body) && hasReturnStatementWithPromiseHandler(node.body, checker) && returnsPromise(node, checker); } /** @internal */ -export function returnsPromise(node: ts.FunctionLikeDeclaration, checker: ts.TypeChecker): boolean { +export function returnsPromise(node: FunctionLikeDeclaration, checker: TypeChecker): boolean { const signature = checker.getSignatureFromDeclaration(node); const returnType = signature ? checker.getReturnTypeOfSignature(signature) : undefined; return !!returnType && !!checker.getPromisedTypeOfPromise(returnType); } -function getErrorNodeFromCommonJsIndicator(commonJsModuleIndicator: ts.Node): ts.Node { - return ts.isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator; +function getErrorNodeFromCommonJsIndicator(commonJsModuleIndicator: Node): Node { + return isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator; } -function hasReturnStatementWithPromiseHandler(body: ts.Block, checker: ts.TypeChecker): boolean { - return !!ts.forEachReturnStatement(body, statement => isReturnStatementWithFixablePromiseHandler(statement, checker)); +function hasReturnStatementWithPromiseHandler(body: Block, checker: TypeChecker): boolean { + return !!forEachReturnStatement(body, statement => isReturnStatementWithFixablePromiseHandler(statement, checker)); } /** @internal */ -export function isReturnStatementWithFixablePromiseHandler(node: ts.Node, checker: ts.TypeChecker): node is ts.ReturnStatement & { expression: ts.CallExpression } { - return ts.isReturnStatement(node) && !!node.expression && isFixablePromiseHandler(node.expression, checker); +export function isReturnStatementWithFixablePromiseHandler(node: Node, checker: TypeChecker): node is ReturnStatement & { expression: CallExpression } { + return isReturnStatement(node) && !!node.expression && isFixablePromiseHandler(node.expression, checker); } // Should be kept up to date with transformExpression in convertToAsyncFunction.ts /** @internal */ -export function isFixablePromiseHandler(node: ts.Node, checker: ts.TypeChecker): boolean { +export function isFixablePromiseHandler(node: Node, checker: TypeChecker): boolean { // ensure outermost call exists and is a promise handler if (!isPromiseHandler(node) || !hasSupportedNumberOfArguments(node) || !node.arguments.every(arg => isFixablePromiseArgument(arg, checker))) { return false; @@ -151,8 +162,8 @@ export function isFixablePromiseHandler(node: ts.Node, checker: ts.TypeChecker): // ensure all chained calls are valid let currentNode = node.expression.expression; - while (isPromiseHandler(currentNode) || ts.isPropertyAccessExpression(currentNode)) { - if (ts.isCallExpression(currentNode)) { + while (isPromiseHandler(currentNode) || isPropertyAccessExpression(currentNode)) { + if (isCallExpression(currentNode)) { if (!hasSupportedNumberOfArguments(currentNode) || !currentNode.arguments.every(arg => isFixablePromiseArgument(arg, checker))) { return false; } @@ -165,59 +176,59 @@ export function isFixablePromiseHandler(node: ts.Node, checker: ts.TypeChecker): return true; } -function isPromiseHandler(node: ts.Node): node is ts.CallExpression & { readonly expression: ts.PropertyAccessExpression } { - return ts.isCallExpression(node) && ( - ts.hasPropertyAccessExpressionWithName(node, "then") || - ts.hasPropertyAccessExpressionWithName(node, "catch") || - ts.hasPropertyAccessExpressionWithName(node, "finally")); +function isPromiseHandler(node: Node): node is CallExpression & { readonly expression: PropertyAccessExpression } { + return isCallExpression(node) && ( + hasPropertyAccessExpressionWithName(node, "then") || + hasPropertyAccessExpressionWithName(node, "catch") || + hasPropertyAccessExpressionWithName(node, "finally")); } -function hasSupportedNumberOfArguments(node: ts.CallExpression & { readonly expression: ts.PropertyAccessExpression }) { +function hasSupportedNumberOfArguments(node: CallExpression & { readonly expression: PropertyAccessExpression }) { const name = node.expression.name.text; const maxArguments = name === "then" ? 2 : name === "catch" ? 1 : name === "finally" ? 1 : 0; if (node.arguments.length > maxArguments) return false; if (node.arguments.length < maxArguments) return true; - return maxArguments === 1 || ts.some(node.arguments, arg => { - return arg.kind === ts.SyntaxKind.NullKeyword || ts.isIdentifier(arg) && arg.text === "undefined"; + return maxArguments === 1 || some(node.arguments, arg => { + return arg.kind === SyntaxKind.NullKeyword || isIdentifier(arg) && arg.text === "undefined"; }); } // should be kept up to date with getTransformationBody in convertToAsyncFunction.ts -function isFixablePromiseArgument(arg: ts.Expression, checker: ts.TypeChecker): boolean { +function isFixablePromiseArgument(arg: Expression, checker: TypeChecker): boolean { switch (arg.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - const functionFlags = ts.getFunctionFlags(arg as ts.FunctionDeclaration | ts.FunctionExpression); - if (functionFlags & ts.FunctionFlags.Generator) { + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + const functionFlags = getFunctionFlags(arg as FunctionDeclaration | FunctionExpression); + if (functionFlags & FunctionFlags.Generator) { return false; } // falls through - case ts.SyntaxKind.ArrowFunction: - visitedNestedConvertibleFunctions.set(getKeyFromNode(arg as ts.FunctionLikeDeclaration), true); + case SyntaxKind.ArrowFunction: + visitedNestedConvertibleFunctions.set(getKeyFromNode(arg as FunctionLikeDeclaration), true); // falls through - case ts.SyntaxKind.NullKeyword: + case SyntaxKind.NullKeyword: return true; - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.PropertyAccessExpression: { + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: { const symbol = checker.getSymbolAtLocation(arg); if (!symbol) { return false; } return checker.isUndefinedSymbol(symbol) || - ts.some(ts.skipAlias(symbol, checker).declarations, d => ts.isFunctionLike(d) || ts.hasInitializer(d) && !!d.initializer && ts.isFunctionLike(d.initializer)); + some(skipAlias(symbol, checker).declarations, d => isFunctionLike(d) || hasInitializer(d) && !!d.initializer && isFunctionLike(d.initializer)); } default: return false; } } -function getKeyFromNode(exp: ts.FunctionLikeDeclaration) { +function getKeyFromNode(exp: FunctionLikeDeclaration) { return `${exp.pos.toString()}:${exp.end.toString()}`; } -function canBeConvertedToClass(node: ts.Node, checker: ts.TypeChecker): boolean { - if (node.kind === ts.SyntaxKind.FunctionExpression) { - if (ts.isVariableDeclaration(node.parent) && node.symbol.members?.size) { +function canBeConvertedToClass(node: Node, checker: TypeChecker): boolean { + if (node.kind === SyntaxKind.FunctionExpression) { + if (isVariableDeclaration(node.parent) && node.symbol.members?.size) { return true; } @@ -225,7 +236,7 @@ function canBeConvertedToClass(node: ts.Node, checker: ts.TypeChecker): boolean return !!(symbol && (symbol.exports?.size || symbol.members?.size)); } - if (node.kind === ts.SyntaxKind.FunctionDeclaration) { + if (node.kind === SyntaxKind.FunctionDeclaration) { return !!node.symbol.members?.size; } @@ -233,12 +244,12 @@ function canBeConvertedToClass(node: ts.Node, checker: ts.TypeChecker): boolean } /** @internal */ -export function canBeConvertedToAsync(node: ts.Node): node is ts.FunctionDeclaration | ts.MethodDeclaration | ts.FunctionExpression | ts.ArrowFunction { +export function canBeConvertedToAsync(node: Node): node is FunctionDeclaration | MethodDeclaration | FunctionExpression | ArrowFunction { switch (node.kind) { - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: return true; default: return false; diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 23408dcae270e..e599ad73666bc 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -1,79 +1,98 @@ -import * as ts from "./_namespaces/ts"; - -const symbolDisplayNodeBuilderFlags = ts.NodeBuilderFlags.OmitParameterModifiers | ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; +import { + addRange, arrayFrom, BinaryExpression, CallExpression, CheckFlags, contains, createPrinter, Debug, displayPart, + EmitHint, emptyArray, EnumMember, ExportAssignment, find, first, firstDefined, forEach, GetAccessorDeclaration, + getCombinedLocalAndExportSymbolFlags, getDeclarationOfKind, getExternalModuleImportEqualsDeclarationExpression, + getMeaningFromLocation, getNameOfDeclaration, getNodeModifiers, getObjectFlags, getParseTreeNode, + getSourceFileOfNode, getTextOfConstantValue, getTextOfIdentifierOrLiteral, getTextOfNode, hasSyntacticModifier, + idText, ImportEqualsDeclaration, isArrowFunction, isBindingElement, isCallExpression, isCallExpressionTarget, + isCallOrNewExpression, isClassExpression, isConstTypeReference, isDeprecatedDeclaration, isEnumConst, + isEnumDeclaration, isExpression, isExternalModuleImportEqualsDeclaration, isFirstDeclarationOfSymbolParameter, + isFunctionBlock, isFunctionExpression, isFunctionLike, isFunctionLikeKind, isIdentifier, isInExpressionContext, + isJsxOpeningLikeElement, isLet, isModuleWithStringLiteralName, isNameOfFunctionDeclaration, isNewExpressionTarget, + isObjectBindingPattern, isTaggedTemplateExpression, isThisInTypeQuery, isVarConst, JSDocTagInfo, + JsxOpeningLikeElement, keywordPart, length, lineBreakPart, ListFormat, mapToDisplayParts, ModifierFlags, + ModuleDeclaration, NewExpression, Node, NodeBuilderFlags, ObjectFlags, operatorPart, Printer, + PropertyAccessExpression, PropertyDeclaration, punctuationPart, ScriptElementKind, ScriptElementKindModifier, + SemanticMeaning, Set, SetAccessorDeclaration, Signature, SignatureDeclaration, SignatureFlags, + signatureToDisplayParts, some, SourceFile, spacePart, Symbol, SymbolDisplayPart, SymbolDisplayPartKind, SymbolFlags, + SymbolFormatFlags, symbolToDisplayParts, SyntaxKind, TaggedTemplateExpression, textOrKeywordPart, textPart, + TransientSymbol, Type, TypeChecker, TypeFormatFlags, TypeParameter, typeToDisplayParts, VariableDeclaration, +} from "./_namespaces/ts"; + +const symbolDisplayNodeBuilderFlags = NodeBuilderFlags.OmitParameterModifiers | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.UseAliasDefinedOutsideCurrentScope; // TODO(drosen): use contextual SemanticMeaning. /** @internal */ -export function getSymbolKind(typeChecker: ts.TypeChecker, symbol: ts.Symbol, location: ts.Node): ts.ScriptElementKind { +export function getSymbolKind(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind { const result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location); - if (result !== ts.ScriptElementKind.unknown) { + if (result !== ScriptElementKind.unknown) { return result; } - const flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & ts.SymbolFlags.Class) { - return ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ClassExpression) ? - ts.ScriptElementKind.localClassElement : ts.ScriptElementKind.classElement; + const flags = getCombinedLocalAndExportSymbolFlags(symbol); + if (flags & SymbolFlags.Class) { + return getDeclarationOfKind(symbol, SyntaxKind.ClassExpression) ? + ScriptElementKind.localClassElement : ScriptElementKind.classElement; } - if (flags & ts.SymbolFlags.Enum) return ts.ScriptElementKind.enumElement; - if (flags & ts.SymbolFlags.TypeAlias) return ts.ScriptElementKind.typeElement; - if (flags & ts.SymbolFlags.Interface) return ts.ScriptElementKind.interfaceElement; - if (flags & ts.SymbolFlags.TypeParameter) return ts.ScriptElementKind.typeParameterElement; - if (flags & ts.SymbolFlags.EnumMember) return ts.ScriptElementKind.enumMemberElement; - if (flags & ts.SymbolFlags.Alias) return ts.ScriptElementKind.alias; - if (flags & ts.SymbolFlags.Module) return ts.ScriptElementKind.moduleElement; + if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement; + if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement; + if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement; + if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; + if (flags & SymbolFlags.EnumMember) return ScriptElementKind.enumMemberElement; + if (flags & SymbolFlags.Alias) return ScriptElementKind.alias; + if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement; return result; } -function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker: ts.TypeChecker, symbol: ts.Symbol, location: ts.Node): ts.ScriptElementKind { +function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker: TypeChecker, symbol: Symbol, location: Node): ScriptElementKind { const roots = typeChecker.getRootSymbols(symbol); // If this is a method from a mapped type, leave as a method so long as it still has a call signature. if (roots.length === 1 - && ts.first(roots).flags & ts.SymbolFlags.Method + && first(roots).flags & SymbolFlags.Method // Ensure the mapped version is still a method, as opposed to `{ [K in keyof I]: number }`. && typeChecker.getTypeOfSymbolAtLocation(symbol, location).getNonNullableType().getCallSignatures().length !== 0) { - return ts.ScriptElementKind.memberFunctionElement; + return ScriptElementKind.memberFunctionElement; } if (typeChecker.isUndefinedSymbol(symbol)) { - return ts.ScriptElementKind.variableElement; + return ScriptElementKind.variableElement; } if (typeChecker.isArgumentsSymbol(symbol)) { - return ts.ScriptElementKind.localVariableElement; + return ScriptElementKind.localVariableElement; } - if (location.kind === ts.SyntaxKind.ThisKeyword && ts.isExpression(location) || ts.isThisInTypeQuery(location)) { - return ts.ScriptElementKind.parameterElement; + if (location.kind === SyntaxKind.ThisKeyword && isExpression(location) || isThisInTypeQuery(location)) { + return ScriptElementKind.parameterElement; } - const flags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - if (flags & ts.SymbolFlags.Variable) { - if (ts.isFirstDeclarationOfSymbolParameter(symbol)) { - return ts.ScriptElementKind.parameterElement; + const flags = getCombinedLocalAndExportSymbolFlags(symbol); + if (flags & SymbolFlags.Variable) { + if (isFirstDeclarationOfSymbolParameter(symbol)) { + return ScriptElementKind.parameterElement; } - else if (symbol.valueDeclaration && ts.isVarConst(symbol.valueDeclaration as ts.VariableDeclaration)) { - return ts.ScriptElementKind.constElement; + else if (symbol.valueDeclaration && isVarConst(symbol.valueDeclaration as VariableDeclaration)) { + return ScriptElementKind.constElement; } - else if (ts.forEach(symbol.declarations, ts.isLet)) { - return ts.ScriptElementKind.letElement; + else if (forEach(symbol.declarations, isLet)) { + return ScriptElementKind.letElement; } - return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localVariableElement : ts.ScriptElementKind.variableElement; + return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement; } - if (flags & ts.SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ts.ScriptElementKind.localFunctionElement : ts.ScriptElementKind.functionElement; + if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement; // FIXME: getter and setter use the same symbol. And it is rare to use only setter without getter, so in most cases the symbol always has getter flag. // So, even when the location is just on the declaration of setter, this function returns getter. - if (flags & ts.SymbolFlags.GetAccessor) return ts.ScriptElementKind.memberGetAccessorElement; - if (flags & ts.SymbolFlags.SetAccessor) return ts.ScriptElementKind.memberSetAccessorElement; - if (flags & ts.SymbolFlags.Method) return ts.ScriptElementKind.memberFunctionElement; - if (flags & ts.SymbolFlags.Constructor) return ts.ScriptElementKind.constructorImplementationElement; - if (flags & ts.SymbolFlags.Signature) return ts.ScriptElementKind.indexSignatureElement; - - if (flags & ts.SymbolFlags.Property) { - if (flags & ts.SymbolFlags.Transient && (symbol as ts.TransientSymbol).checkFlags & ts.CheckFlags.Synthetic) { + if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement; + if (flags & SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement; + if (flags & SymbolFlags.Method) return ScriptElementKind.memberFunctionElement; + if (flags & SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement; + if (flags & SymbolFlags.Signature) return ScriptElementKind.indexSignatureElement; + + if (flags & SymbolFlags.Property) { + if (flags & SymbolFlags.Transient && (symbol as TransientSymbol).checkFlags & CheckFlags.Synthetic) { // If union property is result of union of non method (property/accessors/variables), it is labeled as property - const unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { + const unionPropertyKind = forEach(typeChecker.getRootSymbols(symbol), rootSymbol => { const rootSymbolFlags = rootSymbol.getFlags(); - if (rootSymbolFlags & (ts.SymbolFlags.PropertyOrAccessor | ts.SymbolFlags.Variable)) { - return ts.ScriptElementKind.memberVariableElement; + if (rootSymbolFlags & (SymbolFlags.PropertyOrAccessor | SymbolFlags.Variable)) { + return ScriptElementKind.memberVariableElement; } }); if (!unionPropertyKind) { @@ -81,27 +100,27 @@ function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeCheck // make sure it has call signatures before we can label it as method const typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location); if (typeOfUnionProperty.getCallSignatures().length) { - return ts.ScriptElementKind.memberFunctionElement; + return ScriptElementKind.memberFunctionElement; } - return ts.ScriptElementKind.memberVariableElement; + return ScriptElementKind.memberVariableElement; } return unionPropertyKind; } - return ts.ScriptElementKind.memberVariableElement; + return ScriptElementKind.memberVariableElement; } - return ts.ScriptElementKind.unknown; + return ScriptElementKind.unknown; } -function getNormalizedSymbolModifiers(symbol: ts.Symbol) { +function getNormalizedSymbolModifiers(symbol: Symbol) { if (symbol.declarations && symbol.declarations.length) { const [declaration, ...declarations] = symbol.declarations; // omit deprecated flag if some declarations are not deprecated - const excludeFlags = ts.length(declarations) && ts.isDeprecatedDeclaration(declaration) && ts.some(declarations, d => !ts.isDeprecatedDeclaration(d)) - ? ts.ModifierFlags.Deprecated - : ts.ModifierFlags.None; - const modifiers = ts.getNodeModifiers(declaration, excludeFlags); + const excludeFlags = length(declarations) && isDeprecatedDeclaration(declaration) && some(declarations, d => !isDeprecatedDeclaration(d)) + ? ModifierFlags.Deprecated + : ModifierFlags.None; + const modifiers = getNodeModifiers(declaration, excludeFlags); if (modifiers) { return modifiers.split(","); } @@ -110,84 +129,84 @@ function getNormalizedSymbolModifiers(symbol: ts.Symbol) { } /** @internal */ -export function getSymbolModifiers(typeChecker: ts.TypeChecker, symbol: ts.Symbol): string { +export function getSymbolModifiers(typeChecker: TypeChecker, symbol: Symbol): string { if (!symbol) { - return ts.ScriptElementKindModifier.none; + return ScriptElementKindModifier.none; } - const modifiers = new ts.Set(getNormalizedSymbolModifiers(symbol)); - if (symbol.flags & ts.SymbolFlags.Alias) { + const modifiers = new Set(getNormalizedSymbolModifiers(symbol)); + if (symbol.flags & SymbolFlags.Alias) { const resolvedSymbol = typeChecker.getAliasedSymbol(symbol); if (resolvedSymbol !== symbol) { - ts.forEach(getNormalizedSymbolModifiers(resolvedSymbol), modifier => { + forEach(getNormalizedSymbolModifiers(resolvedSymbol), modifier => { modifiers.add(modifier); }); } } - if (symbol.flags & ts.SymbolFlags.Optional) { - modifiers.add(ts.ScriptElementKindModifier.optionalModifier); + if (symbol.flags & SymbolFlags.Optional) { + modifiers.add(ScriptElementKindModifier.optionalModifier); } - return modifiers.size > 0 ? ts.arrayFrom(modifiers.values()).join(",") : ts.ScriptElementKindModifier.none; + return modifiers.size > 0 ? arrayFrom(modifiers.values()).join(",") : ScriptElementKindModifier.none; } interface SymbolDisplayPartsDocumentationAndSymbolKind { - displayParts: ts.SymbolDisplayPart[]; - documentation: ts.SymbolDisplayPart[]; - symbolKind: ts.ScriptElementKind; - tags: ts.JSDocTagInfo[] | undefined; + displayParts: SymbolDisplayPart[]; + documentation: SymbolDisplayPart[]; + symbolKind: ScriptElementKind; + tags: JSDocTagInfo[] | undefined; } // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location /** @internal */ -export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts.TypeChecker, symbol: ts.Symbol, sourceFile: ts.SourceFile, enclosingDeclaration: ts.Node | undefined, - location: ts.Node, semanticMeaning = ts.getMeaningFromLocation(location), alias?: ts.Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { - const displayParts: ts.SymbolDisplayPart[] = []; - let documentation: ts.SymbolDisplayPart[] = []; - let tags: ts.JSDocTagInfo[] = []; - const symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol); - let symbolKind = semanticMeaning & ts.SemanticMeaning.Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : ts.ScriptElementKind.unknown; +export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: TypeChecker, symbol: Symbol, sourceFile: SourceFile, enclosingDeclaration: Node | undefined, + location: Node, semanticMeaning = getMeaningFromLocation(location), alias?: Symbol): SymbolDisplayPartsDocumentationAndSymbolKind { + const displayParts: SymbolDisplayPart[] = []; + let documentation: SymbolDisplayPart[] = []; + let tags: JSDocTagInfo[] = []; + const symbolFlags = getCombinedLocalAndExportSymbolFlags(symbol); + let symbolKind = semanticMeaning & SemanticMeaning.Value ? getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) : ScriptElementKind.unknown; let hasAddedSymbolInfo = false; - const isThisExpression = location.kind === ts.SyntaxKind.ThisKeyword && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); - let type: ts.Type | undefined; - let printer: ts.Printer; - let documentationFromAlias: ts.SymbolDisplayPart[] | undefined; - let tagsFromAlias: ts.JSDocTagInfo[] | undefined; + const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) || isThisInTypeQuery(location); + let type: Type | undefined; + let printer: Printer; + let documentationFromAlias: SymbolDisplayPart[] | undefined; + let tagsFromAlias: JSDocTagInfo[] | undefined; let hasMultipleSignatures = false; - if (location.kind === ts.SyntaxKind.ThisKeyword && !isThisExpression) { - return { displayParts: [ts.keywordPart(ts.SyntaxKind.ThisKeyword)], documentation: [], symbolKind: ts.ScriptElementKind.primitiveType, tags: undefined }; + if (location.kind === SyntaxKind.ThisKeyword && !isThisExpression) { + return { displayParts: [keywordPart(SyntaxKind.ThisKeyword)], documentation: [], symbolKind: ScriptElementKind.primitiveType, tags: undefined }; } // Class at constructor site need to be shown as constructor apart from property,method, vars - if (symbolKind !== ts.ScriptElementKind.unknown || symbolFlags & ts.SymbolFlags.Class || symbolFlags & ts.SymbolFlags.Alias) { + if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Alias) { // If symbol is accessor, they are allowed only if location is at declaration identifier of the accessor - if (symbolKind === ts.ScriptElementKind.memberGetAccessorElement || symbolKind === ts.ScriptElementKind.memberSetAccessorElement) { - const declaration = ts.find(symbol.declarations as ((ts.GetAccessorDeclaration | ts.SetAccessorDeclaration | ts.PropertyDeclaration)[]), declaration => declaration.name === location); + if (symbolKind === ScriptElementKind.memberGetAccessorElement || symbolKind === ScriptElementKind.memberSetAccessorElement) { + const declaration = find(symbol.declarations as ((GetAccessorDeclaration | SetAccessorDeclaration | PropertyDeclaration)[]), declaration => declaration.name === location); if (declaration) { switch(declaration.kind){ - case ts.SyntaxKind.GetAccessor: - symbolKind = ts.ScriptElementKind.memberGetAccessorElement; + case SyntaxKind.GetAccessor: + symbolKind = ScriptElementKind.memberGetAccessorElement; break; - case ts.SyntaxKind.SetAccessor: - symbolKind = ts.ScriptElementKind.memberSetAccessorElement; + case SyntaxKind.SetAccessor: + symbolKind = ScriptElementKind.memberSetAccessorElement; break; - case ts.SyntaxKind.PropertyDeclaration: - symbolKind = ts.ScriptElementKind.memberAccessorVariableElement; + case SyntaxKind.PropertyDeclaration: + symbolKind = ScriptElementKind.memberAccessorVariableElement; break; default: - ts.Debug.assertNever(declaration); + Debug.assertNever(declaration); } } else { - symbolKind = ts.ScriptElementKind.memberVariableElement; + symbolKind = ScriptElementKind.memberVariableElement; } } - let signature: ts.Signature | undefined; + let signature: Signature | undefined; type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol, location); - if (location.parent && location.parent.kind === ts.SyntaxKind.PropertyAccessExpression) { - const right = (location.parent as ts.PropertyAccessExpression).name; + if (location.parent && location.parent.kind === SyntaxKind.PropertyAccessExpression) { + const right = (location.parent as PropertyAccessExpression).name; // Either the location is on the right of a property access, or on the left and the right is missing if (right === location || (right && right.getFullWidth() === 0)) { location = location.parent; @@ -195,47 +214,47 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } // try get the call/construct signature from the type if it matches - let callExpressionLike: ts.CallExpression | ts.NewExpression | ts.JsxOpeningLikeElement | ts.TaggedTemplateExpression | undefined; - if (ts.isCallOrNewExpression(location)) { + let callExpressionLike: CallExpression | NewExpression | JsxOpeningLikeElement | TaggedTemplateExpression | undefined; + if (isCallOrNewExpression(location)) { callExpressionLike = location; } - else if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location)) { - callExpressionLike = location.parent as ts.CallExpression | ts.NewExpression; + else if (isCallExpressionTarget(location) || isNewExpressionTarget(location)) { + callExpressionLike = location.parent as CallExpression | NewExpression; } - else if (location.parent && (ts.isJsxOpeningLikeElement(location.parent) || ts.isTaggedTemplateExpression(location.parent)) && ts.isFunctionLike(symbol.valueDeclaration)) { + else if (location.parent && (isJsxOpeningLikeElement(location.parent) || isTaggedTemplateExpression(location.parent)) && isFunctionLike(symbol.valueDeclaration)) { callExpressionLike = location.parent; } if (callExpressionLike) { signature = typeChecker.getResolvedSignature(callExpressionLike); // TODO: GH#18217 - const useConstructSignatures = callExpressionLike.kind === ts.SyntaxKind.NewExpression || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === ts.SyntaxKind.SuperKeyword); + const useConstructSignatures = callExpressionLike.kind === SyntaxKind.NewExpression || (isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === SyntaxKind.SuperKeyword); const allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures(); - if (signature && !ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) { + if (signature && !contains(allSignatures, signature.target) && !contains(allSignatures, signature)) { // Get the first signature if there is one -- allSignatures may contain // either the original signature or its target, so check for either signature = allSignatures.length ? allSignatures[0] : undefined; } if (signature) { - if (useConstructSignatures && (symbolFlags & ts.SymbolFlags.Class)) { + if (useConstructSignatures && (symbolFlags & SymbolFlags.Class)) { // Constructor - symbolKind = ts.ScriptElementKind.constructorImplementationElement; + symbolKind = ScriptElementKind.constructorImplementationElement; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } - else if (symbolFlags & ts.SymbolFlags.Alias) { - symbolKind = ts.ScriptElementKind.alias; + else if (symbolFlags & SymbolFlags.Alias) { + symbolKind = ScriptElementKind.alias; pushSymbolKind(symbolKind); - displayParts.push(ts.spacePart()); + displayParts.push(spacePart()); if (useConstructSignatures) { - if (signature.flags & ts.SignatureFlags.Abstract) { - displayParts.push(ts.keywordPart(ts.SyntaxKind.AbstractKeyword)); - displayParts.push(ts.spacePart()); + if (signature.flags & SignatureFlags.Abstract) { + displayParts.push(keywordPart(SyntaxKind.AbstractKeyword)); + displayParts.push(spacePart()); } - displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); } addFullSymbolName(symbol); } @@ -244,29 +263,29 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } switch (symbolKind) { - case ts.ScriptElementKind.jsxAttribute: - case ts.ScriptElementKind.memberVariableElement: - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.parameterElement: - case ts.ScriptElementKind.localVariableElement: + case ScriptElementKind.jsxAttribute: + case ScriptElementKind.memberVariableElement: + case ScriptElementKind.variableElement: + case ScriptElementKind.constElement: + case ScriptElementKind.letElement: + case ScriptElementKind.parameterElement: + case ScriptElementKind.localVariableElement: // If it is call or construct signature of lambda's write type name - displayParts.push(ts.punctuationPart(ts.SyntaxKind.ColonToken)); - displayParts.push(ts.spacePart()); - if (!(ts.getObjectFlags(type) & ts.ObjectFlags.Anonymous) && type.symbol) { - ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, ts.SymbolFormatFlags.AllowAnyNodeKind | ts.SymbolFormatFlags.WriteTypeParametersOrArguments)); - displayParts.push(ts.lineBreakPart()); + displayParts.push(punctuationPart(SyntaxKind.ColonToken)); + displayParts.push(spacePart()); + if (!(getObjectFlags(type) & ObjectFlags.Anonymous) && type.symbol) { + addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.AllowAnyNodeKind | SymbolFormatFlags.WriteTypeParametersOrArguments)); + displayParts.push(lineBreakPart()); } if (useConstructSignatures) { - if (signature.flags & ts.SignatureFlags.Abstract) { - displayParts.push(ts.keywordPart(ts.SyntaxKind.AbstractKeyword)); - displayParts.push(ts.spacePart()); + if (signature.flags & SignatureFlags.Abstract) { + displayParts.push(keywordPart(SyntaxKind.AbstractKeyword)); + displayParts.push(spacePart()); } - displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); } - addSignatureDisplayParts(signature, allSignatures, ts.TypeFormatFlags.WriteArrowStyleSignature); + addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature); break; default: @@ -277,16 +296,16 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. hasMultipleSignatures = allSignatures.length > 1; } } - else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & ts.SymbolFlags.Accessor)) || // name of function declaration - (location.kind === ts.SyntaxKind.ConstructorKeyword && location.parent.kind === ts.SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration + else if ((isNameOfFunctionDeclaration(location) && !(symbolFlags & SymbolFlags.Accessor)) || // name of function declaration + (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - const functionDeclaration = location.parent as ts.SignatureDeclaration; + const functionDeclaration = location.parent as SignatureDeclaration; // Use function declaration to write the signatures only if the symbol corresponding to this declaration - const locationIsSymbolDeclaration = symbol.declarations && ts.find(symbol.declarations, declaration => - declaration === (location.kind === ts.SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); + const locationIsSymbolDeclaration = symbol.declarations && find(symbol.declarations, declaration => + declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration)); if (locationIsSymbolDeclaration) { - const allSignatures = functionDeclaration.kind === ts.SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); + const allSignatures = functionDeclaration.kind === SyntaxKind.Constructor ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures(); if (!typeChecker.isImplementationOfOverload(functionDeclaration)) { signature = typeChecker.getSignatureFromDeclaration(functionDeclaration); // TODO: GH#18217 } @@ -294,15 +313,15 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. signature = allSignatures[0]; } - if (functionDeclaration.kind === ts.SyntaxKind.Constructor) { + if (functionDeclaration.kind === SyntaxKind.Constructor) { // show (constructor) Type(...) signature - symbolKind = ts.ScriptElementKind.constructorImplementationElement; + symbolKind = ScriptElementKind.constructorImplementationElement; addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { // (function/method) symbol(..signature) - addPrefixForAnyFunctionOrVar(functionDeclaration.kind === ts.SyntaxKind.CallSignature && - !(type.symbol.flags & ts.SymbolFlags.TypeLiteral || type.symbol.flags & ts.SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); + addPrefixForAnyFunctionOrVar(functionDeclaration.kind === SyntaxKind.CallSignature && + !(type.symbol.flags & SymbolFlags.TypeLiteral || type.symbol.flags & SymbolFlags.ObjectLiteral) ? type.symbol : symbol, symbolKind); } if (signature) { addSignatureDisplayParts(signature, allSignatures); @@ -312,64 +331,64 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } } } - if (symbolFlags & ts.SymbolFlags.Class && !hasAddedSymbolInfo && !isThisExpression) { + if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo && !isThisExpression) { addAliasPrefixIfNecessary(); - if (ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ClassExpression)) { + if (getDeclarationOfKind(symbol, SyntaxKind.ClassExpression)) { // Special case for class expressions because we would like to indicate that // the class name is local to the class body (similar to function expression) // (local class) class - pushSymbolKind(ts.ScriptElementKind.localClassElement); + pushSymbolKind(ScriptElementKind.localClassElement); } else { // Class declaration has name which is not local. - displayParts.push(ts.keywordPart(ts.SyntaxKind.ClassKeyword)); + displayParts.push(keywordPart(SyntaxKind.ClassKeyword)); } - displayParts.push(ts.spacePart()); + displayParts.push(spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if ((symbolFlags & ts.SymbolFlags.Interface) && (semanticMeaning & ts.SemanticMeaning.Type)) { + if ((symbolFlags & SymbolFlags.Interface) && (semanticMeaning & SemanticMeaning.Type)) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(ts.SyntaxKind.InterfaceKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword)); + displayParts.push(spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); } - if ((symbolFlags & ts.SymbolFlags.TypeAlias) && (semanticMeaning & ts.SemanticMeaning.Type)) { + if ((symbolFlags & SymbolFlags.TypeAlias) && (semanticMeaning & SemanticMeaning.Type)) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(ts.SyntaxKind.TypeKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); + displayParts.push(spacePart()); addFullSymbolName(symbol); writeTypeParametersOfSymbol(symbol, sourceFile); - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(ts.SyntaxKind.EqualsToken)); - displayParts.push(ts.spacePart()); - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, ts.isConstTypeReference(location.parent) ? typeChecker.getTypeAtLocation(location.parent) : typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, ts.TypeFormatFlags.InTypeAlias)); + displayParts.push(spacePart()); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); + displayParts.push(spacePart()); + addRange(displayParts, typeToDisplayParts(typeChecker, isConstTypeReference(location.parent) ? typeChecker.getTypeAtLocation(location.parent) : typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, TypeFormatFlags.InTypeAlias)); } - if (symbolFlags & ts.SymbolFlags.Enum) { + if (symbolFlags & SymbolFlags.Enum) { prefixNextMeaning(); - if (ts.some(symbol.declarations, d => ts.isEnumDeclaration(d) && ts.isEnumConst(d))) { - displayParts.push(ts.keywordPart(ts.SyntaxKind.ConstKeyword)); - displayParts.push(ts.spacePart()); + if (some(symbol.declarations, d => isEnumDeclaration(d) && isEnumConst(d))) { + displayParts.push(keywordPart(SyntaxKind.ConstKeyword)); + displayParts.push(spacePart()); } - displayParts.push(ts.keywordPart(ts.SyntaxKind.EnumKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.EnumKeyword)); + displayParts.push(spacePart()); addFullSymbolName(symbol); } - if (symbolFlags & ts.SymbolFlags.Module && !isThisExpression) { + if (symbolFlags & SymbolFlags.Module && !isThisExpression) { prefixNextMeaning(); - const declaration = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.ModuleDeclaration); - const isNamespace = declaration && declaration.name && declaration.name.kind === ts.SyntaxKind.Identifier; - displayParts.push(ts.keywordPart(isNamespace ? ts.SyntaxKind.NamespaceKeyword : ts.SyntaxKind.ModuleKeyword)); - displayParts.push(ts.spacePart()); + const declaration = getDeclarationOfKind(symbol, SyntaxKind.ModuleDeclaration); + const isNamespace = declaration && declaration.name && declaration.name.kind === SyntaxKind.Identifier; + displayParts.push(keywordPart(isNamespace ? SyntaxKind.NamespaceKeyword : SyntaxKind.ModuleKeyword)); + displayParts.push(spacePart()); addFullSymbolName(symbol); } - if ((symbolFlags & ts.SymbolFlags.TypeParameter) && (semanticMeaning & ts.SemanticMeaning.Type)) { + if ((symbolFlags & SymbolFlags.TypeParameter) && (semanticMeaning & SemanticMeaning.Type)) { prefixNextMeaning(); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenParenToken)); - displayParts.push(ts.textPart("type parameter")); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseParenToken)); - displayParts.push(ts.spacePart()); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(textPart("type parameter")); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); + displayParts.push(spacePart()); addFullSymbolName(symbol); if (symbol.parent) { // Class/Interface type parameter @@ -379,74 +398,74 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } else { // Method/function type parameter - const decl = ts.getDeclarationOfKind(symbol, ts.SyntaxKind.TypeParameter); - if (decl === undefined) return ts.Debug.fail(); + const decl = getDeclarationOfKind(symbol, SyntaxKind.TypeParameter); + if (decl === undefined) return Debug.fail(); const declaration = decl.parent; if (declaration) { - if (ts.isFunctionLikeKind(declaration.kind)) { + if (isFunctionLikeKind(declaration.kind)) { addInPrefix(); - const signature = typeChecker.getSignatureFromDeclaration(declaration as ts.SignatureDeclaration)!; // TODO: GH#18217 - if (declaration.kind === ts.SyntaxKind.ConstructSignature) { - displayParts.push(ts.keywordPart(ts.SyntaxKind.NewKeyword)); - displayParts.push(ts.spacePart()); + const signature = typeChecker.getSignatureFromDeclaration(declaration as SignatureDeclaration)!; // TODO: GH#18217 + if (declaration.kind === SyntaxKind.ConstructSignature) { + displayParts.push(keywordPart(SyntaxKind.NewKeyword)); + displayParts.push(spacePart()); } - else if (declaration.kind !== ts.SyntaxKind.CallSignature && (declaration as ts.SignatureDeclaration).name) { + else if (declaration.kind !== SyntaxKind.CallSignature && (declaration as SignatureDeclaration).name) { addFullSymbolName(declaration.symbol); } - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, ts.TypeFormatFlags.WriteTypeArgumentsOfSignature)); + addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } - else if (declaration.kind === ts.SyntaxKind.TypeAliasDeclaration) { + else if (declaration.kind === SyntaxKind.TypeAliasDeclaration) { // Type alias type parameter // For example // type list = T[]; // Both T will go through same code path addInPrefix(); - displayParts.push(ts.keywordPart(ts.SyntaxKind.TypeKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(keywordPart(SyntaxKind.TypeKeyword)); + displayParts.push(spacePart()); addFullSymbolName(declaration.symbol); writeTypeParametersOfSymbol(declaration.symbol, sourceFile); } } } } - if (symbolFlags & ts.SymbolFlags.EnumMember) { - symbolKind = ts.ScriptElementKind.enumMemberElement; + if (symbolFlags & SymbolFlags.EnumMember) { + symbolKind = ScriptElementKind.enumMemberElement; addPrefixForAnyFunctionOrVar(symbol, "enum member"); const declaration = symbol.declarations?.[0]; - if (declaration?.kind === ts.SyntaxKind.EnumMember) { - const constantValue = typeChecker.getConstantValue(declaration as ts.EnumMember); + if (declaration?.kind === SyntaxKind.EnumMember) { + const constantValue = typeChecker.getConstantValue(declaration as EnumMember); if (constantValue !== undefined) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(ts.SyntaxKind.EqualsToken)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), - typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral)); + displayParts.push(spacePart()); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); + displayParts.push(spacePart()); + displayParts.push(displayPart(getTextOfConstantValue(constantValue), + typeof constantValue === "number" ? SymbolDisplayPartKind.numericLiteral : SymbolDisplayPartKind.stringLiteral)); } } } // don't use symbolFlags since getAliasedSymbol requires the flag on the symbol itself - if (symbol.flags & ts.SymbolFlags.Alias) { + if (symbol.flags & SymbolFlags.Alias) { prefixNextMeaning(); if (!hasAddedSymbolInfo) { const resolvedSymbol = typeChecker.getAliasedSymbol(symbol); if (resolvedSymbol !== symbol && resolvedSymbol.declarations && resolvedSymbol.declarations.length > 0) { const resolvedNode = resolvedSymbol.declarations[0]; - const declarationName = ts.getNameOfDeclaration(resolvedNode); + const declarationName = getNameOfDeclaration(resolvedNode); if (declarationName) { const isExternalModuleDeclaration = - ts.isModuleWithStringLiteralName(resolvedNode) && - ts.hasSyntacticModifier(resolvedNode, ts.ModifierFlags.Ambient); + isModuleWithStringLiteralName(resolvedNode) && + hasSyntacticModifier(resolvedNode, ModifierFlags.Ambient); const shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration; const resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind( typeChecker, resolvedSymbol, - ts.getSourceFileOfNode(resolvedNode), + getSourceFileOfNode(resolvedNode), resolvedNode, declarationName, semanticMeaning, shouldUseAliasName ? symbol : resolvedSymbol); displayParts.push(...resolvedInfo.displayParts); - displayParts.push(ts.lineBreakPart()); + displayParts.push(lineBreakPart()); documentationFromAlias = resolvedInfo.documentation; tagsFromAlias = resolvedInfo.tags; } @@ -459,43 +478,43 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. if (symbol.declarations) { switch (symbol.declarations[0].kind) { - case ts.SyntaxKind.NamespaceExportDeclaration: - displayParts.push(ts.keywordPart(ts.SyntaxKind.ExportKeyword)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(ts.SyntaxKind.NamespaceKeyword)); + case SyntaxKind.NamespaceExportDeclaration: + displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); + displayParts.push(spacePart()); + displayParts.push(keywordPart(SyntaxKind.NamespaceKeyword)); break; - case ts.SyntaxKind.ExportAssignment: - displayParts.push(ts.keywordPart(ts.SyntaxKind.ExportKeyword)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart((symbol.declarations[0] as ts.ExportAssignment).isExportEquals ? ts.SyntaxKind.EqualsToken : ts.SyntaxKind.DefaultKeyword)); + case SyntaxKind.ExportAssignment: + displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); + displayParts.push(spacePart()); + displayParts.push(keywordPart((symbol.declarations[0] as ExportAssignment).isExportEquals ? SyntaxKind.EqualsToken : SyntaxKind.DefaultKeyword)); break; - case ts.SyntaxKind.ExportSpecifier: - displayParts.push(ts.keywordPart(ts.SyntaxKind.ExportKeyword)); + case SyntaxKind.ExportSpecifier: + displayParts.push(keywordPart(SyntaxKind.ExportKeyword)); break; default: - displayParts.push(ts.keywordPart(ts.SyntaxKind.ImportKeyword)); + displayParts.push(keywordPart(SyntaxKind.ImportKeyword)); } } - displayParts.push(ts.spacePart()); + displayParts.push(spacePart()); addFullSymbolName(symbol); - ts.forEach(symbol.declarations, declaration => { - if (declaration.kind === ts.SyntaxKind.ImportEqualsDeclaration) { - const importEqualsDeclaration = declaration as ts.ImportEqualsDeclaration; - if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(ts.SyntaxKind.EqualsToken)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(ts.SyntaxKind.RequireKeyword)); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenParenToken)); - displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral)); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseParenToken)); + forEach(symbol.declarations, declaration => { + if (declaration.kind === SyntaxKind.ImportEqualsDeclaration) { + const importEqualsDeclaration = declaration as ImportEqualsDeclaration; + if (isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) { + displayParts.push(spacePart()); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); + displayParts.push(spacePart()); + displayParts.push(keywordPart(SyntaxKind.RequireKeyword)); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(displayPart(getTextOfNode(getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), SymbolDisplayPartKind.stringLiteral)); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } else { const internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference); if (internalAliasSymbol) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.operatorPart(ts.SyntaxKind.EqualsToken)); - displayParts.push(ts.spacePart()); + displayParts.push(spacePart()); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); + displayParts.push(spacePart()); addFullSymbolName(internalAliasSymbol, enclosingDeclaration); } } @@ -504,53 +523,53 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. }); } if (!hasAddedSymbolInfo) { - if (symbolKind !== ts.ScriptElementKind.unknown) { + if (symbolKind !== ScriptElementKind.unknown) { if (type) { if (isThisExpression) { prefixNextMeaning(); - displayParts.push(ts.keywordPart(ts.SyntaxKind.ThisKeyword)); + displayParts.push(keywordPart(SyntaxKind.ThisKeyword)); } else { addPrefixForAnyFunctionOrVar(symbol, symbolKind); } // For properties, variables and local vars: show the type - if (symbolKind === ts.ScriptElementKind.memberVariableElement || - symbolKind === ts.ScriptElementKind.memberAccessorVariableElement || - symbolKind === ts.ScriptElementKind.memberGetAccessorElement || - symbolKind === ts.ScriptElementKind.memberSetAccessorElement || - symbolKind === ts.ScriptElementKind.jsxAttribute || - symbolFlags & ts.SymbolFlags.Variable || - symbolKind === ts.ScriptElementKind.localVariableElement || - symbolKind === ts.ScriptElementKind.indexSignatureElement || + if (symbolKind === ScriptElementKind.memberVariableElement || + symbolKind === ScriptElementKind.memberAccessorVariableElement || + symbolKind === ScriptElementKind.memberGetAccessorElement || + symbolKind === ScriptElementKind.memberSetAccessorElement || + symbolKind === ScriptElementKind.jsxAttribute || + symbolFlags & SymbolFlags.Variable || + symbolKind === ScriptElementKind.localVariableElement || + symbolKind === ScriptElementKind.indexSignatureElement || isThisExpression) { - displayParts.push(ts.punctuationPart(ts.SyntaxKind.ColonToken)); - displayParts.push(ts.spacePart()); + displayParts.push(punctuationPart(SyntaxKind.ColonToken)); + displayParts.push(spacePart()); // If the type is type parameter, format it specially - if (type.symbol && type.symbol.flags & ts.SymbolFlags.TypeParameter && symbolKind !== ts.ScriptElementKind.indexSignatureElement) { - const typeParameterParts = ts.mapToDisplayParts(writer => { - const param = typeChecker.typeParameterToDeclaration(type as ts.TypeParameter, enclosingDeclaration, symbolDisplayNodeBuilderFlags)!; - getPrinter().writeNode(ts.EmitHint.Unspecified, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter && symbolKind !== ScriptElementKind.indexSignatureElement) { + const typeParameterParts = mapToDisplayParts(writer => { + const param = typeChecker.typeParameterToDeclaration(type as TypeParameter, enclosingDeclaration, symbolDisplayNodeBuilderFlags)!; + getPrinter().writeNode(EmitHint.Unspecified, param, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); }); - ts.addRange(displayParts, typeParameterParts); + addRange(displayParts, typeParameterParts); } else { - ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration)); + addRange(displayParts, typeToDisplayParts(typeChecker, type, enclosingDeclaration)); } - if ((symbol as ts.TransientSymbol).target && ((symbol as ts.TransientSymbol).target as ts.TransientSymbol).tupleLabelDeclaration) { - const labelDecl = ((symbol as ts.TransientSymbol).target as ts.TransientSymbol).tupleLabelDeclaration!; - ts.Debug.assertNode(labelDecl.name, ts.isIdentifier); - displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenParenToken)); - displayParts.push(ts.textPart(ts.idText(labelDecl.name))); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseParenToken)); + if ((symbol as TransientSymbol).target && ((symbol as TransientSymbol).target as TransientSymbol).tupleLabelDeclaration) { + const labelDecl = ((symbol as TransientSymbol).target as TransientSymbol).tupleLabelDeclaration!; + Debug.assertNode(labelDecl.name, isIdentifier); + displayParts.push(spacePart()); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(textPart(idText(labelDecl.name))); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } } - else if (symbolFlags & ts.SymbolFlags.Function || - symbolFlags & ts.SymbolFlags.Method || - symbolFlags & ts.SymbolFlags.Constructor || - symbolFlags & ts.SymbolFlags.Signature || - symbolFlags & ts.SymbolFlags.Accessor || - symbolKind === ts.ScriptElementKind.memberFunctionElement) { + else if (symbolFlags & SymbolFlags.Function || + symbolFlags & SymbolFlags.Method || + symbolFlags & SymbolFlags.Constructor || + symbolFlags & SymbolFlags.Signature || + symbolFlags & SymbolFlags.Accessor || + symbolKind === ScriptElementKind.memberFunctionElement) { const allSignatures = type.getNonNullableType().getCallSignatures(); if (allSignatures.length) { addSignatureDisplayParts(allSignatures[0], allSignatures); @@ -568,17 +587,17 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. documentation = symbol.getContextualDocumentationComment(enclosingDeclaration, typeChecker); } - if (documentation.length === 0 && symbolFlags & ts.SymbolFlags.Property) { + if (documentation.length === 0 && symbolFlags & SymbolFlags.Property) { // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo` // there documentation comments might be attached to the right hand side symbol of their declarations. // The pattern of such special property access is that the parent symbol is the symbol of the file. - if (symbol.parent && symbol.declarations && ts.forEach(symbol.parent.declarations, declaration => declaration.kind === ts.SyntaxKind.SourceFile)) { + if (symbol.parent && symbol.declarations && forEach(symbol.parent.declarations, declaration => declaration.kind === SyntaxKind.SourceFile)) { for (const declaration of symbol.declarations) { - if (!declaration.parent || declaration.parent.kind !== ts.SyntaxKind.BinaryExpression) { + if (!declaration.parent || declaration.parent.kind !== SyntaxKind.BinaryExpression) { continue; } - const rhsSymbol = typeChecker.getSymbolAtLocation((declaration.parent as ts.BinaryExpression).right); + const rhsSymbol = typeChecker.getSymbolAtLocation((declaration.parent as BinaryExpression).right); if (!rhsSymbol) { continue; } @@ -592,16 +611,16 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } } - if (documentation.length === 0 && ts.isIdentifier(location) && symbol.valueDeclaration && ts.isBindingElement(symbol.valueDeclaration)) { + if (documentation.length === 0 && isIdentifier(location) && symbol.valueDeclaration && isBindingElement(symbol.valueDeclaration)) { const declaration = symbol.valueDeclaration; const parent = declaration.parent; - if (ts.isIdentifier(declaration.name) && ts.isObjectBindingPattern(parent)) { - const name = ts.getTextOfIdentifierOrLiteral(declaration.name); + if (isIdentifier(declaration.name) && isObjectBindingPattern(parent)) { + const name = getTextOfIdentifierOrLiteral(declaration.name); const objectType = typeChecker.getTypeAtLocation(parent); - documentation = ts.firstDefined(objectType.isUnion() ? objectType.types : [objectType], t => { + documentation = firstDefined(objectType.isUnion() ? objectType.types : [objectType], t => { const prop = t.getProperty(name); return prop ? prop.getDocumentationComment(typeChecker) : undefined; - }) || ts.emptyArray; + }) || emptyArray; } } @@ -621,75 +640,75 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. function getPrinter() { if (!printer) { - printer = ts.createPrinter({ removeComments: true }); + printer = createPrinter({ removeComments: true }); } return printer; } function prefixNextMeaning() { if (displayParts.length) { - displayParts.push(ts.lineBreakPart()); + displayParts.push(lineBreakPart()); } addAliasPrefixIfNecessary(); } function addAliasPrefixIfNecessary() { if (alias) { - pushSymbolKind(ts.ScriptElementKind.alias); - displayParts.push(ts.spacePart()); + pushSymbolKind(ScriptElementKind.alias); + displayParts.push(spacePart()); } } function addInPrefix() { - displayParts.push(ts.spacePart()); - displayParts.push(ts.keywordPart(ts.SyntaxKind.InKeyword)); - displayParts.push(ts.spacePart()); + displayParts.push(spacePart()); + displayParts.push(keywordPart(SyntaxKind.InKeyword)); + displayParts.push(spacePart()); } - function addFullSymbolName(symbolToDisplay: ts.Symbol, enclosingDeclaration?: ts.Node) { + function addFullSymbolName(symbolToDisplay: Symbol, enclosingDeclaration?: Node) { let indexInfos; if (alias && symbolToDisplay === symbol) { symbolToDisplay = alias; } - if (symbolKind === ts.ScriptElementKind.indexSignatureElement) { + if (symbolKind === ScriptElementKind.indexSignatureElement) { indexInfos = typeChecker.getIndexInfosOfIndexSymbol(symbolToDisplay); } - let fullSymbolDisplayParts: ts.SymbolDisplayPart[] = []; - if (symbolToDisplay.flags & ts.SymbolFlags.Signature && indexInfos) { + let fullSymbolDisplayParts: SymbolDisplayPart[] = []; + if (symbolToDisplay.flags & SymbolFlags.Signature && indexInfos) { if (symbolToDisplay.parent) { - fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay.parent); + fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay.parent); } - fullSymbolDisplayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenBracketToken)); + fullSymbolDisplayParts.push(punctuationPart(SyntaxKind.OpenBracketToken)); //Needed to handle more than one type of index indexInfos.forEach((info, i) => { //Needed to handle template literals - fullSymbolDisplayParts.push(...ts.typeToDisplayParts(typeChecker, info.keyType)); + fullSymbolDisplayParts.push(...typeToDisplayParts(typeChecker, info.keyType)); if (i !== indexInfos.length - 1) { - fullSymbolDisplayParts.push(ts.spacePart()); - fullSymbolDisplayParts.push(ts.punctuationPart(ts.SyntaxKind.BarToken)); - fullSymbolDisplayParts.push(ts.spacePart()); + fullSymbolDisplayParts.push(spacePart()); + fullSymbolDisplayParts.push(punctuationPart(SyntaxKind.BarToken)); + fullSymbolDisplayParts.push(spacePart()); } }); - fullSymbolDisplayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseBracketToken)); + fullSymbolDisplayParts.push(punctuationPart(SyntaxKind.CloseBracketToken)); } else { - fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, - ts.SymbolFormatFlags.WriteTypeParametersOrArguments | ts.SymbolFormatFlags.UseOnlyExternalAliasing | ts.SymbolFormatFlags.AllowAnyNodeKind); + fullSymbolDisplayParts = symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, + SymbolFormatFlags.WriteTypeParametersOrArguments | SymbolFormatFlags.UseOnlyExternalAliasing | SymbolFormatFlags.AllowAnyNodeKind); } - ts.addRange(displayParts, fullSymbolDisplayParts); - if (symbol.flags & ts.SymbolFlags.Optional) { - displayParts.push(ts.punctuationPart(ts.SyntaxKind.QuestionToken)); + addRange(displayParts, fullSymbolDisplayParts); + if (symbol.flags & SymbolFlags.Optional) { + displayParts.push(punctuationPart(SyntaxKind.QuestionToken)); } } - function addPrefixForAnyFunctionOrVar(symbol: ts.Symbol, symbolKind: string) { + function addPrefixForAnyFunctionOrVar(symbol: Symbol, symbolKind: string) { prefixNextMeaning(); if (symbolKind) { pushSymbolKind(symbolKind); - if (symbol && !ts.some(symbol.declarations, d => ts.isArrowFunction(d) || (ts.isFunctionExpression(d) || ts.isClassExpression(d)) && !d.name)) { - displayParts.push(ts.spacePart()); + if (symbol && !some(symbol.declarations, d => isArrowFunction(d) || (isFunctionExpression(d) || isClassExpression(d)) && !d.name)) { + displayParts.push(spacePart()); addFullSymbolName(symbol); } } @@ -697,31 +716,31 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. function pushSymbolKind(symbolKind: string) { switch (symbolKind) { - case ts.ScriptElementKind.variableElement: - case ts.ScriptElementKind.functionElement: - case ts.ScriptElementKind.letElement: - case ts.ScriptElementKind.constElement: - case ts.ScriptElementKind.constructorImplementationElement: - displayParts.push(ts.textOrKeywordPart(symbolKind)); + case ScriptElementKind.variableElement: + case ScriptElementKind.functionElement: + case ScriptElementKind.letElement: + case ScriptElementKind.constElement: + case ScriptElementKind.constructorImplementationElement: + displayParts.push(textOrKeywordPart(symbolKind)); return; default: - displayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenParenToken)); - displayParts.push(ts.textOrKeywordPart(symbolKind)); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseParenToken)); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(textOrKeywordPart(symbolKind)); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); return; } } - function addSignatureDisplayParts(signature: ts.Signature, allSignatures: readonly ts.Signature[], flags = ts.TypeFormatFlags.None) { - ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | ts.TypeFormatFlags.WriteTypeArgumentsOfSignature)); + function addSignatureDisplayParts(signature: Signature, allSignatures: readonly Signature[], flags = TypeFormatFlags.None) { + addRange(displayParts, signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | TypeFormatFlags.WriteTypeArgumentsOfSignature)); if (allSignatures.length > 1) { - displayParts.push(ts.spacePart()); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.OpenParenToken)); - displayParts.push(ts.operatorPart(ts.SyntaxKind.PlusToken)); - displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral)); - displayParts.push(ts.spacePart()); - displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads")); - displayParts.push(ts.punctuationPart(ts.SyntaxKind.CloseParenToken)); + displayParts.push(spacePart()); + displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); + displayParts.push(operatorPart(SyntaxKind.PlusToken)); + displayParts.push(displayPart((allSignatures.length - 1).toString(), SymbolDisplayPartKind.numericLiteral)); + displayParts.push(spacePart()); + displayParts.push(textPart(allSignatures.length === 2 ? "overload" : "overloads")); + displayParts.push(punctuationPart(SyntaxKind.CloseParenToken)); } documentation = signature.getDocumentationComment(typeChecker); tags = signature.getJsDocTags(); @@ -733,34 +752,34 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: ts. } - function writeTypeParametersOfSymbol(symbol: ts.Symbol, enclosingDeclaration: ts.Node | undefined) { - const typeParameterParts = ts.mapToDisplayParts(writer => { + function writeTypeParametersOfSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined) { + const typeParameterParts = mapToDisplayParts(writer => { const params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration, symbolDisplayNodeBuilderFlags); - getPrinter().writeList(ts.ListFormat.TypeParameters, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer); + getPrinter().writeList(ListFormat.TypeParameters, params, getSourceFileOfNode(getParseTreeNode(enclosingDeclaration)), writer); }); - ts.addRange(displayParts, typeParameterParts); + addRange(displayParts, typeParameterParts); } } -function isLocalVariableOrFunction(symbol: ts.Symbol) { +function isLocalVariableOrFunction(symbol: Symbol) { if (symbol.parent) { return false; // This is exported symbol } - return ts.forEach(symbol.declarations, declaration => { + return forEach(symbol.declarations, declaration => { // Function expressions are local - if (declaration.kind === ts.SyntaxKind.FunctionExpression) { + if (declaration.kind === SyntaxKind.FunctionExpression) { return true; } - if (declaration.kind !== ts.SyntaxKind.VariableDeclaration && declaration.kind !== ts.SyntaxKind.FunctionDeclaration) { + if (declaration.kind !== SyntaxKind.VariableDeclaration && declaration.kind !== SyntaxKind.FunctionDeclaration) { return false; } // If the parent is not sourceFile or module block it is local variable - for (let parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) { + for (let parent = declaration.parent; !isFunctionBlock(parent); parent = parent.parent) { // Reached source file or module block - if (parent.kind === ts.SyntaxKind.SourceFile || parent.kind === ts.SyntaxKind.ModuleBlock) { + if (parent.kind === SyntaxKind.SourceFile || parent.kind === SyntaxKind.ModuleBlock) { return false; } } diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 06904686618c2..0f3562715c517 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1,28 +1,56 @@ -import * as ts from "./_namespaces/ts"; +import { + addToSeen, ArrowFunction, BindingElement, CharacterCodes, ClassElement, ClassExpression, ClassLikeDeclaration, + CommentRange, concatenate, ConstructorDeclaration, contains, createNodeFactory, createPrinter, createRange, + createSourceFile, createTextChange, createTextRangeFromSpan, createTextSpan, createTextSpanFromRange, + createTextWriter, Debug, DeclarationStatement, EmitHint, EmitTextWriter, endsWith, Expression, factory, + FileTextChanges, filter, find, findChildOfKind, findLastIndex, findNextToken, findPrecedingToken, first, + firstOrUndefined, flatMap, flatMapToMutable, formatting, FunctionDeclaration, FunctionExpression, getAncestor, + getFirstNonSpaceCharacterPosition, getFormatCodeSettingsForWriting, getJSDocCommentRanges, getLeadingCommentRanges, + getLineAndCharacterOfPosition, getLineOfLocalPosition, getLineStartPositionForPosition, getNewLineKind, + getNewLineOrDefaultFromHost, getNodeId, getPrecedingNonSpaceCharacterPosition, getScriptKindFromFileName, + getShebang, getStartPositionOfLine, getTokenAtPosition, getTouchingToken, getTrailingCommentRanges, group, HasJSDoc, + hasJSDocNodes, ImportClause, ImportSpecifier, indexOfNode, InterfaceDeclaration, intersperse, isAnyImportSyntax, + isArray, isArrowFunction, isCallExpression, isClassElement, isClassOrTypeElement, isExpressionStatement, + isFunctionDeclaration, isFunctionExpression, isFunctionLike, isIdentifier, isImportClause, isImportDeclaration, + isImportSpecifier, isInComment, isInJSXText, isInString, isInTemplateString, isInterfaceDeclaration, + isJsonSourceFile, isLineBreak, isNamedImports, isObjectLiteralExpression, isParameter, isPinnedComment, + isPrologueDirective, isPropertyDeclaration, isPropertySignature, isRecognizedTripleSlashComment, isStatement, + isStatementButNotDeclaration, isString, isStringLiteral, isSuperCall, isVariableDeclaration, isWhiteSpaceLike, + isWhiteSpaceSingleLine, JSDoc, JSDocComment, JSDocParameterTag, JSDocReturnTag, JSDocTag, JSDocTypeTag, + LanguageServiceHost, last, lastOrUndefined, length, Map, mapDefined, MethodSignature, Modifier, NamedImportBindings, + NamedImports, NamespaceImport, Node, NodeArray, NodeFactoryFlags, nodeIsSynthesized, nullTransformationContext, + ObjectLiteralElementLike, ObjectLiteralExpression, ParameterDeclaration, positionsAreOnSameLine, PrintHandlers, + PrologueDirective, PropertyAssignment, PropertyDeclaration, PropertySignature, rangeContainsPosition, + rangeContainsRangeExclusive, rangeOfNode, rangeOfTypeParameters, rangeStartPositionsAreOnSameLine, removeSuffix, + ScriptKind, ScriptTarget, Set, setTextRangePosEnd, SignatureDeclaration, singleOrUndefined, skipTrivia, SourceFile, + SourceFileLike, stableSort, Statement, stringContainsAt, Symbol, SyntaxKind, TextChange, TextRange, textSpanEnd, + Token, tokenToString, TransformationContext, TypeLiteralNode, TypeNode, TypeParameterDeclaration, UserPreferences, + VariableDeclaration, VariableStatement, visitEachChild, visitNodes, Visitor, +} from "./_namespaces/ts"; /** * Currently for simplicity we store recovered positions on the node itself. * It can be changed to side-table later if we decide that current design is too invasive. */ -function getPos(n: ts.TextRange): number { +function getPos(n: TextRange): number { const result = (n as any).__pos; - ts.Debug.assert(typeof result === "number"); + Debug.assert(typeof result === "number"); return result; } -function setPos(n: ts.TextRange, pos: number): void { - ts.Debug.assert(typeof pos === "number"); +function setPos(n: TextRange, pos: number): void { + Debug.assert(typeof pos === "number"); (n as any).__pos = pos; } -function getEnd(n: ts.TextRange): number { +function getEnd(n: TextRange): number { const result = (n as any).__end; - ts.Debug.assert(typeof result === "number"); + Debug.assert(typeof result === "number"); return result; } -function setEnd(n: ts.TextRange, end: number): void { - ts.Debug.assert(typeof end === "number"); +function setEnd(n: TextRange, end: number): void { + Debug.assert(typeof end === "number"); (n as any).__end = end; } @@ -66,18 +94,18 @@ export enum TrailingTriviaOption { } function skipWhitespacesAndLineBreaks(text: string, start: number) { - return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } function hasCommentsBeforeLineBreak(text: string, start: number) { let i = start; while (i < text.length) { const ch = text.charCodeAt(i); - if (ts.isWhiteSpaceSingleLine(ch)) { + if (isWhiteSpaceSingleLine(ch)) { i++; continue; } - return ch === ts.CharacterCodes.slash; + return ch === CharacterCodes.slash; } return false; } @@ -138,15 +166,15 @@ enum ChangeKind { type Change = ReplaceWithSingleNode | ReplaceWithMultipleNodes | RemoveNode | ChangeText; interface BaseChange { - readonly sourceFile: ts.SourceFile; - readonly range: ts.TextRange; + readonly sourceFile: SourceFile; + readonly range: TextRange; } /** @internal */ export interface ChangeNodeOptions extends ConfigurableStartEnd, InsertNodeOptions {} interface ReplaceWithSingleNode extends BaseChange { readonly kind: ChangeKind.ReplaceWithSingleNode; - readonly node: ts.Node; + readonly node: Node; readonly options?: InsertNodeOptions; } @@ -158,7 +186,7 @@ interface RemoveNode extends BaseChange { interface ReplaceWithMultipleNodes extends BaseChange { readonly kind: ChangeKind.ReplaceWithMultipleNodes; - readonly nodes: readonly ts.Node[]; + readonly nodes: readonly Node[]; readonly options?: ReplaceWithMultipleNodesOptions; } @@ -167,24 +195,24 @@ interface ChangeText extends BaseChange { readonly text: string; } -function getAdjustedRange(sourceFile: ts.SourceFile, startNode: ts.Node, endNode: ts.Node, options: ConfigurableStartEnd): ts.TextRange { +function getAdjustedRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd): TextRange { return { pos: getAdjustedStartPosition(sourceFile, startNode, options), end: getAdjustedEndPosition(sourceFile, endNode, options) }; } -function getAdjustedStartPosition(sourceFile: ts.SourceFile, node: ts.Node, options: ConfigurableStartEnd, hasTrailingComment = false) { +function getAdjustedStartPosition(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd, hasTrailingComment = false) { const { leadingTriviaOption } = options; if (leadingTriviaOption === LeadingTriviaOption.Exclude) { return node.getStart(sourceFile); } if (leadingTriviaOption === LeadingTriviaOption.StartLine) { const startPos = node.getStart(sourceFile); - const pos = ts.getLineStartPositionForPosition(startPos, sourceFile); - return ts.rangeContainsPosition(node, pos) ? pos : startPos; + const pos = getLineStartPositionForPosition(startPos, sourceFile); + return rangeContainsPosition(node, pos) ? pos : startPos; } if (leadingTriviaOption === LeadingTriviaOption.JSDoc) { - const JSDocComments = ts.getJSDocCommentRanges(node, sourceFile.text); + const JSDocComments = getJSDocCommentRanges(node, sourceFile.text); if (JSDocComments?.length) { - return ts.getLineStartPositionForPosition(JSDocComments[0].pos, sourceFile); + return getLineStartPositionForPosition(JSDocComments[0].pos, sourceFile); } } const fullStart = node.getFullStart(); @@ -192,8 +220,8 @@ function getAdjustedStartPosition(sourceFile: ts.SourceFile, node: ts.Node, opti if (fullStart === start) { return start; } - const fullStartLine = ts.getLineStartPositionForPosition(fullStart, sourceFile); - const startLine = ts.getLineStartPositionForPosition(start, sourceFile); + const fullStartLine = getLineStartPositionForPosition(fullStart, sourceFile); + const startLine = getLineStartPositionForPosition(start, sourceFile); if (startLine === fullStartLine) { // full start and start of the node are on the same line // a, b; @@ -209,44 +237,44 @@ function getAdjustedStartPosition(sourceFile: ts.SourceFile, node: ts.Node, opti if (hasTrailingComment) { // Check first for leading comments as if the node is the first import, we want to exclude the trivia; // otherwise we get the trailing comments. - const comment = ts.getLeadingCommentRanges(sourceFile.text, fullStart)?.[0] || ts.getTrailingCommentRanges(sourceFile.text, fullStart)?.[0]; + const comment = getLeadingCommentRanges(sourceFile.text, fullStart)?.[0] || getTrailingCommentRanges(sourceFile.text, fullStart)?.[0]; if (comment) { - return ts.skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); + return skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); } } // get start position of the line following the line that contains fullstart position // (but only if the fullstart isn't the very beginning of the file) const nextLineStart = fullStart > 0 ? 1 : 0; - let adjustedStartPosition = ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile); + let adjustedStartPosition = getStartPositionOfLine(getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile); // skip whitespaces/newlines adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition); - return ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); + return getStartPositionOfLine(getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile); } /** Return the end position of a multiline comment of it is on another line; otherwise returns `undefined`; */ -function getEndPositionOfMultilineTrailingComment(sourceFile: ts.SourceFile, node: ts.Node, options: ConfigurableEnd): number | undefined { +function getEndPositionOfMultilineTrailingComment(sourceFile: SourceFile, node: Node, options: ConfigurableEnd): number | undefined { const { end } = node; const { trailingTriviaOption } = options; if (trailingTriviaOption === TrailingTriviaOption.Include) { // If the trailing comment is a multiline comment that extends to the next lines, // return the end of the comment and track it for the next nodes to adjust. - const comments = ts.getTrailingCommentRanges(sourceFile.text, end); + const comments = getTrailingCommentRanges(sourceFile.text, end); if (comments) { - const nodeEndLine = ts.getLineOfLocalPosition(sourceFile, node.end); + const nodeEndLine = getLineOfLocalPosition(sourceFile, node.end); for (const comment of comments) { // Single line can break the loop as trivia will only be this line. // Comments on subsequest lines are also ignored. - if (comment.kind === ts.SyntaxKind.SingleLineCommentTrivia || ts.getLineOfLocalPosition(sourceFile, comment.pos) > nodeEndLine) { + if (comment.kind === SyntaxKind.SingleLineCommentTrivia || getLineOfLocalPosition(sourceFile, comment.pos) > nodeEndLine) { break; } // Get the end line of the comment and compare against the end line of the node. // If the comment end line position and the multiline comment extends to multiple lines, // then is safe to return the end position. - const commentEndLine = ts.getLineOfLocalPosition(sourceFile, comment.end); + const commentEndLine = getLineOfLocalPosition(sourceFile, comment.end); if (commentEndLine > nodeEndLine) { - return ts.skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); + return skipTrivia(sourceFile.text, comment.end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); } } } @@ -255,14 +283,14 @@ function getEndPositionOfMultilineTrailingComment(sourceFile: ts.SourceFile, nod return undefined; } -function getAdjustedEndPosition(sourceFile: ts.SourceFile, node: ts.Node, options: ConfigurableEnd): number { +function getAdjustedEndPosition(sourceFile: SourceFile, node: Node, options: ConfigurableEnd): number { const { end } = node; const { trailingTriviaOption } = options; if (trailingTriviaOption === TrailingTriviaOption.Exclude) { return end; } if (trailingTriviaOption === TrailingTriviaOption.ExcludeWhitespace) { - const comments = ts.concatenate(ts.getTrailingCommentRanges(sourceFile.text, end), ts.getLeadingCommentRanges(sourceFile.text, end)); + const comments = concatenate(getTrailingCommentRanges(sourceFile.text, end), getLeadingCommentRanges(sourceFile.text, end)); const realEnd = comments?.[comments.length - 1]?.end; if (realEnd) { return realEnd; @@ -275,9 +303,9 @@ function getAdjustedEndPosition(sourceFile: ts.SourceFile, node: ts.Node, option return multilineEndPosition; } - const newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); + const newEnd = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true); - return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) + return newEnd !== end && (trailingTriviaOption === TrailingTriviaOption.Include || isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))) ? newEnd : end; } @@ -285,74 +313,74 @@ function getAdjustedEndPosition(sourceFile: ts.SourceFile, node: ts.Node, option /** * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element */ -function isSeparator(node: ts.Node, candidate: ts.Node | undefined): candidate is ts.Token { - return !!candidate && !!node.parent && (candidate.kind === ts.SyntaxKind.CommaToken || (candidate.kind === ts.SyntaxKind.SemicolonToken && node.parent.kind === ts.SyntaxKind.ObjectLiteralExpression)); +function isSeparator(node: Node, candidate: Node | undefined): candidate is Token { + return !!candidate && !!node.parent && (candidate.kind === SyntaxKind.CommaToken || (candidate.kind === SyntaxKind.SemicolonToken && node.parent.kind === SyntaxKind.ObjectLiteralExpression)); } /** @internal */ export interface TextChangesContext { - host: ts.LanguageServiceHost; - formatContext: ts.formatting.FormatContext; - preferences: ts.UserPreferences; + host: LanguageServiceHost; + formatContext: formatting.FormatContext; + preferences: UserPreferences; } /** @internal */ -export type TypeAnnotatable = ts.SignatureDeclaration | ts.VariableDeclaration | ts.ParameterDeclaration | ts.PropertyDeclaration | ts.PropertySignature; +export type TypeAnnotatable = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature; /** @internal */ -export type ThisTypeAnnotatable = ts.FunctionDeclaration | ts.FunctionExpression; +export type ThisTypeAnnotatable = FunctionDeclaration | FunctionExpression; /** @internal */ -export function isThisTypeAnnotatable(containingFunction: ts.SignatureDeclaration): containingFunction is ThisTypeAnnotatable { - return ts.isFunctionExpression(containingFunction) || ts.isFunctionDeclaration(containingFunction); +export function isThisTypeAnnotatable(containingFunction: SignatureDeclaration): containingFunction is ThisTypeAnnotatable { + return isFunctionExpression(containingFunction) || isFunctionDeclaration(containingFunction); } /** @internal */ export class ChangeTracker { private readonly changes: Change[] = []; - private readonly newFiles: { readonly oldFile: ts.SourceFile | undefined, readonly fileName: string, readonly statements: readonly (ts.Statement | ts.SyntaxKind.NewLineTrivia)[] }[] = []; - private readonly classesWithNodesInsertedAtStart = new ts.Map(); // Set implemented as Map - private readonly deletedNodes: { readonly sourceFile: ts.SourceFile, readonly node: ts.Node | ts.NodeArray }[] = []; + private readonly newFiles: { readonly oldFile: SourceFile | undefined, readonly fileName: string, readonly statements: readonly (Statement | SyntaxKind.NewLineTrivia)[] }[] = []; + private readonly classesWithNodesInsertedAtStart = new Map(); // Set implemented as Map + private readonly deletedNodes: { readonly sourceFile: SourceFile, readonly node: Node | NodeArray }[] = []; public static fromContext(context: TextChangesContext): ChangeTracker { - return new ChangeTracker(ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext); + return new ChangeTracker(getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext); } - public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): ts.FileTextChanges[] { + public static with(context: TextChangesContext, cb: (tracker: ChangeTracker) => void): FileTextChanges[] { const tracker = ChangeTracker.fromContext(context); cb(tracker); return tracker.getChanges(); } /** Public for tests only. Other callers should use `ChangeTracker.with`. */ - constructor(private readonly newLineCharacter: string, private readonly formatContext: ts.formatting.FormatContext) {} + constructor(private readonly newLineCharacter: string, private readonly formatContext: formatting.FormatContext) {} - public pushRaw(sourceFile: ts.SourceFile, change: ts.FileTextChanges) { - ts.Debug.assertEqual(sourceFile.fileName, change.fileName); + public pushRaw(sourceFile: SourceFile, change: FileTextChanges) { + Debug.assertEqual(sourceFile.fileName, change.fileName); for (const c of change.textChanges) { this.changes.push({ kind: ChangeKind.Text, sourceFile, text: c.newText, - range: ts.createTextRangeFromSpan(c.span), + range: createTextRangeFromSpan(c.span), }); } } - public deleteRange(sourceFile: ts.SourceFile, range: ts.TextRange): void { + public deleteRange(sourceFile: SourceFile, range: TextRange): void { this.changes.push({ kind: ChangeKind.Remove, sourceFile, range }); } - delete(sourceFile: ts.SourceFile, node: ts.Node | ts.NodeArray): void { + delete(sourceFile: SourceFile, node: Node | NodeArray): void { this.deletedNodes.push({ sourceFile, node }); } /** Stop! Consider using `delete` instead, which has logic for deleting nodes from delimited lists. */ - public deleteNode(sourceFile: ts.SourceFile, node: ts.Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNode(sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { this.deleteRange(sourceFile, getAdjustedRange(sourceFile, node, node, options)); } - public deleteNodes(sourceFile: ts.SourceFile, nodes: readonly ts.Node[], options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, hasTrailingComment: boolean): void { + public deleteNodes(sourceFile: SourceFile, nodes: readonly Node[], options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }, hasTrailingComment: boolean): void { // When deleting multiple nodes we need to track if the end position is including multiline trailing comments. for (const node of nodes) { const pos = getAdjustedStartPosition(sourceFile, node, options, hasTrailingComment); @@ -364,87 +392,87 @@ export class ChangeTracker { } } - public deleteModifier(sourceFile: ts.SourceFile, modifier: ts.Modifier): void { - this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: ts.skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); + public deleteModifier(sourceFile: SourceFile, modifier: Modifier): void { + this.deleteRange(sourceFile, { pos: modifier.getStart(sourceFile), end: skipTrivia(sourceFile.text, modifier.end, /*stopAfterLineBreak*/ true) }); } - public deleteNodeRange(sourceFile: ts.SourceFile, startNode: ts.Node, endNode: ts.Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { const startPosition = getAdjustedStartPosition(sourceFile, startNode, options); const endPosition = getAdjustedEndPosition(sourceFile, endNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } - public deleteNodeRangeExcludingEnd(sourceFile: ts.SourceFile, startNode: ts.Node, afterEndNode: ts.Node | undefined, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { + public deleteNodeRangeExcludingEnd(sourceFile: SourceFile, startNode: Node, afterEndNode: Node | undefined, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { const startPosition = getAdjustedStartPosition(sourceFile, startNode, options); const endPosition = afterEndNode === undefined ? sourceFile.text.length : getAdjustedStartPosition(sourceFile, afterEndNode, options); this.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } - public replaceRange(sourceFile: ts.SourceFile, range: ts.TextRange, newNode: ts.Node, options: InsertNodeOptions = {}): void { + public replaceRange(sourceFile: SourceFile, range: TextRange, newNode: Node, options: InsertNodeOptions = {}): void { this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile, range, options, node: newNode }); } - public replaceNode(sourceFile: ts.SourceFile, oldNode: ts.Node, newNode: ts.Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { + public replaceNode(sourceFile: SourceFile, oldNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { this.replaceRange(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNode, options); } - public replaceNodeRange(sourceFile: ts.SourceFile, startNode: ts.Node, endNode: ts.Node, newNode: ts.Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { + public replaceNodeRange(sourceFile: SourceFile, startNode: Node, endNode: Node, newNode: Node, options: ChangeNodeOptions = useNonAdjustedPositions): void { this.replaceRange(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNode, options); } - private replaceRangeWithNodes(sourceFile: ts.SourceFile, range: ts.TextRange, newNodes: readonly ts.Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}): void { + private replaceRangeWithNodes(sourceFile: SourceFile, range: TextRange, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = {}): void { this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile, range, options, nodes: newNodes }); } - public replaceNodeWithNodes(sourceFile: ts.SourceFile, oldNode: ts.Node, newNodes: readonly ts.Node[], options: ChangeNodeOptions = useNonAdjustedPositions): void { + public replaceNodeWithNodes(sourceFile: SourceFile, oldNode: Node, newNodes: readonly Node[], options: ChangeNodeOptions = useNonAdjustedPositions): void { this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, options), newNodes, options); } - public replaceNodeWithText(sourceFile: ts.SourceFile, oldNode: ts.Node, text: string): void { + public replaceNodeWithText(sourceFile: SourceFile, oldNode: Node, text: string): void { this.replaceRangeWithText(sourceFile, getAdjustedRange(sourceFile, oldNode, oldNode, useNonAdjustedPositions), text); } - public replaceNodeRangeWithNodes(sourceFile: ts.SourceFile, startNode: ts.Node, endNode: ts.Node, newNodes: readonly ts.Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions): void { + public replaceNodeRangeWithNodes(sourceFile: SourceFile, startNode: Node, endNode: Node, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions & ConfigurableStartEnd = useNonAdjustedPositions): void { this.replaceRangeWithNodes(sourceFile, getAdjustedRange(sourceFile, startNode, endNode, options), newNodes, options); } - public nodeHasTrailingComment(sourceFile: ts.SourceFile, oldNode: ts.Node, configurableEnd: ConfigurableEnd = useNonAdjustedPositions): boolean { + public nodeHasTrailingComment(sourceFile: SourceFile, oldNode: Node, configurableEnd: ConfigurableEnd = useNonAdjustedPositions): boolean { return !!getEndPositionOfMultilineTrailingComment(sourceFile, oldNode, configurableEnd); } - private nextCommaToken(sourceFile: ts.SourceFile, node: ts.Node): ts.Node | undefined { - const next = ts.findNextToken(node, node.parent, sourceFile); - return next && next.kind === ts.SyntaxKind.CommaToken ? next : undefined; + private nextCommaToken(sourceFile: SourceFile, node: Node): Node | undefined { + const next = findNextToken(node, node.parent, sourceFile); + return next && next.kind === SyntaxKind.CommaToken ? next : undefined; } - public replacePropertyAssignment(sourceFile: ts.SourceFile, oldNode: ts.PropertyAssignment, newNode: ts.PropertyAssignment): void { + public replacePropertyAssignment(sourceFile: SourceFile, oldNode: PropertyAssignment, newNode: PropertyAssignment): void { const suffix = this.nextCommaToken(sourceFile, oldNode) ? "" : ("," + this.newLineCharacter); this.replaceNode(sourceFile, oldNode, newNode, { suffix }); } - public insertNodeAt(sourceFile: ts.SourceFile, pos: number, newNode: ts.Node, options: InsertNodeOptions = {}): void { - this.replaceRange(sourceFile, ts.createRange(pos), newNode, options); + public insertNodeAt(sourceFile: SourceFile, pos: number, newNode: Node, options: InsertNodeOptions = {}): void { + this.replaceRange(sourceFile, createRange(pos), newNode, options); } - private insertNodesAt(sourceFile: ts.SourceFile, pos: number, newNodes: readonly ts.Node[], options: ReplaceWithMultipleNodesOptions = {}): void { - this.replaceRangeWithNodes(sourceFile, ts.createRange(pos), newNodes, options); + private insertNodesAt(sourceFile: SourceFile, pos: number, newNodes: readonly Node[], options: ReplaceWithMultipleNodesOptions = {}): void { + this.replaceRangeWithNodes(sourceFile, createRange(pos), newNodes, options); } - public insertNodeAtTopOfFile(sourceFile: ts.SourceFile, newNode: ts.Statement, blankLineBetween: boolean): void { + public insertNodeAtTopOfFile(sourceFile: SourceFile, newNode: Statement, blankLineBetween: boolean): void { this.insertAtTopOfFile(sourceFile, newNode, blankLineBetween); } - public insertNodesAtTopOfFile(sourceFile: ts.SourceFile, newNodes: readonly ts.Statement[], blankLineBetween: boolean): void { + public insertNodesAtTopOfFile(sourceFile: SourceFile, newNodes: readonly Statement[], blankLineBetween: boolean): void { this.insertAtTopOfFile(sourceFile, newNodes, blankLineBetween); } - private insertAtTopOfFile(sourceFile: ts.SourceFile, insert: ts.Statement | readonly ts.Statement[], blankLineBetween: boolean): void { + private insertAtTopOfFile(sourceFile: SourceFile, insert: Statement | readonly Statement[], blankLineBetween: boolean): void { const pos = getInsertionPositionAtSourceFileTop(sourceFile); const options = { prefix: pos === 0 ? undefined : this.newLineCharacter, - suffix: (ts.isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""), + suffix: (isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""), }; - if (ts.isArray(insert)) { + if (isArray(insert)) { this.insertNodesAt(sourceFile, pos, insert, options); } else { @@ -452,8 +480,8 @@ export class ChangeTracker { } } - public insertFirstParameter(sourceFile: ts.SourceFile, parameters: ts.NodeArray, newParam: ts.ParameterDeclaration): void { - const p0 = ts.firstOrUndefined(parameters); + public insertFirstParameter(sourceFile: SourceFile, parameters: NodeArray, newParam: ParameterDeclaration): void { + const p0 = firstOrUndefined(parameters); if (p0) { this.insertNodeBefore(sourceFile, p0, newParam); } @@ -462,61 +490,61 @@ export class ChangeTracker { } } - public insertNodeBefore(sourceFile: ts.SourceFile, before: ts.Node, newNode: ts.Node, blankLineBetween = false, options: ConfigurableStartEnd = {}): void { + public insertNodeBefore(sourceFile: SourceFile, before: Node, newNode: Node, blankLineBetween = false, options: ConfigurableStartEnd = {}): void { this.insertNodeAt(sourceFile, getAdjustedStartPosition(sourceFile, before, options), newNode, this.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)); } - public insertModifierAt(sourceFile: ts.SourceFile, pos: number, modifier: ts.SyntaxKind, options: InsertNodeOptions = {}): void { - this.insertNodeAt(sourceFile, pos, ts.factory.createToken(modifier), options); + public insertModifierAt(sourceFile: SourceFile, pos: number, modifier: SyntaxKind, options: InsertNodeOptions = {}): void { + this.insertNodeAt(sourceFile, pos, factory.createToken(modifier), options); } - public insertModifierBefore(sourceFile: ts.SourceFile, modifier: ts.SyntaxKind, before: ts.Node): void { + public insertModifierBefore(sourceFile: SourceFile, modifier: SyntaxKind, before: Node): void { return this.insertModifierAt(sourceFile, before.getStart(sourceFile), modifier, { suffix: " " }); } - public insertCommentBeforeLine(sourceFile: ts.SourceFile, lineNumber: number, position: number, commentText: string): void { - const lineStartPosition = ts.getStartPositionOfLine(lineNumber, sourceFile); - const startPosition = ts.getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); + public insertCommentBeforeLine(sourceFile: SourceFile, lineNumber: number, position: number, commentText: string): void { + const lineStartPosition = getStartPositionOfLine(lineNumber, sourceFile); + const startPosition = getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition); // First try to see if we can put the comment on the previous line. // We need to make sure that we are not in the middle of a string literal or a comment. // If so, we do not want to separate the node from its comment if we can. // Otherwise, add an extra new line immediately before the error span. const insertAtLineStart = isValidLocationToAddComment(sourceFile, startPosition); - const token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position); + const token = getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position); const indent = sourceFile.text.slice(lineStartPosition, startPosition); const text = `${insertAtLineStart ? "" : this.newLineCharacter}//${commentText}${this.newLineCharacter}${indent}`; this.insertText(sourceFile, token.getStart(sourceFile), text); } - public insertJsdocCommentBefore(sourceFile: ts.SourceFile, node: ts.HasJSDoc, tag: ts.JSDoc): void { + public insertJsdocCommentBefore(sourceFile: SourceFile, node: HasJSDoc, tag: JSDoc): void { const fnStart = node.getStart(sourceFile); if (node.jsDoc) { for (const jsdoc of node.jsDoc) { this.deleteRange(sourceFile, { - pos: ts.getLineStartPositionForPosition(jsdoc.getStart(sourceFile), sourceFile), + pos: getLineStartPositionForPosition(jsdoc.getStart(sourceFile), sourceFile), end: getAdjustedEndPosition(sourceFile, jsdoc, /*options*/ {}) }); } } - const startPosition = ts.getPrecedingNonSpaceCharacterPosition(sourceFile.text, fnStart - 1); + const startPosition = getPrecedingNonSpaceCharacterPosition(sourceFile.text, fnStart - 1); const indent = sourceFile.text.slice(startPosition, fnStart); this.insertNodeAt(sourceFile, fnStart, tag, { suffix: this.newLineCharacter + indent }); } - private createJSDocText(sourceFile: ts.SourceFile, node: ts.HasJSDoc) { - const comments = ts.flatMap(node.jsDoc, jsDoc => - ts.isString(jsDoc.comment) ? ts.factory.createJSDocText(jsDoc.comment) : jsDoc.comment) as ts.JSDocComment[]; - const jsDoc = ts.singleOrUndefined(node.jsDoc); - return jsDoc && ts.positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && ts.length(comments) === 0 ? undefined : - ts.factory.createNodeArray(ts.intersperse(comments, ts.factory.createJSDocText("\n"))); + private createJSDocText(sourceFile: SourceFile, node: HasJSDoc) { + const comments = flatMap(node.jsDoc, jsDoc => + isString(jsDoc.comment) ? factory.createJSDocText(jsDoc.comment) : jsDoc.comment) as JSDocComment[]; + const jsDoc = singleOrUndefined(node.jsDoc); + return jsDoc && positionsAreOnSameLine(jsDoc.pos, jsDoc.end, sourceFile) && length(comments) === 0 ? undefined : + factory.createNodeArray(intersperse(comments, factory.createJSDocText("\n"))); } - public replaceJSDocComment(sourceFile: ts.SourceFile, node: ts.HasJSDoc, tags: readonly ts.JSDocTag[]) { - this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), ts.factory.createJSDocComment(this.createJSDocText(sourceFile, node), ts.factory.createNodeArray(tags))); + public replaceJSDocComment(sourceFile: SourceFile, node: HasJSDoc, tags: readonly JSDocTag[]) { + this.insertJsdocCommentBefore(sourceFile, updateJSDocHost(node), factory.createJSDocComment(this.createJSDocText(sourceFile, node), factory.createNodeArray(tags))); } - public addJSDocTags(sourceFile: ts.SourceFile, parent: ts.HasJSDoc, newTags: readonly ts.JSDocTag[]): void { - const oldTags = ts.flatMapToMutable(parent.jsDoc, j => j.tags); + public addJSDocTags(sourceFile: SourceFile, parent: HasJSDoc, newTags: readonly JSDocTag[]): void { + const oldTags = flatMapToMutable(parent.jsDoc, j => j.tags); const unmergedNewTags = newTags.filter(newTag => !oldTags.some((tag, i) => { const merged = tryMergeJsdocTags(tag, newTag); if (merged) oldTags[i] = merged; @@ -525,71 +553,71 @@ export class ChangeTracker { this.replaceJSDocComment(sourceFile, parent, [...oldTags, ...unmergedNewTags]); } - public filterJSDocTags(sourceFile: ts.SourceFile, parent: ts.HasJSDoc, predicate: (tag: ts.JSDocTag) => boolean): void { - this.replaceJSDocComment(sourceFile, parent, ts.filter(ts.flatMapToMutable(parent.jsDoc, j => j.tags), predicate)); + public filterJSDocTags(sourceFile: SourceFile, parent: HasJSDoc, predicate: (tag: JSDocTag) => boolean): void { + this.replaceJSDocComment(sourceFile, parent, filter(flatMapToMutable(parent.jsDoc, j => j.tags), predicate)); } - public replaceRangeWithText(sourceFile: ts.SourceFile, range: ts.TextRange, text: string): void { + public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string): void { this.changes.push({ kind: ChangeKind.Text, sourceFile, range, text }); } - public insertText(sourceFile: ts.SourceFile, pos: number, text: string): void { - this.replaceRangeWithText(sourceFile, ts.createRange(pos), text); + public insertText(sourceFile: SourceFile, pos: number, text: string): void { + this.replaceRangeWithText(sourceFile, createRange(pos), text); } /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */ - public tryInsertTypeAnnotation(sourceFile: ts.SourceFile, node: TypeAnnotatable, type: ts.TypeNode): boolean { - let endNode: ts.Node | undefined; - if (ts.isFunctionLike(node)) { - endNode = ts.findChildOfKind(node, ts.SyntaxKind.CloseParenToken, sourceFile); + public tryInsertTypeAnnotation(sourceFile: SourceFile, node: TypeAnnotatable, type: TypeNode): boolean { + let endNode: Node | undefined; + if (isFunctionLike(node)) { + endNode = findChildOfKind(node, SyntaxKind.CloseParenToken, sourceFile); if (!endNode) { - if (!ts.isArrowFunction(node)) return false; // Function missing parentheses, give up + if (!isArrowFunction(node)) return false; // Function missing parentheses, give up // If no `)`, is an arrow function `x => x`, so use the end of the first parameter - endNode = ts.first(node.parameters); + endNode = first(node.parameters); } } else { - endNode = (node.kind === ts.SyntaxKind.VariableDeclaration ? node.exclamationToken : node.questionToken) ?? node.name; + endNode = (node.kind === SyntaxKind.VariableDeclaration ? node.exclamationToken : node.questionToken) ?? node.name; } this.insertNodeAt(sourceFile, endNode.end, type, { prefix: ": " }); return true; } - public tryInsertThisTypeAnnotation(sourceFile: ts.SourceFile, node: ThisTypeAnnotatable, type: ts.TypeNode): void { - const start = ts.findChildOfKind(node, ts.SyntaxKind.OpenParenToken, sourceFile)!.getStart(sourceFile) + 1; + public tryInsertThisTypeAnnotation(sourceFile: SourceFile, node: ThisTypeAnnotatable, type: TypeNode): void { + const start = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile)!.getStart(sourceFile) + 1; const suffix = node.parameters.length ? ", " : ""; this.insertNodeAt(sourceFile, start, type, { prefix: "this: ", suffix }); } - public insertTypeParameters(sourceFile: ts.SourceFile, node: ts.SignatureDeclaration, typeParameters: readonly ts.TypeParameterDeclaration[]): void { + public insertTypeParameters(sourceFile: SourceFile, node: SignatureDeclaration, typeParameters: readonly TypeParameterDeclaration[]): void { // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter - const start = (ts.findChildOfKind(node, ts.SyntaxKind.OpenParenToken, sourceFile) || ts.first(node.parameters)).getStart(sourceFile); + const start = (findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile) || first(node.parameters)).getStart(sourceFile); this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">", joiner: ", " }); } - private getOptionsForInsertNodeBefore(before: ts.Node, inserted: ts.Node, blankLineBetween: boolean): InsertNodeOptions { - if (ts.isStatement(before) || ts.isClassElement(before)) { + private getOptionsForInsertNodeBefore(before: Node, inserted: Node, blankLineBetween: boolean): InsertNodeOptions { + if (isStatement(before) || isClassElement(before)) { return { suffix: blankLineBetween ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter }; } - else if (ts.isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2; + else if (isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2; return { suffix: ", " }; } - else if (ts.isParameter(before)) { - return ts.isParameter(inserted) ? { suffix: ", " } : {}; + else if (isParameter(before)) { + return isParameter(inserted) ? { suffix: ", " } : {}; } - else if (ts.isStringLiteral(before) && ts.isImportDeclaration(before.parent) || ts.isNamedImports(before)) { + else if (isStringLiteral(before) && isImportDeclaration(before.parent) || isNamedImports(before)) { return { suffix: ", " }; } - else if (ts.isImportSpecifier(before)) { + else if (isImportSpecifier(before)) { return { suffix: "," + (blankLineBetween ? this.newLineCharacter : " ") }; } - return ts.Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it + return Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it } - public insertNodeAtConstructorStart(sourceFile: ts.SourceFile, ctr: ts.ConstructorDeclaration, newStatement: ts.Statement): void { - const firstStatement = ts.firstOrUndefined(ctr.body!.statements); + public insertNodeAtConstructorStart(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { + const firstStatement = firstOrUndefined(ctr.body!.statements); if (!firstStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [newStatement, ...ctr.body!.statements]); } @@ -598,8 +626,8 @@ export class ChangeTracker { } } - public insertNodeAtConstructorStartAfterSuperCall(sourceFile: ts.SourceFile, ctr: ts.ConstructorDeclaration, newStatement: ts.Statement): void { - const superCallStatement = ts.find(ctr.body!.statements, stmt => ts.isExpressionStatement(stmt) && ts.isSuperCall(stmt.expression)); + public insertNodeAtConstructorStartAfterSuperCall(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { + const superCallStatement = find(ctr.body!.statements, stmt => isExpressionStatement(stmt) && isSuperCall(stmt.expression)); if (!superCallStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]); } @@ -608,8 +636,8 @@ export class ChangeTracker { } } - public insertNodeAtConstructorEnd(sourceFile: ts.SourceFile, ctr: ts.ConstructorDeclaration, newStatement: ts.Statement): void { - const lastStatement = ts.lastOrUndefined(ctr.body!.statements); + public insertNodeAtConstructorEnd(sourceFile: SourceFile, ctr: ConstructorDeclaration, newStatement: Statement): void { + const lastStatement = lastOrUndefined(ctr.body!.statements); if (!lastStatement || !ctr.body!.multiLine) { this.replaceConstructorBody(sourceFile, ctr, [...ctr.body!.statements, newStatement]); } @@ -618,27 +646,27 @@ export class ChangeTracker { } } - private replaceConstructorBody(sourceFile: ts.SourceFile, ctr: ts.ConstructorDeclaration, statements: readonly ts.Statement[]): void { - this.replaceNode(sourceFile, ctr.body!, ts.factory.createBlock(statements, /*multiLine*/ true)); + private replaceConstructorBody(sourceFile: SourceFile, ctr: ConstructorDeclaration, statements: readonly Statement[]): void { + this.replaceNode(sourceFile, ctr.body!, factory.createBlock(statements, /*multiLine*/ true)); } - public insertNodeAtEndOfScope(sourceFile: ts.SourceFile, scope: ts.Node, newNode: ts.Node): void { + public insertNodeAtEndOfScope(sourceFile: SourceFile, scope: Node, newNode: Node): void { const pos = getAdjustedStartPosition(sourceFile, scope.getLastToken()!, {}); this.insertNodeAt(sourceFile, pos, newNode, { - prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, + prefix: isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken()!.pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter, suffix: this.newLineCharacter }); } - public insertMemberAtStart(sourceFile: ts.SourceFile, node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.TypeLiteralNode, newElement: ts.ClassElement | ts.PropertySignature | ts.MethodSignature): void { + public insertMemberAtStart(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode, newElement: ClassElement | PropertySignature | MethodSignature): void { this.insertNodeAtStartWorker(sourceFile, node, newElement); } - public insertNodeAtObjectStart(sourceFile: ts.SourceFile, obj: ts.ObjectLiteralExpression, newElement: ts.ObjectLiteralElementLike): void { + public insertNodeAtObjectStart(sourceFile: SourceFile, obj: ObjectLiteralExpression, newElement: ObjectLiteralElementLike): void { this.insertNodeAtStartWorker(sourceFile, obj, newElement); } - private insertNodeAtStartWorker(sourceFile: ts.SourceFile, node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode, newElement: ts.ClassElement | ts.ObjectLiteralElementLike | ts.PropertySignature | ts.MethodSignature): void { + private insertNodeAtStartWorker(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, newElement: ClassElement | ObjectLiteralElementLike | PropertySignature | MethodSignature): void { const indentation = this.guessIndentationFromExistingMembers(sourceFile, node) ?? this.computeIndentationForNewMember(sourceFile, node); this.insertNodeAt(sourceFile, getMembersOrProperties(node).pos, newElement, this.getInsertNodeAtStartInsertOptions(sourceFile, node, indentation)); } @@ -647,16 +675,16 @@ export class ChangeTracker { * Tries to guess the indentation from the existing members of a class/interface/object. All members must be on * new lines and must share the same indentation. */ - private guessIndentationFromExistingMembers(sourceFile: ts.SourceFile, node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode) { + private guessIndentationFromExistingMembers(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode) { let indentation: number | undefined; - let lastRange: ts.TextRange = node; + let lastRange: TextRange = node; for (const member of getMembersOrProperties(node)) { - if (ts.rangeStartPositionsAreOnSameLine(lastRange, member, sourceFile)) { + if (rangeStartPositionsAreOnSameLine(lastRange, member, sourceFile)) { // each indented member must be on a new line return undefined; } const memberStart = member.getStart(sourceFile); - const memberIndentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(ts.getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options); + const memberIndentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(memberStart, sourceFile), memberStart, sourceFile, this.formatContext.options); if (indentation === undefined) { indentation = memberIndentation; } @@ -669,13 +697,13 @@ export class ChangeTracker { return indentation; } - private computeIndentationForNewMember(sourceFile: ts.SourceFile, node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode) { + private computeIndentationForNewMember(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode) { const nodeStart = node.getStart(sourceFile); - return ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(ts.getLineStartPositionForPosition(nodeStart, sourceFile), nodeStart, sourceFile, this.formatContext.options) + return formatting.SmartIndenter.findFirstNonWhitespaceColumn(getLineStartPositionForPosition(nodeStart, sourceFile), nodeStart, sourceFile, this.formatContext.options) + (this.formatContext.options.indentSize ?? 4); } - private getInsertNodeAtStartInsertOptions(sourceFile: ts.SourceFile, node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode, indentation: number): InsertNodeOptions { + private getInsertNodeAtStartInsertOptions(sourceFile: SourceFile, node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode, indentation: number): InsertNodeOptions { // Rules: // - Always insert leading newline. // - For object literals: @@ -688,115 +716,115 @@ export class ChangeTracker { const members = getMembersOrProperties(node); const isEmpty = members.length === 0; - const isFirstInsertion = ts.addToSeen(this.classesWithNodesInsertedAtStart, ts.getNodeId(node), { node, sourceFile }); - const insertTrailingComma = ts.isObjectLiteralExpression(node) && (!ts.isJsonSourceFile(sourceFile) || !isEmpty); - const insertLeadingComma = ts.isObjectLiteralExpression(node) && ts.isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion; + const isFirstInsertion = addToSeen(this.classesWithNodesInsertedAtStart, getNodeId(node), { node, sourceFile }); + const insertTrailingComma = isObjectLiteralExpression(node) && (!isJsonSourceFile(sourceFile) || !isEmpty); + const insertLeadingComma = isObjectLiteralExpression(node) && isJsonSourceFile(sourceFile) && isEmpty && !isFirstInsertion; return { indentation, prefix: (insertLeadingComma ? "," : "") + this.newLineCharacter, - suffix: insertTrailingComma ? "," : ts.isInterfaceDeclaration(node) && isEmpty ? ";" : "" + suffix: insertTrailingComma ? "," : isInterfaceDeclaration(node) && isEmpty ? ";" : "" }; } - public insertNodeAfterComma(sourceFile: ts.SourceFile, after: ts.Node, newNode: ts.Node): void { + public insertNodeAfterComma(sourceFile: SourceFile, after: Node, newNode: Node): void { const endPosition = this.insertNodeAfterWorker(sourceFile, this.nextCommaToken(sourceFile, after) || after, newNode); this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after)); } - public insertNodeAfter(sourceFile: ts.SourceFile, after: ts.Node, newNode: ts.Node): void { + public insertNodeAfter(sourceFile: SourceFile, after: Node, newNode: Node): void { const endPosition = this.insertNodeAfterWorker(sourceFile, after, newNode); this.insertNodeAt(sourceFile, endPosition, newNode, this.getInsertNodeAfterOptions(sourceFile, after)); } - public insertNodeAtEndOfList(sourceFile: ts.SourceFile, list: ts.NodeArray, newNode: ts.Node): void { + public insertNodeAtEndOfList(sourceFile: SourceFile, list: NodeArray, newNode: Node): void { this.insertNodeAt(sourceFile, list.end, newNode, { prefix: ", " }); } - public insertNodesAfter(sourceFile: ts.SourceFile, after: ts.Node, newNodes: readonly ts.Node[]): void { - const endPosition = this.insertNodeAfterWorker(sourceFile, after, ts.first(newNodes)); + public insertNodesAfter(sourceFile: SourceFile, after: Node, newNodes: readonly Node[]): void { + const endPosition = this.insertNodeAfterWorker(sourceFile, after, first(newNodes)); this.insertNodesAt(sourceFile, endPosition, newNodes, this.getInsertNodeAfterOptions(sourceFile, after)); } - private insertNodeAfterWorker(sourceFile: ts.SourceFile, after: ts.Node, newNode: ts.Node): number { + private insertNodeAfterWorker(sourceFile: SourceFile, after: Node, newNode: Node): number { if (needSemicolonBetween(after, newNode)) { // check if previous statement ends with semicolon // if not - insert semicolon to preserve the code from changing the meaning due to ASI - if (sourceFile.text.charCodeAt(after.end - 1) !== ts.CharacterCodes.semicolon) { - this.replaceRange(sourceFile, ts.createRange(after.end), ts.factory.createToken(ts.SyntaxKind.SemicolonToken)); + if (sourceFile.text.charCodeAt(after.end - 1) !== CharacterCodes.semicolon) { + this.replaceRange(sourceFile, createRange(after.end), factory.createToken(SyntaxKind.SemicolonToken)); } } const endPosition = getAdjustedEndPosition(sourceFile, after, {}); return endPosition; } - private getInsertNodeAfterOptions(sourceFile: ts.SourceFile, after: ts.Node): InsertNodeOptions { + private getInsertNodeAfterOptions(sourceFile: SourceFile, after: Node): InsertNodeOptions { const options = this.getInsertNodeAfterOptionsWorker(after); return { ...options, - prefix: after.end === sourceFile.end && ts.isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") : options.prefix, + prefix: after.end === sourceFile.end && isStatement(after) ? (options.prefix ? `\n${options.prefix}` : "\n") : options.prefix, }; } - private getInsertNodeAfterOptionsWorker(node: ts.Node): InsertNodeOptions { + private getInsertNodeAfterOptionsWorker(node: Node): InsertNodeOptions { switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ModuleDeclaration: return { prefix: this.newLineCharacter, suffix: this.newLineCharacter }; - case ts.SyntaxKind.VariableDeclaration: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.Identifier: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.StringLiteral: + case SyntaxKind.Identifier: return { prefix: ", " }; - case ts.SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyAssignment: return { suffix: "," + this.newLineCharacter }; - case ts.SyntaxKind.ExportKeyword: + case SyntaxKind.ExportKeyword: return { prefix: " " }; - case ts.SyntaxKind.Parameter: + case SyntaxKind.Parameter: return {}; default: - ts.Debug.assert(ts.isStatement(node) || ts.isClassOrTypeElement(node)); // Else we haven't handled this kind of node yet -- add it + Debug.assert(isStatement(node) || isClassOrTypeElement(node)); // Else we haven't handled this kind of node yet -- add it return { suffix: this.newLineCharacter }; } } - public insertName(sourceFile: ts.SourceFile, node: ts.FunctionExpression | ts.ClassExpression | ts.ArrowFunction, name: string): void { - ts.Debug.assert(!node.name); - if (node.kind === ts.SyntaxKind.ArrowFunction) { - const arrow = ts.findChildOfKind(node, ts.SyntaxKind.EqualsGreaterThanToken, sourceFile)!; - const lparen = ts.findChildOfKind(node, ts.SyntaxKind.OpenParenToken, sourceFile); + public insertName(sourceFile: SourceFile, node: FunctionExpression | ClassExpression | ArrowFunction, name: string): void { + Debug.assert(!node.name); + if (node.kind === SyntaxKind.ArrowFunction) { + const arrow = findChildOfKind(node, SyntaxKind.EqualsGreaterThanToken, sourceFile)!; + const lparen = findChildOfKind(node, SyntaxKind.OpenParenToken, sourceFile); if (lparen) { // `() => {}` --> `function f() {}` - this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [ts.factory.createToken(ts.SyntaxKind.FunctionKeyword), ts.factory.createIdentifier(name)], { joiner: " " }); + this.insertNodesAt(sourceFile, lparen.getStart(sourceFile), [factory.createToken(SyntaxKind.FunctionKeyword), factory.createIdentifier(name)], { joiner: " " }); deleteNode(this, sourceFile, arrow); } else { // `x => {}` -> `function f(x) {}` - this.insertText(sourceFile, ts.first(node.parameters).getStart(sourceFile), `function ${name}(`); + this.insertText(sourceFile, first(node.parameters).getStart(sourceFile), `function ${name}(`); // Replacing full range of arrow to get rid of the leading space -- replace ` =>` with `)` - this.replaceRange(sourceFile, arrow, ts.factory.createToken(ts.SyntaxKind.CloseParenToken)); + this.replaceRange(sourceFile, arrow, factory.createToken(SyntaxKind.CloseParenToken)); } - if (node.body.kind !== ts.SyntaxKind.Block) { + if (node.body.kind !== SyntaxKind.Block) { // `() => 0` => `function f() { return 0; }` - this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [ts.factory.createToken(ts.SyntaxKind.OpenBraceToken), ts.factory.createToken(ts.SyntaxKind.ReturnKeyword)], { joiner: " ", suffix: " " }); - this.insertNodesAt(sourceFile, node.body.end, [ts.factory.createToken(ts.SyntaxKind.SemicolonToken), ts.factory.createToken(ts.SyntaxKind.CloseBraceToken)], { joiner: " " }); + this.insertNodesAt(sourceFile, node.body.getStart(sourceFile), [factory.createToken(SyntaxKind.OpenBraceToken), factory.createToken(SyntaxKind.ReturnKeyword)], { joiner: " ", suffix: " " }); + this.insertNodesAt(sourceFile, node.body.end, [factory.createToken(SyntaxKind.SemicolonToken), factory.createToken(SyntaxKind.CloseBraceToken)], { joiner: " " }); } } else { - const pos = ts.findChildOfKind(node, node.kind === ts.SyntaxKind.FunctionExpression ? ts.SyntaxKind.FunctionKeyword : ts.SyntaxKind.ClassKeyword, sourceFile)!.end; - this.insertNodeAt(sourceFile, pos, ts.factory.createIdentifier(name), { prefix: " " }); + const pos = findChildOfKind(node, node.kind === SyntaxKind.FunctionExpression ? SyntaxKind.FunctionKeyword : SyntaxKind.ClassKeyword, sourceFile)!.end; + this.insertNodeAt(sourceFile, pos, factory.createIdentifier(name), { prefix: " " }); } } - public insertExportModifier(sourceFile: ts.SourceFile, node: ts.DeclarationStatement | ts.VariableStatement): void { + public insertExportModifier(sourceFile: SourceFile, node: DeclarationStatement | VariableStatement): void { this.insertText(sourceFile, node.getStart(sourceFile), "export "); } - public insertImportSpecifierAtIndex(sourceFile: ts.SourceFile, importSpecifier: ts.ImportSpecifier, namedImports: ts.NamedImports, index: number) { + public insertImportSpecifierAtIndex(sourceFile: SourceFile, importSpecifier: ImportSpecifier, namedImports: NamedImports, index: number) { const prevSpecifier = namedImports.elements[index - 1]; if (prevSpecifier) { this.insertNodeInListAfter(sourceFile, prevSpecifier, importSpecifier); @@ -806,7 +834,7 @@ export class ChangeTracker { sourceFile, namedImports.elements[0], importSpecifier, - !ts.positionsAreOnSameLine(namedImports.elements[0].getStart(), namedImports.parent.parent.getStart(), sourceFile)); + !positionsAreOnSameLine(namedImports.elements[0].getStart(), namedImports.parent.parent.getStart(), sourceFile)); } } @@ -815,12 +843,12 @@ export class ChangeTracker { * i.e. arguments in arguments lists, parameters in parameter lists etc. * Note that separators are part of the node in statements and class elements. */ - public insertNodeInListAfter(sourceFile: ts.SourceFile, after: ts.Node, newNode: ts.Node, containingList = ts.formatting.SmartIndenter.getContainingList(after, sourceFile)): void { + public insertNodeInListAfter(sourceFile: SourceFile, after: Node, newNode: Node, containingList = formatting.SmartIndenter.getContainingList(after, sourceFile)): void { if (!containingList) { - ts.Debug.fail("node is not a list element"); + Debug.fail("node is not a list element"); return; } - const index = ts.indexOfNode(containingList, after); + const index = indexOfNode(containingList, after); if (index < 0) { return; } @@ -828,7 +856,7 @@ export class ChangeTracker { if (index !== containingList.length - 1) { // any element except the last one // use next sibling as an anchor - const nextToken = ts.getTokenAtPosition(sourceFile, after.end); + const nextToken = getTokenAtPosition(sourceFile, after.end); if (nextToken && isSeparator(after, nextToken)) { // for list // a, b, c @@ -850,15 +878,15 @@ export class ChangeTracker { const startPos = skipWhitespacesAndLineBreaks(sourceFile.text, nextNode.getFullStart()); // write separator and leading trivia of the next element as suffix - const suffix = `${ts.tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, startPos)}`; + const suffix = `${tokenToString(nextToken.kind)}${sourceFile.text.substring(nextToken.end, startPos)}`; this.insertNodesAt(sourceFile, startPos, [newNode], { suffix }); } } else { const afterStart = after.getStart(sourceFile); - const afterStartLinePosition = ts.getLineStartPositionForPosition(afterStart, sourceFile); + const afterStartLinePosition = getLineStartPositionForPosition(afterStart, sourceFile); - let separator: ts.SyntaxKind.CommaToken | ts.SyntaxKind.SemicolonToken | undefined; + let separator: SyntaxKind.CommaToken | SyntaxKind.SemicolonToken | undefined; let multilineList = false; // insert element after the last element in the list that has more than one item @@ -869,14 +897,14 @@ export class ChangeTracker { // if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise // i.e. var x = 1 // this is x // | new element will be inserted at this position - separator = ts.SyntaxKind.CommaToken; + separator = SyntaxKind.CommaToken; } else { // element has more than one element, pick separator from the list - const tokenBeforeInsertPosition = ts.findPrecedingToken(after.pos, sourceFile); - separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : ts.SyntaxKind.CommaToken; + const tokenBeforeInsertPosition = findPrecedingToken(after.pos, sourceFile); + separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : SyntaxKind.CommaToken; // determine if list is multiline by checking lines of after element and element that precedes it. - const afterMinusOneStartLinePosition = ts.getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile); + const afterMinusOneStartLinePosition = getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile); multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition; } if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) { @@ -885,25 +913,25 @@ export class ChangeTracker { } if (multilineList) { // insert separator immediately following the 'after' node to preserve comments in trailing trivia - this.replaceRange(sourceFile, ts.createRange(end), ts.factory.createToken(separator)); + this.replaceRange(sourceFile, createRange(end), factory.createToken(separator)); // use the same indentation as 'after' item - const indentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); + const indentation = formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options); // insert element before the line break on the line that contains 'after' element - let insertPos = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); + let insertPos = skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false); // find position before "\n" or "\r\n" - while (insertPos !== end && ts.isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { + while (insertPos !== end && isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) { insertPos--; } - this.replaceRange(sourceFile, ts.createRange(insertPos), newNode, { indentation, prefix: this.newLineCharacter }); + this.replaceRange(sourceFile, createRange(insertPos), newNode, { indentation, prefix: this.newLineCharacter }); } else { - this.replaceRange(sourceFile, ts.createRange(end), newNode, { prefix: `${ts.tokenToString(separator)} ` }); + this.replaceRange(sourceFile, createRange(end), newNode, { prefix: `${tokenToString(separator)} ` }); } } } - public parenthesizeExpression(sourceFile: ts.SourceFile, expression: ts.Expression) { - this.replaceRange(sourceFile, ts.rangeOfNode(expression), ts.factory.createParenthesizedExpression(expression)); + public parenthesizeExpression(sourceFile: SourceFile, expression: Expression) { + this.replaceRange(sourceFile, rangeOfNode(expression), factory.createParenthesizedExpression(expression)); } private finishClassesWithNodesInsertedAtStart(): void { @@ -911,10 +939,10 @@ export class ChangeTracker { const [openBraceEnd, closeBraceEnd] = getClassOrObjectBraceEnds(node, sourceFile); if (openBraceEnd !== undefined && closeBraceEnd !== undefined) { const isEmpty = getMembersOrProperties(node).length === 0; - const isSingleLine = ts.positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile); + const isSingleLine = positionsAreOnSameLine(openBraceEnd, closeBraceEnd, sourceFile); if (isEmpty && isSingleLine && openBraceEnd !== closeBraceEnd - 1) { // For `class C { }` remove the whitespace inside the braces. - this.deleteRange(sourceFile, ts.createRange(openBraceEnd, closeBraceEnd - 1)); + this.deleteRange(sourceFile, createRange(openBraceEnd, closeBraceEnd - 1)); } if (isSingleLine) { this.insertText(sourceFile, closeBraceEnd - 1, this.newLineCharacter); @@ -924,11 +952,11 @@ export class ChangeTracker { } private finishDeleteDeclarations(): void { - const deletedNodesInLists = new ts.Set(); // Stores nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. + const deletedNodesInLists = new Set(); // Stores nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`. for (const { sourceFile, node } of this.deletedNodes) { - if (!this.deletedNodes.some(d => d.sourceFile === sourceFile && ts.rangeContainsRangeExclusive(d.node, node))) { - if (ts.isArray(node)) { - this.deleteRange(sourceFile, ts.rangeOfTypeParameters(sourceFile, node)); + if (!this.deletedNodes.some(d => d.sourceFile === sourceFile && rangeContainsRangeExclusive(d.node, node))) { + if (isArray(node)) { + this.deleteRange(sourceFile, rangeOfTypeParameters(sourceFile, node)); } else { deleteDeclaration.deleteDeclaration(this, deletedNodesInLists, sourceFile, node); @@ -938,10 +966,10 @@ export class ChangeTracker { deletedNodesInLists.forEach(node => { const sourceFile = node.getSourceFile(); - const list = ts.formatting.SmartIndenter.getContainingList(node, sourceFile)!; - if (node !== ts.last(list)) return; + const list = formatting.SmartIndenter.getContainingList(node, sourceFile)!; + if (node !== last(list)) return; - const lastNonDeletedIndex = ts.findLastIndex(list, n => !deletedNodesInLists.has(n), list.length - 2); + const lastNonDeletedIndex = findLastIndex(list, n => !deletedNodesInLists.has(n), list.length - 2); if (lastNonDeletedIndex !== -1) { this.deleteRange(sourceFile, { pos: list[lastNonDeletedIndex].end, end: startPositionToDeleteNodeInList(sourceFile, list[lastNonDeletedIndex + 1]) }); } @@ -954,7 +982,7 @@ export class ChangeTracker { * The reason we must validate as part of this method is that `getNonFormattedText` changes the node's positions, * so we can only call this once and can't get the non-formatted text separately. */ - public getChanges(validate?: ValidateNonFormattedText): ts.FileTextChanges[] { + public getChanges(validate?: ValidateNonFormattedText): FileTextChanges[] { this.finishDeleteDeclarations(); this.finishClassesWithNodesInsertedAtStart(); const changes = changesToText.getTextChangesFromChanges(this.changes, this.newLineCharacter, this.formatContext, validate); @@ -964,61 +992,61 @@ export class ChangeTracker { return changes; } - public createNewFile(oldFile: ts.SourceFile | undefined, fileName: string, statements: readonly (ts.Statement | ts.SyntaxKind.NewLineTrivia)[]): void { + public createNewFile(oldFile: SourceFile | undefined, fileName: string, statements: readonly (Statement | SyntaxKind.NewLineTrivia)[]): void { this.newFiles.push({ oldFile, fileName, statements }); } } -function updateJSDocHost(parent: ts.HasJSDoc): ts.HasJSDoc { - if (parent.kind !== ts.SyntaxKind.ArrowFunction) { +function updateJSDocHost(parent: HasJSDoc): HasJSDoc { + if (parent.kind !== SyntaxKind.ArrowFunction) { return parent; } - const jsDocNode = parent.parent.kind === ts.SyntaxKind.PropertyDeclaration ? - parent.parent as ts.HasJSDoc : - parent.parent.parent as ts.HasJSDoc; + const jsDocNode = parent.parent.kind === SyntaxKind.PropertyDeclaration ? + parent.parent as HasJSDoc : + parent.parent.parent as HasJSDoc; jsDocNode.jsDoc = parent.jsDoc; jsDocNode.jsDocCache = parent.jsDocCache; return jsDocNode; } -function tryMergeJsdocTags(oldTag: ts.JSDocTag, newTag: ts.JSDocTag): ts.JSDocTag | undefined { +function tryMergeJsdocTags(oldTag: JSDocTag, newTag: JSDocTag): JSDocTag | undefined { if (oldTag.kind !== newTag.kind) { return undefined; } switch (oldTag.kind) { - case ts.SyntaxKind.JSDocParameterTag: { - const oldParam = oldTag as ts.JSDocParameterTag; - const newParam = newTag as ts.JSDocParameterTag; - return ts.isIdentifier(oldParam.name) && ts.isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText - ? ts.factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, /*isBracketed*/ false, newParam.typeExpression, newParam.isNameFirst, oldParam.comment) + case SyntaxKind.JSDocParameterTag: { + const oldParam = oldTag as JSDocParameterTag; + const newParam = newTag as JSDocParameterTag; + return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText + ? factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, /*isBracketed*/ false, newParam.typeExpression, newParam.isNameFirst, oldParam.comment) : undefined; } - case ts.SyntaxKind.JSDocReturnTag: - return ts.factory.createJSDocReturnTag(/*tagName*/ undefined, (newTag as ts.JSDocReturnTag).typeExpression, oldTag.comment); - case ts.SyntaxKind.JSDocTypeTag: - return ts.factory.createJSDocTypeTag(/*tagName*/ undefined, (newTag as ts.JSDocTypeTag).typeExpression, oldTag.comment); + case SyntaxKind.JSDocReturnTag: + return factory.createJSDocReturnTag(/*tagName*/ undefined, (newTag as JSDocReturnTag).typeExpression, oldTag.comment); + case SyntaxKind.JSDocTypeTag: + return factory.createJSDocTypeTag(/*tagName*/ undefined, (newTag as JSDocTypeTag).typeExpression, oldTag.comment); } } // find first non-whitespace position in the leading trivia of the node -function startPositionToDeleteNodeInList(sourceFile: ts.SourceFile, node: ts.Node): number { - return ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); +function startPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node): number { + return skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.IncludeAll }), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); } -function endPositionToDeleteNodeInList(sourceFile: ts.SourceFile, node: ts.Node, prevNode: ts.Node | undefined, nextNode: ts.Node): number { +function endPositionToDeleteNodeInList(sourceFile: SourceFile, node: Node, prevNode: Node | undefined, nextNode: Node): number { const end = startPositionToDeleteNodeInList(sourceFile, nextNode); - if (prevNode === undefined || ts.positionsAreOnSameLine(getAdjustedEndPosition(sourceFile, node, {}), end, sourceFile)) { + if (prevNode === undefined || positionsAreOnSameLine(getAdjustedEndPosition(sourceFile, node, {}), end, sourceFile)) { return end; } - const token = ts.findPrecedingToken(nextNode.getStart(sourceFile), sourceFile); + const token = findPrecedingToken(nextNode.getStart(sourceFile), sourceFile); if (isSeparator(node, token)) { - const prevToken = ts.findPrecedingToken(node.getStart(sourceFile), sourceFile); + const prevToken = findPrecedingToken(node.getStart(sourceFile), sourceFile); if (isSeparator(prevNode, prevToken)) { - const pos = ts.skipTrivia(sourceFile.text, token.getEnd(), /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); - if (ts.positionsAreOnSameLine(prevToken.getStart(sourceFile), token.getStart(sourceFile), sourceFile)) { - return ts.isLineBreak(sourceFile.text.charCodeAt(pos - 1)) ? pos - 1 : pos; + const pos = skipTrivia(sourceFile.text, token.getEnd(), /*stopAfterLineBreak*/ true, /*stopAtComments*/ true); + if (positionsAreOnSameLine(prevToken.getStart(sourceFile), token.getStart(sourceFile), sourceFile)) { + return isLineBreak(sourceFile.text.charCodeAt(pos - 1)) ? pos - 1 : pos; } - if (ts.isLineBreak(sourceFile.text.charCodeAt(pos))) { + if (isLineBreak(sourceFile.text.charCodeAt(pos))) { return pos; } } @@ -1026,66 +1054,66 @@ function endPositionToDeleteNodeInList(sourceFile: ts.SourceFile, node: ts.Node, return end; } -function getClassOrObjectBraceEnds(cls: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression, sourceFile: ts.SourceFile): [number | undefined, number | undefined] { - const open = ts.findChildOfKind(cls, ts.SyntaxKind.OpenBraceToken, sourceFile); - const close = ts.findChildOfKind(cls, ts.SyntaxKind.CloseBraceToken, sourceFile); +function getClassOrObjectBraceEnds(cls: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression, sourceFile: SourceFile): [number | undefined, number | undefined] { + const open = findChildOfKind(cls, SyntaxKind.OpenBraceToken, sourceFile); + const close = findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile); return [open?.end, close?.end]; } -function getMembersOrProperties(node: ts.ClassLikeDeclaration | ts.InterfaceDeclaration | ts.ObjectLiteralExpression | ts.TypeLiteralNode): ts.NodeArray { - return ts.isObjectLiteralExpression(node) ? node.properties : node.members; +function getMembersOrProperties(node: ClassLikeDeclaration | InterfaceDeclaration | ObjectLiteralExpression | TypeLiteralNode): NodeArray { + return isObjectLiteralExpression(node) ? node.properties : node.members; } /** @internal */ -export type ValidateNonFormattedText = (node: ts.Node, text: string) => void; +export type ValidateNonFormattedText = (node: Node, text: string) => void; /** @internal */ -export function getNewFileText(statements: readonly ts.Statement[], scriptKind: ts.ScriptKind, newLineCharacter: string, formatContext: ts.formatting.FormatContext): string { +export function getNewFileText(statements: readonly Statement[], scriptKind: ScriptKind, newLineCharacter: string, formatContext: formatting.FormatContext): string { return changesToText.newFileChangesWorker(/*oldFile*/ undefined, scriptKind, statements, newLineCharacter, formatContext); } namespace changesToText { - export function getTextChangesFromChanges(changes: readonly Change[], newLineCharacter: string, formatContext: ts.formatting.FormatContext, validate: ValidateNonFormattedText | undefined): ts.FileTextChanges[] { - return ts.mapDefined(ts.group(changes, c => c.sourceFile.path), changesInFile => { + export function getTextChangesFromChanges(changes: readonly Change[], newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): FileTextChanges[] { + return mapDefined(group(changes, c => c.sourceFile.path), changesInFile => { const sourceFile = changesInFile[0].sourceFile; // order changes by start position // If the start position is the same, put the shorter range first, since an empty range (x, x) may precede (x, y) but not vice-versa. - const normalized = ts.stableSort(changesInFile, (a, b) => (a.range.pos - b.range.pos) || (a.range.end - b.range.end)); + const normalized = stableSort(changesInFile, (a, b) => (a.range.pos - b.range.pos) || (a.range.end - b.range.end)); // verify that change intervals do not overlap, except possibly at end points. for (let i = 0; i < normalized.length - 1; i++) { - ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => + Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", () => `${JSON.stringify(normalized[i].range)} and ${JSON.stringify(normalized[i + 1].range)}`); } - const textChanges = ts.mapDefined(normalized, c => { - const span = ts.createTextSpanFromRange(c.range); + const textChanges = mapDefined(normalized, c => { + const span = createTextSpanFromRange(c.range); const newText = computeNewText(c, sourceFile, newLineCharacter, formatContext, validate); // Filter out redundant changes. - if (span.length === newText.length && ts.stringContainsAt(sourceFile.text, newText, span.start)) { + if (span.length === newText.length && stringContainsAt(sourceFile.text, newText, span.start)) { return undefined; } - return ts.createTextChange(span, newText); + return createTextChange(span, newText); }); return textChanges.length > 0 ? { fileName: sourceFile.fileName, textChanges } : undefined; }); } - export function newFileChanges(oldFile: ts.SourceFile | undefined, fileName: string, statements: readonly (ts.Statement | ts.SyntaxKind.NewLineTrivia)[], newLineCharacter: string, formatContext: ts.formatting.FormatContext): ts.FileTextChanges { - const text = newFileChangesWorker(oldFile, ts.getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext); - return { fileName, textChanges: [ts.createTextChange(ts.createTextSpan(0, 0), text)], isNewFile: true }; + export function newFileChanges(oldFile: SourceFile | undefined, fileName: string, statements: readonly (Statement | SyntaxKind.NewLineTrivia)[], newLineCharacter: string, formatContext: formatting.FormatContext): FileTextChanges { + const text = newFileChangesWorker(oldFile, getScriptKindFromFileName(fileName), statements, newLineCharacter, formatContext); + return { fileName, textChanges: [createTextChange(createTextSpan(0, 0), text)], isNewFile: true }; } - export function newFileChangesWorker(oldFile: ts.SourceFile | undefined, scriptKind: ts.ScriptKind, statements: readonly (ts.Statement | ts.SyntaxKind.NewLineTrivia)[], newLineCharacter: string, formatContext: ts.formatting.FormatContext): string { + export function newFileChangesWorker(oldFile: SourceFile | undefined, scriptKind: ScriptKind, statements: readonly (Statement | SyntaxKind.NewLineTrivia)[], newLineCharacter: string, formatContext: formatting.FormatContext): string { // TODO: this emits the file, parses it back, then formats it that -- may be a less roundabout way to do this - const nonFormattedText = statements.map(s => s === ts.SyntaxKind.NewLineTrivia ? "" : getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter); - const sourceFile = ts.createSourceFile("any file name", nonFormattedText, ts.ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind); - const changes = ts.formatting.formatDocument(sourceFile, formatContext); + const nonFormattedText = statements.map(s => s === SyntaxKind.NewLineTrivia ? "" : getNonformattedText(s, oldFile, newLineCharacter).text).join(newLineCharacter); + const sourceFile = createSourceFile("any file name", nonFormattedText, ScriptTarget.ESNext, /*setParentNodes*/ true, scriptKind); + const changes = formatting.formatDocument(sourceFile, formatContext); return applyChanges(nonFormattedText, changes) + newLineCharacter; } - function computeNewText(change: Change, sourceFile: ts.SourceFile, newLineCharacter: string, formatContext: ts.formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { + function computeNewText(change: Change, sourceFile: SourceFile, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { if (change.kind === ChangeKind.Remove) { return ""; } @@ -1094,129 +1122,129 @@ namespace changesToText { } const { options = {}, range: { pos } } = change; - const format = (n: ts.Node) => getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); + const format = (n: Node) => getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); const text = change.kind === ChangeKind.ReplaceWithMultipleNodes - ? change.nodes.map(n => ts.removeSuffix(format(n), newLineCharacter)).join(change.options?.joiner || newLineCharacter) + ? change.nodes.map(n => removeSuffix(format(n), newLineCharacter)).join(change.options?.joiner || newLineCharacter) : format(change.node); // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line - const noIndent = (options.indentation !== undefined || ts.getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, ""); + const noIndent = (options.indentation !== undefined || getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, ""); return (options.prefix || "") + noIndent - + ((!options.suffix || ts.endsWith(noIndent, options.suffix)) + + ((!options.suffix || endsWith(noIndent, options.suffix)) ? "" : options.suffix); } /** Note: this may mutate `nodeIn`. */ - function getFormattedTextOfNode(nodeIn: ts.Node, sourceFile: ts.SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: ts.formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { + function getFormattedTextOfNode(nodeIn: Node, sourceFile: SourceFile, pos: number, { indentation, prefix, delta }: InsertNodeOptions, newLineCharacter: string, formatContext: formatting.FormatContext, validate: ValidateNonFormattedText | undefined): string { const { node, text } = getNonformattedText(nodeIn, sourceFile, newLineCharacter); if (validate) validate(node, text); - const formatOptions = ts.getFormatCodeSettingsForWriting(formatContext, sourceFile); + const formatOptions = getFormatCodeSettingsForWriting(formatContext, sourceFile); const initialIndentation = indentation !== undefined ? indentation - : ts.formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || ts.getLineStartPositionForPosition(pos, sourceFile) === pos); + : formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, prefix === newLineCharacter || getLineStartPositionForPosition(pos, sourceFile) === pos); if (delta === undefined) { - delta = ts.formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? (formatOptions.indentSize || 0) : 0; + delta = formatting.SmartIndenter.shouldIndentChildNode(formatOptions, nodeIn) ? (formatOptions.indentSize || 0) : 0; } - const file: ts.SourceFileLike = { + const file: SourceFileLike = { text, getLineAndCharacterOfPosition(pos) { - return ts.getLineAndCharacterOfPosition(this, pos); + return getLineAndCharacterOfPosition(this, pos); } }; - const changes = ts.formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, { ...formatContext, options: formatOptions }); + const changes = formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, { ...formatContext, options: formatOptions }); return applyChanges(text, changes); } /** Note: output node may be mutated input node. */ - export function getNonformattedText(node: ts.Node, sourceFile: ts.SourceFile | undefined, newLineCharacter: string): { text: string, node: ts.Node } { + export function getNonformattedText(node: Node, sourceFile: SourceFile | undefined, newLineCharacter: string): { text: string, node: Node } { const writer = createWriter(newLineCharacter); - const newLine = ts.getNewLineKind(newLineCharacter); - ts.createPrinter({ + const newLine = getNewLineKind(newLineCharacter); + createPrinter({ newLine, neverAsciiEscape: true, preserveSourceNewlines: true, terminateUnterminatedLiterals: true - }, writer).writeNode(ts.EmitHint.Unspecified, node, sourceFile, writer); + }, writer).writeNode(EmitHint.Unspecified, node, sourceFile, writer); return { text: writer.getText(), node: assignPositionsToNode(node) }; } } /** @internal */ -export function applyChanges(text: string, changes: readonly ts.TextChange[]): string { +export function applyChanges(text: string, changes: readonly TextChange[]): string { for (let i = changes.length - 1; i >= 0; i--) { const { span, newText } = changes[i]; - text = `${text.substring(0, span.start)}${newText}${text.substring(ts.textSpanEnd(span))}`; + text = `${text.substring(0, span.start)}${newText}${text.substring(textSpanEnd(span))}`; } return text; } function isTrivia(s: string) { - return ts.skipTrivia(s, 0) === s.length; + return skipTrivia(s, 0) === s.length; } // A transformation context that won't perform parenthesization, as some parenthesization rules // are more aggressive than is strictly necessary. -const textChangesTransformationContext: ts.TransformationContext = { - ...ts.nullTransformationContext, - factory: ts.createNodeFactory( - ts.nullTransformationContext.factory.flags | ts.NodeFactoryFlags.NoParenthesizerRules, - ts.nullTransformationContext.factory.baseFactory), +const textChangesTransformationContext: TransformationContext = { + ...nullTransformationContext, + factory: createNodeFactory( + nullTransformationContext.factory.flags | NodeFactoryFlags.NoParenthesizerRules, + nullTransformationContext.factory.baseFactory), }; /** @internal */ -export function assignPositionsToNode(node: ts.Node): ts.Node { - const visited = ts.visitEachChild(node, assignPositionsToNode, textChangesTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); +export function assignPositionsToNode(node: Node): Node { + const visited = visitEachChild(node, assignPositionsToNode, textChangesTransformationContext, assignPositionsToNodeArray, assignPositionsToNode); // create proxy node for non synthesized nodes - const newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited) as ts.Node; - ts.setTextRangePosEnd(newNode, getPos(node), getEnd(node)); + const newNode = nodeIsSynthesized(visited) ? visited : Object.create(visited) as Node; + setTextRangePosEnd(newNode, getPos(node), getEnd(node)); return newNode; } -function assignPositionsToNodeArray(nodes: ts.NodeArray, visitor: ts.Visitor, test?: (node: ts.Node) => boolean, start?: number, count?: number) { - const visited = ts.visitNodes(nodes, visitor, test, start, count); +function assignPositionsToNodeArray(nodes: NodeArray, visitor: Visitor, test?: (node: Node) => boolean, start?: number, count?: number) { + const visited = visitNodes(nodes, visitor, test, start, count); if (!visited) { return visited; } // clone nodearray if necessary - const nodeArray = visited === nodes ? ts.factory.createNodeArray(visited.slice(0)) : visited; - ts.setTextRangePosEnd(nodeArray, getPos(nodes), getEnd(nodes)); + const nodeArray = visited === nodes ? factory.createNodeArray(visited.slice(0)) : visited; + setTextRangePosEnd(nodeArray, getPos(nodes), getEnd(nodes)); return nodeArray; } -interface TextChangesWriter extends ts.EmitTextWriter, ts.PrintHandlers {} +interface TextChangesWriter extends EmitTextWriter, PrintHandlers {} /** @internal */ export function createWriter(newLine: string): TextChangesWriter { let lastNonTriviaPosition = 0; - const writer = ts.createTextWriter(newLine); - const onBeforeEmitNode: ts.PrintHandlers["onBeforeEmitNode"] = node => { + const writer = createTextWriter(newLine); + const onBeforeEmitNode: PrintHandlers["onBeforeEmitNode"] = node => { if (node) { setPos(node, lastNonTriviaPosition); } }; - const onAfterEmitNode: ts.PrintHandlers["onAfterEmitNode"] = node => { + const onAfterEmitNode: PrintHandlers["onAfterEmitNode"] = node => { if (node) { setEnd(node, lastNonTriviaPosition); } }; - const onBeforeEmitNodeArray: ts.PrintHandlers["onBeforeEmitNodeArray"] = nodes => { + const onBeforeEmitNodeArray: PrintHandlers["onBeforeEmitNodeArray"] = nodes => { if (nodes) { setPos(nodes, lastNonTriviaPosition); } }; - const onAfterEmitNodeArray: ts.PrintHandlers["onAfterEmitNodeArray"] = nodes => { + const onAfterEmitNodeArray: PrintHandlers["onAfterEmitNodeArray"] = nodes => { if (nodes) { setEnd(nodes, lastNonTriviaPosition); } }; - const onBeforeEmitToken: ts.PrintHandlers["onBeforeEmitToken"] = node => { + const onBeforeEmitToken: PrintHandlers["onBeforeEmitToken"] = node => { if (node) { setPos(node, lastNonTriviaPosition); } }; - const onAfterEmitToken: ts.PrintHandlers["onAfterEmitToken"] = node => { + const onAfterEmitToken: PrintHandlers["onAfterEmitToken"] = node => { if (node) { setEnd(node, lastNonTriviaPosition); } @@ -1226,7 +1254,7 @@ export function createWriter(newLine: string): TextChangesWriter { if (force || !isTrivia(s)) { lastNonTriviaPosition = writer.getTextPos(); let i = 0; - while (ts.isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { + while (isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) { i++; } // trim trailing whitespaces @@ -1273,7 +1301,7 @@ export function createWriter(newLine: string): TextChangesWriter { writer.writeStringLiteral(s); setLastNonTriviaPosition(s, /*force*/ false); } - function writeSymbol(s: string, sym: ts.Symbol): void { + function writeSymbol(s: string, sym: Symbol): void { writer.writeSymbol(s, sym); setLastNonTriviaPosition(s, /*force*/ false); } @@ -1352,10 +1380,10 @@ export function createWriter(newLine: string): TextChangesWriter { }; } -function getInsertionPositionAtSourceFileTop(sourceFile: ts.SourceFile): number { - let lastPrologue: ts.PrologueDirective | undefined; +function getInsertionPositionAtSourceFileTop(sourceFile: SourceFile): number { + let lastPrologue: PrologueDirective | undefined; for (const node of sourceFile.statements) { - if (ts.isPrologueDirective(node)) { + if (isPrologueDirective(node)) { lastPrologue = node; } else { @@ -1371,26 +1399,26 @@ function getInsertionPositionAtSourceFileTop(sourceFile: ts.SourceFile): number return position; } - const shebang = ts.getShebang(text); + const shebang = getShebang(text); if (shebang !== undefined) { position = shebang.length; advancePastLineBreak(); } - const ranges = ts.getLeadingCommentRanges(text, position); + const ranges = getLeadingCommentRanges(text, position); if (!ranges) return position; // Find the first attached comment to the first node and add before it - let lastComment: { range: ts.CommentRange; pinnedOrTripleSlash: boolean; } | undefined; + let lastComment: { range: CommentRange; pinnedOrTripleSlash: boolean; } | undefined; let firstNodeLine: number | undefined; for (const range of ranges) { - if (range.kind === ts.SyntaxKind.MultiLineCommentTrivia) { - if (ts.isPinnedComment(text, range.pos)) { + if (range.kind === SyntaxKind.MultiLineCommentTrivia) { + if (isPinnedComment(text, range.pos)) { lastComment = { range, pinnedOrTripleSlash: true }; continue; } } - else if (ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) { + else if (isRecognizedTripleSlashComment(text, range.pos, range.end)) { lastComment = { range, pinnedOrTripleSlash: true }; continue; } @@ -1423,10 +1451,10 @@ function getInsertionPositionAtSourceFileTop(sourceFile: ts.SourceFile): number function advancePastLineBreak() { if (position < text.length) { const charCode = text.charCodeAt(position); - if (ts.isLineBreak(charCode)) { + if (isLineBreak(charCode)) { position++; - if (position < text.length && charCode === ts.CharacterCodes.carriageReturn && text.charCodeAt(position) === ts.CharacterCodes.lineFeed) { + if (position < text.length && charCode === CharacterCodes.carriageReturn && text.charCodeAt(position) === CharacterCodes.lineFeed) { position++; } } @@ -1435,23 +1463,23 @@ function getInsertionPositionAtSourceFileTop(sourceFile: ts.SourceFile): number } /** @internal */ -export function isValidLocationToAddComment(sourceFile: ts.SourceFile, position: number) { - return !ts.isInComment(sourceFile, position) && !ts.isInString(sourceFile, position) && !ts.isInTemplateString(sourceFile, position) && !ts.isInJSXText(sourceFile, position); +export function isValidLocationToAddComment(sourceFile: SourceFile, position: number) { + return !isInComment(sourceFile, position) && !isInString(sourceFile, position) && !isInTemplateString(sourceFile, position) && !isInJSXText(sourceFile, position); } -function needSemicolonBetween(a: ts.Node, b: ts.Node): boolean { - return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name!.kind === ts.SyntaxKind.ComputedPropertyName - || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` +function needSemicolonBetween(a: Node, b: Node): boolean { + return (isPropertySignature(a) || isPropertyDeclaration(a)) && isClassOrTypeElement(b) && b.name!.kind === SyntaxKind.ComputedPropertyName + || isStatementButNotDeclaration(a) && isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[` } namespace deleteDeclaration { - export function deleteDeclaration(changes: ChangeTracker, deletedNodesInLists: ts.Set, sourceFile: ts.SourceFile, node: ts.Node): void { + export function deleteDeclaration(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: Node): void { switch (node.kind) { - case ts.SyntaxKind.Parameter: { + case SyntaxKind.Parameter: { const oldFunction = node.parent; - if (ts.isArrowFunction(oldFunction) && + if (isArrowFunction(oldFunction) && oldFunction.parameters.length === 1 && - !ts.findChildOfKind(oldFunction, ts.SyntaxKind.OpenParenToken, sourceFile)) { + !findChildOfKind(oldFunction, SyntaxKind.OpenParenToken, sourceFile)) { // Lambdas with exactly one parameter are special because, after removal, there // must be an empty parameter list (i.e. `()`) and this won't necessarily be the // case if the parameter is simply removed (e.g. in `x => 1`). @@ -1463,18 +1491,18 @@ namespace deleteDeclaration { break; } - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ImportEqualsDeclaration: - const isFirstImport = sourceFile.imports.length && node === ts.first(sourceFile.imports).parent || node === ts.find(sourceFile.statements, ts.isAnyImportSyntax); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + const isFirstImport = sourceFile.imports.length && node === first(sourceFile.imports).parent || node === find(sourceFile.statements, isAnyImportSyntax); // For first import, leave header comment in place, otherwise only delete JSDoc comments deleteNode(changes, sourceFile, node, { - leadingTriviaOption: isFirstImport ? LeadingTriviaOption.Exclude : ts.hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine, + leadingTriviaOption: isFirstImport ? LeadingTriviaOption.Exclude : hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine, }); break; - case ts.SyntaxKind.BindingElement: - const pattern = (node as ts.BindingElement).parent; - const preserveComma = pattern.kind === ts.SyntaxKind.ArrayBindingPattern && node !== ts.last(pattern.elements); + case SyntaxKind.BindingElement: + const pattern = (node as BindingElement).parent; + const preserveComma = pattern.kind === SyntaxKind.ArrayBindingPattern && node !== last(pattern.elements); if (preserveComma) { deleteNode(changes, sourceFile, node); } @@ -1483,16 +1511,16 @@ namespace deleteDeclaration { } break; - case ts.SyntaxKind.VariableDeclaration: - deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node as ts.VariableDeclaration); + case SyntaxKind.VariableDeclaration: + deleteVariableDeclaration(changes, deletedNodesInLists, sourceFile, node as VariableDeclaration); break; - case ts.SyntaxKind.TypeParameter: + case SyntaxKind.TypeParameter: deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); break; - case ts.SyntaxKind.ImportSpecifier: - const namedImports = (node as ts.ImportSpecifier).parent; + case SyntaxKind.ImportSpecifier: + const namedImports = (node as ImportSpecifier).parent; if (namedImports.elements.length === 1) { deleteImportBinding(changes, sourceFile, namedImports); } @@ -1501,21 +1529,21 @@ namespace deleteDeclaration { } break; - case ts.SyntaxKind.NamespaceImport: - deleteImportBinding(changes, sourceFile, node as ts.NamespaceImport); + case SyntaxKind.NamespaceImport: + deleteImportBinding(changes, sourceFile, node as NamespaceImport); break; - case ts.SyntaxKind.SemicolonToken: + case SyntaxKind.SemicolonToken: deleteNode(changes, sourceFile, node, { trailingTriviaOption: TrailingTriviaOption.Exclude }); break; - case ts.SyntaxKind.FunctionKeyword: + case SyntaxKind.FunctionKeyword: deleteNode(changes, sourceFile, node, { leadingTriviaOption: LeadingTriviaOption.Exclude }); break; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - deleteNode(changes, sourceFile, node, { leadingTriviaOption: ts.hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.FunctionDeclaration: + deleteNode(changes, sourceFile, node, { leadingTriviaOption: hasJSDocNodes(node) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); break; default: @@ -1523,10 +1551,10 @@ namespace deleteDeclaration { // a misbehaving client can reach here with the SourceFile node deleteNode(changes, sourceFile, node); } - else if (ts.isImportClause(node.parent) && node.parent.name === node) { + else if (isImportClause(node.parent) && node.parent.name === node) { deleteDefaultImport(changes, sourceFile, node.parent); } - else if (ts.isCallExpression(node.parent) && ts.contains(node.parent.arguments, node)) { + else if (isCallExpression(node.parent) && contains(node.parent.arguments, node)) { deleteNodeInList(changes, deletedNodesInLists, sourceFile, node); } else { @@ -1535,7 +1563,7 @@ namespace deleteDeclaration { } } - function deleteDefaultImport(changes: ChangeTracker, sourceFile: ts.SourceFile, importClause: ts.ImportClause): void { + function deleteDefaultImport(changes: ChangeTracker, sourceFile: SourceFile, importClause: ImportClause): void { if (!importClause.namedBindings) { // Delete the whole import deleteNode(changes, sourceFile, importClause.parent); @@ -1543,10 +1571,10 @@ namespace deleteDeclaration { else { // import |d,| * as ns from './file' const start = importClause.name!.getStart(sourceFile); - const nextToken = ts.getTokenAtPosition(sourceFile, importClause.name!.end); - if (nextToken && nextToken.kind === ts.SyntaxKind.CommaToken) { + const nextToken = getTokenAtPosition(sourceFile, importClause.name!.end); + if (nextToken && nextToken.kind === SyntaxKind.CommaToken) { // shift first non-whitespace position after comma to the start position of the node - const end = ts.skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true); + const end = skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true); changes.deleteRange(sourceFile, { pos: start, end }); } else { @@ -1555,29 +1583,29 @@ namespace deleteDeclaration { } } - function deleteImportBinding(changes: ChangeTracker, sourceFile: ts.SourceFile, node: ts.NamedImportBindings): void { + function deleteImportBinding(changes: ChangeTracker, sourceFile: SourceFile, node: NamedImportBindings): void { if (node.parent.name) { // Delete named imports while preserving the default import // import d|, * as ns| from './file' // import d|, { a }| from './file' - const previousToken = ts.Debug.checkDefined(ts.getTokenAtPosition(sourceFile, node.pos - 1)); + const previousToken = Debug.checkDefined(getTokenAtPosition(sourceFile, node.pos - 1)); changes.deleteRange(sourceFile, { pos: previousToken.getStart(sourceFile), end: node.end }); } else { // Delete the entire import declaration // |import * as ns from './file'| // |import { a } from './file'| - const importDecl = ts.getAncestor(node, ts.SyntaxKind.ImportDeclaration)!; + const importDecl = getAncestor(node, SyntaxKind.ImportDeclaration)!; deleteNode(changes, sourceFile, importDecl); } } - function deleteVariableDeclaration(changes: ChangeTracker, deletedNodesInLists: ts.Set, sourceFile: ts.SourceFile, node: ts.VariableDeclaration): void { + function deleteVariableDeclaration(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: VariableDeclaration): void { const { parent } = node; - if (parent.kind === ts.SyntaxKind.CatchClause) { + if (parent.kind === SyntaxKind.CatchClause) { // TODO: There's currently no unused diagnostic for this, could be a suggestion - changes.deleteNodeRange(sourceFile, ts.findChildOfKind(parent, ts.SyntaxKind.OpenParenToken, sourceFile)!, ts.findChildOfKind(parent, ts.SyntaxKind.CloseParenToken, sourceFile)!); + changes.deleteNodeRange(sourceFile, findChildOfKind(parent, SyntaxKind.OpenParenToken, sourceFile)!, findChildOfKind(parent, SyntaxKind.CloseParenToken, sourceFile)!); return; } @@ -1588,21 +1616,21 @@ namespace deleteDeclaration { const gp = parent.parent; switch (gp.kind) { - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.ForInStatement: - changes.replaceNode(sourceFile, node, ts.factory.createObjectLiteralExpression()); + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForInStatement: + changes.replaceNode(sourceFile, node, factory.createObjectLiteralExpression()); break; - case ts.SyntaxKind.ForStatement: + case SyntaxKind.ForStatement: deleteNode(changes, sourceFile, parent); break; - case ts.SyntaxKind.VariableStatement: - deleteNode(changes, sourceFile, gp, { leadingTriviaOption: ts.hasJSDocNodes(gp) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); + case SyntaxKind.VariableStatement: + deleteNode(changes, sourceFile, gp, { leadingTriviaOption: hasJSDocNodes(gp) ? LeadingTriviaOption.JSDoc : LeadingTriviaOption.StartLine }); break; default: - ts.Debug.assertNever(gp); + Debug.assertNever(gp); } } } @@ -1610,16 +1638,16 @@ namespace deleteDeclaration { /** @internal */ /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */ // Exported for tests only! (TODO: improve tests to not need this) -export function deleteNode(changes: ChangeTracker, sourceFile: ts.SourceFile, node: ts.Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { +export function deleteNode(changes: ChangeTracker, sourceFile: SourceFile, node: Node, options: ConfigurableStartEnd = { leadingTriviaOption: LeadingTriviaOption.IncludeAll }): void { const startPosition = getAdjustedStartPosition(sourceFile, node, options); const endPosition = getAdjustedEndPosition(sourceFile, node, options); changes.deleteRange(sourceFile, { pos: startPosition, end: endPosition }); } -function deleteNodeInList(changes: ChangeTracker, deletedNodesInLists: ts.Set, sourceFile: ts.SourceFile, node: ts.Node): void { - const containingList = ts.Debug.checkDefined(ts.formatting.SmartIndenter.getContainingList(node, sourceFile)); - const index = ts.indexOfNode(containingList, node); - ts.Debug.assert(index !== -1); +function deleteNodeInList(changes: ChangeTracker, deletedNodesInLists: Set, sourceFile: SourceFile, node: Node): void { + const containingList = Debug.checkDefined(formatting.SmartIndenter.getContainingList(node, sourceFile)); + const index = indexOfNode(containingList, node); + Debug.assert(index !== -1); if (containingList.length === 1) { deleteNode(changes, sourceFile, node); return; @@ -1627,7 +1655,7 @@ function deleteNodeInList(changes: ChangeTracker, deletedNodesInLists: ts.Set(source: T | T[], transformers: ts.TransformerFactory[], compilerOptions?: ts.CompilerOptions) { - const diagnostics: ts.DiagnosticWithLocation[] = []; - compilerOptions = ts.fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217 - const nodes = ts.isArray(source) ? source : [source]; - const result = ts.transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, ts.factory, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); - result.diagnostics = ts.concatenate(result.diagnostics, diagnostics); +export function transform(source: T | T[], transformers: TransformerFactory[], compilerOptions?: CompilerOptions) { + const diagnostics: DiagnosticWithLocation[] = []; + compilerOptions = fixupCompilerOptions(compilerOptions!, diagnostics); // TODO: GH#18217 + const nodes = isArray(source) ? source : [source]; + const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, factory, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true); + result.diagnostics = concatenate(result.diagnostics, diagnostics); return result; } \ No newline at end of file diff --git a/src/services/transpile.ts b/src/services/transpile.ts index e080de22ce1f5..d588995353023 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -1,17 +1,23 @@ -import * as ts from "./_namespaces/ts"; +import { + addRange, cloneCompilerOptions, CommandLineOptionOfCustomType, CompilerHost, CompilerOptions, + createCompilerDiagnosticForInvalidCustomType, createProgram, createSourceFile, CustomTransformers, Debug, + Diagnostic, fileExtensionIs, filter, forEachEntry, getDefaultCompilerOptions, getEmitScriptTarget, getEntries, + getImpliedNodeFormatForFile, getNewLineCharacter, getSetExternalModuleIndicator, hasProperty, isString, Map, + MapLike, normalizePath, optionDeclarations, parseCustomTypeOption, toPath, transpileOptionValueCompilerOptions, +} from "./_namespaces/ts"; export interface TranspileOptions { - compilerOptions?: ts.CompilerOptions; + compilerOptions?: CompilerOptions; fileName?: string; reportDiagnostics?: boolean; moduleName?: string; - renamedDependencies?: ts.MapLike; - transformers?: ts.CustomTransformers; + renamedDependencies?: MapLike; + transformers?: CustomTransformers; } export interface TranspileOutput { outputText: string; - diagnostics?: ts.Diagnostic[]; + diagnostics?: Diagnostic[]; sourceMapText?: string; } @@ -25,19 +31,19 @@ export interface TranspileOutput { * - noResolve = true */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - const diagnostics: ts.Diagnostic[] = []; + const diagnostics: Diagnostic[] = []; - const options: ts.CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {}; + const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {}; // mix in default options - const defaultOptions = ts.getDefaultCompilerOptions(); + const defaultOptions = getDefaultCompilerOptions(); for (const key in defaultOptions) { - if (ts.hasProperty(defaultOptions, key) && options[key] === undefined) { + if (hasProperty(defaultOptions, key) && options[key] === undefined) { options[key] = defaultOptions[key]; } } - for (const option of ts.transpileOptionValueCompilerOptions) { + for (const option of transpileOptionValueCompilerOptions) { options[option.name] = option.transpileOptionValue; } @@ -47,17 +53,17 @@ export function transpileModule(input: string, transpileOptions: TranspileOption // Filename can be non-ts file. options.allowNonTsExtensions = true; - const newLine = ts.getNewLineCharacter(options); + const newLine = getNewLineCharacter(options); // Create a compilerHost object to allow the compiler to read and write files - const compilerHost: ts.CompilerHost = { - getSourceFile: (fileName) => fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined, + const compilerHost: CompilerHost = { + getSourceFile: (fileName) => fileName === normalizePath(inputFileName) ? sourceFile : undefined, writeFile: (name, text) => { - if (ts.fileExtensionIs(name, ".map")) { - ts.Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name); + if (fileExtensionIs(name, ".map")) { + Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name); sourceMapText = text; } else { - ts.Debug.assertEqual(outputText, undefined, "Unexpected multiple outputs, file:", name); + Debug.assertEqual(outputText, undefined, "Unexpected multiple outputs, file:", name); outputText = text; } }, @@ -74,13 +80,13 @@ export function transpileModule(input: string, transpileOptions: TranspileOption // if jsx is specified then treat file as .tsx const inputFileName = transpileOptions.fileName || (transpileOptions.compilerOptions && transpileOptions.compilerOptions.jsx ? "module.tsx" : "module.ts"); - const sourceFile = ts.createSourceFile( + const sourceFile = createSourceFile( inputFileName, input, { - languageVersion: ts.getEmitScriptTarget(options), - impliedNodeFormat: ts.getImpliedNodeFormatForFile(ts.toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*cache*/ undefined, compilerHost, options), - setExternalModuleIndicator: ts.getSetExternalModuleIndicator(options) + languageVersion: getEmitScriptTarget(options), + impliedNodeFormat: getImpliedNodeFormatForFile(toPath(inputFileName, "", compilerHost.getCanonicalFileName), /*cache*/ undefined, compilerHost, options), + setExternalModuleIndicator: getSetExternalModuleIndicator(options) } ); if (transpileOptions.moduleName) { @@ -88,23 +94,23 @@ export function transpileModule(input: string, transpileOptions: TranspileOption } if (transpileOptions.renamedDependencies) { - sourceFile.renamedDependencies = new ts.Map(ts.getEntries(transpileOptions.renamedDependencies)); + sourceFile.renamedDependencies = new Map(getEntries(transpileOptions.renamedDependencies)); } // Output let outputText: string | undefined; let sourceMapText: string | undefined; - const program = ts.createProgram([inputFileName], options, compilerHost); + const program = createProgram([inputFileName], options, compilerHost); if (transpileOptions.reportDiagnostics) { - ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); - ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); + addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); + addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); - if (outputText === undefined) return ts.Debug.fail("Output generation failed"); + if (outputText === undefined) return Debug.fail("Output generation failed"); return { outputText, diagnostics, sourceMapText }; } @@ -112,39 +118,39 @@ export function transpileModule(input: string, transpileOptions: TranspileOption /* * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result. */ -export function transpile(input: string, compilerOptions?: ts.CompilerOptions, fileName?: string, diagnostics?: ts.Diagnostic[], moduleName?: string): string { +export function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string { const output = transpileModule(input, { compilerOptions, fileName, reportDiagnostics: !!diagnostics, moduleName }); // addRange correctly handles cases when wither 'from' or 'to' argument is missing - ts.addRange(diagnostics, output.diagnostics); + addRange(diagnostics, output.diagnostics); return output.outputText; } -let commandLineOptionsStringToEnum: ts.CommandLineOptionOfCustomType[]; +let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[]; /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */ /*@internal*/ -export function fixupCompilerOptions(options: ts.CompilerOptions, diagnostics: ts.Diagnostic[]): ts.CompilerOptions { +export function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions { // Lazily create this value to fix module loading errors. commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || - ts.filter(ts.optionDeclarations, o => typeof o.type === "object" && !ts.forEachEntry(o.type, v => typeof v !== "number")) as ts.CommandLineOptionOfCustomType[]; + filter(optionDeclarations, o => typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number")) as CommandLineOptionOfCustomType[]; - options = ts.cloneCompilerOptions(options); + options = cloneCompilerOptions(options); for (const opt of commandLineOptionsStringToEnum) { - if (!ts.hasProperty(options, opt.name)) { + if (!hasProperty(options, opt.name)) { continue; } const value = options[opt.name]; // Value should be a key of opt.type - if (ts.isString(value)) { + if (isString(value)) { // If value is not a string, this will fail - options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics); + options[opt.name] = parseCustomTypeOption(opt, value, diagnostics); } else { - if (!ts.forEachEntry(opt.type, v => v === value)) { + if (!forEachEntry(opt.type, v => v === value)) { // Supplied value isn't a valid enum value. - diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt)); + diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt)); } } } diff --git a/src/services/types.ts b/src/services/types.ts index 0ef33905ae597..1178bd48d4115 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1,32 +1,40 @@ -import * as ts from "./_namespaces/ts"; +import { + CancellationToken, CompilerHost, CompilerOptions, CustomTransformers, Diagnostic, DiagnosticWithLocation, + DocumentHighlights, DocumentPositionMapper, EmitOutput, ESMap, ExportInfoMap, FileReference, + GetEffectiveTypeRootsHost, HasChangedAutomaticTypeDirectiveNames, HasInvalidatedResolutions, LineAndCharacter, + MinimalResolutionCacheHost, ModuleKind, ModuleResolutionCache, ModuleSpecifierCache, ParsedCommandLine, Path, + Program, ProjectReference, ResolvedModule, ResolvedModuleWithFailedLookupLocations, ResolvedProjectReference, + ResolvedTypeReferenceDirective, ScriptKind, Set, SourceFile, SourceFileLike, SourceMapper, Symbol, SymlinkCache, + TextChangeRange, textChanges, TextRange, TextSpan, UserPreferences, +} from "./_namespaces/ts"; declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface Node { - getSourceFile(): ts.SourceFile; - getChildCount(sourceFile?: ts.SourceFile): number; - getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node; - getChildren(sourceFile?: ts.SourceFile): ts.Node[]; + getSourceFile(): SourceFile; + getChildCount(sourceFile?: SourceFile): number; + getChildAt(index: number, sourceFile?: SourceFile): Node; + getChildren(sourceFile?: SourceFile): Node[]; /* @internal */ - getChildren(sourceFile?: ts.SourceFileLike): ts.Node[]; // eslint-disable-line @typescript-eslint/unified-signatures - getStart(sourceFile?: ts.SourceFile, includeJsDocComment?: boolean): number; + getChildren(sourceFile?: SourceFileLike): Node[]; // eslint-disable-line @typescript-eslint/unified-signatures + getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number; /* @internal */ - getStart(sourceFile?: ts.SourceFileLike, includeJsDocComment?: boolean): number; // eslint-disable-line @typescript-eslint/unified-signatures + getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number; // eslint-disable-line @typescript-eslint/unified-signatures getFullStart(): number; getEnd(): number; - getWidth(sourceFile?: ts.SourceFileLike): number; + getWidth(sourceFile?: SourceFileLike): number; getFullWidth(): number; - getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number; - getFullText(sourceFile?: ts.SourceFile): string; - getText(sourceFile?: ts.SourceFile): string; - getFirstToken(sourceFile?: ts.SourceFile): ts.Node | undefined; + getLeadingTriviaWidth(sourceFile?: SourceFile): number; + getFullText(sourceFile?: SourceFile): string; + getText(sourceFile?: SourceFile): string; + getFirstToken(sourceFile?: SourceFile): Node | undefined; /* @internal */ - getFirstToken(sourceFile?: ts.SourceFileLike): ts.Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures - getLastToken(sourceFile?: ts.SourceFile): ts.Node | undefined; + getFirstToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures + getLastToken(sourceFile?: SourceFile): Node | undefined; /* @internal */ - getLastToken(sourceFile?: ts.SourceFileLike): ts.Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures + getLastToken(sourceFile?: SourceFileLike): Node | undefined; // eslint-disable-line @typescript-eslint/unified-signatures // See ts.forEachChild for documentation. - forEachChild(cbNode: (node: ts.Node) => T | undefined, cbNodeArray?: (nodes: ts.NodeArray) => T | undefined): T | undefined; + forEachChild(cbNode: (node: Node) => T | undefined, cbNodeArray?: (nodes: NodeArray) => T | undefined): T | undefined; } } @@ -48,67 +56,67 @@ declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface Symbol { readonly name: string; - getFlags(): ts.SymbolFlags; - getEscapedName(): ts.__String; + getFlags(): SymbolFlags; + getEscapedName(): __String; getName(): string; - getDeclarations(): ts.Declaration[] | undefined; - getDocumentationComment(typeChecker: ts.TypeChecker | undefined): SymbolDisplayPart[]; + getDeclarations(): Declaration[] | undefined; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; /* @internal */ - getContextualDocumentationComment(context: ts.Node | undefined, checker: ts.TypeChecker | undefined): SymbolDisplayPart[] - getJsDocTags(checker?: ts.TypeChecker): JSDocTagInfo[]; + getContextualDocumentationComment(context: Node | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[] + getJsDocTags(checker?: TypeChecker): JSDocTagInfo[]; /* @internal */ - getContextualJsDocTags(context: ts.Node | undefined, checker: ts.TypeChecker | undefined): JSDocTagInfo[]; + getContextualJsDocTags(context: Node | undefined, checker: TypeChecker | undefined): JSDocTagInfo[]; } } declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface Type { - getFlags(): ts.TypeFlags; - getSymbol(): ts.Symbol | undefined; - getProperties(): ts.Symbol[]; - getProperty(propertyName: string): ts.Symbol | undefined; - getApparentProperties(): ts.Symbol[]; - getCallSignatures(): readonly ts.Signature[]; - getConstructSignatures(): readonly ts.Signature[]; - getStringIndexType(): ts.Type | undefined; - getNumberIndexType(): ts.Type | undefined; - getBaseTypes(): ts.BaseType[] | undefined; - getNonNullableType(): ts.Type; - /*@internal*/ getNonOptionalType(): ts.Type; + getFlags(): TypeFlags; + getSymbol(): Symbol | undefined; + getProperties(): Symbol[]; + getProperty(propertyName: string): Symbol | undefined; + getApparentProperties(): Symbol[]; + getCallSignatures(): readonly Signature[]; + getConstructSignatures(): readonly Signature[]; + getStringIndexType(): Type | undefined; + getNumberIndexType(): Type | undefined; + getBaseTypes(): BaseType[] | undefined; + getNonNullableType(): Type; + /*@internal*/ getNonOptionalType(): Type; /*@internal*/ isNullableType(): boolean; - getConstraint(): ts.Type | undefined; - getDefault(): ts.Type | undefined; - - isUnion(): this is ts.UnionType; - isIntersection(): this is ts.IntersectionType; - isUnionOrIntersection(): this is ts.UnionOrIntersectionType; - isLiteral(): this is ts.LiteralType; - isStringLiteral(): this is ts.StringLiteralType; - isNumberLiteral(): this is ts.NumberLiteralType; - isTypeParameter(): this is ts.TypeParameter; - isClassOrInterface(): this is ts.InterfaceType; - isClass(): this is ts.InterfaceType; - isIndexType(): this is ts.IndexType; + getConstraint(): Type | undefined; + getDefault(): Type | undefined; + + isUnion(): this is UnionType; + isIntersection(): this is IntersectionType; + isUnionOrIntersection(): this is UnionOrIntersectionType; + isLiteral(): this is LiteralType; + isStringLiteral(): this is StringLiteralType; + isNumberLiteral(): this is NumberLiteralType; + isTypeParameter(): this is TypeParameter; + isClassOrInterface(): this is InterfaceType; + isClass(): this is InterfaceType; + isIndexType(): this is IndexType; } } declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface TypeReference { - typeArguments?: readonly ts.Type[]; + typeArguments?: readonly Type[]; } } declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface Signature { - getDeclaration(): ts.SignatureDeclaration; - getTypeParameters(): ts.TypeParameter[] | undefined; - getParameters(): ts.Symbol[]; - getTypeParameterAtPosition(pos: number): ts.Type; - getReturnType(): ts.Type; - getDocumentationComment(typeChecker: ts.TypeChecker | undefined): SymbolDisplayPart[]; + getDeclaration(): SignatureDeclaration; + getTypeParameters(): TypeParameter[] | undefined; + getParameters(): Symbol[]; + getTypeParameterAtPosition(pos: number): Type; + getReturnType(): Type; + getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(): JSDocTagInfo[]; } } @@ -118,31 +126,31 @@ declare module "../compiler/types" { export interface SourceFile { /* @internal */ version: string; /* @internal */ scriptSnapshot: IScriptSnapshot | undefined; - /* @internal */ nameTable: ts.UnderscoreEscapedMap | undefined; + /* @internal */ nameTable: UnderscoreEscapedMap | undefined; - /* @internal */ getNamedDeclarations(): ts.ESMap; + /* @internal */ getNamedDeclarations(): ESMap; - getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter; + getLineAndCharacterOfPosition(pos: number): LineAndCharacter; getLineEndOfPosition(pos: number): number; getLineStarts(): readonly number[]; getPositionOfLineAndCharacter(line: number, character: number): number; - update(newText: string, textChangeRange: ts.TextChangeRange): ts.SourceFile; + update(newText: string, textChangeRange: TextChangeRange): SourceFile; - /* @internal */ sourceMapper?: ts.DocumentPositionMapper; + /* @internal */ sourceMapper?: DocumentPositionMapper; } } declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface SourceFileLike { - getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter; + getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } } declare module "../compiler/types" { // Module transform: converted from interface augmentation export interface SourceMapSource { - getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter; + getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } } @@ -166,7 +174,7 @@ export interface IScriptSnapshot { * change range cannot be determined. However, in that case, incremental parsing will * not happen and the entire document will be re - parsed. */ - getChangeRange(oldSnapshot: IScriptSnapshot): ts.TextChangeRange | undefined; + getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange | undefined; /** Releases all resources held by this script snapshot */ dispose?(): void; @@ -188,7 +196,7 @@ export namespace ScriptSnapshot { return this.text.length; } - public getChangeRange(): ts.TextChangeRange | undefined { + public getChangeRange(): TextChangeRange | undefined { // Text-based snapshots do not support incremental parsing. Return undefined // to signal that to the caller. return undefined; @@ -201,10 +209,10 @@ export namespace ScriptSnapshot { } export interface PreProcessedFileInfo { - referencedFiles: ts.FileReference[]; - typeReferenceDirectives: ts.FileReference[]; - libReferenceDirectives: ts.FileReference[]; - importedFiles: ts.FileReference[]; + referencedFiles: FileReference[]; + typeReferenceDirectives: FileReference[]; + libReferenceDirectives: FileReference[]; + importedFiles: FileReference[]; ambientExternalModules?: string[]; isLibFile: boolean; } @@ -214,7 +222,7 @@ export interface HostCancellationToken { } export interface InstallPackageOptions { - fileName: ts.Path; + fileName: Path; packageName: string; } @@ -231,10 +239,10 @@ export const enum PackageJsonDependencyGroup { export interface ProjectPackageJsonInfo { fileName: string; parseable: boolean; - dependencies?: ts.ESMap; - devDependencies?: ts.ESMap; - peerDependencies?: ts.ESMap; - optionalDependencies?: ts.ESMap; + dependencies?: ESMap; + devDependencies?: ESMap; + peerDependencies?: ESMap; + optionalDependencies?: ESMap; get(dependencyName: string, inGroups?: PackageJsonDependencyGroup): string | undefined; has(dependencyName: string, inGroups?: PackageJsonDependencyGroup): boolean; } @@ -271,19 +279,19 @@ export interface IncompleteCompletionsCache { // // Public interface of the host of a language service instance. // -export interface LanguageServiceHost extends ts.GetEffectiveTypeRootsHost, ts.MinimalResolutionCacheHost { - getCompilationSettings(): ts.CompilerOptions; +export interface LanguageServiceHost extends GetEffectiveTypeRootsHost, MinimalResolutionCacheHost { + getCompilationSettings(): CompilerOptions; getNewLine?(): string; getProjectVersion?(): string; getScriptFileNames(): string[]; - getScriptKind?(fileName: string): ts.ScriptKind; + getScriptKind?(fileName: string): ScriptKind; getScriptVersion(fileName: string): string; getScriptSnapshot(fileName: string): IScriptSnapshot | undefined; - getProjectReferences?(): readonly ts.ProjectReference[] | undefined; + getProjectReferences?(): readonly ProjectReference[] | undefined; getLocalizedDiagnosticMessages?(): any; getCancellationToken?(): HostCancellationToken; getCurrentDirectory(): string; - getDefaultLibFileName(options: ts.CompilerOptions): string; + getDefaultLibFileName(options: CompilerOptions): string; log?(s: string): void; trace?(s: string): void; error?(s: string): void; @@ -315,15 +323,15 @@ export interface LanguageServiceHost extends ts.GetEffectiveTypeRootsHost, ts.Mi * * If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too. */ - resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ts.ResolvedProjectReference | undefined, options: ts.CompilerOptions, containingSourceFile?: ts.SourceFile): (ts.ResolvedModule | undefined)[]; - getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string, resolutionMode?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext): ts.ResolvedModuleWithFailedLookupLocations | undefined; - resolveTypeReferenceDirectives?(typeDirectiveNames: string[] | ts.FileReference[], containingFile: string, redirectedReference: ts.ResolvedProjectReference | undefined, options: ts.CompilerOptions, containingFileMode?: ts.SourceFile["impliedNodeFormat"] | undefined): (ts.ResolvedTypeReferenceDirective | undefined)[]; - /* @internal */ hasInvalidatedResolutions?: ts.HasInvalidatedResolutions; - /* @internal */ hasChangedAutomaticTypeDirectiveNames?: ts.HasChangedAutomaticTypeDirectiveNames; + resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingSourceFile?: SourceFile): (ResolvedModule | undefined)[]; + getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string, resolutionMode?: ModuleKind.CommonJS | ModuleKind.ESNext): ResolvedModuleWithFailedLookupLocations | undefined; + resolveTypeReferenceDirectives?(typeDirectiveNames: string[] | FileReference[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions, containingFileMode?: SourceFile["impliedNodeFormat"] | undefined): (ResolvedTypeReferenceDirective | undefined)[]; + /* @internal */ hasInvalidatedResolutions?: HasInvalidatedResolutions; + /* @internal */ hasChangedAutomaticTypeDirectiveNames?: HasChangedAutomaticTypeDirectiveNames; /* @internal */ getGlobalTypingsCacheLocation?(): string | undefined; - /* @internal */ getSymlinkCache?(files?: readonly ts.SourceFile[]): ts.SymlinkCache; + /* @internal */ getSymlinkCache?(files?: readonly SourceFile[]): SymlinkCache; /* Lets the Program from a AutoImportProviderProject use its host project's ModuleResolutionCache */ - /* @internal */ getModuleResolutionCache?(): ts.ModuleResolutionCache | undefined; + /* @internal */ getModuleResolutionCache?(): ModuleResolutionCache | undefined; /* * Required for full import and type reference completions. @@ -334,25 +342,25 @@ export interface LanguageServiceHost extends ts.GetEffectiveTypeRootsHost, ts.Mi /** * Gets a set of custom transformers to use during emit. */ - getCustomTransformers?(): ts.CustomTransformers | undefined; + getCustomTransformers?(): CustomTransformers | undefined; isKnownTypesPackageName?(name: string): boolean; installPackage?(options: InstallPackageOptions): Promise; writeFile?(fileName: string, content: string): void; - /* @internal */ getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): ts.DocumentPositionMapper | undefined; - /* @internal */ getSourceFileLike?(fileName: string): ts.SourceFileLike | undefined; + /* @internal */ getDocumentPositionMapper?(generatedFileName: string, sourceFileName?: string): DocumentPositionMapper | undefined; + /* @internal */ getSourceFileLike?(fileName: string): SourceFileLike | undefined; /* @internal */ getPackageJsonsVisibleToFile?(fileName: string, rootDir?: string): readonly ProjectPackageJsonInfo[]; /* @internal */ getNearestAncestorDirectoryWithPackageJson?(fileName: string): string | undefined; /* @internal */ getPackageJsonsForAutoImport?(rootDir?: string): readonly ProjectPackageJsonInfo[]; - /* @internal */ getCachedExportInfoMap?(): ts.ExportInfoMap; - /* @internal */ getModuleSpecifierCache?(): ts.ModuleSpecifierCache; - /* @internal */ setCompilerHost?(host: ts.CompilerHost): void; + /* @internal */ getCachedExportInfoMap?(): ExportInfoMap; + /* @internal */ getModuleSpecifierCache?(): ModuleSpecifierCache; + /* @internal */ setCompilerHost?(host: CompilerHost): void; /* @internal */ useSourceOfProjectReferenceRedirect?(): boolean; - /* @internal */ getPackageJsonAutoImportProvider?(): ts.Program | undefined; + /* @internal */ getPackageJsonAutoImportProvider?(): Program | undefined; /* @internal */ sendPerformanceEvent?(kind: PerformanceEvent["kind"], durationMs: number): void; - getParsedCommandLine?(fileName: string): ts.ParsedCommandLine | undefined; - /* @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ts.ResolvedProjectReference | undefined, optionOptions: ts.CompilerOptions): void; + getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; + /* @internal */ onReleaseParsedCommandLine?(configFileName: string, oldResolvedRef: ResolvedProjectReference | undefined, optionOptions: CompilerOptions): void; /* @internal */ getIncompleteCompletionsCache?(): IncompleteCompletionsCache; } @@ -391,7 +399,7 @@ export interface LanguageService { * * @param fileName A path to the file you want syntactic diagnostics for */ - getSyntacticDiagnostics(fileName: string): ts.DiagnosticWithLocation[]; + getSyntacticDiagnostics(fileName: string): DiagnosticWithLocation[]; /** * Gets warnings or errors indicating type system issues in a given file. @@ -408,7 +416,7 @@ export interface LanguageService { * * @param fileName A path to the file you want semantic diagnostics for */ - getSemanticDiagnostics(fileName: string): ts.Diagnostic[]; + getSemanticDiagnostics(fileName: string): Diagnostic[]; /** * Gets suggestion diagnostics for a specific file. These diagnostics tend to @@ -417,7 +425,7 @@ export interface LanguageService { * * @param fileName A path to the file you want semantic diagnostics for */ - getSuggestionDiagnostics(fileName: string): ts.DiagnosticWithLocation[]; + getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[]; // TODO: Rename this to getProgramDiagnostics to better indicate that these are any // diagnostics present for the program level, and not just 'options' diagnostics. @@ -425,18 +433,18 @@ export interface LanguageService { /** * Gets global diagnostics related to the program configuration and compiler options. */ - getCompilerOptionsDiagnostics(): ts.Diagnostic[]; + getCompilerOptionsDiagnostics(): Diagnostic[]; /** @deprecated Use getEncodedSyntacticClassifications instead. */ - getSyntacticClassifications(fileName: string, span: ts.TextSpan): ClassifiedSpan[]; - getSyntacticClassifications(fileName: string, span: ts.TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSyntacticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + getSyntacticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; /** @deprecated Use getEncodedSemanticClassifications instead. */ - getSemanticClassifications(fileName: string, span: ts.TextSpan): ClassifiedSpan[]; - getSemanticClassifications(fileName: string, span: ts.TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; + getSemanticClassifications(fileName: string, span: TextSpan): ClassifiedSpan[]; + getSemanticClassifications(fileName: string, span: TextSpan, format: SemanticClassificationFormat): ClassifiedSpan[] | ClassifiedSpan2020[]; /** Encoded as triples of [start, length, ClassificationType]. */ - getEncodedSyntacticClassifications(fileName: string, span: ts.TextSpan): Classifications; + getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications; /** * Gets semantic highlights information for a particular file. Has two formats, an older @@ -447,7 +455,7 @@ export interface LanguageService { * @param format Which format to use, defaults to "original" * @returns a number array encoded as triples of [start, length, ClassificationType, ...]. */ - getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan, format?: SemanticClassificationFormat): Classifications; + getEncodedSemanticClassifications(fileName: string, span: TextSpan, format?: SemanticClassificationFormat): Classifications; /** * Gets completion entries at a particular position in a file. @@ -477,11 +485,11 @@ export interface LanguageService { entryName: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, - preferences: ts.UserPreferences | undefined, + preferences: UserPreferences | undefined, data: CompletionEntryData | undefined, ): CompletionEntryDetails | undefined; - getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): ts.Symbol | undefined; + getCompletionEntrySymbol(fileName: string, position: number, name: string, source: string | undefined): Symbol | undefined; /** * Gets semantic information about the identifier at a particular position in a @@ -492,13 +500,13 @@ export interface LanguageService { */ getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined; - getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): ts.TextSpan | undefined; + getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined; - getBreakpointStatementAtPosition(fileName: string, position: number): ts.TextSpan | undefined; + getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined; getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined; - getRenameInfo(fileName: string, position: number, preferences: ts.UserPreferences): RenameInfo; + getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo; /** @deprecated Use the signature with `UserPreferences` instead. */ getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo; @@ -519,7 +527,7 @@ export interface LanguageService { getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined; findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined; - getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): ts.DocumentHighlights[] | undefined; + getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined; getFileReferences(fileName: string): ReferenceEntry[]; /** @deprecated */ @@ -533,11 +541,11 @@ export interface LanguageService { provideCallHierarchyIncomingCalls(fileName: string, position: number): CallHierarchyIncomingCall[]; provideCallHierarchyOutgoingCalls(fileName: string, position: number): CallHierarchyOutgoingCall[]; - provideInlayHints(fileName: string, span: ts.TextSpan, preferences: ts.UserPreferences | undefined): InlayHint[] + provideInlayHints(fileName: string, span: TextSpan, preferences: UserPreferences | undefined): InlayHint[] getOutliningSpans(fileName: string): OutliningSpan[]; getTodoComments(fileName: string, descriptors: TodoCommentDescriptor[]): TodoComment[]; - getBraceMatchingAtPosition(fileName: string, position: number): ts.TextSpan[]; + getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[]; getIndentationAtPosition(fileName: string, position: number, options: EditorOptions | EditorSettings): number; getFormattingEditsForRange(fileName: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): TextChange[]; @@ -553,16 +561,16 @@ export interface LanguageService { */ getJsxClosingTagAtPosition(fileName: string, position: number): JsxClosingTagInfo | undefined; - getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan | undefined; + getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): TextSpan | undefined; - toLineColumnOffset?(fileName: string, position: number): ts.LineAndCharacter; + toLineColumnOffset?(fileName: string, position: number): LineAndCharacter; /** @internal */ - getSourceMapper(): ts.SourceMapper; + getSourceMapper(): SourceMapper; /** @internal */ clearSourceMapperCache(): void; - getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: ts.UserPreferences): readonly CodeFixAction[]; - getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: ts.UserPreferences): CombinedCodeActions; + getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): readonly CodeFixAction[]; + getCombinedCodeFix(scope: CombinedCodeFixScope, fixId: {}, formatOptions: FormatCodeSettings, preferences: UserPreferences): CombinedCodeActions; applyCodeActionCommand(action: CodeActionCommand, formatSettings?: FormatCodeSettings): Promise; applyCodeActionCommand(action: CodeActionCommand[], formatSettings?: FormatCodeSettings): Promise; @@ -574,28 +582,28 @@ export interface LanguageService { /** @deprecated `fileName` will be ignored */ applyCodeActionCommand(fileName: string, action: CodeActionCommand | CodeActionCommand[]): Promise; - getApplicableRefactors(fileName: string, positionOrRange: number | ts.TextRange, preferences: ts.UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[]; - getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | ts.TextRange, refactorName: string, actionName: string, preferences: ts.UserPreferences | undefined): RefactorEditInfo | undefined; - organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: ts.UserPreferences | undefined): readonly FileTextChanges[]; - getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: ts.UserPreferences | undefined): readonly FileTextChanges[]; + getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences | undefined, triggerReason?: RefactorTriggerReason, kind?: string): ApplicableRefactorInfo[]; + getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined; + organizeImports(args: OrganizeImportsArgs, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; + getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): readonly FileTextChanges[]; - getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): ts.EmitOutput; + getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean, forceDtsEmit?: boolean): EmitOutput; - getProgram(): ts.Program | undefined; - /*@internal*/ getCurrentProgram(): ts.Program | undefined; + getProgram(): Program | undefined; + /*@internal*/ getCurrentProgram(): Program | undefined; - /* @internal */ getNonBoundSourceFile(fileName: string): ts.SourceFile; - /* @internal */ getAutoImportProvider(): ts.Program | undefined; + /* @internal */ getNonBoundSourceFile(fileName: string): SourceFile; + /* @internal */ getAutoImportProvider(): Program | undefined; /// Returns true if a suitable symbol was found in the project. /// May set isDefinition properties in `referencedSymbols` to false. /// May add elements to `knownSymbolSpans`. - /* @internal */ updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ReferencedSymbol[], knownSymbolSpans: ts.Set): boolean; + /* @internal */ updateIsDefinitionOfReferencedSymbols(referencedSymbols: readonly ReferencedSymbol[], knownSymbolSpans: Set): boolean; - toggleLineComment(fileName: string, textRange: ts.TextRange): TextChange[]; - toggleMultilineComment(fileName: string, textRange: ts.TextRange): TextChange[]; - commentSelection(fileName: string, textRange: ts.TextRange): TextChange[]; - uncommentSelection(fileName: string, textRange: ts.TextRange): TextChange[]; + toggleLineComment(fileName: string, textRange: TextRange): TextChange[]; + toggleMultilineComment(fileName: string, textRange: TextRange): TextChange[]; + commentSelection(fileName: string, textRange: TextRange): TextChange[]; + uncommentSelection(fileName: string, textRange: TextRange): TextChange[]; dispose(): void; } @@ -631,7 +639,7 @@ export const enum CompletionTriggerKind { TriggerForIncompleteCompletions = 3, } -export interface GetCompletionsAtPositionOptions extends ts.UserPreferences { +export interface GetCompletionsAtPositionOptions extends UserPreferences { /** * If the editor is asking for completions because a certain character was typed * (as opposed to when the user explicitly requested them) this should be set. @@ -701,12 +709,12 @@ export interface Classifications { } export interface ClassifiedSpan { - textSpan: ts.TextSpan; + textSpan: TextSpan; classificationType: ClassificationTypeNames; } export interface ClassifiedSpan2020 { - textSpan: ts.TextSpan; + textSpan: TextSpan; classificationType: number; } @@ -720,7 +728,7 @@ export interface NavigationBarItem { text: string; kind: ScriptElementKind; kindModifiers: string; - spans: ts.TextSpan[]; + spans: TextSpan[]; childItems: NavigationBarItem[]; indent: number; bolded: boolean; @@ -741,8 +749,8 @@ export interface NavigationTree { * Spans of the nodes that generated this declaration. * There will be more than one if this is the result of merging. */ - spans: ts.TextSpan[]; - nameSpan: ts.TextSpan | undefined; + spans: TextSpan[]; + nameSpan: TextSpan | undefined; /** Present if non-empty */ childItems?: NavigationTree[]; } @@ -752,19 +760,19 @@ export interface CallHierarchyItem { kind: ScriptElementKind; kindModifiers?: string; file: string; - span: ts.TextSpan; - selectionSpan: ts.TextSpan; + span: TextSpan; + selectionSpan: TextSpan; containerName?: string; } export interface CallHierarchyIncomingCall { from: CallHierarchyItem; - fromSpans: ts.TextSpan[]; + fromSpans: TextSpan[]; } export interface CallHierarchyOutgoingCall { to: CallHierarchyItem; - fromSpans: ts.TextSpan[]; + fromSpans: TextSpan[]; } export const enum InlayHintKind { @@ -793,7 +801,7 @@ export interface TodoComment { } export interface TextChange { - span: ts.TextSpan; + span: TextSpan; newText: string; } @@ -915,22 +923,22 @@ export interface TextInsertion { } export interface DocumentSpan { - textSpan: ts.TextSpan; + textSpan: TextSpan; fileName: string; /** * If the span represents a location that was remapped (e.g. via a .d.ts.map file), * then the original filename and span will be specified here */ - originalTextSpan?: ts.TextSpan; + originalTextSpan?: TextSpan; originalFileName?: string; /** * If DocumentSpan.textSpan is the span for name of the declaration, * then this is the span for relevant declaration */ - contextSpan?: ts.TextSpan; - originalContextSpan?: ts.TextSpan; + contextSpan?: TextSpan; + originalContextSpan?: TextSpan; } export interface RenameLocation extends DocumentSpan { @@ -958,8 +966,8 @@ export const enum HighlightSpanKind { export interface HighlightSpan { fileName?: string; isInString?: true; - textSpan: ts.TextSpan; - contextSpan?: ts.TextSpan; + textSpan: TextSpan; + contextSpan?: TextSpan; kind: HighlightSpanKind; } @@ -970,7 +978,7 @@ export interface NavigateToItem { matchKind: "exact" | "prefix" | "substring" | "camelCase"; isCaseSensitive: boolean; fileName: string; - textSpan: ts.TextSpan; + textSpan: TextSpan; containerName: string; containerKind: ScriptElementKind; } @@ -1097,7 +1105,7 @@ export interface DefinitionInfo extends DocumentSpan { export interface DefinitionInfoAndBoundSpan { definitions?: readonly DefinitionInfo[]; - textSpan: ts.TextSpan; + textSpan: TextSpan; } export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo { @@ -1158,7 +1166,7 @@ export interface JSDocTagInfo { export interface QuickInfo { kind: ScriptElementKind; kindModifiers: string; - textSpan: ts.TextSpan; + textSpan: TextSpan; displayParts?: SymbolDisplayPart[]; documentation?: SymbolDisplayPart[]; tags?: JSDocTagInfo[]; @@ -1176,7 +1184,7 @@ export interface RenameInfoSuccess { fullDisplayName: string; kind: ScriptElementKind; kindModifiers: string; - triggerSpan: ts.TextSpan; + triggerSpan: TextSpan; } export interface RenameInfoFailure { canRename: false; @@ -1203,7 +1211,7 @@ export interface SignatureHelpParameter { } export interface SelectionRange { - textSpan: ts.TextSpan; + textSpan: TextSpan; parent?: SelectionRange; } @@ -1229,7 +1237,7 @@ export interface SignatureHelpItem { */ export interface SignatureHelpItems { items: SignatureHelpItem[]; - applicableSpan: ts.TextSpan; + applicableSpan: TextSpan; selectedItemIndex: number; argumentIndex: number; argumentCount: number; @@ -1257,7 +1265,7 @@ export interface CompletionInfo { * this span or its default one. If `CompletionEntry["replacementSpan"]` is defined, that span * must be used to commit that completion entry. */ - optionalReplacementSpan?: ts.TextSpan; + optionalReplacementSpan?: TextSpan; /** * true when the current location also allows for a new identifier */ @@ -1308,7 +1316,7 @@ export interface CompletionEntry { * If present, this span should be used instead of the default one. * It will be set if the required span differs from the one generated by the default replacement behavior. */ - replacementSpan?: ts.TextSpan; + replacementSpan?: TextSpan; hasAction?: true; source?: string; sourceDisplay?: SymbolDisplayPart[]; @@ -1348,10 +1356,10 @@ export interface CompletionEntryDetails { export interface OutliningSpan { /** The span of the document to actually collapse. */ - textSpan: ts.TextSpan; + textSpan: TextSpan; /** The span of the document to display when the user hovers over the collapsed span. */ - hintSpan: ts.TextSpan; + hintSpan: TextSpan; /** The text to display in the editor for the collapsed region. */ bannerText: string; @@ -1655,11 +1663,11 @@ export interface CodeFixRegistration { } /** @internal */ -export interface CodeFixContextBase extends ts.textChanges.TextChangesContext { - sourceFile: ts.SourceFile; - program: ts.Program; - cancellationToken: ts.CancellationToken; - preferences: ts.UserPreferences; +export interface CodeFixContextBase extends textChanges.TextChangesContext { + sourceFile: SourceFile; + program: Program; + cancellationToken: CancellationToken; + preferences: UserPreferences; } /** @internal */ @@ -1670,7 +1678,7 @@ export interface CodeFixAllContext extends CodeFixContextBase { /** @internal */ export interface CodeFixContext extends CodeFixContextBase { errorCode: number; - span: ts.TextSpan; + span: TextSpan; } /** @internal */ @@ -1687,22 +1695,22 @@ export interface Refactor { } /** @internal */ -export interface RefactorContext extends ts.textChanges.TextChangesContext { - file: ts.SourceFile; +export interface RefactorContext extends textChanges.TextChangesContext { + file: SourceFile; startPosition: number; endPosition?: number; - program: ts.Program; - cancellationToken?: ts.CancellationToken; - preferences: ts.UserPreferences; + program: Program; + cancellationToken?: CancellationToken; + preferences: UserPreferences; triggerReason?: RefactorTriggerReason; kind?: string; } export interface InlayHintsContext { - file: ts.SourceFile; - program: ts.Program; - cancellationToken: ts.CancellationToken; + file: SourceFile; + program: Program; + cancellationToken: CancellationToken; host: LanguageServiceHost; - span: ts.TextSpan; - preferences: ts.UserPreferences; + span: TextSpan; + preferences: UserPreferences; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 761096a4ee688..5d23a2c4611f8 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1,4 +1,64 @@ -import * as ts from "./_namespaces/ts"; +import { + __String, addEmitFlags, addSyntheticLeadingComment, addSyntheticTrailingComment, AnyImportOrRequireStatement, + assertType, AssignmentDeclarationKind, BinaryExpression, binarySearchKey, BindingElement, BreakOrContinueStatement, + CallExpression, canHaveModifiers, CaseClause, cast, CatchClause, CharacterCodes, ClassDeclaration, ClassExpression, + clone, codefix, combinePaths, CommentKind, CommentRange, compareTextSpans, compareValues, Comparison, + CompilerOptions, ConditionalExpression, contains, createPrinter, createRange, createScanner, createTextSpan, + createTextSpanFromBounds, Debug, Declaration, Decorator, defaultMaximumTruncationLength, DeleteExpression, + Diagnostic, DiagnosticMessage, DiagnosticWithLocation, directoryProbablyExists, DisplayPartsSymbolWriter, + DocumentPosition, DocumentSpan, DoStatement, ElementAccessExpression, EmitFlags, EmitHint, emptyArray, + EndOfFileToken, ensureScriptKind, EqualityOperator, escapeString, ExportAssignment, ExportDeclaration, Expression, + ExpressionStatement, factory, FileTextChanges, filter, find, findAncestor, findConfigFile, first, firstDefined, + firstOrUndefined, forEachAncestorDirectory, forEachChild, forEachLeadingCommentRange, forEachTrailingCommentRange, + FormatCodeSettings, formatStringFromArgs, formatting, FormattingHost, ForOfStatement, FunctionDeclaration, + FunctionExpression, FunctionLikeDeclaration, getAssignmentDeclarationKind, getCombinedNodeFlagsAlwaysIncludeJSDoc, + getDirectoryPath, getEmitScriptTarget, getExternalModuleImportEqualsDeclarationExpression, getIndentString, + getJSDocEnumTag, getLastChild, getLineAndCharacterOfPosition, getLineStarts, getLocaleSpecificMessage, + getModuleInstanceState, getNameOfDeclaration, getNodeId, getPackageNameFromTypesPackageName, getPathComponents, + getRootDeclaration, getSourceFileOfNode, getSpanOfTokenAtPosition, getSymbolId, getTextOfIdentifierOrLiteral, + getTextOfNode, getTypesPackageName, hasSyntacticModifier, HeritageClause, Identifier, identifierIsThisKeyword, + identity, idText, IfStatement, ImportClause, ImportDeclaration, ImportSpecifier, ImportTypeNode, indexOfNode, + IndexSignatureDeclaration, InternalSymbolName, isAmbientModule, isAnyImportSyntax, isArray, isArrayBindingPattern, + isArrayTypeNode, isAsExpression, isAwaitExpression, isBinaryExpression, isBindingElement, + isBreakOrContinueStatement, isCallExpression, isCallOrNewExpression, isClassDeclaration, isClassExpression, + isClassStaticBlockDeclaration, isConditionalTypeNode, IScriptSnapshot, isDeclaration, isDeclarationName, + isDecorator, isDeleteExpression, isElementAccessExpression, isEntityName, isEnumDeclaration, isExportAssignment, + isExportDeclaration, isExportSpecifier, isExpression, isExpressionNode, isExternalModule, + isExternalModuleImportEqualsDeclaration, isExternalModuleReference, isFileLevelUniqueName, isForInStatement, + isForOfStatement, isFunctionBlock, isFunctionDeclaration, isFunctionExpression, isFunctionLike, + isGetAccessorDeclaration, isGlobalScopeAugmentation, isHeritageClause, isIdentifier, isImportCall, isImportClause, + isImportDeclaration, isImportEqualsDeclaration, isImportOrExportSpecifier, isImportSpecifier, isInferTypeNode, + isInJSFile, isInterfaceDeclaration, isInternalModuleImportEqualsDeclaration, isJSDoc, isJSDocCommentContainingNode, + isJSDocLink, isJSDocLinkCode, isJSDocLinkLike, isJSDocMemberName, isJSDocNameReference, isJSDocTag, + isJSDocTemplateTag, isJSDocTypeAlias, isJsxElement, isJsxExpression, isJsxOpeningLikeElement, isJsxText, isKeyword, + isLabeledStatement, isLet, isLiteralTypeNode, isMappedTypeNode, isModifier, isModuleBlock, isModuleDeclaration, + isNamedDeclaration, isNamedExports, isNamedImports, isNamespaceExport, isNamespaceImport, isNewExpression, + isNumericLiteral, isObjectBindingPattern, isObjectLiteralExpression, isOptionalChain, isOptionalChainRoot, + isParameter, isPartOfTypeNode, isPrivateIdentifier, isPropertyAccessExpression, isPropertyNameLiteral, + isQualifiedName, isRequireCall, isRequireVariableStatement, isRightSideOfQualifiedNameOrPropertyAccess, + isRootedDiskPath, isSetAccessorDeclaration, isSourceFile, isSourceFileJS, isStringDoubleQuoted, isStringLiteral, + isStringLiteralLike, isStringOrNumericLiteralLike, isStringTextContainingNode, isSyntaxList, + isTaggedTemplateExpression, isTemplateLiteralKind, isToken, isTypeAliasDeclaration, isTypeElement, isTypeNode, + isTypeOfExpression, isTypeOperatorNode, isTypeParameterDeclaration, isTypeReferenceNode, isVarConst, + isVariableDeclarationList, isVoidExpression, isWhiteSpaceLike, isWhiteSpaceSingleLine, isYieldExpression, + IterationStatement, JSDocLink, JSDocLinkCode, JSDocLinkDisplayPart, JSDocLinkPlain, JSDocTypedefTag, JsTyping, + JsxEmit, JsxOpeningLikeElement, LabeledStatement, LanguageServiceHost, last, lastOrUndefined, LiteralExpression, + map, Map, maybeBind, Modifier, ModifierFlags, ModuleDeclaration, ModuleInstanceState, ModuleResolutionKind, + ModuleSpecifierResolutionHost, moduleSpecifiers, Mutable, NewExpression, NewLineKind, Node, NodeArray, + NodeBuilderFlags, NodeFlags, nodeIsMissing, nodeIsPresent, nodeIsSynthesized, noop, normalizePath, + NoSubstitutionTemplateLiteral, notImplemented, nullTransformationContext, NumericLiteral, or, OrganizeImports, + PackageJsonDependencyGroup, pathIsRelative, PrefixUnaryExpression, Program, ProjectPackageJsonInfo, + PropertyAccessExpression, PropertyAssignment, PropertyName, QualifiedName, RefactorContext, Scanner, + ScriptElementKind, ScriptElementKindModifier, ScriptKind, ScriptTarget, SemicolonPreference, setConfigFileInOptions, + setOriginalNode, setTextRange, Signature, SignatureDeclaration, singleOrUndefined, skipAlias, skipOuterExpressions, + some, SourceFile, SourceFileLike, SourceMapper, SpreadElement, stableSort, startsWith, stringContains, + StringLiteral, StringLiteralLike, stringToToken, stripQuotes, Symbol, SymbolAccessibility, SymbolDisplayPart, + SymbolDisplayPartKind, SymbolFlags, SymbolFormatFlags, SymbolTracker, SyntaxKind, SyntaxList, + TaggedTemplateExpression, TemplateExpression, TemplateLiteralToken, TemplateSpan, TextChange, textChanges, + TextRange, TextSpan, textSpanContainsPosition, textSpanContainsTextSpan, textSpanEnd, Token, tokenToString, + TransientSymbol, tryCast, Type, TypeChecker, TypeFormatFlags, TypeNode, TypeOfExpression, TypeQueryNode, + unescapeLeadingUnderscores, UserPreferences, VariableDeclaration, visitEachChild, VoidExpression, YieldExpression, +} from "./_namespaces/ts"; /* @internal */ // Don't expose that we use this // Based on lib.es6.d.ts @@ -21,7 +81,7 @@ declare global { // These utilities are common to multiple language service features. //#region /** @internal */ -export const scanner: ts.Scanner = ts.createScanner(ts.ScriptTarget.Latest, /*skipTrivia*/ true); +export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true); /** @internal */ export const enum SemanticMeaning { @@ -33,65 +93,65 @@ export const enum SemanticMeaning { } /** @internal */ -export function getMeaningFromDeclaration(node: ts.Node): SemanticMeaning { +export function getMeaningFromDeclaration(node: Node): SemanticMeaning { switch (node.kind) { - case ts.SyntaxKind.VariableDeclaration: - return ts.isInJSFile(node) && ts.getJSDocEnumTag(node) ? SemanticMeaning.All : SemanticMeaning.Value; - - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.BindingElement: - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.CatchClause: - case ts.SyntaxKind.JsxAttribute: + case SyntaxKind.VariableDeclaration: + return isInJSFile(node) && getJSDocEnumTag(node) ? SemanticMeaning.All : SemanticMeaning.Value; + + case SyntaxKind.Parameter: + case SyntaxKind.BindingElement: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.CatchClause: + case SyntaxKind.JsxAttribute: return SemanticMeaning.Value; - case ts.SyntaxKind.TypeParameter: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.TypeLiteral: + case SyntaxKind.TypeParameter: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeLiteral: return SemanticMeaning.Type; - case ts.SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocTypedefTag: // If it has no name node, it shares the name with the value declaration below it. - return (node as ts.JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type : SemanticMeaning.Type; + return (node as JSDocTypedefTag).name === undefined ? SemanticMeaning.Value | SemanticMeaning.Type : SemanticMeaning.Type; - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.ClassDeclaration: return SemanticMeaning.Value | SemanticMeaning.Type; - case ts.SyntaxKind.ModuleDeclaration: - if (ts.isAmbientModule(node as ts.ModuleDeclaration)) { + case SyntaxKind.ModuleDeclaration: + if (isAmbientModule(node as ModuleDeclaration)) { return SemanticMeaning.Namespace | SemanticMeaning.Value; } - else if (ts.getModuleInstanceState(node as ts.ModuleDeclaration) === ts.ModuleInstanceState.Instantiated) { + else if (getModuleInstanceState(node as ModuleDeclaration) === ModuleInstanceState.Instantiated) { return SemanticMeaning.Namespace | SemanticMeaning.Value; } else { return SemanticMeaning.Namespace; } - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportAssignment: - case ts.SyntaxKind.ExportDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.NamedImports: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: return SemanticMeaning.All; // An external module can be a Value - case ts.SyntaxKind.SourceFile: + case SyntaxKind.SourceFile: return SemanticMeaning.Namespace | SemanticMeaning.Value; } @@ -99,27 +159,27 @@ export function getMeaningFromDeclaration(node: ts.Node): SemanticMeaning { } /** @internal */ -export function getMeaningFromLocation(node: ts.Node): SemanticMeaning { +export function getMeaningFromLocation(node: Node): SemanticMeaning { node = getAdjustedReferenceLocation(node); const parent = node.parent; - if (node.kind === ts.SyntaxKind.SourceFile) { + if (node.kind === SyntaxKind.SourceFile) { return SemanticMeaning.Value; } - else if (ts.isExportAssignment(parent) - || ts.isExportSpecifier(parent) - || ts.isExternalModuleReference(parent) - || ts.isImportSpecifier(parent) - || ts.isImportClause(parent) - || ts.isImportEqualsDeclaration(parent) && node === parent.name) { + else if (isExportAssignment(parent) + || isExportSpecifier(parent) + || isExternalModuleReference(parent) + || isImportSpecifier(parent) + || isImportClause(parent) + || isImportEqualsDeclaration(parent) && node === parent.name) { return SemanticMeaning.All; } else if (isInRightSideOfInternalImportEqualsDeclaration(node)) { - return getMeaningFromRightHandSideOfImportEquals(node as ts.Identifier); + return getMeaningFromRightHandSideOfImportEquals(node as Identifier); } - else if (ts.isDeclarationName(node)) { + else if (isDeclarationName(node)) { return getMeaningFromDeclaration(parent); } - else if (ts.isEntityName(node) && ts.findAncestor(node, ts.or(ts.isJSDocNameReference, ts.isJSDocLinkLike, ts.isJSDocMemberName))) { + else if (isEntityName(node) && findAncestor(node, or(isJSDocNameReference, isJSDocLinkLike, isJSDocMemberName))) { return SemanticMeaning.All; } else if (isTypeReference(node)) { @@ -128,11 +188,11 @@ export function getMeaningFromLocation(node: ts.Node): SemanticMeaning { else if (isNamespaceReference(node)) { return SemanticMeaning.Namespace; } - else if (ts.isTypeParameterDeclaration(parent)) { - ts.Debug.assert(ts.isJSDocTemplateTag(parent.parent)); // Else would be handled by isDeclarationName + else if (isTypeParameterDeclaration(parent)) { + Debug.assert(isJSDocTemplateTag(parent.parent)); // Else would be handled by isDeclarationName return SemanticMeaning.Type; } - else if (ts.isLiteralTypeNode(parent)) { + else if (isLiteralTypeNode(parent)) { // This might be T["name"], which is actually referencing a property and not a type. So allow both meanings. return SemanticMeaning.Type | SemanticMeaning.Value; } @@ -141,149 +201,149 @@ export function getMeaningFromLocation(node: ts.Node): SemanticMeaning { } } -function getMeaningFromRightHandSideOfImportEquals(node: ts.Node): SemanticMeaning { +function getMeaningFromRightHandSideOfImportEquals(node: Node): SemanticMeaning { // import a = |b|; // Namespace // import a = |b.c|; // Value, type, namespace // import a = |b.c|.d; // Namespace - const name = node.kind === ts.SyntaxKind.QualifiedName ? node : ts.isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; - return name && name.parent.kind === ts.SyntaxKind.ImportEqualsDeclaration ? SemanticMeaning.All : SemanticMeaning.Namespace; + const name = node.kind === SyntaxKind.QualifiedName ? node : isQualifiedName(node.parent) && node.parent.right === node ? node.parent : undefined; + return name && name.parent.kind === SyntaxKind.ImportEqualsDeclaration ? SemanticMeaning.All : SemanticMeaning.Namespace; } /** @internal */ -export function isInRightSideOfInternalImportEqualsDeclaration(node: ts.Node) { - while (node.parent.kind === ts.SyntaxKind.QualifiedName) { +export function isInRightSideOfInternalImportEqualsDeclaration(node: Node) { + while (node.parent.kind === SyntaxKind.QualifiedName) { node = node.parent; } - return ts.isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; + return isInternalModuleImportEqualsDeclaration(node.parent) && node.parent.moduleReference === node; } -function isNamespaceReference(node: ts.Node): boolean { +function isNamespaceReference(node: Node): boolean { return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node); } -function isQualifiedNameNamespaceReference(node: ts.Node): boolean { +function isQualifiedNameNamespaceReference(node: Node): boolean { let root = node; let isLastClause = true; - if (root.parent.kind === ts.SyntaxKind.QualifiedName) { - while (root.parent && root.parent.kind === ts.SyntaxKind.QualifiedName) { + if (root.parent.kind === SyntaxKind.QualifiedName) { + while (root.parent && root.parent.kind === SyntaxKind.QualifiedName) { root = root.parent; } - isLastClause = (root as ts.QualifiedName).right === node; + isLastClause = (root as QualifiedName).right === node; } - return root.parent.kind === ts.SyntaxKind.TypeReference && !isLastClause; + return root.parent.kind === SyntaxKind.TypeReference && !isLastClause; } -function isPropertyAccessNamespaceReference(node: ts.Node): boolean { +function isPropertyAccessNamespaceReference(node: Node): boolean { let root = node; let isLastClause = true; - if (root.parent.kind === ts.SyntaxKind.PropertyAccessExpression) { - while (root.parent && root.parent.kind === ts.SyntaxKind.PropertyAccessExpression) { + if (root.parent.kind === SyntaxKind.PropertyAccessExpression) { + while (root.parent && root.parent.kind === SyntaxKind.PropertyAccessExpression) { root = root.parent; } - isLastClause = (root as ts.PropertyAccessExpression).name === node; + isLastClause = (root as PropertyAccessExpression).name === node; } - if (!isLastClause && root.parent.kind === ts.SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === ts.SyntaxKind.HeritageClause) { + if (!isLastClause && root.parent.kind === SyntaxKind.ExpressionWithTypeArguments && root.parent.parent.kind === SyntaxKind.HeritageClause) { const decl = root.parent.parent.parent; - return (decl.kind === ts.SyntaxKind.ClassDeclaration && (root.parent.parent as ts.HeritageClause).token === ts.SyntaxKind.ImplementsKeyword) || - (decl.kind === ts.SyntaxKind.InterfaceDeclaration && (root.parent.parent as ts.HeritageClause).token === ts.SyntaxKind.ExtendsKeyword); + return (decl.kind === SyntaxKind.ClassDeclaration && (root.parent.parent as HeritageClause).token === SyntaxKind.ImplementsKeyword) || + (decl.kind === SyntaxKind.InterfaceDeclaration && (root.parent.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword); } return false; } -function isTypeReference(node: ts.Node): boolean { - if (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) { +function isTypeReference(node: Node): boolean { + if (isRightSideOfQualifiedNameOrPropertyAccess(node)) { node = node.parent; } switch (node.kind) { - case ts.SyntaxKind.ThisKeyword: - return !ts.isExpressionNode(node); - case ts.SyntaxKind.ThisType: + case SyntaxKind.ThisKeyword: + return !isExpressionNode(node); + case SyntaxKind.ThisType: return true; } switch (node.parent.kind) { - case ts.SyntaxKind.TypeReference: + case SyntaxKind.TypeReference: return true; - case ts.SyntaxKind.ImportType: - return !(node.parent as ts.ImportTypeNode).isTypeOf; - case ts.SyntaxKind.ExpressionWithTypeArguments: - return ts.isPartOfTypeNode(node.parent); + case SyntaxKind.ImportType: + return !(node.parent as ImportTypeNode).isTypeOf; + case SyntaxKind.ExpressionWithTypeArguments: + return isPartOfTypeNode(node.parent); } return false; } /** @internal */ -export function isCallExpressionTarget(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isCallExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isCallExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isCallExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); } /** @internal */ -export function isNewExpressionTarget(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isNewExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); } /** @internal */ -export function isCallOrNewExpressionTarget(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isCallOrNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isCallOrNewExpressionTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isCallOrNewExpression, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); } /** @internal */ -export function isTaggedTemplateTag(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isTaggedTemplateExpression, selectTagOfTaggedTemplateExpression, includeElementAccess, skipPastOuterExpressions); +export function isTaggedTemplateTag(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isTaggedTemplateExpression, selectTagOfTaggedTemplateExpression, includeElementAccess, skipPastOuterExpressions); } /** @internal */ -export function isDecoratorTarget(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isDecorator, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); +export function isDecoratorTarget(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isDecorator, selectExpressionOfCallOrNewExpressionOrDecorator, includeElementAccess, skipPastOuterExpressions); } /** @internal */ -export function isJsxOpeningLikeElementTagName(node: ts.Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { - return isCalleeWorker(node, ts.isJsxOpeningLikeElement, selectTagNameOfJsxOpeningLikeElement, includeElementAccess, skipPastOuterExpressions); +export function isJsxOpeningLikeElementTagName(node: Node, includeElementAccess = false, skipPastOuterExpressions = false): boolean { + return isCalleeWorker(node, isJsxOpeningLikeElement, selectTagNameOfJsxOpeningLikeElement, includeElementAccess, skipPastOuterExpressions); } -function selectExpressionOfCallOrNewExpressionOrDecorator(node: ts.CallExpression | ts.NewExpression | ts.Decorator) { +function selectExpressionOfCallOrNewExpressionOrDecorator(node: CallExpression | NewExpression | Decorator) { return node.expression; } -function selectTagOfTaggedTemplateExpression(node: ts.TaggedTemplateExpression) { +function selectTagOfTaggedTemplateExpression(node: TaggedTemplateExpression) { return node.tag; } -function selectTagNameOfJsxOpeningLikeElement(node: ts.JsxOpeningLikeElement) { +function selectTagNameOfJsxOpeningLikeElement(node: JsxOpeningLikeElement) { return node.tagName; } -function isCalleeWorker(node: ts.Node, pred: (node: ts.Node) => node is T, calleeSelector: (node: T) => ts.Expression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) { +function isCalleeWorker(node: Node, pred: (node: Node) => node is T, calleeSelector: (node: T) => Expression, includeElementAccess: boolean, skipPastOuterExpressions: boolean) { let target = includeElementAccess ? climbPastPropertyOrElementAccess(node) : climbPastPropertyAccess(node); if (skipPastOuterExpressions) { - target = ts.skipOuterExpressions(target); + target = skipOuterExpressions(target); } return !!target && !!target.parent && pred(target.parent) && calleeSelector(target.parent) === target; } /** @internal */ -export function climbPastPropertyAccess(node: ts.Node) { +export function climbPastPropertyAccess(node: Node) { return isRightSideOfPropertyAccess(node) ? node.parent : node; } /** @internal */ -export function climbPastPropertyOrElementAccess(node: ts.Node) { +export function climbPastPropertyOrElementAccess(node: Node) { return isRightSideOfPropertyAccess(node) || isArgumentExpressionOfElementAccess(node) ? node.parent : node; } /** @internal */ -export function getTargetLabel(referenceNode: ts.Node, labelName: string): ts.Identifier | undefined { +export function getTargetLabel(referenceNode: Node, labelName: string): Identifier | undefined { while (referenceNode) { - if (referenceNode.kind === ts.SyntaxKind.LabeledStatement && (referenceNode as ts.LabeledStatement).label.escapedText === labelName) { - return (referenceNode as ts.LabeledStatement).label; + if (referenceNode.kind === SyntaxKind.LabeledStatement && (referenceNode as LabeledStatement).label.escapedText === labelName) { + return (referenceNode as LabeledStatement).label; } referenceNode = referenceNode.parent; } @@ -291,8 +351,8 @@ export function getTargetLabel(referenceNode: ts.Node, labelName: string): ts.Id } /** @internal */ -export function hasPropertyAccessExpressionWithName(node: ts.CallExpression, funcName: string): boolean { - if (!ts.isPropertyAccessExpression(node.expression)) { +export function hasPropertyAccessExpressionWithName(node: CallExpression, funcName: string): boolean { + if (!isPropertyAccessExpression(node.expression)) { return false; } @@ -300,83 +360,83 @@ export function hasPropertyAccessExpressionWithName(node: ts.CallExpression, fun } /** @internal */ -export function isJumpStatementTarget(node: ts.Node): node is ts.Identifier & { parent: ts.BreakOrContinueStatement } { - return ts.isIdentifier(node) && ts.tryCast(node.parent, ts.isBreakOrContinueStatement)?.label === node; +export function isJumpStatementTarget(node: Node): node is Identifier & { parent: BreakOrContinueStatement } { + return isIdentifier(node) && tryCast(node.parent, isBreakOrContinueStatement)?.label === node; } /** @internal */ -export function isLabelOfLabeledStatement(node: ts.Node): node is ts.Identifier { - return ts.isIdentifier(node) && ts.tryCast(node.parent, ts.isLabeledStatement)?.label === node; +export function isLabelOfLabeledStatement(node: Node): node is Identifier { + return isIdentifier(node) && tryCast(node.parent, isLabeledStatement)?.label === node; } /** @internal */ -export function isLabelName(node: ts.Node): boolean { +export function isLabelName(node: Node): boolean { return isLabelOfLabeledStatement(node) || isJumpStatementTarget(node); } /** @internal */ -export function isTagName(node: ts.Node): boolean { - return ts.tryCast(node.parent, ts.isJSDocTag)?.tagName === node; +export function isTagName(node: Node): boolean { + return tryCast(node.parent, isJSDocTag)?.tagName === node; } /** @internal */ -export function isRightSideOfQualifiedName(node: ts.Node) { - return ts.tryCast(node.parent, ts.isQualifiedName)?.right === node; +export function isRightSideOfQualifiedName(node: Node) { + return tryCast(node.parent, isQualifiedName)?.right === node; } /** @internal */ -export function isRightSideOfPropertyAccess(node: ts.Node) { - return ts.tryCast(node.parent, ts.isPropertyAccessExpression)?.name === node; +export function isRightSideOfPropertyAccess(node: Node) { + return tryCast(node.parent, isPropertyAccessExpression)?.name === node; } /** @internal */ -export function isArgumentExpressionOfElementAccess(node: ts.Node) { - return ts.tryCast(node.parent, ts.isElementAccessExpression)?.argumentExpression === node; +export function isArgumentExpressionOfElementAccess(node: Node) { + return tryCast(node.parent, isElementAccessExpression)?.argumentExpression === node; } /** @internal */ -export function isNameOfModuleDeclaration(node: ts.Node) { - return ts.tryCast(node.parent, ts.isModuleDeclaration)?.name === node; +export function isNameOfModuleDeclaration(node: Node) { + return tryCast(node.parent, isModuleDeclaration)?.name === node; } /** @internal */ -export function isNameOfFunctionDeclaration(node: ts.Node): boolean { - return ts.isIdentifier(node) && ts.tryCast(node.parent, ts.isFunctionLike)?.name === node; +export function isNameOfFunctionDeclaration(node: Node): boolean { + return isIdentifier(node) && tryCast(node.parent, isFunctionLike)?.name === node; } /** @internal */ -export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: ts.StringLiteral | ts.NumericLiteral | ts.NoSubstitutionTemplateLiteral): boolean { +export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: StringLiteral | NumericLiteral | NoSubstitutionTemplateLiteral): boolean { switch (node.parent.kind) { - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.PropertyAssignment: - case ts.SyntaxKind.EnumMember: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.ModuleDeclaration: - return ts.getNameOfDeclaration(node.parent as ts.Declaration) === node; - case ts.SyntaxKind.ElementAccessExpression: - return (node.parent as ts.ElementAccessExpression).argumentExpression === node; - case ts.SyntaxKind.ComputedPropertyName: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.EnumMember: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.ModuleDeclaration: + return getNameOfDeclaration(node.parent as Declaration) === node; + case SyntaxKind.ElementAccessExpression: + return (node.parent as ElementAccessExpression).argumentExpression === node; + case SyntaxKind.ComputedPropertyName: return true; - case ts.SyntaxKind.LiteralType: - return node.parent.parent.kind === ts.SyntaxKind.IndexedAccessType; + case SyntaxKind.LiteralType: + return node.parent.parent.kind === SyntaxKind.IndexedAccessType; default: return false; } } /** @internal */ -export function isExpressionOfExternalModuleImportEqualsDeclaration(node: ts.Node) { - return ts.isExternalModuleImportEqualsDeclaration(node.parent.parent) && - ts.getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; +export function isExpressionOfExternalModuleImportEqualsDeclaration(node: Node) { + return isExternalModuleImportEqualsDeclaration(node.parent.parent) && + getExternalModuleImportEqualsDeclarationExpression(node.parent.parent) === node; } /** @internal */ -export function getContainerNode(node: ts.Node): ts.Declaration | undefined { - if (ts.isJSDocTypeAlias(node)) { +export function getContainerNode(node: Node): Declaration | undefined { + if (isJSDocTypeAlias(node)) { // This doesn't just apply to the node immediately under the comment, but to everything in its parent's scope. // node.parent = the JSDoc comment, node.parent.parent = the node having the comment. // Then we get parent again in the loop. @@ -389,129 +449,129 @@ export function getContainerNode(node: ts.Node): ts.Declaration | undefined { return undefined; } switch (node.kind) { - case ts.SyntaxKind.SourceFile: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - return node as ts.Declaration; + case SyntaxKind.SourceFile: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + return node as Declaration; } } } /** @internal */ -export function getNodeKind(node: ts.Node): ts.ScriptElementKind { +export function getNodeKind(node: Node): ScriptElementKind { switch (node.kind) { - case ts.SyntaxKind.SourceFile: - return ts.isExternalModule(node as ts.SourceFile) ? ts.ScriptElementKind.moduleElement : ts.ScriptElementKind.scriptElement; - case ts.SyntaxKind.ModuleDeclaration: - return ts.ScriptElementKind.moduleElement; - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - return ts.ScriptElementKind.classElement; - case ts.SyntaxKind.InterfaceDeclaration: return ts.ScriptElementKind.interfaceElement; - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.JSDocCallbackTag: - case ts.SyntaxKind.JSDocTypedefTag: - return ts.ScriptElementKind.typeElement; - case ts.SyntaxKind.EnumDeclaration: return ts.ScriptElementKind.enumElement; - case ts.SyntaxKind.VariableDeclaration: - return getKindOfVariableDeclaration(node as ts.VariableDeclaration); - case ts.SyntaxKind.BindingElement: - return getKindOfVariableDeclaration(ts.getRootDeclaration(node) as ts.VariableDeclaration); - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - return ts.ScriptElementKind.functionElement; - case ts.SyntaxKind.GetAccessor: return ts.ScriptElementKind.memberGetAccessorElement; - case ts.SyntaxKind.SetAccessor: return ts.ScriptElementKind.memberSetAccessorElement; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - return ts.ScriptElementKind.memberFunctionElement; - case ts.SyntaxKind.PropertyAssignment: - const { initializer } = node as ts.PropertyAssignment; - return ts.isFunctionLike(initializer) ? ts.ScriptElementKind.memberFunctionElement : ts.ScriptElementKind.memberVariableElement; - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - case ts.SyntaxKind.ShorthandPropertyAssignment: - case ts.SyntaxKind.SpreadAssignment: - return ts.ScriptElementKind.memberVariableElement; - case ts.SyntaxKind.IndexSignature: return ts.ScriptElementKind.indexSignatureElement; - case ts.SyntaxKind.ConstructSignature: return ts.ScriptElementKind.constructSignatureElement; - case ts.SyntaxKind.CallSignature: return ts.ScriptElementKind.callSignatureElement; - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ClassStaticBlockDeclaration: - return ts.ScriptElementKind.constructorImplementationElement; - case ts.SyntaxKind.TypeParameter: return ts.ScriptElementKind.typeParameterElement; - case ts.SyntaxKind.EnumMember: return ts.ScriptElementKind.enumMemberElement; - case ts.SyntaxKind.Parameter: return ts.hasSyntacticModifier(node, ts.ModifierFlags.ParameterPropertyModifier) ? ts.ScriptElementKind.memberVariableElement : ts.ScriptElementKind.parameterElement; - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.ImportSpecifier: - case ts.SyntaxKind.ExportSpecifier: - case ts.SyntaxKind.NamespaceImport: - case ts.SyntaxKind.NamespaceExport: - return ts.ScriptElementKind.alias; - case ts.SyntaxKind.BinaryExpression: - const kind = ts.getAssignmentDeclarationKind(node as ts.BinaryExpression); - const { right } = node as ts.BinaryExpression; + case SyntaxKind.SourceFile: + return isExternalModule(node as SourceFile) ? ScriptElementKind.moduleElement : ScriptElementKind.scriptElement; + case SyntaxKind.ModuleDeclaration: + return ScriptElementKind.moduleElement; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return ScriptElementKind.classElement; + case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement; + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocTypedefTag: + return ScriptElementKind.typeElement; + case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement; + case SyntaxKind.VariableDeclaration: + return getKindOfVariableDeclaration(node as VariableDeclaration); + case SyntaxKind.BindingElement: + return getKindOfVariableDeclaration(getRootDeclaration(node) as VariableDeclaration); + case SyntaxKind.ArrowFunction: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + return ScriptElementKind.functionElement; + case SyntaxKind.GetAccessor: return ScriptElementKind.memberGetAccessorElement; + case SyntaxKind.SetAccessor: return ScriptElementKind.memberSetAccessorElement; + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + return ScriptElementKind.memberFunctionElement; + case SyntaxKind.PropertyAssignment: + const { initializer } = node as PropertyAssignment; + return isFunctionLike(initializer) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SpreadAssignment: + return ScriptElementKind.memberVariableElement; + case SyntaxKind.IndexSignature: return ScriptElementKind.indexSignatureElement; + case SyntaxKind.ConstructSignature: return ScriptElementKind.constructSignatureElement; + case SyntaxKind.CallSignature: return ScriptElementKind.callSignatureElement; + case SyntaxKind.Constructor: + case SyntaxKind.ClassStaticBlockDeclaration: + return ScriptElementKind.constructorImplementationElement; + case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement; + case SyntaxKind.EnumMember: return ScriptElementKind.enumMemberElement; + case SyntaxKind.Parameter: return hasSyntacticModifier(node, ModifierFlags.ParameterPropertyModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement; + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.NamespaceImport: + case SyntaxKind.NamespaceExport: + return ScriptElementKind.alias; + case SyntaxKind.BinaryExpression: + const kind = getAssignmentDeclarationKind(node as BinaryExpression); + const { right } = node as BinaryExpression; switch (kind) { - case ts.AssignmentDeclarationKind.ObjectDefinePropertyValue: - case ts.AssignmentDeclarationKind.ObjectDefinePropertyExports: - case ts.AssignmentDeclarationKind.ObjectDefinePrototypeProperty: - case ts.AssignmentDeclarationKind.None: - return ts.ScriptElementKind.unknown; - case ts.AssignmentDeclarationKind.ExportsProperty: - case ts.AssignmentDeclarationKind.ModuleExports: + case AssignmentDeclarationKind.ObjectDefinePropertyValue: + case AssignmentDeclarationKind.ObjectDefinePropertyExports: + case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: + case AssignmentDeclarationKind.None: + return ScriptElementKind.unknown; + case AssignmentDeclarationKind.ExportsProperty: + case AssignmentDeclarationKind.ModuleExports: const rightKind = getNodeKind(right); - return rightKind === ts.ScriptElementKind.unknown ? ts.ScriptElementKind.constElement : rightKind; - case ts.AssignmentDeclarationKind.PrototypeProperty: - return ts.isFunctionExpression(right) ? ts.ScriptElementKind.memberFunctionElement : ts.ScriptElementKind.memberVariableElement; - case ts.AssignmentDeclarationKind.ThisProperty: - return ts.ScriptElementKind.memberVariableElement; // property - case ts.AssignmentDeclarationKind.Property: + return rightKind === ScriptElementKind.unknown ? ScriptElementKind.constElement : rightKind; + case AssignmentDeclarationKind.PrototypeProperty: + return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + case AssignmentDeclarationKind.ThisProperty: + return ScriptElementKind.memberVariableElement; // property + case AssignmentDeclarationKind.Property: // static method / property - return ts.isFunctionExpression(right) ? ts.ScriptElementKind.memberFunctionElement : ts.ScriptElementKind.memberVariableElement; - case ts.AssignmentDeclarationKind.Prototype: - return ts.ScriptElementKind.localClassElement; + return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + case AssignmentDeclarationKind.Prototype: + return ScriptElementKind.localClassElement; default: { - ts.assertType(kind); - return ts.ScriptElementKind.unknown; + assertType(kind); + return ScriptElementKind.unknown; } } - case ts.SyntaxKind.Identifier: - return ts.isImportClause(node.parent) ? ts.ScriptElementKind.alias : ts.ScriptElementKind.unknown; - case ts.SyntaxKind.ExportAssignment: - const scriptKind = getNodeKind((node as ts.ExportAssignment).expression); + case SyntaxKind.Identifier: + return isImportClause(node.parent) ? ScriptElementKind.alias : ScriptElementKind.unknown; + case SyntaxKind.ExportAssignment: + const scriptKind = getNodeKind((node as ExportAssignment).expression); // If the expression didn't come back with something (like it does for an identifiers) - return scriptKind === ts.ScriptElementKind.unknown ? ts.ScriptElementKind.constElement : scriptKind; + return scriptKind === ScriptElementKind.unknown ? ScriptElementKind.constElement : scriptKind; default: - return ts.ScriptElementKind.unknown; + return ScriptElementKind.unknown; } - function getKindOfVariableDeclaration(v: ts.VariableDeclaration): ts.ScriptElementKind { - return ts.isVarConst(v) - ? ts.ScriptElementKind.constElement - : ts.isLet(v) - ? ts.ScriptElementKind.letElement - : ts.ScriptElementKind.variableElement; + function getKindOfVariableDeclaration(v: VariableDeclaration): ScriptElementKind { + return isVarConst(v) + ? ScriptElementKind.constElement + : isLet(v) + ? ScriptElementKind.letElement + : ScriptElementKind.variableElement; } } /** @internal */ -export function isThis(node: ts.Node): boolean { +export function isThis(node: Node): boolean { switch (node.kind) { - case ts.SyntaxKind.ThisKeyword: + case SyntaxKind.ThisKeyword: // case SyntaxKind.ThisType: TODO: GH#9267 return true; - case ts.SyntaxKind.Identifier: + case SyntaxKind.Identifier: // 'this' as a parameter - return ts.identifierIsThisKeyword(node as ts.Identifier) && node.parent.kind === ts.SyntaxKind.Parameter; + return identifierIsThisKeyword(node as Identifier) && node.parent.kind === SyntaxKind.Parameter; default: return false; } @@ -523,53 +583,53 @@ const tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= range.end; } /** @internal */ -export function rangeContainsStartEnd(range: ts.TextRange, start: number, end: number): boolean { +export function rangeContainsStartEnd(range: TextRange, start: number, end: number): boolean { return range.pos <= start && range.end >= end; } /** @internal */ -export function rangeOverlapsWithStartEnd(r1: ts.TextRange, start: number, end: number) { +export function rangeOverlapsWithStartEnd(r1: TextRange, start: number, end: number) { return startEndOverlapsWithStartEnd(r1.pos, r1.end, start, end); } /** @internal */ -export function nodeOverlapsWithStartEnd(node: ts.Node, sourceFile: ts.SourceFile, start: number, end: number) { +export function nodeOverlapsWithStartEnd(node: Node, sourceFile: SourceFile, start: number, end: number) { return startEndOverlapsWithStartEnd(node.getStart(sourceFile), node.end, start, end); } @@ -584,140 +644,140 @@ export function startEndOverlapsWithStartEnd(start1: number, end1: number, start /** * Assumes `candidate.start <= position` holds. */ -export function positionBelongsToNode(candidate: ts.Node, position: number, sourceFile: ts.SourceFile): boolean { - ts.Debug.assert(candidate.pos <= position); +export function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean { + Debug.assert(candidate.pos <= position); return position < candidate.end || !isCompletedNode(candidate, sourceFile); } -function isCompletedNode(n: ts.Node | undefined, sourceFile: ts.SourceFile): boolean { - if (n === undefined || ts.nodeIsMissing(n)) { +function isCompletedNode(n: Node | undefined, sourceFile: SourceFile): boolean { + if (n === undefined || nodeIsMissing(n)) { return false; } switch (n.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.EnumDeclaration: - case ts.SyntaxKind.ObjectLiteralExpression: - case ts.SyntaxKind.ObjectBindingPattern: - case ts.SyntaxKind.TypeLiteral: - case ts.SyntaxKind.Block: - case ts.SyntaxKind.ModuleBlock: - case ts.SyntaxKind.CaseBlock: - case ts.SyntaxKind.NamedImports: - case ts.SyntaxKind.NamedExports: - return nodeEndsWith(n, ts.SyntaxKind.CloseBraceToken, sourceFile); - case ts.SyntaxKind.CatchClause: - return isCompletedNode((n as ts.CatchClause).block, sourceFile); - case ts.SyntaxKind.NewExpression: - if (!(n as ts.NewExpression).arguments) { + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.TypeLiteral: + case SyntaxKind.Block: + case SyntaxKind.ModuleBlock: + case SyntaxKind.CaseBlock: + case SyntaxKind.NamedImports: + case SyntaxKind.NamedExports: + return nodeEndsWith(n, SyntaxKind.CloseBraceToken, sourceFile); + case SyntaxKind.CatchClause: + return isCompletedNode((n as CatchClause).block, sourceFile); + case SyntaxKind.NewExpression: + if (!(n as NewExpression).arguments) { return true; } // falls through - case ts.SyntaxKind.CallExpression: - case ts.SyntaxKind.ParenthesizedExpression: - case ts.SyntaxKind.ParenthesizedType: - return nodeEndsWith(n, ts.SyntaxKind.CloseParenToken, sourceFile); - - case ts.SyntaxKind.FunctionType: - case ts.SyntaxKind.ConstructorType: - return isCompletedNode((n as ts.SignatureDeclaration).type, sourceFile); - - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.GetAccessor: - case ts.SyntaxKind.SetAccessor: - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - case ts.SyntaxKind.ConstructSignature: - case ts.SyntaxKind.CallSignature: - case ts.SyntaxKind.ArrowFunction: - if ((n as ts.FunctionLikeDeclaration).body) { - return isCompletedNode((n as ts.FunctionLikeDeclaration).body, sourceFile); + case SyntaxKind.CallExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.ParenthesizedType: + return nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile); + + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + return isCompletedNode((n as SignatureDeclaration).type, sourceFile); + + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.ArrowFunction: + if ((n as FunctionLikeDeclaration).body) { + return isCompletedNode((n as FunctionLikeDeclaration).body, sourceFile); } - if ((n as ts.FunctionLikeDeclaration).type) { - return isCompletedNode((n as ts.FunctionLikeDeclaration).type, sourceFile); + if ((n as FunctionLikeDeclaration).type) { + return isCompletedNode((n as FunctionLikeDeclaration).type, sourceFile); } // Even though type parameters can be unclosed, we can get away with // having at least a closing paren. - return hasChildOfKind(n, ts.SyntaxKind.CloseParenToken, sourceFile); + return hasChildOfKind(n, SyntaxKind.CloseParenToken, sourceFile); - case ts.SyntaxKind.ModuleDeclaration: - return !!(n as ts.ModuleDeclaration).body && isCompletedNode((n as ts.ModuleDeclaration).body, sourceFile); + case SyntaxKind.ModuleDeclaration: + return !!(n as ModuleDeclaration).body && isCompletedNode((n as ModuleDeclaration).body, sourceFile); - case ts.SyntaxKind.IfStatement: - if ((n as ts.IfStatement).elseStatement) { - return isCompletedNode((n as ts.IfStatement).elseStatement, sourceFile); + case SyntaxKind.IfStatement: + if ((n as IfStatement).elseStatement) { + return isCompletedNode((n as IfStatement).elseStatement, sourceFile); } - return isCompletedNode((n as ts.IfStatement).thenStatement, sourceFile); - - case ts.SyntaxKind.ExpressionStatement: - return isCompletedNode((n as ts.ExpressionStatement).expression, sourceFile) || - hasChildOfKind(n, ts.SyntaxKind.SemicolonToken, sourceFile); - - case ts.SyntaxKind.ArrayLiteralExpression: - case ts.SyntaxKind.ArrayBindingPattern: - case ts.SyntaxKind.ElementAccessExpression: - case ts.SyntaxKind.ComputedPropertyName: - case ts.SyntaxKind.TupleType: - return nodeEndsWith(n, ts.SyntaxKind.CloseBracketToken, sourceFile); - - case ts.SyntaxKind.IndexSignature: - if ((n as ts.IndexSignatureDeclaration).type) { - return isCompletedNode((n as ts.IndexSignatureDeclaration).type, sourceFile); + return isCompletedNode((n as IfStatement).thenStatement, sourceFile); + + case SyntaxKind.ExpressionStatement: + return isCompletedNode((n as ExpressionStatement).expression, sourceFile) || + hasChildOfKind(n, SyntaxKind.SemicolonToken, sourceFile); + + case SyntaxKind.ArrayLiteralExpression: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TupleType: + return nodeEndsWith(n, SyntaxKind.CloseBracketToken, sourceFile); + + case SyntaxKind.IndexSignature: + if ((n as IndexSignatureDeclaration).type) { + return isCompletedNode((n as IndexSignatureDeclaration).type, sourceFile); } - return hasChildOfKind(n, ts.SyntaxKind.CloseBracketToken, sourceFile); + return hasChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile); - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: + case SyntaxKind.CaseClause: + case SyntaxKind.DefaultClause: // there is no such thing as terminator token for CaseClause/DefaultClause so for simplicity always consider them non-completed return false; - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.ForInStatement: - case ts.SyntaxKind.ForOfStatement: - case ts.SyntaxKind.WhileStatement: - return isCompletedNode((n as ts.IterationStatement).statement, sourceFile); - case ts.SyntaxKind.DoStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.WhileStatement: + return isCompletedNode((n as IterationStatement).statement, sourceFile); + case SyntaxKind.DoStatement: // rough approximation: if DoStatement has While keyword - then if node is completed is checking the presence of ')'; - return hasChildOfKind(n, ts.SyntaxKind.WhileKeyword, sourceFile) - ? nodeEndsWith(n, ts.SyntaxKind.CloseParenToken, sourceFile) - : isCompletedNode((n as ts.DoStatement).statement, sourceFile); - - case ts.SyntaxKind.TypeQuery: - return isCompletedNode((n as ts.TypeQueryNode).exprName, sourceFile); - - case ts.SyntaxKind.TypeOfExpression: - case ts.SyntaxKind.DeleteExpression: - case ts.SyntaxKind.VoidExpression: - case ts.SyntaxKind.YieldExpression: - case ts.SyntaxKind.SpreadElement: - const unaryWordExpression = n as (ts.TypeOfExpression | ts.DeleteExpression | ts.VoidExpression | ts.YieldExpression | ts.SpreadElement); + return hasChildOfKind(n, SyntaxKind.WhileKeyword, sourceFile) + ? nodeEndsWith(n, SyntaxKind.CloseParenToken, sourceFile) + : isCompletedNode((n as DoStatement).statement, sourceFile); + + case SyntaxKind.TypeQuery: + return isCompletedNode((n as TypeQueryNode).exprName, sourceFile); + + case SyntaxKind.TypeOfExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.YieldExpression: + case SyntaxKind.SpreadElement: + const unaryWordExpression = n as (TypeOfExpression | DeleteExpression | VoidExpression | YieldExpression | SpreadElement); return isCompletedNode(unaryWordExpression.expression, sourceFile); - case ts.SyntaxKind.TaggedTemplateExpression: - return isCompletedNode((n as ts.TaggedTemplateExpression).template, sourceFile); - case ts.SyntaxKind.TemplateExpression: - const lastSpan = ts.lastOrUndefined((n as ts.TemplateExpression).templateSpans); + case SyntaxKind.TaggedTemplateExpression: + return isCompletedNode((n as TaggedTemplateExpression).template, sourceFile); + case SyntaxKind.TemplateExpression: + const lastSpan = lastOrUndefined((n as TemplateExpression).templateSpans); return isCompletedNode(lastSpan, sourceFile); - case ts.SyntaxKind.TemplateSpan: - return ts.nodeIsPresent((n as ts.TemplateSpan).literal); + case SyntaxKind.TemplateSpan: + return nodeIsPresent((n as TemplateSpan).literal); - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ImportDeclaration: - return ts.nodeIsPresent((n as ts.ExportDeclaration | ts.ImportDeclaration).moduleSpecifier); + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ImportDeclaration: + return nodeIsPresent((n as ExportDeclaration | ImportDeclaration).moduleSpecifier); - case ts.SyntaxKind.PrefixUnaryExpression: - return isCompletedNode((n as ts.PrefixUnaryExpression).operand, sourceFile); - case ts.SyntaxKind.BinaryExpression: - return isCompletedNode((n as ts.BinaryExpression).right, sourceFile); - case ts.SyntaxKind.ConditionalExpression: - return isCompletedNode((n as ts.ConditionalExpression).whenFalse, sourceFile); + case SyntaxKind.PrefixUnaryExpression: + return isCompletedNode((n as PrefixUnaryExpression).operand, sourceFile); + case SyntaxKind.BinaryExpression: + return isCompletedNode((n as BinaryExpression).right, sourceFile); + case SyntaxKind.ConditionalExpression: + return isCompletedNode((n as ConditionalExpression).whenFalse, sourceFile); default: return true; @@ -728,14 +788,14 @@ function isCompletedNode(n: ts.Node | undefined, sourceFile: ts.SourceFile): boo * Checks if node ends with 'expectedLastToken'. * If child at position 'length - 1' is 'SemicolonToken' it is skipped and 'expectedLastToken' is compared with child at position 'length - 2'. */ -function nodeEndsWith(n: ts.Node, expectedLastToken: ts.SyntaxKind, sourceFile: ts.SourceFile): boolean { +function nodeEndsWith(n: Node, expectedLastToken: SyntaxKind, sourceFile: SourceFile): boolean { const children = n.getChildren(sourceFile); if (children.length) { - const lastChild = ts.last(children); + const lastChild = last(children); if (lastChild.kind === expectedLastToken) { return true; } - else if (lastChild.kind === ts.SyntaxKind.SemicolonToken && children.length !== 1) { + else if (lastChild.kind === SyntaxKind.SemicolonToken && children.length !== 1) { return children[children.length - 2].kind === expectedLastToken; } } @@ -743,7 +803,7 @@ function nodeEndsWith(n: ts.Node, expectedLastToken: ts.SyntaxKind, sourceFile: } /** @internal */ -export function findListItemInfo(node: ts.Node): ListItemInfo | undefined { +export function findListItemInfo(node: Node): ListItemInfo | undefined { const list = findContainingList(node); // It is possible at this point for syntaxList to be undefined, either if @@ -755,7 +815,7 @@ export function findListItemInfo(node: ts.Node): ListItemInfo | undefined { } const children = list.getChildren(); - const listItemIndex = ts.indexOfNode(children, node); + const listItemIndex = indexOfNode(children, node); return { listItemIndex, @@ -764,87 +824,87 @@ export function findListItemInfo(node: ts.Node): ListItemInfo | undefined { } /** @internal */ -export function hasChildOfKind(n: ts.Node, kind: ts.SyntaxKind, sourceFile: ts.SourceFile): boolean { +export function hasChildOfKind(n: Node, kind: SyntaxKind, sourceFile: SourceFile): boolean { return !!findChildOfKind(n, kind, sourceFile); } /** @internal */ -export function findChildOfKind(n: ts.Node, kind: T["kind"], sourceFile: ts.SourceFileLike): T | undefined { - return ts.find(n.getChildren(sourceFile), (c): c is T => c.kind === kind); +export function findChildOfKind(n: Node, kind: T["kind"], sourceFile: SourceFileLike): T | undefined { + return find(n.getChildren(sourceFile), (c): c is T => c.kind === kind); } /** @internal */ -export function findContainingList(node: ts.Node): ts.SyntaxList | undefined { +export function findContainingList(node: Node): SyntaxList | undefined { // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will // be parented by the container of the SyntaxList, not the SyntaxList itself. // In order to find the list item index, we first need to locate SyntaxList itself and then search // for the position of the relevant node (or comma). - const syntaxList = ts.find(node.parent.getChildren(), (c): c is ts.SyntaxList => ts.isSyntaxList(c) && rangeContainsRange(c, node)); + const syntaxList = find(node.parent.getChildren(), (c): c is SyntaxList => isSyntaxList(c) && rangeContainsRange(c, node)); // Either we didn't find an appropriate list, or the list must contain us. - ts.Debug.assert(!syntaxList || ts.contains(syntaxList.getChildren(), node)); + Debug.assert(!syntaxList || contains(syntaxList.getChildren(), node)); return syntaxList; } -function isDefaultModifier(node: ts.Node) { - return node.kind === ts.SyntaxKind.DefaultKeyword; +function isDefaultModifier(node: Node) { + return node.kind === SyntaxKind.DefaultKeyword; } -function isClassKeyword(node: ts.Node) { - return node.kind === ts.SyntaxKind.ClassKeyword; +function isClassKeyword(node: Node) { + return node.kind === SyntaxKind.ClassKeyword; } -function isFunctionKeyword(node: ts.Node) { - return node.kind === ts.SyntaxKind.FunctionKeyword; +function isFunctionKeyword(node: Node) { + return node.kind === SyntaxKind.FunctionKeyword; } -function getAdjustedLocationForClass(node: ts.ClassDeclaration | ts.ClassExpression) { - if (ts.isNamedDeclaration(node)) { +function getAdjustedLocationForClass(node: ClassDeclaration | ClassExpression) { + if (isNamedDeclaration(node)) { return node.name; } - if (ts.isClassDeclaration(node)) { + if (isClassDeclaration(node)) { // for class and function declarations, use the `default` modifier // when the declaration is unnamed. - const defaultModifier = node.modifiers && ts.find(node.modifiers, isDefaultModifier); + const defaultModifier = node.modifiers && find(node.modifiers, isDefaultModifier); if (defaultModifier) return defaultModifier; } - if (ts.isClassExpression(node)) { + if (isClassExpression(node)) { // for class expressions, use the `class` keyword when the class is unnamed - const classKeyword = ts.find(node.getChildren(), isClassKeyword); + const classKeyword = find(node.getChildren(), isClassKeyword); if (classKeyword) return classKeyword; } } -function getAdjustedLocationForFunction(node: ts.FunctionDeclaration | ts.FunctionExpression) { - if (ts.isNamedDeclaration(node)) { +function getAdjustedLocationForFunction(node: FunctionDeclaration | FunctionExpression) { + if (isNamedDeclaration(node)) { return node.name; } - if (ts.isFunctionDeclaration(node)) { + if (isFunctionDeclaration(node)) { // for class and function declarations, use the `default` modifier // when the declaration is unnamed. - const defaultModifier = ts.find(node.modifiers, isDefaultModifier); + const defaultModifier = find(node.modifiers, isDefaultModifier); if (defaultModifier) return defaultModifier; } - if (ts.isFunctionExpression(node)) { + if (isFunctionExpression(node)) { // for function expressions, use the `function` keyword when the function is unnamed - const functionKeyword = ts.find(node.getChildren(), isFunctionKeyword); + const functionKeyword = find(node.getChildren(), isFunctionKeyword); if (functionKeyword) return functionKeyword; } } -function getAncestorTypeNode(node: ts.Node) { - let lastTypeNode: ts.TypeNode | undefined; - ts.findAncestor(node, a => { - if (ts.isTypeNode(a)) { +function getAncestorTypeNode(node: Node) { + let lastTypeNode: TypeNode | undefined; + findAncestor(node, a => { + if (isTypeNode(a)) { lastTypeNode = a; } - return !ts.isQualifiedName(a.parent) && !ts.isTypeNode(a.parent) && !ts.isTypeElement(a.parent); + return !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent); }); return lastTypeNode; } /** @internal */ -export function getContextualTypeFromParentOrAncestorTypeNode(node: ts.Expression, checker: ts.TypeChecker): ts.Type | undefined { - if (node.flags & (ts.NodeFlags.JSDoc & ~ts.NodeFlags.JavaScriptFile)) return undefined; +export function getContextualTypeFromParentOrAncestorTypeNode(node: Expression, checker: TypeChecker): Type | undefined { + if (node.flags & (NodeFlags.JSDoc & ~NodeFlags.JavaScriptFile)) return undefined; const contextualType = getContextualTypeFromParent(node, checker); if (contextualType) return contextualType; @@ -853,25 +913,25 @@ export function getContextualTypeFromParentOrAncestorTypeNode(node: ts.Expressio return ancestorTypeNode && checker.getTypeAtLocation(ancestorTypeNode); } -function getAdjustedLocationForDeclaration(node: ts.Node, forRename: boolean) { +function getAdjustedLocationForDeclaration(node: Node, forRename: boolean) { if (!forRename) { switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - return getAdjustedLocationForClass(node as ts.ClassDeclaration | ts.ClassExpression); - case ts.SyntaxKind.FunctionDeclaration: - case ts.SyntaxKind.FunctionExpression: - return getAdjustedLocationForFunction(node as ts.FunctionDeclaration | ts.FunctionExpression); - case ts.SyntaxKind.Constructor: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + return getAdjustedLocationForClass(node as ClassDeclaration | ClassExpression); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + return getAdjustedLocationForFunction(node as FunctionDeclaration | FunctionExpression); + case SyntaxKind.Constructor: return node; } } - if (ts.isNamedDeclaration(node)) { + if (isNamedDeclaration(node)) { return node.name; } } -function getAdjustedLocationForImportDeclaration(node: ts.ImportDeclaration, forRename: boolean) { +function getAdjustedLocationForImportDeclaration(node: ImportDeclaration, forRename: boolean) { if (node.importClause) { if (node.importClause.name && node.importClause.namedBindings) { // do not adjust if we have both a name and named bindings @@ -891,15 +951,15 @@ function getAdjustedLocationForImportDeclaration(node: ts.ImportDeclaration, for // import /**/type { propertyName as [|name|] } from ...; // import /**/type * as [|name|] from ...; if (node.importClause.namedBindings) { - if (ts.isNamedImports(node.importClause.namedBindings)) { + if (isNamedImports(node.importClause.namedBindings)) { // do nothing if there is more than one binding - const onlyBinding = ts.singleOrUndefined(node.importClause.namedBindings.elements); + const onlyBinding = singleOrUndefined(node.importClause.namedBindings.elements); if (!onlyBinding) { return; } return onlyBinding.name; } - else if (ts.isNamespaceImport(node.importClause.namedBindings)) { + else if (isNamespaceImport(node.importClause.namedBindings)) { return node.importClause.namedBindings.name; } } @@ -912,7 +972,7 @@ function getAdjustedLocationForImportDeclaration(node: ts.ImportDeclaration, for } } -function getAdjustedLocationForExportDeclaration(node: ts.ExportDeclaration, forRename: boolean) { +function getAdjustedLocationForExportDeclaration(node: ExportDeclaration, forRename: boolean) { if (node.exportClause) { // /**/export { [|name|] } ... // /**/export { propertyName as [|name|] } ... @@ -920,15 +980,15 @@ function getAdjustedLocationForExportDeclaration(node: ts.ExportDeclaration, for // export /**/type { [|name|] } from ... // export /**/type { propertyName as [|name|] } from ... // export /**/type * as [|name|] ... - if (ts.isNamedExports(node.exportClause)) { + if (isNamedExports(node.exportClause)) { // do nothing if there is more than one binding - const onlyBinding = ts.singleOrUndefined(node.exportClause.elements); + const onlyBinding = singleOrUndefined(node.exportClause.elements); if (!onlyBinding) { return; } return node.exportClause.elements[0].name; } - else if (ts.isNamespaceExport(node.exportClause)) { + else if (isNamespaceExport(node.exportClause)) { return node.exportClause.name; } } @@ -939,7 +999,7 @@ function getAdjustedLocationForExportDeclaration(node: ts.ExportDeclaration, for } } -function getAdjustedLocationForHeritageClause(node: ts.HeritageClause) { +function getAdjustedLocationForHeritageClause(node: HeritageClause) { // /**/extends [|name|] // /**/implements [|name|] if (node.types.length === 1) { @@ -950,7 +1010,7 @@ function getAdjustedLocationForHeritageClause(node: ts.HeritageClause) { // /**/implements name1, name2 ... } -function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { +function getAdjustedLocation(node: Node, forRename: boolean): Node { const { parent } = node; // /**/ [|name|] ... // /**/ [|name|] ... @@ -959,35 +1019,35 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // // NOTE: If the node is a modifier, we don't adjust its location if it is the `default` modifier as that is handled // specially by `getSymbolAtLocation`. - if (ts.isModifier(node) && (forRename || node.kind !== ts.SyntaxKind.DefaultKeyword) ? ts.canHaveModifiers(parent) && ts.contains(parent.modifiers, node) : - node.kind === ts.SyntaxKind.ClassKeyword ? ts.isClassDeclaration(parent) || ts.isClassExpression(node) : - node.kind === ts.SyntaxKind.FunctionKeyword ? ts.isFunctionDeclaration(parent) || ts.isFunctionExpression(node) : - node.kind === ts.SyntaxKind.InterfaceKeyword ? ts.isInterfaceDeclaration(parent) : - node.kind === ts.SyntaxKind.EnumKeyword ? ts.isEnumDeclaration(parent) : - node.kind === ts.SyntaxKind.TypeKeyword ? ts.isTypeAliasDeclaration(parent) : - node.kind === ts.SyntaxKind.NamespaceKeyword || node.kind === ts.SyntaxKind.ModuleKeyword ? ts.isModuleDeclaration(parent) : - node.kind === ts.SyntaxKind.ImportKeyword ? ts.isImportEqualsDeclaration(parent) : - node.kind === ts.SyntaxKind.GetKeyword ? ts.isGetAccessorDeclaration(parent) : - node.kind === ts.SyntaxKind.SetKeyword && ts.isSetAccessorDeclaration(parent)) { + if (isModifier(node) && (forRename || node.kind !== SyntaxKind.DefaultKeyword) ? canHaveModifiers(parent) && contains(parent.modifiers, node) : + node.kind === SyntaxKind.ClassKeyword ? isClassDeclaration(parent) || isClassExpression(node) : + node.kind === SyntaxKind.FunctionKeyword ? isFunctionDeclaration(parent) || isFunctionExpression(node) : + node.kind === SyntaxKind.InterfaceKeyword ? isInterfaceDeclaration(parent) : + node.kind === SyntaxKind.EnumKeyword ? isEnumDeclaration(parent) : + node.kind === SyntaxKind.TypeKeyword ? isTypeAliasDeclaration(parent) : + node.kind === SyntaxKind.NamespaceKeyword || node.kind === SyntaxKind.ModuleKeyword ? isModuleDeclaration(parent) : + node.kind === SyntaxKind.ImportKeyword ? isImportEqualsDeclaration(parent) : + node.kind === SyntaxKind.GetKeyword ? isGetAccessorDeclaration(parent) : + node.kind === SyntaxKind.SetKeyword && isSetAccessorDeclaration(parent)) { const location = getAdjustedLocationForDeclaration(parent, forRename); if (location) { return location; } } // /**/ [|name|] ... - if ((node.kind === ts.SyntaxKind.VarKeyword || node.kind === ts.SyntaxKind.ConstKeyword || node.kind === ts.SyntaxKind.LetKeyword) && - ts.isVariableDeclarationList(parent) && parent.declarations.length === 1) { + if ((node.kind === SyntaxKind.VarKeyword || node.kind === SyntaxKind.ConstKeyword || node.kind === SyntaxKind.LetKeyword) && + isVariableDeclarationList(parent) && parent.declarations.length === 1) { const decl = parent.declarations[0]; - if (ts.isIdentifier(decl.name)) { + if (isIdentifier(decl.name)) { return decl.name; } } - if (node.kind === ts.SyntaxKind.TypeKeyword) { + if (node.kind === SyntaxKind.TypeKeyword) { // import /**/type [|name|] from ...; // import /**/type { [|name|] } from ...; // import /**/type { propertyName as [|name|] } from ...; // import /**/type ... from "[|module|]"; - if (ts.isImportClause(parent) && parent.isTypeOnly) { + if (isImportClause(parent) && parent.isTypeOnly) { const location = getAdjustedLocationForImportDeclaration(parent.parent, forRename); if (location) { return location; @@ -997,7 +1057,7 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // export /**/type { propertyName as [|name|] } from ...; // export /**/type * from "[|module|]"; // export /**/type * as ... from "[|module|]"; - if (ts.isExportDeclaration(parent) && parent.isTypeOnly) { + if (isExportDeclaration(parent) && parent.isTypeOnly) { const location = getAdjustedLocationForExportDeclaration(parent, forRename); if (location) { return location; @@ -1008,14 +1068,14 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // import * /**/as [|name|] ... // export { propertyName /**/as [|name|] } ... // export * /**/as [|name|] ... - if (node.kind === ts.SyntaxKind.AsKeyword) { - if (ts.isImportSpecifier(parent) && parent.propertyName || - ts.isExportSpecifier(parent) && parent.propertyName || - ts.isNamespaceImport(parent) || - ts.isNamespaceExport(parent)) { + if (node.kind === SyntaxKind.AsKeyword) { + if (isImportSpecifier(parent) && parent.propertyName || + isExportSpecifier(parent) && parent.propertyName || + isNamespaceImport(parent) || + isNamespaceExport(parent)) { return parent.name; } - if (ts.isExportDeclaration(parent) && parent.exportClause && ts.isNamespaceExport(parent.exportClause)) { + if (isExportDeclaration(parent) && parent.exportClause && isNamespaceExport(parent.exportClause)) { return parent.exportClause.name; } } @@ -1024,18 +1084,18 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // /**/import { propertyName as [|name|] } from ...; // /**/import ... from "[|module|]"; // /**/import "[|module|]"; - if (node.kind === ts.SyntaxKind.ImportKeyword && ts.isImportDeclaration(parent)) { + if (node.kind === SyntaxKind.ImportKeyword && isImportDeclaration(parent)) { const location = getAdjustedLocationForImportDeclaration(parent, forRename); if (location) { return location; } } - if (node.kind === ts.SyntaxKind.ExportKeyword) { + if (node.kind === SyntaxKind.ExportKeyword) { // /**/export { [|name|] } ...; // /**/export { propertyName as [|name|] } ...; // /**/export * from "[|module|]"; // /**/export * as ... from "[|module|]"; - if (ts.isExportDeclaration(parent)) { + if (isExportDeclaration(parent)) { const location = getAdjustedLocationForExportDeclaration(parent, forRename); if (location) { return location; @@ -1044,17 +1104,17 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // NOTE: We don't adjust the location of the `default` keyword as that is handled specially by `getSymbolAtLocation`. // /**/export default [|name|]; // /**/export = [|name|]; - if (ts.isExportAssignment(parent)) { - return ts.skipOuterExpressions(parent.expression); + if (isExportAssignment(parent)) { + return skipOuterExpressions(parent.expression); } } // import name = /**/require("[|module|]"); - if (node.kind === ts.SyntaxKind.RequireKeyword && ts.isExternalModuleReference(parent)) { + if (node.kind === SyntaxKind.RequireKeyword && isExternalModuleReference(parent)) { return parent.expression; } // import ... /**/from "[|module|]"; // export ... /**/from "[|module|]"; - if (node.kind === ts.SyntaxKind.FromKeyword && (ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent)) && parent.moduleSpecifier) { + if (node.kind === SyntaxKind.FromKeyword && (isImportDeclaration(parent) || isExportDeclaration(parent)) && parent.moduleSpecifier) { return parent.moduleSpecifier; } // class ... /**/extends [|name|] ... @@ -1062,38 +1122,38 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // class ... /**/implements name1, name2 ... // interface ... /**/extends [|name|] ... // interface ... /**/extends name1, name2 ... - if ((node.kind === ts.SyntaxKind.ExtendsKeyword || node.kind === ts.SyntaxKind.ImplementsKeyword) && ts.isHeritageClause(parent) && parent.token === node.kind) { + if ((node.kind === SyntaxKind.ExtendsKeyword || node.kind === SyntaxKind.ImplementsKeyword) && isHeritageClause(parent) && parent.token === node.kind) { const location = getAdjustedLocationForHeritageClause(parent); if (location) { return location; } } - if (node.kind === ts.SyntaxKind.ExtendsKeyword) { + if (node.kind === SyntaxKind.ExtendsKeyword) { // ... ... - if (ts.isTypeParameterDeclaration(parent) && parent.constraint && ts.isTypeReferenceNode(parent.constraint)) { + if (isTypeParameterDeclaration(parent) && parent.constraint && isTypeReferenceNode(parent.constraint)) { return parent.constraint.typeName; } // ... T /**/extends [|U|] ? ... - if (ts.isConditionalTypeNode(parent) && ts.isTypeReferenceNode(parent.extendsType)) { + if (isConditionalTypeNode(parent) && isTypeReferenceNode(parent.extendsType)) { return parent.extendsType.typeName; } } // ... T extends /**/infer [|U|] ? ... - if (node.kind === ts.SyntaxKind.InferKeyword && ts.isInferTypeNode(parent)) { + if (node.kind === SyntaxKind.InferKeyword && isInferTypeNode(parent)) { return parent.typeParameter.name; } // { [ [|K|] /**/in keyof T]: ... } - if (node.kind === ts.SyntaxKind.InKeyword && ts.isTypeParameterDeclaration(parent) && ts.isMappedTypeNode(parent.parent)) { + if (node.kind === SyntaxKind.InKeyword && isTypeParameterDeclaration(parent) && isMappedTypeNode(parent.parent)) { return parent.name; } // /**/keyof [|T|] - if (node.kind === ts.SyntaxKind.KeyOfKeyword && ts.isTypeOperatorNode(parent) && parent.operator === ts.SyntaxKind.KeyOfKeyword && - ts.isTypeReferenceNode(parent.type)) { + if (node.kind === SyntaxKind.KeyOfKeyword && isTypeOperatorNode(parent) && parent.operator === SyntaxKind.KeyOfKeyword && + isTypeReferenceNode(parent.type)) { return parent.type.typeName; } // /**/readonly [|name|][] - if (node.kind === ts.SyntaxKind.ReadonlyKeyword && ts.isTypeOperatorNode(parent) && parent.operator === ts.SyntaxKind.ReadonlyKeyword && - ts.isArrayTypeNode(parent.type) && ts.isTypeReferenceNode(parent.type.elementType)) { + if (node.kind === SyntaxKind.ReadonlyKeyword && isTypeOperatorNode(parent) && parent.operator === SyntaxKind.ReadonlyKeyword && + isArrayTypeNode(parent.type) && isTypeReferenceNode(parent.type.elementType)) { return parent.type.elementType.typeName; } if (!forRename) { @@ -1107,30 +1167,30 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { // /**/yield [|name|] // /**/yield obj.[|name|] // /**/delete obj.[|name|] - if (node.kind === ts.SyntaxKind.NewKeyword && ts.isNewExpression(parent) || - node.kind === ts.SyntaxKind.VoidKeyword && ts.isVoidExpression(parent) || - node.kind === ts.SyntaxKind.TypeOfKeyword && ts.isTypeOfExpression(parent) || - node.kind === ts.SyntaxKind.AwaitKeyword && ts.isAwaitExpression(parent) || - node.kind === ts.SyntaxKind.YieldKeyword && ts.isYieldExpression(parent) || - node.kind === ts.SyntaxKind.DeleteKeyword && ts.isDeleteExpression(parent)) { + if (node.kind === SyntaxKind.NewKeyword && isNewExpression(parent) || + node.kind === SyntaxKind.VoidKeyword && isVoidExpression(parent) || + node.kind === SyntaxKind.TypeOfKeyword && isTypeOfExpression(parent) || + node.kind === SyntaxKind.AwaitKeyword && isAwaitExpression(parent) || + node.kind === SyntaxKind.YieldKeyword && isYieldExpression(parent) || + node.kind === SyntaxKind.DeleteKeyword && isDeleteExpression(parent)) { if (parent.expression) { - return ts.skipOuterExpressions(parent.expression); + return skipOuterExpressions(parent.expression); } } // left /**/in [|name|] // left /**/instanceof [|name|] - if ((node.kind === ts.SyntaxKind.InKeyword || node.kind === ts.SyntaxKind.InstanceOfKeyword) && ts.isBinaryExpression(parent) && parent.operatorToken === node) { - return ts.skipOuterExpressions(parent.right); + if ((node.kind === SyntaxKind.InKeyword || node.kind === SyntaxKind.InstanceOfKeyword) && isBinaryExpression(parent) && parent.operatorToken === node) { + return skipOuterExpressions(parent.right); } // left /**/as [|name|] - if (node.kind === ts.SyntaxKind.AsKeyword && ts.isAsExpression(parent) && ts.isTypeReferenceNode(parent.type)) { + if (node.kind === SyntaxKind.AsKeyword && isAsExpression(parent) && isTypeReferenceNode(parent.type)) { return parent.type.typeName; } // for (... /**/in [|name|]) // for (... /**/of [|name|]) - if (node.kind === ts.SyntaxKind.InKeyword && ts.isForInStatement(parent) || - node.kind === ts.SyntaxKind.OfKeyword && ts.isForOfStatement(parent)) { - return ts.skipOuterExpressions(parent.expression); + if (node.kind === SyntaxKind.InKeyword && isForInStatement(parent) || + node.kind === SyntaxKind.OfKeyword && isForOfStatement(parent)) { + return skipOuterExpressions(parent.expression); } } return node; @@ -1141,7 +1201,7 @@ function getAdjustedLocation(node: ts.Node, forRename: boolean): ts.Node { * Adjusts the location used for "find references" and "go to definition" when the cursor was not * on a property name. */ -export function getAdjustedReferenceLocation(node: ts.Node): ts.Node { +export function getAdjustedReferenceLocation(node: Node): Node { return getAdjustedLocation(node, /*forRename*/ false); } @@ -1149,7 +1209,7 @@ export function getAdjustedReferenceLocation(node: ts.Node): ts.Node { /** * Adjusts the location used for "rename" when the cursor was not on a property name. */ -export function getAdjustedRenameLocation(node: ts.Node): ts.Node { +export function getAdjustedRenameLocation(node: Node): Node { return getAdjustedLocation(node, /*forRename*/ true); } @@ -1158,8 +1218,8 @@ export function getAdjustedRenameLocation(node: ts.Node): ts.Node { * Gets the token whose text has range [start, end) and * position >= start and (position < end or (position === end && token is literal or keyword or identifier)) */ -export function getTouchingPropertyName(sourceFile: ts.SourceFile, position: number): ts.Node { - return getTouchingToken(sourceFile, position, n => ts.isPropertyNameLiteral(n) || ts.isKeyword(n.kind) || ts.isPrivateIdentifier(n)); +export function getTouchingPropertyName(sourceFile: SourceFile, position: number): Node { + return getTouchingToken(sourceFile, position, n => isPropertyNameLiteral(n) || isKeyword(n.kind) || isPrivateIdentifier(n)); } /** @internal */ @@ -1167,25 +1227,25 @@ export function getTouchingPropertyName(sourceFile: ts.SourceFile, position: num * Returns the token if position is in [start, end). * If position === end, returns the preceding token if includeItemAtEndPosition(previousToken) === true */ -export function getTouchingToken(sourceFile: ts.SourceFile, position: number, includePrecedingTokenAtEndPosition?: (n: ts.Node) => boolean): ts.Node { +export function getTouchingToken(sourceFile: SourceFile, position: number, includePrecedingTokenAtEndPosition?: (n: Node) => boolean): Node { return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ false, includePrecedingTokenAtEndPosition, /*includeEndPosition*/ false); } /** @internal */ /** Returns a token if position is in [start-of-leading-trivia, end) */ -export function getTokenAtPosition(sourceFile: ts.SourceFile, position: number): ts.Node { +export function getTokenAtPosition(sourceFile: SourceFile, position: number): Node { return getTokenAtPositionWorker(sourceFile, position, /*allowPositionInLeadingTrivia*/ true, /*includePrecedingTokenAtEndPosition*/ undefined, /*includeEndPosition*/ false); } /** Get the token whose text contains the position */ -function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: ((n: ts.Node) => boolean) | undefined, includeEndPosition: boolean): ts.Node { - let current: ts.Node = sourceFile; - let foundToken: ts.Node | undefined; +function getTokenAtPositionWorker(sourceFile: SourceFile, position: number, allowPositionInLeadingTrivia: boolean, includePrecedingTokenAtEndPosition: ((n: Node) => boolean) | undefined, includeEndPosition: boolean): Node { + let current: Node = sourceFile; + let foundToken: Node | undefined; outer: while (true) { // find the child that contains 'position' const children = current.getChildren(sourceFile); - const i = ts.binarySearchKey(children, position, (_, i) => i, (middle, _) => { + const i = binarySearchKey(children, position, (_, i) => i, (middle, _) => { // This last callback is more of a selector than a comparator - // `EqualTo` causes the `middle` result to be returned // `GreaterThan` causes recursion on the left of the middle @@ -1212,12 +1272,12 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a // and allows us to skip a bunch of work const end = children[middle].getEnd(); if (end < position) { - return ts.Comparison.LessThan; + return Comparison.LessThan; } const start = allowPositionInLeadingTrivia ? children[middle].getFullStart() : children[middle].getStart(sourceFile, /*includeJsDoc*/ true); if (start > position) { - return ts.Comparison.GreaterThan; + return Comparison.GreaterThan; } // first element whose start position is before the input and whose end position is after or equal to the input @@ -1225,17 +1285,17 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a if (children[middle - 1]) { // we want the _first_ element that contains the position, so left-recur if the prior node also contains the position if (nodeContainsPosition(children[middle - 1])) { - return ts.Comparison.GreaterThan; + return Comparison.GreaterThan; } } - return ts.Comparison.EqualTo; + return Comparison.EqualTo; } // this complex condition makes us left-recur around a zero-length node when includePrecedingTokenAtEndPosition is set, rather than right-recur on it if (includePrecedingTokenAtEndPosition && start === position && children[middle - 1] && children[middle - 1].getEnd() === position && nodeContainsPosition(children[middle - 1])) { - return ts.Comparison.GreaterThan; + return Comparison.GreaterThan; } - return ts.Comparison.LessThan; + return Comparison.LessThan; }); if (foundToken) { @@ -1249,7 +1309,7 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a return current; } - function nodeContainsPosition(node: ts.Node, start?: number, end?: number) { + function nodeContainsPosition(node: Node, start?: number, end?: number) { end ??= node.getEnd(); if (end < position) { return false; @@ -1259,7 +1319,7 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a // If this child begins after position, then all subsequent children will as well. return false; } - if (position < end || (position === end && (node.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) { + if (position < end || (position === end && (node.kind === SyntaxKind.EndOfFileToken || includeEndPosition))) { return true; } else if (includePrecedingTokenAtEndPosition && end === position) { @@ -1278,7 +1338,7 @@ function getTokenAtPositionWorker(sourceFile: ts.SourceFile, position: number, a * Returns the first token where position is in [start, end), * excluding `JsxText` tokens containing only whitespace. */ -export function findFirstNonJsxWhitespaceToken(sourceFile: ts.SourceFile, position: number): ts.Node | undefined { +export function findFirstNonJsxWhitespaceToken(sourceFile: SourceFile, position: number): Node | undefined { let tokenAtPosition = getTokenAtPosition(sourceFile, position); while (isWhiteSpaceOnlyJsxText(tokenAtPosition)) { const nextToken = findNextToken(tokenAtPosition, tokenAtPosition.parent, sourceFile); @@ -1297,11 +1357,11 @@ export function findFirstNonJsxWhitespaceToken(sourceFile: ts.SourceFile, positi * foo |bar -> will return foo * */ -export function findTokenOnLeftOfPosition(file: ts.SourceFile, position: number): ts.Node | undefined { +export function findTokenOnLeftOfPosition(file: SourceFile, position: number): Node | undefined { // Ideally, getTokenAtPosition should return a token. However, it is currently // broken, so we do a check to make sure the result was indeed a token. const tokenAtPosition = getTokenAtPosition(file, position); - if (ts.isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { + if (isToken(tokenAtPosition) && position > tokenAtPosition.getStart(file) && position < tokenAtPosition.getEnd()) { return tokenAtPosition; } @@ -1309,15 +1369,15 @@ export function findTokenOnLeftOfPosition(file: ts.SourceFile, position: number) } /** @internal */ -export function findNextToken(previousToken: ts.Node, parent: ts.Node, sourceFile: ts.SourceFileLike): ts.Node | undefined { +export function findNextToken(previousToken: Node, parent: Node, sourceFile: SourceFileLike): Node | undefined { return find(parent); - function find(n: ts.Node): ts.Node | undefined { - if (ts.isToken(n) && n.pos === previousToken.end) { + function find(n: Node): Node | undefined { + if (isToken(n) && n.pos === previousToken.end) { // this is token that starts at the end of previous token - return it return n; } - return ts.firstDefined(n.getChildren(sourceFile), child => { + return firstDefined(n.getChildren(sourceFile), child => { const shouldDiveInChildNode = // previous token is enclosed somewhere in the child (child.pos <= previousToken.pos && child.end > previousToken.end) || @@ -1333,22 +1393,22 @@ export function findNextToken(previousToken: ts.Node, parent: ts.Node, sourceFil * Finds the rightmost token satisfying `token.end <= position`, * excluding `JsxText` tokens containing only whitespace. */ -export function findPrecedingToken(position: number, sourceFile: ts.SourceFileLike, startNode: ts.Node, excludeJsdoc?: boolean): ts.Node | undefined; +export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode: Node, excludeJsdoc?: boolean): Node | undefined; /** @internal */ -export function findPrecedingToken(position: number, sourceFile: ts.SourceFile, startNode?: ts.Node, excludeJsdoc?: boolean): ts.Node | undefined; +export function findPrecedingToken(position: number, sourceFile: SourceFile, startNode?: Node, excludeJsdoc?: boolean): Node | undefined; /** @internal */ -export function findPrecedingToken(position: number, sourceFile: ts.SourceFileLike, startNode?: ts.Node, excludeJsdoc?: boolean): ts.Node | undefined { - const result = find((startNode || sourceFile) as ts.Node); - ts.Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result))); +export function findPrecedingToken(position: number, sourceFile: SourceFileLike, startNode?: Node, excludeJsdoc?: boolean): Node | undefined { + const result = find((startNode || sourceFile) as Node); + Debug.assert(!(result && isWhiteSpaceOnlyJsxText(result))); return result; - function find(n: ts.Node): ts.Node | undefined { - if (isNonWhitespaceToken(n) && n.kind !== ts.SyntaxKind.EndOfFileToken) { + function find(n: Node): Node | undefined { + if (isNonWhitespaceToken(n) && n.kind !== SyntaxKind.EndOfFileToken) { return n; } const children = n.getChildren(sourceFile); - const i = ts.binarySearchKey(children, position, (_, i) => i, (middle, _) => { + const i = binarySearchKey(children, position, (_, i) => i, (middle, _) => { // This last callback is more of a selector than a comparator - // `EqualTo` causes the `middle` result to be returned // `GreaterThan` causes recursion on the left of the middle @@ -1356,11 +1416,11 @@ export function findPrecedingToken(position: number, sourceFile: ts.SourceFileLi if (position < children[middle].end) { // first element whose end position is greater than the input position if (!children[middle - 1] || position >= children[middle - 1].end) { - return ts.Comparison.EqualTo; + return Comparison.EqualTo; } - return ts.Comparison.GreaterThan; + return Comparison.GreaterThan; } - return ts.Comparison.LessThan; + return Comparison.LessThan; }); if (i >= 0 && children[i]) { const child = children[i]; @@ -1388,7 +1448,7 @@ export function findPrecedingToken(position: number, sourceFile: ts.SourceFileLi } } - ts.Debug.assert(startNode !== undefined || n.kind === ts.SyntaxKind.SourceFile || n.kind === ts.SyntaxKind.EndOfFileToken || ts.isJSDocCommentContainingNode(n)); + Debug.assert(startNode !== undefined || n.kind === SyntaxKind.SourceFile || n.kind === SyntaxKind.EndOfFileToken || isJSDocCommentContainingNode(n)); // Here we know that none of child token nodes embrace the position, // the only known case is when position is at the end of the file. @@ -1399,11 +1459,11 @@ export function findPrecedingToken(position: number, sourceFile: ts.SourceFileLi } } -function isNonWhitespaceToken(n: ts.Node): boolean { - return ts.isToken(n) && !isWhiteSpaceOnlyJsxText(n); +function isNonWhitespaceToken(n: Node): boolean { + return isToken(n) && !isWhiteSpaceOnlyJsxText(n); } -function findRightmostToken(n: ts.Node, sourceFile: ts.SourceFileLike): ts.Node | undefined { +function findRightmostToken(n: Node, sourceFile: SourceFileLike): Node | undefined { if (isNonWhitespaceToken(n)) { return n; } @@ -1420,13 +1480,13 @@ function findRightmostToken(n: ts.Node, sourceFile: ts.SourceFileLike): ts.Node /** * Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens. */ -function findRightmostChildNodeWithTokens(children: ts.Node[], exclusiveStartPosition: number, sourceFile: ts.SourceFileLike, parentKind: ts.SyntaxKind): ts.Node | undefined { +function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number, sourceFile: SourceFileLike, parentKind: SyntaxKind): Node | undefined { for (let i = exclusiveStartPosition - 1; i >= 0; i--) { const child = children[i]; if (isWhiteSpaceOnlyJsxText(child)) { - if (i === 0 && (parentKind === ts.SyntaxKind.JsxText || parentKind === ts.SyntaxKind.JsxSelfClosingElement)) { - ts.Debug.fail("`JsxText` tokens should not be the first child of `JsxElement | JsxSelfClosingElement`"); + if (i === 0 && (parentKind === SyntaxKind.JsxText || parentKind === SyntaxKind.JsxSelfClosingElement)) { + Debug.fail("`JsxText` tokens should not be the first child of `JsxElement | JsxSelfClosingElement`"); } } else if (nodeHasTokens(children[i], sourceFile)) { @@ -1436,8 +1496,8 @@ function findRightmostChildNodeWithTokens(children: ts.Node[], exclusiveStartPos } /** @internal */ -export function isInString(sourceFile: ts.SourceFile, position: number, previousToken = findPrecedingToken(position, sourceFile)): boolean { - if (previousToken && ts.isStringTextContainingNode(previousToken)) { +export function isInString(sourceFile: SourceFile, position: number, previousToken = findPrecedingToken(position, sourceFile)): boolean { + if (previousToken && isStringTextContainingNode(previousToken)) { const start = previousToken.getStart(sourceFile); const end = previousToken.getEnd(); @@ -1450,7 +1510,7 @@ export function isInString(sourceFile: ts.SourceFile, position: number, previous } if (position === end) { - return !!(previousToken as ts.LiteralExpression).isUnterminated; + return !!(previousToken as LiteralExpression).isUnterminated; } } @@ -1461,82 +1521,82 @@ export function isInString(sourceFile: ts.SourceFile, position: number, previous /** * returns true if the position is in between the open and close elements of an JSX expression. */ -export function isInsideJsxElementOrAttribute(sourceFile: ts.SourceFile, position: number) { +export function isInsideJsxElementOrAttribute(sourceFile: SourceFile, position: number) { const token = getTokenAtPosition(sourceFile, position); if (!token) { return false; } - if (token.kind === ts.SyntaxKind.JsxText) { + if (token.kind === SyntaxKind.JsxText) { return true; } //
Hello |
- if (token.kind === ts.SyntaxKind.LessThanToken && token.parent.kind === ts.SyntaxKind.JsxText) { + if (token.kind === SyntaxKind.LessThanToken && token.parent.kind === SyntaxKind.JsxText) { return true; } //
{ |
or
- if (token.kind === ts.SyntaxKind.LessThanToken && token.parent.kind === ts.SyntaxKind.JsxExpression) { + if (token.kind === SyntaxKind.LessThanToken && token.parent.kind === SyntaxKind.JsxExpression) { return true; } //
{ // | // } < /div> - if (token && token.kind === ts.SyntaxKind.CloseBraceToken && token.parent.kind === ts.SyntaxKind.JsxExpression) { + if (token && token.kind === SyntaxKind.CloseBraceToken && token.parent.kind === SyntaxKind.JsxExpression) { return true; } //
|
- if (token.kind === ts.SyntaxKind.LessThanToken && token.parent.kind === ts.SyntaxKind.JsxClosingElement) { + if (token.kind === SyntaxKind.LessThanToken && token.parent.kind === SyntaxKind.JsxClosingElement) { return true; } return false; } -function isWhiteSpaceOnlyJsxText(node: ts.Node): boolean { - return ts.isJsxText(node) && node.containsOnlyTriviaWhiteSpaces; +function isWhiteSpaceOnlyJsxText(node: Node): boolean { + return isJsxText(node) && node.containsOnlyTriviaWhiteSpaces; } /** @internal */ -export function isInTemplateString(sourceFile: ts.SourceFile, position: number) { +export function isInTemplateString(sourceFile: SourceFile, position: number) { const token = getTokenAtPosition(sourceFile, position); - return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); + return isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile); } /** @internal */ -export function isInJSXText(sourceFile: ts.SourceFile, position: number) { +export function isInJSXText(sourceFile: SourceFile, position: number) { const token = getTokenAtPosition(sourceFile, position); - if (ts.isJsxText(token)) { + if (isJsxText(token)) { return true; } - if (token.kind === ts.SyntaxKind.OpenBraceToken && ts.isJsxExpression(token.parent) && ts.isJsxElement(token.parent.parent)) { + if (token.kind === SyntaxKind.OpenBraceToken && isJsxExpression(token.parent) && isJsxElement(token.parent.parent)) { return true; } - if (token.kind === ts.SyntaxKind.LessThanToken && ts.isJsxOpeningLikeElement(token.parent) && ts.isJsxElement(token.parent.parent)) { + if (token.kind === SyntaxKind.LessThanToken && isJsxOpeningLikeElement(token.parent) && isJsxElement(token.parent.parent)) { return true; } return false; } /** @internal */ -export function isInsideJsxElement(sourceFile: ts.SourceFile, position: number): boolean { - function isInsideJsxElementTraversal(node: ts.Node): boolean { +export function isInsideJsxElement(sourceFile: SourceFile, position: number): boolean { + function isInsideJsxElementTraversal(node: Node): boolean { while (node) { - if (node.kind >= ts.SyntaxKind.JsxSelfClosingElement && node.kind <= ts.SyntaxKind.JsxExpression - || node.kind === ts.SyntaxKind.JsxText - || node.kind === ts.SyntaxKind.LessThanToken - || node.kind === ts.SyntaxKind.GreaterThanToken - || node.kind === ts.SyntaxKind.Identifier - || node.kind === ts.SyntaxKind.CloseBraceToken - || node.kind === ts.SyntaxKind.OpenBraceToken - || node.kind === ts.SyntaxKind.SlashToken) { + if (node.kind >= SyntaxKind.JsxSelfClosingElement && node.kind <= SyntaxKind.JsxExpression + || node.kind === SyntaxKind.JsxText + || node.kind === SyntaxKind.LessThanToken + || node.kind === SyntaxKind.GreaterThanToken + || node.kind === SyntaxKind.Identifier + || node.kind === SyntaxKind.CloseBraceToken + || node.kind === SyntaxKind.OpenBraceToken + || node.kind === SyntaxKind.SlashToken) { node = node.parent; } - else if (node.kind === ts.SyntaxKind.JsxElement) { + else if (node.kind === SyntaxKind.JsxElement) { if (position > node.getStart(sourceFile)) return true; node = node.parent; @@ -1553,9 +1613,9 @@ export function isInsideJsxElement(sourceFile: ts.SourceFile, position: number): } /** @internal */ -export function findPrecedingMatchingToken(token: ts.Node, matchingTokenKind: ts.SyntaxKind.OpenBraceToken | ts.SyntaxKind.OpenParenToken | ts.SyntaxKind.OpenBracketToken, sourceFile: ts.SourceFile) { - const closeTokenText = ts.tokenToString(token.kind)!; - const matchingTokenText = ts.tokenToString(matchingTokenKind)!; +export function findPrecedingMatchingToken(token: Node, matchingTokenKind: SyntaxKind.OpenBraceToken | SyntaxKind.OpenParenToken | SyntaxKind.OpenBracketToken, sourceFile: SourceFile) { + const closeTokenText = tokenToString(token.kind)!; + const matchingTokenText = tokenToString(matchingTokenKind)!; const tokenFullStart = token.getFullStart(); // Text-scan based fast path - can be bamboozled by comments and other trivia, but often provides // a good, fast approximation without too much extra work in the cases where it fails. @@ -1593,34 +1653,34 @@ export function findPrecedingMatchingToken(token: ts.Node, matchingTokenKind: ts } /** @internal */ -export function removeOptionality(type: ts.Type, isOptionalExpression: boolean, isOptionalChain: boolean) { +export function removeOptionality(type: Type, isOptionalExpression: boolean, isOptionalChain: boolean) { return isOptionalExpression ? type.getNonNullableType() : isOptionalChain ? type.getNonOptionalType() : type; } /** @internal */ -export function isPossiblyTypeArgumentPosition(token: ts.Node, sourceFile: ts.SourceFile, checker: ts.TypeChecker): boolean { +export function isPossiblyTypeArgumentPosition(token: Node, sourceFile: SourceFile, checker: TypeChecker): boolean { const info = getPossibleTypeArgumentsInfo(token, sourceFile); - return info !== undefined && (ts.isPartOfTypeNode(info.called) || + return info !== undefined && (isPartOfTypeNode(info.called) || getPossibleGenericSignatures(info.called, info.nTypeArguments, checker).length !== 0 || isPossiblyTypeArgumentPosition(info.called, sourceFile, checker)); } /** @internal */ -export function getPossibleGenericSignatures(called: ts.Expression, typeArgumentCount: number, checker: ts.TypeChecker): readonly ts.Signature[] { +export function getPossibleGenericSignatures(called: Expression, typeArgumentCount: number, checker: TypeChecker): readonly Signature[] { let type = checker.getTypeAtLocation(called); - if (ts.isOptionalChain(called.parent)) { - type = removeOptionality(type, ts.isOptionalChainRoot(called.parent), /*isOptionalChain*/ true); + if (isOptionalChain(called.parent)) { + type = removeOptionality(type, isOptionalChainRoot(called.parent), /*isOptionalChain*/ true); } - const signatures = ts.isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures(); + const signatures = isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures(); return signatures.filter(candidate => !!candidate.typeParameters && candidate.typeParameters.length >= typeArgumentCount); } /** @internal */ export interface PossibleTypeArgumentInfo { - readonly called: ts.Identifier; + readonly called: Identifier; readonly nTypeArguments: number; } @@ -1631,7 +1691,7 @@ export interface PossibleProgramFileInfo { // Get info for an expression like `f <` that may be the start of type arguments. /** @internal */ -export function getPossibleTypeArgumentsInfo(tokenIn: ts.Node | undefined, sourceFile: ts.SourceFile): PossibleTypeArgumentInfo | undefined { +export function getPossibleTypeArgumentsInfo(tokenIn: Node | undefined, sourceFile: SourceFile): PossibleTypeArgumentInfo | undefined { // This is a rare case, but one that saves on a _lot_ of work if true - if the source file has _no_ `<` character, // then there obviously can't be any type arguments - no expensive brace-matching backwards scanning required @@ -1639,7 +1699,7 @@ export function getPossibleTypeArgumentsInfo(tokenIn: ts.Node | undefined, sourc return undefined; } - let token: ts.Node | undefined = tokenIn; + let token: Node | undefined = tokenIn; // This function determines if the node could be type argument position // Since during editing, when type argument list is not complete, // the tree could be of any shape depending on the tokens parsed before current node, @@ -1649,79 +1709,79 @@ export function getPossibleTypeArgumentsInfo(tokenIn: ts.Node | undefined, sourc let nTypeArguments = 0; while (token) { switch (token.kind) { - case ts.SyntaxKind.LessThanToken: + case SyntaxKind.LessThanToken: // Found the beginning of the generic argument expression token = findPrecedingToken(token.getFullStart(), sourceFile); - if (token && token.kind === ts.SyntaxKind.QuestionDotToken) { + if (token && token.kind === SyntaxKind.QuestionDotToken) { token = findPrecedingToken(token.getFullStart(), sourceFile); } - if (!token || !ts.isIdentifier(token)) return undefined; + if (!token || !isIdentifier(token)) return undefined; if (!remainingLessThanTokens) { - return ts.isDeclarationName(token) ? undefined : { called: token, nTypeArguments }; + return isDeclarationName(token) ? undefined : { called: token, nTypeArguments }; } remainingLessThanTokens--; break; - case ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanGreaterThanToken: remainingLessThanTokens = + 3; break; - case ts.SyntaxKind.GreaterThanGreaterThanToken: + case SyntaxKind.GreaterThanGreaterThanToken: remainingLessThanTokens = + 2; break; - case ts.SyntaxKind.GreaterThanToken: + case SyntaxKind.GreaterThanToken: remainingLessThanTokens++; break; - case ts.SyntaxKind.CloseBraceToken: + case SyntaxKind.CloseBraceToken: // This can be object type, skip until we find the matching open brace token // Skip until the matching open brace token - token = findPrecedingMatchingToken(token, ts.SyntaxKind.OpenBraceToken, sourceFile); + token = findPrecedingMatchingToken(token, SyntaxKind.OpenBraceToken, sourceFile); if (!token) return undefined; break; - case ts.SyntaxKind.CloseParenToken: + case SyntaxKind.CloseParenToken: // This can be object type, skip until we find the matching open brace token // Skip until the matching open brace token - token = findPrecedingMatchingToken(token, ts.SyntaxKind.OpenParenToken, sourceFile); + token = findPrecedingMatchingToken(token, SyntaxKind.OpenParenToken, sourceFile); if (!token) return undefined; break; - case ts.SyntaxKind.CloseBracketToken: + case SyntaxKind.CloseBracketToken: // This can be object type, skip until we find the matching open brace token // Skip until the matching open brace token - token = findPrecedingMatchingToken(token, ts.SyntaxKind.OpenBracketToken, sourceFile); + token = findPrecedingMatchingToken(token, SyntaxKind.OpenBracketToken, sourceFile); if (!token) return undefined; break; // Valid tokens in a type name. Skip. - case ts.SyntaxKind.CommaToken: + case SyntaxKind.CommaToken: nTypeArguments++; break; - case ts.SyntaxKind.EqualsGreaterThanToken: + case SyntaxKind.EqualsGreaterThanToken: // falls through - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - case ts.SyntaxKind.BigIntLiteral: - case ts.SyntaxKind.TrueKeyword: - case ts.SyntaxKind.FalseKeyword: + case SyntaxKind.Identifier: + case SyntaxKind.StringLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.TrueKeyword: + case SyntaxKind.FalseKeyword: // falls through - case ts.SyntaxKind.TypeOfKeyword: - case ts.SyntaxKind.ExtendsKeyword: - case ts.SyntaxKind.KeyOfKeyword: - case ts.SyntaxKind.DotToken: - case ts.SyntaxKind.BarToken: - case ts.SyntaxKind.QuestionToken: - case ts.SyntaxKind.ColonToken: + case SyntaxKind.TypeOfKeyword: + case SyntaxKind.ExtendsKeyword: + case SyntaxKind.KeyOfKeyword: + case SyntaxKind.DotToken: + case SyntaxKind.BarToken: + case SyntaxKind.QuestionToken: + case SyntaxKind.ColonToken: break; default: - if (ts.isTypeNode(token)) { + if (isTypeNode(token)) { break; } @@ -1742,87 +1802,87 @@ export function getPossibleTypeArgumentsInfo(tokenIn: ts.Node | undefined, sourc * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position)` * @param predicate Additional predicate to test on the comment range. */ -export function isInComment(sourceFile: ts.SourceFile, position: number, tokenAtPosition?: ts.Node): ts.CommentRange | undefined { - return ts.formatting.getRangeOfEnclosingComment(sourceFile, position, /*precedingToken*/ undefined, tokenAtPosition); +export function isInComment(sourceFile: SourceFile, position: number, tokenAtPosition?: Node): CommentRange | undefined { + return formatting.getRangeOfEnclosingComment(sourceFile, position, /*precedingToken*/ undefined, tokenAtPosition); } /** @internal */ -export function hasDocComment(sourceFile: ts.SourceFile, position: number): boolean { +export function hasDocComment(sourceFile: SourceFile, position: number): boolean { const token = getTokenAtPosition(sourceFile, position); - return !!ts.findAncestor(token, ts.isJSDoc); + return !!findAncestor(token, isJSDoc); } -function nodeHasTokens(n: ts.Node, sourceFile: ts.SourceFileLike): boolean { +function nodeHasTokens(n: Node, sourceFile: SourceFileLike): boolean { // If we have a token or node that has a non-zero width, it must have tokens. // Note: getWidth() does not take trivia into account. - return n.kind === ts.SyntaxKind.EndOfFileToken ? !!(n as ts.EndOfFileToken).jsDoc : n.getWidth(sourceFile) !== 0; + return n.kind === SyntaxKind.EndOfFileToken ? !!(n as EndOfFileToken).jsDoc : n.getWidth(sourceFile) !== 0; } /** @internal */ -export function getNodeModifiers(node: ts.Node, excludeFlags = ts.ModifierFlags.None): string { +export function getNodeModifiers(node: Node, excludeFlags = ModifierFlags.None): string { const result: string[] = []; - const flags = ts.isDeclaration(node) - ? ts.getCombinedNodeFlagsAlwaysIncludeJSDoc(node) & ~excludeFlags - : ts.ModifierFlags.None; + const flags = isDeclaration(node) + ? getCombinedNodeFlagsAlwaysIncludeJSDoc(node) & ~excludeFlags + : ModifierFlags.None; - if (flags & ts.ModifierFlags.Private) result.push(ts.ScriptElementKindModifier.privateMemberModifier); - if (flags & ts.ModifierFlags.Protected) result.push(ts.ScriptElementKindModifier.protectedMemberModifier); - if (flags & ts.ModifierFlags.Public) result.push(ts.ScriptElementKindModifier.publicMemberModifier); - if (flags & ts.ModifierFlags.Static || ts.isClassStaticBlockDeclaration(node)) result.push(ts.ScriptElementKindModifier.staticModifier); - if (flags & ts.ModifierFlags.Abstract) result.push(ts.ScriptElementKindModifier.abstractModifier); - if (flags & ts.ModifierFlags.Export) result.push(ts.ScriptElementKindModifier.exportedModifier); - if (flags & ts.ModifierFlags.Deprecated) result.push(ts.ScriptElementKindModifier.deprecatedModifier); - if (node.flags & ts.NodeFlags.Ambient) result.push(ts.ScriptElementKindModifier.ambientModifier); - if (node.kind === ts.SyntaxKind.ExportAssignment) result.push(ts.ScriptElementKindModifier.exportedModifier); + if (flags & ModifierFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier); + if (flags & ModifierFlags.Protected) result.push(ScriptElementKindModifier.protectedMemberModifier); + if (flags & ModifierFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier); + if (flags & ModifierFlags.Static || isClassStaticBlockDeclaration(node)) result.push(ScriptElementKindModifier.staticModifier); + if (flags & ModifierFlags.Abstract) result.push(ScriptElementKindModifier.abstractModifier); + if (flags & ModifierFlags.Export) result.push(ScriptElementKindModifier.exportedModifier); + if (flags & ModifierFlags.Deprecated) result.push(ScriptElementKindModifier.deprecatedModifier); + if (node.flags & NodeFlags.Ambient) result.push(ScriptElementKindModifier.ambientModifier); + if (node.kind === SyntaxKind.ExportAssignment) result.push(ScriptElementKindModifier.exportedModifier); - return result.length > 0 ? result.join(",") : ts.ScriptElementKindModifier.none; + return result.length > 0 ? result.join(",") : ScriptElementKindModifier.none; } /** @internal */ -export function getTypeArgumentOrTypeParameterList(node: ts.Node): ts.NodeArray | undefined { - if (node.kind === ts.SyntaxKind.TypeReference || node.kind === ts.SyntaxKind.CallExpression) { - return (node as ts.CallExpression).typeArguments; +export function getTypeArgumentOrTypeParameterList(node: Node): NodeArray | undefined { + if (node.kind === SyntaxKind.TypeReference || node.kind === SyntaxKind.CallExpression) { + return (node as CallExpression).typeArguments; } - if (ts.isFunctionLike(node) || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.InterfaceDeclaration) { - return (node as ts.FunctionLikeDeclaration).typeParameters; + if (isFunctionLike(node) || node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.InterfaceDeclaration) { + return (node as FunctionLikeDeclaration).typeParameters; } return undefined; } /** @internal */ -export function isComment(kind: ts.SyntaxKind): boolean { - return kind === ts.SyntaxKind.SingleLineCommentTrivia || kind === ts.SyntaxKind.MultiLineCommentTrivia; +export function isComment(kind: SyntaxKind): boolean { + return kind === SyntaxKind.SingleLineCommentTrivia || kind === SyntaxKind.MultiLineCommentTrivia; } /** @internal */ -export function isStringOrRegularExpressionOrTemplateLiteral(kind: ts.SyntaxKind): boolean { - if (kind === ts.SyntaxKind.StringLiteral - || kind === ts.SyntaxKind.RegularExpressionLiteral - || ts.isTemplateLiteralKind(kind)) { +export function isStringOrRegularExpressionOrTemplateLiteral(kind: SyntaxKind): boolean { + if (kind === SyntaxKind.StringLiteral + || kind === SyntaxKind.RegularExpressionLiteral + || isTemplateLiteralKind(kind)) { return true; } return false; } /** @internal */ -export function isPunctuation(kind: ts.SyntaxKind): boolean { - return ts.SyntaxKind.FirstPunctuation <= kind && kind <= ts.SyntaxKind.LastPunctuation; +export function isPunctuation(kind: SyntaxKind): boolean { + return SyntaxKind.FirstPunctuation <= kind && kind <= SyntaxKind.LastPunctuation; } /** @internal */ -export function isInsideTemplateLiteral(node: ts.TemplateLiteralToken, position: number, sourceFile: ts.SourceFile): boolean { - return ts.isTemplateLiteralKind(node.kind) +export function isInsideTemplateLiteral(node: TemplateLiteralToken, position: number, sourceFile: SourceFile): boolean { + return isTemplateLiteralKind(node.kind) && (node.getStart(sourceFile) < position && position < node.end) || (!!node.isUnterminated && position === node.end); } /** @internal */ -export function isAccessibilityModifier(kind: ts.SyntaxKind) { +export function isAccessibilityModifier(kind: SyntaxKind) { switch (kind) { - case ts.SyntaxKind.PublicKeyword: - case ts.SyntaxKind.PrivateKeyword: - case ts.SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: return true; } @@ -1830,28 +1890,28 @@ export function isAccessibilityModifier(kind: ts.SyntaxKind) { } /** @internal */ -export function cloneCompilerOptions(options: ts.CompilerOptions): ts.CompilerOptions { - const result = ts.clone(options); - ts.setConfigFileInOptions(result, options && options.configFile); +export function cloneCompilerOptions(options: CompilerOptions): CompilerOptions { + const result = clone(options); + setConfigFileInOptions(result, options && options.configFile); return result; } /** @internal */ -export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: ts.Node) { - if (node.kind === ts.SyntaxKind.ArrayLiteralExpression || - node.kind === ts.SyntaxKind.ObjectLiteralExpression) { +export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: Node) { + if (node.kind === SyntaxKind.ArrayLiteralExpression || + node.kind === SyntaxKind.ObjectLiteralExpression) { // [a,b,c] from: // [a, b, c] = someExpression; - if (node.parent.kind === ts.SyntaxKind.BinaryExpression && - (node.parent as ts.BinaryExpression).left === node && - (node.parent as ts.BinaryExpression).operatorToken.kind === ts.SyntaxKind.EqualsToken) { + if (node.parent.kind === SyntaxKind.BinaryExpression && + (node.parent as BinaryExpression).left === node && + (node.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { return true; } // [a, b, c] from: // for([a, b, c] of expression) - if (node.parent.kind === ts.SyntaxKind.ForOfStatement && - (node.parent as ts.ForOfStatement).initializer === node) { + if (node.parent.kind === SyntaxKind.ForOfStatement && + (node.parent as ForOfStatement).initializer === node) { return true; } @@ -1859,7 +1919,7 @@ export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: ts.Node) // [x, [a, b, c] ] = someExpression // or // {x, a: {a, b, c} } = someExpression - if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === ts.SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) { + if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) { return true; } } @@ -1868,127 +1928,127 @@ export function isArrayLiteralOrObjectLiteralDestructuringPattern(node: ts.Node) } /** @internal */ -export function isInReferenceComment(sourceFile: ts.SourceFile, position: number): boolean { +export function isInReferenceComment(sourceFile: SourceFile, position: number): boolean { return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ true); } /** @internal */ -export function isInNonReferenceComment(sourceFile: ts.SourceFile, position: number): boolean { +export function isInNonReferenceComment(sourceFile: SourceFile, position: number): boolean { return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ false); } -function isInReferenceCommentWorker(sourceFile: ts.SourceFile, position: number, shouldBeReference: boolean): boolean { +function isInReferenceCommentWorker(sourceFile: SourceFile, position: number, shouldBeReference: boolean): boolean { const range = isInComment(sourceFile, position, /*tokenAtPosition*/ undefined); return !!range && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end)); } /** @internal */ -export function getReplacementSpanForContextToken(contextToken: ts.Node | undefined) { +export function getReplacementSpanForContextToken(contextToken: Node | undefined) { if (!contextToken) return undefined; switch (contextToken.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - return createTextSpanFromStringLiteralLikeContent(contextToken as ts.StringLiteralLike); + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return createTextSpanFromStringLiteralLikeContent(contextToken as StringLiteralLike); default: return createTextSpanFromNode(contextToken); } } /** @internal */ -export function createTextSpanFromNode(node: ts.Node, sourceFile?: ts.SourceFile, endNode?: ts.Node): ts.TextSpan { - return ts.createTextSpanFromBounds(node.getStart(sourceFile), (endNode || node).getEnd()); +export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile, endNode?: Node): TextSpan { + return createTextSpanFromBounds(node.getStart(sourceFile), (endNode || node).getEnd()); } /** @internal */ -export function createTextSpanFromStringLiteralLikeContent(node: ts.StringLiteralLike) { +export function createTextSpanFromStringLiteralLikeContent(node: StringLiteralLike) { if (node.isUnterminated) return undefined; - return ts.createTextSpanFromBounds(node.getStart() + 1, node.getEnd() - 1); + return createTextSpanFromBounds(node.getStart() + 1, node.getEnd() - 1); } /** @internal */ -export function createTextRangeFromNode(node: ts.Node, sourceFile: ts.SourceFile): ts.TextRange { - return ts.createRange(node.getStart(sourceFile), node.end); +export function createTextRangeFromNode(node: Node, sourceFile: SourceFile): TextRange { + return createRange(node.getStart(sourceFile), node.end); } /** @internal */ -export function createTextSpanFromRange(range: ts.TextRange): ts.TextSpan { - return ts.createTextSpanFromBounds(range.pos, range.end); +export function createTextSpanFromRange(range: TextRange): TextSpan { + return createTextSpanFromBounds(range.pos, range.end); } /** @internal */ -export function createTextRangeFromSpan(span: ts.TextSpan): ts.TextRange { - return ts.createRange(span.start, span.start + span.length); +export function createTextRangeFromSpan(span: TextSpan): TextRange { + return createRange(span.start, span.start + span.length); } /** @internal */ -export function createTextChangeFromStartLength(start: number, length: number, newText: string): ts.TextChange { - return createTextChange(ts.createTextSpan(start, length), newText); +export function createTextChangeFromStartLength(start: number, length: number, newText: string): TextChange { + return createTextChange(createTextSpan(start, length), newText); } /** @internal */ -export function createTextChange(span: ts.TextSpan, newText: string): ts.TextChange { +export function createTextChange(span: TextSpan, newText: string): TextChange { return { span, newText }; } /** @internal */ -export const typeKeywords: readonly ts.SyntaxKind[] = [ - ts.SyntaxKind.AnyKeyword, - ts.SyntaxKind.AssertsKeyword, - ts.SyntaxKind.BigIntKeyword, - ts.SyntaxKind.BooleanKeyword, - ts.SyntaxKind.FalseKeyword, - ts.SyntaxKind.InferKeyword, - ts.SyntaxKind.KeyOfKeyword, - ts.SyntaxKind.NeverKeyword, - ts.SyntaxKind.NullKeyword, - ts.SyntaxKind.NumberKeyword, - ts.SyntaxKind.ObjectKeyword, - ts.SyntaxKind.ReadonlyKeyword, - ts.SyntaxKind.StringKeyword, - ts.SyntaxKind.SymbolKeyword, - ts.SyntaxKind.TrueKeyword, - ts.SyntaxKind.VoidKeyword, - ts.SyntaxKind.UndefinedKeyword, - ts.SyntaxKind.UniqueKeyword, - ts.SyntaxKind.UnknownKeyword, +export const typeKeywords: readonly SyntaxKind[] = [ + SyntaxKind.AnyKeyword, + SyntaxKind.AssertsKeyword, + SyntaxKind.BigIntKeyword, + SyntaxKind.BooleanKeyword, + SyntaxKind.FalseKeyword, + SyntaxKind.InferKeyword, + SyntaxKind.KeyOfKeyword, + SyntaxKind.NeverKeyword, + SyntaxKind.NullKeyword, + SyntaxKind.NumberKeyword, + SyntaxKind.ObjectKeyword, + SyntaxKind.ReadonlyKeyword, + SyntaxKind.StringKeyword, + SyntaxKind.SymbolKeyword, + SyntaxKind.TrueKeyword, + SyntaxKind.VoidKeyword, + SyntaxKind.UndefinedKeyword, + SyntaxKind.UniqueKeyword, + SyntaxKind.UnknownKeyword, ]; /** @internal */ -export function isTypeKeyword(kind: ts.SyntaxKind): boolean { - return ts.contains(typeKeywords, kind); +export function isTypeKeyword(kind: SyntaxKind): boolean { + return contains(typeKeywords, kind); } /** @internal */ -export function isTypeKeywordToken(node: ts.Node): node is ts.Token { - return node.kind === ts.SyntaxKind.TypeKeyword; +export function isTypeKeywordToken(node: Node): node is Token { + return node.kind === SyntaxKind.TypeKeyword; } /** @internal */ -export function isTypeKeywordTokenOrIdentifier(node: ts.Node) { - return isTypeKeywordToken(node) || ts.isIdentifier(node) && node.text === "type"; +export function isTypeKeywordTokenOrIdentifier(node: Node) { + return isTypeKeywordToken(node) || isIdentifier(node) && node.text === "type"; } /** @internal */ /** True if the symbol is for an external module, as opposed to a namespace. */ -export function isExternalModuleSymbol(moduleSymbol: ts.Symbol): boolean { - return !!(moduleSymbol.flags & ts.SymbolFlags.Module) && moduleSymbol.name.charCodeAt(0) === ts.CharacterCodes.doubleQuote; +export function isExternalModuleSymbol(moduleSymbol: Symbol): boolean { + return !!(moduleSymbol.flags & SymbolFlags.Module) && moduleSymbol.name.charCodeAt(0) === CharacterCodes.doubleQuote; } /** @internal */ /** Returns `true` the first time it encounters a node and `false` afterwards. */ -export type NodeSeenTracker = (node: T) => boolean; +export type NodeSeenTracker = (node: T) => boolean; /** @internal */ -export function nodeSeenTracker(): NodeSeenTracker { +export function nodeSeenTracker(): NodeSeenTracker { const seen: true[] = []; return node => { - const id = ts.getNodeId(node); + const id = getNodeId(node); return !seen[id] && (seen[id] = true); }; } /** @internal */ -export function getSnapshotText(snap: ts.IScriptSnapshot): string { +export function getSnapshotText(snap: IScriptSnapshot): string { return snap.getText(0, snap.getLength()); } @@ -2002,54 +2062,54 @@ export function repeatString(str: string, count: number): string { } /** @internal */ -export function skipConstraint(type: ts.Type): ts.Type { +export function skipConstraint(type: Type): Type { return type.isTypeParameter() ? type.getConstraint() || type : type; } /** @internal */ -export function getNameFromPropertyName(name: ts.PropertyName): string | undefined { - return name.kind === ts.SyntaxKind.ComputedPropertyName +export function getNameFromPropertyName(name: PropertyName): string | undefined { + return name.kind === SyntaxKind.ComputedPropertyName // treat computed property names where expression is string/numeric literal as just string/numeric literal - ? ts.isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined - : ts.isPrivateIdentifier(name) ? ts.idText(name) : ts.getTextOfIdentifierOrLiteral(name); + ? isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined + : isPrivateIdentifier(name) ? idText(name) : getTextOfIdentifierOrLiteral(name); } /** @internal */ -export function programContainsModules(program: ts.Program): boolean { +export function programContainsModules(program: Program): boolean { return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!(s.externalModuleIndicator || s.commonJsModuleIndicator)); } /** @internal */ -export function programContainsEsModules(program: ts.Program): boolean { +export function programContainsEsModules(program: Program): boolean { return program.getSourceFiles().some(s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator); } /** @internal */ -export function compilerOptionsIndicateEsModules(compilerOptions: ts.CompilerOptions): boolean { - return !!compilerOptions.module || ts.getEmitScriptTarget(compilerOptions) >= ts.ScriptTarget.ES2015 || !!compilerOptions.noEmit; +export function compilerOptionsIndicateEsModules(compilerOptions: CompilerOptions): boolean { + return !!compilerOptions.module || getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 || !!compilerOptions.noEmit; } /** @internal */ -export function createModuleSpecifierResolutionHost(program: ts.Program, host: ts.LanguageServiceHost): ts.ModuleSpecifierResolutionHost { +export function createModuleSpecifierResolutionHost(program: Program, host: LanguageServiceHost): ModuleSpecifierResolutionHost { // Mix in `getSymlinkCache` from Program when host doesn't have it // in order for non-Project hosts to have a symlinks cache. return { fileExists: fileName => program.fileExists(fileName), getCurrentDirectory: () => host.getCurrentDirectory(), - readFile: ts.maybeBind(host, host.readFile), - useCaseSensitiveFileNames: ts.maybeBind(host, host.useCaseSensitiveFileNames), - getSymlinkCache: ts.maybeBind(host, host.getSymlinkCache) || program.getSymlinkCache, - getModuleSpecifierCache: ts.maybeBind(host, host.getModuleSpecifierCache), + readFile: maybeBind(host, host.readFile), + useCaseSensitiveFileNames: maybeBind(host, host.useCaseSensitiveFileNames), + getSymlinkCache: maybeBind(host, host.getSymlinkCache) || program.getSymlinkCache, + getModuleSpecifierCache: maybeBind(host, host.getModuleSpecifierCache), getPackageJsonInfoCache: () => program.getModuleResolutionCache()?.getPackageJsonInfoCache(), - getGlobalTypingsCacheLocation: ts.maybeBind(host, host.getGlobalTypingsCacheLocation), + getGlobalTypingsCacheLocation: maybeBind(host, host.getGlobalTypingsCacheLocation), redirectTargetsMap: program.redirectTargetsMap, getProjectReferenceRedirect: fileName => program.getProjectReferenceRedirect(fileName), isSourceOfProjectReferenceRedirect: fileName => program.isSourceOfProjectReferenceRedirect(fileName), - getNearestAncestorDirectoryWithPackageJson: ts.maybeBind(host, host.getNearestAncestorDirectoryWithPackageJson), + getNearestAncestorDirectoryWithPackageJson: maybeBind(host, host.getNearestAncestorDirectoryWithPackageJson), getFileIncludeReasons: () => program.getFileIncludeReasons(), }; } /** @internal */ -export function getModuleSpecifierResolverHost(program: ts.Program, host: ts.LanguageServiceHost): ts.SymbolTracker["moduleResolverHost"] { +export function getModuleSpecifierResolverHost(program: Program, host: LanguageServiceHost): SymbolTracker["moduleResolverHost"] { return { ...createModuleSpecifierResolutionHost(program, host), getCommonSourceDirectory: () => program.getCommonSourceDirectory(), @@ -2057,53 +2117,53 @@ export function getModuleSpecifierResolverHost(program: ts.Program, host: ts.Lan } /** @internal */ -export function moduleResolutionRespectsExports(moduleResolution: ts.ModuleResolutionKind): boolean { - return moduleResolution >= ts.ModuleResolutionKind.Node16 && moduleResolution <= ts.ModuleResolutionKind.NodeNext; +export function moduleResolutionRespectsExports(moduleResolution: ModuleResolutionKind): boolean { + return moduleResolution >= ModuleResolutionKind.Node16 && moduleResolution <= ModuleResolutionKind.NodeNext; } /** @internal */ -export function moduleResolutionUsesNodeModules(moduleResolution: ts.ModuleResolutionKind): boolean { - return moduleResolution === ts.ModuleResolutionKind.NodeJs || moduleResolution >= ts.ModuleResolutionKind.Node16 && moduleResolution <= ts.ModuleResolutionKind.NodeNext; +export function moduleResolutionUsesNodeModules(moduleResolution: ModuleResolutionKind): boolean { + return moduleResolution === ModuleResolutionKind.NodeJs || moduleResolution >= ModuleResolutionKind.Node16 && moduleResolution <= ModuleResolutionKind.NodeNext; } /** @internal */ -export function makeImportIfNecessary(defaultImport: ts.Identifier | undefined, namedImports: readonly ts.ImportSpecifier[] | undefined, moduleSpecifier: string, quotePreference: QuotePreference): ts.ImportDeclaration | undefined { +export function makeImportIfNecessary(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string, quotePreference: QuotePreference): ImportDeclaration | undefined { return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined; } /** @internal */ -export function makeImport(defaultImport: ts.Identifier | undefined, namedImports: readonly ts.ImportSpecifier[] | undefined, moduleSpecifier: string | ts.Expression, quotePreference: QuotePreference, isTypeOnly?: boolean): ts.ImportDeclaration { - return ts.factory.createImportDeclaration( +export function makeImport(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string | Expression, quotePreference: QuotePreference, isTypeOnly?: boolean): ImportDeclaration { + return factory.createImportDeclaration( /*modifiers*/ undefined, defaultImport || namedImports - ? ts.factory.createImportClause(!!isTypeOnly, defaultImport, namedImports && namedImports.length ? ts.factory.createNamedImports(namedImports) : undefined) + ? factory.createImportClause(!!isTypeOnly, defaultImport, namedImports && namedImports.length ? factory.createNamedImports(namedImports) : undefined) : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier, /*assertClause*/ undefined); } /** @internal */ -export function makeStringLiteral(text: string, quotePreference: QuotePreference): ts.StringLiteral { - return ts.factory.createStringLiteral(text, quotePreference === QuotePreference.Single); +export function makeStringLiteral(text: string, quotePreference: QuotePreference): StringLiteral { + return factory.createStringLiteral(text, quotePreference === QuotePreference.Single); } /** @internal */ export const enum QuotePreference { Single, Double } /** @internal */ -export function quotePreferenceFromString(str: ts.StringLiteral, sourceFile: ts.SourceFile): QuotePreference { - return ts.isStringDoubleQuoted(str, sourceFile) ? QuotePreference.Double : QuotePreference.Single; +export function quotePreferenceFromString(str: StringLiteral, sourceFile: SourceFile): QuotePreference { + return isStringDoubleQuoted(str, sourceFile) ? QuotePreference.Double : QuotePreference.Single; } /** @internal */ -export function getQuotePreference(sourceFile: ts.SourceFile, preferences: ts.UserPreferences): QuotePreference { +export function getQuotePreference(sourceFile: SourceFile, preferences: UserPreferences): QuotePreference { if (preferences.quotePreference && preferences.quotePreference !== "auto") { return preferences.quotePreference === "single" ? QuotePreference.Single : QuotePreference.Double; } else { // ignore synthetic import added when importHelpers: true const firstModuleSpecifier = sourceFile.imports && - ts.find(sourceFile.imports, n => ts.isStringLiteral(n) && !ts.nodeIsSynthesized(n.parent)) as ts.StringLiteral; + find(sourceFile.imports, n => isStringLiteral(n) && !nodeIsSynthesized(n.parent)) as StringLiteral; return firstModuleSpecifier ? quotePreferenceFromString(firstModuleSpecifier, sourceFile) : QuotePreference.Double; } } @@ -2113,60 +2173,60 @@ export function getQuoteFromPreference(qp: QuotePreference): string { switch (qp) { case QuotePreference.Single: return "'"; case QuotePreference.Double: return '"'; - default: return ts.Debug.assertNever(qp); + default: return Debug.assertNever(qp); } } /** @internal */ -export function symbolNameNoDefault(symbol: ts.Symbol): string | undefined { +export function symbolNameNoDefault(symbol: Symbol): string | undefined { const escaped = symbolEscapedNameNoDefault(symbol); - return escaped === undefined ? undefined : ts.unescapeLeadingUnderscores(escaped); + return escaped === undefined ? undefined : unescapeLeadingUnderscores(escaped); } /** @internal */ -export function symbolEscapedNameNoDefault(symbol: ts.Symbol): ts.__String | undefined { - if (symbol.escapedName !== ts.InternalSymbolName.Default) { +export function symbolEscapedNameNoDefault(symbol: Symbol): __String | undefined { + if (symbol.escapedName !== InternalSymbolName.Default) { return symbol.escapedName; } - return ts.firstDefined(symbol.declarations, decl => { - const name = ts.getNameOfDeclaration(decl); - return name && name.kind === ts.SyntaxKind.Identifier ? name.escapedText : undefined; + return firstDefined(symbol.declarations, decl => { + const name = getNameOfDeclaration(decl); + return name && name.kind === SyntaxKind.Identifier ? name.escapedText : undefined; }); } /** @internal */ -export function isModuleSpecifierLike(node: ts.Node): node is ts.StringLiteralLike { - return ts.isStringLiteralLike(node) && ( - ts.isExternalModuleReference(node.parent) || - ts.isImportDeclaration(node.parent) || - ts.isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) && node.parent.arguments[0] === node || - ts.isImportCall(node.parent) && node.parent.arguments[0] === node); +export function isModuleSpecifierLike(node: Node): node is StringLiteralLike { + return isStringLiteralLike(node) && ( + isExternalModuleReference(node.parent) || + isImportDeclaration(node.parent) || + isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ false) && node.parent.arguments[0] === node || + isImportCall(node.parent) && node.parent.arguments[0] === node); } /** @internal */ -export type ObjectBindingElementWithoutPropertyName = ts.BindingElement & { name: ts.Identifier }; +export type ObjectBindingElementWithoutPropertyName = BindingElement & { name: Identifier }; /** @internal */ -export function isObjectBindingElementWithoutPropertyName(bindingElement: ts.Node): bindingElement is ObjectBindingElementWithoutPropertyName { - return ts.isBindingElement(bindingElement) && - ts.isObjectBindingPattern(bindingElement.parent) && - ts.isIdentifier(bindingElement.name) && +export function isObjectBindingElementWithoutPropertyName(bindingElement: Node): bindingElement is ObjectBindingElementWithoutPropertyName { + return isBindingElement(bindingElement) && + isObjectBindingPattern(bindingElement.parent) && + isIdentifier(bindingElement.name) && !bindingElement.propertyName; } /** @internal */ -export function getPropertySymbolFromBindingElement(checker: ts.TypeChecker, bindingElement: ObjectBindingElementWithoutPropertyName): ts.Symbol | undefined { +export function getPropertySymbolFromBindingElement(checker: TypeChecker, bindingElement: ObjectBindingElementWithoutPropertyName): Symbol | undefined { const typeOfPattern = checker.getTypeAtLocation(bindingElement.parent); return typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text); } /** @internal */ -export function getParentNodeInSpan(node: ts.Node | undefined, file: ts.SourceFile, span: ts.TextSpan): ts.Node | undefined { +export function getParentNodeInSpan(node: Node | undefined, file: SourceFile, span: TextSpan): Node | undefined { if (!node) return undefined; while (node.parent) { - if (ts.isSourceFile(node.parent) || !spanContainsNode(span, node.parent, file)) { + if (isSourceFile(node.parent) || !spanContainsNode(span, node.parent, file)) { return node; } @@ -2174,32 +2234,32 @@ export function getParentNodeInSpan(node: ts.Node | undefined, file: ts.SourceFi } } -function spanContainsNode(span: ts.TextSpan, node: ts.Node, file: ts.SourceFile): boolean { - return ts.textSpanContainsPosition(span, node.getStart(file)) && - node.getEnd() <= ts.textSpanEnd(span); +function spanContainsNode(span: TextSpan, node: Node, file: SourceFile): boolean { + return textSpanContainsPosition(span, node.getStart(file)) && + node.getEnd() <= textSpanEnd(span); } /** @internal */ -export function findModifier(node: ts.Node, kind: ts.Modifier["kind"]): ts.Modifier | undefined { - return ts.canHaveModifiers(node) ? ts.find(node.modifiers, (m): m is ts.Modifier => m.kind === kind) : undefined; +export function findModifier(node: Node, kind: Modifier["kind"]): Modifier | undefined { + return canHaveModifiers(node) ? find(node.modifiers, (m): m is Modifier => m.kind === kind) : undefined; } /** @internal */ -export function insertImports(changes: ts.textChanges.ChangeTracker, sourceFile: ts.SourceFile, imports: ts.AnyImportOrRequireStatement | readonly ts.AnyImportOrRequireStatement[], blankLineBetween: boolean): void { - const decl = ts.isArray(imports) ? imports[0] : imports; - const importKindPredicate: (node: ts.Node) => node is ts.AnyImportOrRequireStatement = decl.kind === ts.SyntaxKind.VariableStatement ? ts.isRequireVariableStatement : ts.isAnyImportSyntax; - const existingImportStatements = ts.filter(sourceFile.statements, importKindPredicate); - const sortedNewImports = ts.isArray(imports) ? ts.stableSort(imports, ts.OrganizeImports.compareImportsOrRequireStatements) : [imports]; +export function insertImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, imports: AnyImportOrRequireStatement | readonly AnyImportOrRequireStatement[], blankLineBetween: boolean): void { + const decl = isArray(imports) ? imports[0] : imports; + const importKindPredicate: (node: Node) => node is AnyImportOrRequireStatement = decl.kind === SyntaxKind.VariableStatement ? isRequireVariableStatement : isAnyImportSyntax; + const existingImportStatements = filter(sourceFile.statements, importKindPredicate); + const sortedNewImports = isArray(imports) ? stableSort(imports, OrganizeImports.compareImportsOrRequireStatements) : [imports]; if (!existingImportStatements.length) { changes.insertNodesAtTopOfFile(sourceFile, sortedNewImports, blankLineBetween); } - else if (existingImportStatements && ts.OrganizeImports.importsAreSorted(existingImportStatements)) { + else if (existingImportStatements && OrganizeImports.importsAreSorted(existingImportStatements)) { for (const newImport of sortedNewImports) { - const insertionIndex = ts.OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); + const insertionIndex = OrganizeImports.getImportDeclarationInsertionIndex(existingImportStatements, newImport); if (insertionIndex === 0) { // If the first import is top-of-file, insert after the leading comment which is likely the header. const options = existingImportStatements[0] === sourceFile.statements[0] ? - { leadingTriviaOption: ts.textChanges.LeadingTriviaOption.Exclude } : {}; + { leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude } : {}; changes.insertNodeBefore(sourceFile, existingImportStatements[0], newImport, /*blankLineBetween*/ false, options); } else { @@ -2209,7 +2269,7 @@ export function insertImports(changes: ts.textChanges.ChangeTracker, sourceFile: } } else { - const lastExistingImport = ts.lastOrUndefined(existingImportStatements); + const lastExistingImport = lastOrUndefined(existingImportStatements); if (lastExistingImport) { changes.insertNodesAfter(sourceFile, lastExistingImport, sortedNewImports); } @@ -2220,17 +2280,17 @@ export function insertImports(changes: ts.textChanges.ChangeTracker, sourceFile: } /** @internal */ -export function getTypeKeywordOfTypeOnlyImport(importClause: ts.ImportClause, sourceFile: ts.SourceFile): ts.Token { - ts.Debug.assert(importClause.isTypeOnly); - return ts.cast(importClause.getChildAt(0, sourceFile), isTypeKeywordToken); +export function getTypeKeywordOfTypeOnlyImport(importClause: ImportClause, sourceFile: SourceFile): Token { + Debug.assert(importClause.isTypeOnly); + return cast(importClause.getChildAt(0, sourceFile), isTypeKeywordToken); } /** @internal */ -export function textSpansEqual(a: ts.TextSpan | undefined, b: ts.TextSpan | undefined): boolean { +export function textSpansEqual(a: TextSpan | undefined, b: TextSpan | undefined): boolean { return !!a && !!b && a.start === b.start && a.length === b.length; } /** @internal */ -export function documentSpansEqual(a: ts.DocumentSpan, b: ts.DocumentSpan): boolean { +export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean { return a.fileName === b.fileName && textSpansEqual(a.textSpan, b.textSpan); } @@ -2257,7 +2317,7 @@ export function forEachUnique(array: readonly T[] | undefined, callback: ( /** @internal */ export function isTextWhiteSpaceLike(text: string, startPos: number, endPos: number): boolean { for (let i = startPos; i < endPos; i++) { - if (!ts.isWhiteSpaceLike(text.charCodeAt(i))) { + if (!isWhiteSpaceLike(text.charCodeAt(i))) { return false; } } @@ -2266,13 +2326,13 @@ export function isTextWhiteSpaceLike(text: string, startPos: number, endPos: num } /** @internal */ -export function getMappedLocation(location: ts.DocumentPosition, sourceMapper: ts.SourceMapper, fileExists: ((path: string) => boolean) | undefined): ts.DocumentPosition | undefined { +export function getMappedLocation(location: DocumentPosition, sourceMapper: SourceMapper, fileExists: ((path: string) => boolean) | undefined): DocumentPosition | undefined { const mapsTo = sourceMapper.tryGetSourcePosition(location); - return mapsTo && (!fileExists || fileExists(ts.normalizePath(mapsTo.fileName)) ? mapsTo : undefined); + return mapsTo && (!fileExists || fileExists(normalizePath(mapsTo.fileName)) ? mapsTo : undefined); } /** @internal */ -export function getMappedDocumentSpan(documentSpan: ts.DocumentSpan, sourceMapper: ts.SourceMapper, fileExists?: (path: string) => boolean): ts.DocumentSpan | undefined { +export function getMappedDocumentSpan(documentSpan: DocumentSpan, sourceMapper: SourceMapper, fileExists?: (path: string) => boolean): DocumentSpan | undefined { const { fileName, textSpan } = documentSpan; const newPosition = getMappedLocation({ fileName, pos: textSpan.start }, sourceMapper, fileExists); if (!newPosition) return undefined; @@ -2294,7 +2354,7 @@ export function getMappedDocumentSpan(documentSpan: ts.DocumentSpan, sourceMappe } /** @internal */ -export function getMappedContextSpan(documentSpan: ts.DocumentSpan, sourceMapper: ts.SourceMapper, fileExists?: (path: string) => boolean): ts.TextSpan | undefined { +export function getMappedContextSpan(documentSpan: DocumentSpan, sourceMapper: SourceMapper, fileExists?: (path: string) => boolean): TextSpan | undefined { const contextSpanStart = documentSpan.contextSpan && getMappedLocation( { fileName: documentSpan.fileName, pos: documentSpan.contextSpan.start }, sourceMapper, @@ -2315,42 +2375,42 @@ export function getMappedContextSpan(documentSpan: ts.DocumentSpan, sourceMapper // Display-part writer helpers // #region /** @internal */ -export function isFirstDeclarationOfSymbolParameter(symbol: ts.Symbol) { - const declaration = symbol.declarations ? ts.firstOrUndefined(symbol.declarations) : undefined; - return !!ts.findAncestor(declaration, n => - ts.isParameter(n) ? true : ts.isBindingElement(n) || ts.isObjectBindingPattern(n) || ts.isArrayBindingPattern(n) ? false : "quit"); +export function isFirstDeclarationOfSymbolParameter(symbol: Symbol) { + const declaration = symbol.declarations ? firstOrUndefined(symbol.declarations) : undefined; + return !!findAncestor(declaration, n => + isParameter(n) ? true : isBindingElement(n) || isObjectBindingPattern(n) || isArrayBindingPattern(n) ? false : "quit"); } const displayPartWriter = getDisplayPartWriter(); -function getDisplayPartWriter(): ts.DisplayPartsSymbolWriter { - const absoluteMaximumLength = ts.defaultMaximumTruncationLength * 10; // A hard cutoff to avoid overloading the messaging channel in worst-case scenarios - let displayParts: ts.SymbolDisplayPart[]; +function getDisplayPartWriter(): DisplayPartsSymbolWriter { + const absoluteMaximumLength = defaultMaximumTruncationLength * 10; // A hard cutoff to avoid overloading the messaging channel in worst-case scenarios + let displayParts: SymbolDisplayPart[]; let lineStart: boolean; let indent: number; let length: number; resetWriter(); - const unknownWrite = (text: string) => writeKind(text, ts.SymbolDisplayPartKind.text); + const unknownWrite = (text: string) => writeKind(text, SymbolDisplayPartKind.text); return { displayParts: () => { const finalText = displayParts.length && displayParts[displayParts.length - 1].text; if (length > absoluteMaximumLength && finalText && finalText !== "...") { - if (!ts.isWhiteSpaceLike(finalText.charCodeAt(finalText.length - 1))) { - displayParts.push(displayPart(" ", ts.SymbolDisplayPartKind.space)); + if (!isWhiteSpaceLike(finalText.charCodeAt(finalText.length - 1))) { + displayParts.push(displayPart(" ", SymbolDisplayPartKind.space)); } - displayParts.push(displayPart("...", ts.SymbolDisplayPartKind.punctuation)); + displayParts.push(displayPart("...", SymbolDisplayPartKind.punctuation)); } return displayParts; }, - writeKeyword: text => writeKind(text, ts.SymbolDisplayPartKind.keyword), - writeOperator: text => writeKind(text, ts.SymbolDisplayPartKind.operator), - writePunctuation: text => writeKind(text, ts.SymbolDisplayPartKind.punctuation), - writeTrailingSemicolon: text => writeKind(text, ts.SymbolDisplayPartKind.punctuation), - writeSpace: text => writeKind(text, ts.SymbolDisplayPartKind.space), - writeStringLiteral: text => writeKind(text, ts.SymbolDisplayPartKind.stringLiteral), - writeParameter: text => writeKind(text, ts.SymbolDisplayPartKind.parameterName), - writeProperty: text => writeKind(text, ts.SymbolDisplayPartKind.propertyName), - writeLiteral: text => writeKind(text, ts.SymbolDisplayPartKind.stringLiteral), + writeKeyword: text => writeKind(text, SymbolDisplayPartKind.keyword), + writeOperator: text => writeKind(text, SymbolDisplayPartKind.operator), + writePunctuation: text => writeKind(text, SymbolDisplayPartKind.punctuation), + writeTrailingSemicolon: text => writeKind(text, SymbolDisplayPartKind.punctuation), + writeSpace: text => writeKind(text, SymbolDisplayPartKind.space), + writeStringLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), + writeParameter: text => writeKind(text, SymbolDisplayPartKind.parameterName), + writeProperty: text => writeKind(text, SymbolDisplayPartKind.propertyName), + writeLiteral: text => writeKind(text, SymbolDisplayPartKind.stringLiteral), writeSymbol, writeLine, write: unknownWrite, @@ -2362,37 +2422,37 @@ function getDisplayPartWriter(): ts.DisplayPartsSymbolWriter { isAtStartOfLine: () => false, hasTrailingWhitespace: () => false, hasTrailingComment: () => false, - rawWrite: ts.notImplemented, + rawWrite: notImplemented, getIndent: () => indent, increaseIndent: () => { indent++; }, decreaseIndent: () => { indent--; }, clear: resetWriter, trackSymbol: () => false, - reportInaccessibleThisError: ts.noop, - reportInaccessibleUniqueSymbolError: ts.noop, - reportPrivateInBaseOfClassExpression: ts.noop, + reportInaccessibleThisError: noop, + reportInaccessibleUniqueSymbolError: noop, + reportPrivateInBaseOfClassExpression: noop, }; function writeIndent() { if (length > absoluteMaximumLength) return; if (lineStart) { - const indentString = ts.getIndentString(indent); + const indentString = getIndentString(indent); if (indentString) { length += indentString.length; - displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space)); + displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space)); } lineStart = false; } } - function writeKind(text: string, kind: ts.SymbolDisplayPartKind) { + function writeKind(text: string, kind: SymbolDisplayPartKind) { if (length > absoluteMaximumLength) return; writeIndent(); length += text.length; displayParts.push(displayPart(text, kind)); } - function writeSymbol(text: string, symbol: ts.Symbol) { + function writeSymbol(text: string, symbol: Symbol) { if (length > absoluteMaximumLength) return; writeIndent(); length += text.length; @@ -2415,71 +2475,71 @@ function getDisplayPartWriter(): ts.DisplayPartsSymbolWriter { } /** @internal */ -export function symbolPart(text: string, symbol: ts.Symbol) { +export function symbolPart(text: string, symbol: Symbol) { return displayPart(text, displayPartKind(symbol)); - function displayPartKind(symbol: ts.Symbol): ts.SymbolDisplayPartKind { + function displayPartKind(symbol: Symbol): SymbolDisplayPartKind { const flags = symbol.flags; - if (flags & ts.SymbolFlags.Variable) { - return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName; + if (flags & SymbolFlags.Variable) { + return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName; } - if (flags & ts.SymbolFlags.Property) return ts.SymbolDisplayPartKind.propertyName; - if (flags & ts.SymbolFlags.GetAccessor) return ts.SymbolDisplayPartKind.propertyName; - if (flags & ts.SymbolFlags.SetAccessor) return ts.SymbolDisplayPartKind.propertyName; - if (flags & ts.SymbolFlags.EnumMember) return ts.SymbolDisplayPartKind.enumMemberName; - if (flags & ts.SymbolFlags.Function) return ts.SymbolDisplayPartKind.functionName; - if (flags & ts.SymbolFlags.Class) return ts.SymbolDisplayPartKind.className; - if (flags & ts.SymbolFlags.Interface) return ts.SymbolDisplayPartKind.interfaceName; - if (flags & ts.SymbolFlags.Enum) return ts.SymbolDisplayPartKind.enumName; - if (flags & ts.SymbolFlags.Module) return ts.SymbolDisplayPartKind.moduleName; - if (flags & ts.SymbolFlags.Method) return ts.SymbolDisplayPartKind.methodName; - if (flags & ts.SymbolFlags.TypeParameter) return ts.SymbolDisplayPartKind.typeParameterName; - if (flags & ts.SymbolFlags.TypeAlias) return ts.SymbolDisplayPartKind.aliasName; - if (flags & ts.SymbolFlags.Alias) return ts.SymbolDisplayPartKind.aliasName; + if (flags & SymbolFlags.Property) return SymbolDisplayPartKind.propertyName; + if (flags & SymbolFlags.GetAccessor) return SymbolDisplayPartKind.propertyName; + if (flags & SymbolFlags.SetAccessor) return SymbolDisplayPartKind.propertyName; + if (flags & SymbolFlags.EnumMember) return SymbolDisplayPartKind.enumMemberName; + if (flags & SymbolFlags.Function) return SymbolDisplayPartKind.functionName; + if (flags & SymbolFlags.Class) return SymbolDisplayPartKind.className; + if (flags & SymbolFlags.Interface) return SymbolDisplayPartKind.interfaceName; + if (flags & SymbolFlags.Enum) return SymbolDisplayPartKind.enumName; + if (flags & SymbolFlags.Module) return SymbolDisplayPartKind.moduleName; + if (flags & SymbolFlags.Method) return SymbolDisplayPartKind.methodName; + if (flags & SymbolFlags.TypeParameter) return SymbolDisplayPartKind.typeParameterName; + if (flags & SymbolFlags.TypeAlias) return SymbolDisplayPartKind.aliasName; + if (flags & SymbolFlags.Alias) return SymbolDisplayPartKind.aliasName; - return ts.SymbolDisplayPartKind.text; + return SymbolDisplayPartKind.text; } } /** @internal */ -export function displayPart(text: string, kind: ts.SymbolDisplayPartKind): ts.SymbolDisplayPart { - return { text, kind: ts.SymbolDisplayPartKind[kind] }; +export function displayPart(text: string, kind: SymbolDisplayPartKind): SymbolDisplayPart { + return { text, kind: SymbolDisplayPartKind[kind] }; } /** @internal */ export function spacePart() { - return displayPart(" ", ts.SymbolDisplayPartKind.space); + return displayPart(" ", SymbolDisplayPartKind.space); } /** @internal */ -export function keywordPart(kind: ts.SyntaxKind) { - return displayPart(ts.tokenToString(kind)!, ts.SymbolDisplayPartKind.keyword); +export function keywordPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.keyword); } /** @internal */ -export function punctuationPart(kind: ts.SyntaxKind) { - return displayPart(ts.tokenToString(kind)!, ts.SymbolDisplayPartKind.punctuation); +export function punctuationPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.punctuation); } /** @internal */ -export function operatorPart(kind: ts.SyntaxKind) { - return displayPart(ts.tokenToString(kind)!, ts.SymbolDisplayPartKind.operator); +export function operatorPart(kind: SyntaxKind) { + return displayPart(tokenToString(kind)!, SymbolDisplayPartKind.operator); } /** @internal */ export function parameterNamePart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.parameterName); + return displayPart(text, SymbolDisplayPartKind.parameterName); } /** @internal */ export function propertyNamePart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.propertyName); + return displayPart(text, SymbolDisplayPartKind.propertyName); } /** @internal */ export function textOrKeywordPart(text: string) { - const kind = ts.stringToToken(text); + const kind = stringToToken(text); return kind === undefined ? textPart(text) : keywordPart(kind); @@ -2487,31 +2547,31 @@ export function textOrKeywordPart(text: string) { /** @internal */ export function textPart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.text); + return displayPart(text, SymbolDisplayPartKind.text); } /** @internal */ export function typeAliasNamePart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.aliasName); + return displayPart(text, SymbolDisplayPartKind.aliasName); } /** @internal */ export function typeParameterNamePart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.typeParameterName); + return displayPart(text, SymbolDisplayPartKind.typeParameterName); } /** @internal */ export function linkTextPart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.linkText); + return displayPart(text, SymbolDisplayPartKind.linkText); } /** @internal */ -export function linkNamePart(text: string, target: ts.Declaration): ts.JSDocLinkDisplayPart { +export function linkNamePart(text: string, target: Declaration): JSDocLinkDisplayPart { return { text, - kind: ts.SymbolDisplayPartKind[ts.SymbolDisplayPartKind.linkName], + kind: SymbolDisplayPartKind[SymbolDisplayPartKind.linkName], target: { - fileName: ts.getSourceFileOfNode(target).fileName, + fileName: getSourceFileOfNode(target).fileName, textSpan: createTextSpanFromNode(target), }, }; @@ -2519,13 +2579,13 @@ export function linkNamePart(text: string, target: ts.Declaration): ts.JSDocLink /** @internal */ export function linkPart(text: string) { - return displayPart(text, ts.SymbolDisplayPartKind.link); + return displayPart(text, SymbolDisplayPartKind.link); } /** @internal */ -export function buildLinkParts(link: ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain, checker?: ts.TypeChecker): ts.SymbolDisplayPart[] { - const prefix = ts.isJSDocLink(link) ? "link" - : ts.isJSDocLinkCode(link) ? "linkcode" +export function buildLinkParts(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain, checker?: TypeChecker): SymbolDisplayPart[] { + const prefix = isJSDocLink(link) ? "link" + : isJSDocLinkCode(link) ? "linkcode" : "linkplain"; const parts = [linkPart(`{@${prefix} `)]; if (!link.name) { @@ -2536,7 +2596,7 @@ export function buildLinkParts(link: ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocL else { const symbol = checker?.getSymbolAtLocation(link.name); const suffix = findLinkNameEnd(link.text); - const name = ts.getTextOfNode(link.name) + link.text.slice(0, suffix); + const name = getTextOfNode(link.name) + link.text.slice(0, suffix); const text = skipSeparatorFromLinkText(link.text.slice(suffix)); const decl = symbol?.valueDeclaration || symbol?.declarations?.[0]; if (decl) { @@ -2553,8 +2613,8 @@ export function buildLinkParts(link: ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocL function skipSeparatorFromLinkText(text: string) { let pos = 0; - if (text.charCodeAt(pos++) === ts.CharacterCodes.bar) { - while (pos < text.length && text.charCodeAt(pos) === ts.CharacterCodes.space) pos++; + if (text.charCodeAt(pos++) === CharacterCodes.bar) { + while (pos < text.length && text.charCodeAt(pos) === CharacterCodes.space) pos++; return text.slice(pos); } return text; @@ -2579,7 +2639,7 @@ const carriageReturnLineFeed = "\r\n"; /** * The default is CRLF. */ -export function getNewLineOrDefaultFromHost(host: ts.FormattingHost, formatSettings?: ts.FormatCodeSettings) { +export function getNewLineOrDefaultFromHost(host: FormattingHost, formatSettings?: FormatCodeSettings) { return formatSettings?.newLineCharacter || host.getNewLine?.() || carriageReturnLineFeed; @@ -2587,11 +2647,11 @@ export function getNewLineOrDefaultFromHost(host: ts.FormattingHost, formatSetti /** @internal */ export function lineBreakPart() { - return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak); + return displayPart("\n", SymbolDisplayPartKind.lineBreak); } /** @internal */ -export function mapToDisplayParts(writeDisplayParts: (writer: ts.DisplayPartsSymbolWriter) => void): ts.SymbolDisplayPart[] { +export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] { try { writeDisplayParts(displayPartWriter); return displayPartWriter.displayParts(); @@ -2602,78 +2662,78 @@ export function mapToDisplayParts(writeDisplayParts: (writer: ts.DisplayPartsSym } /** @internal */ -export function typeToDisplayParts(typechecker: ts.TypeChecker, type: ts.Type, enclosingDeclaration?: ts.Node, flags: ts.TypeFormatFlags = ts.TypeFormatFlags.None): ts.SymbolDisplayPart[] { +export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typechecker.writeType(type, enclosingDeclaration, flags | ts.TypeFormatFlags.MultilineObjectLiterals | ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); + typechecker.writeType(type, enclosingDeclaration, flags | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); }); } /** @internal */ -export function symbolToDisplayParts(typeChecker: ts.TypeChecker, symbol: ts.Symbol, enclosingDeclaration?: ts.Node, meaning?: ts.SymbolFlags, flags: ts.SymbolFormatFlags = ts.SymbolFormatFlags.None): ts.SymbolDisplayPart[] { +export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.None): SymbolDisplayPart[] { return mapToDisplayParts(writer => { - typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | ts.SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); + typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | SymbolFormatFlags.UseAliasDefinedOutsideCurrentScope, writer); }); } /** @internal */ -export function signatureToDisplayParts(typechecker: ts.TypeChecker, signature: ts.Signature, enclosingDeclaration?: ts.Node, flags: ts.TypeFormatFlags = ts.TypeFormatFlags.None): ts.SymbolDisplayPart[] { - flags |= ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | ts.TypeFormatFlags.MultilineObjectLiterals | ts.TypeFormatFlags.WriteTypeArgumentsOfSignature | ts.TypeFormatFlags.OmitParameterModifiers; +export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.None): SymbolDisplayPart[] { + flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope | TypeFormatFlags.MultilineObjectLiterals | TypeFormatFlags.WriteTypeArgumentsOfSignature | TypeFormatFlags.OmitParameterModifiers; return mapToDisplayParts(writer => { typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer); }); } /** @internal */ -export function nodeToDisplayParts(node: ts.Node, enclosingDeclaration: ts.Node): ts.SymbolDisplayPart[] { +export function nodeToDisplayParts(node: Node, enclosingDeclaration: Node): SymbolDisplayPart[] { const file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(writer => { - const printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); - printer.writeNode(ts.EmitHint.Unspecified, node, file, writer); + const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + printer.writeNode(EmitHint.Unspecified, node, file, writer); }); } /** @internal */ -export function isImportOrExportSpecifierName(location: ts.Node): location is ts.Identifier { - return !!location.parent && ts.isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location; +export function isImportOrExportSpecifierName(location: Node): location is Identifier { + return !!location.parent && isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location; } /** @internal */ -export function getScriptKind(fileName: string, host: ts.LanguageServiceHost): ts.ScriptKind { +export function getScriptKind(fileName: string, host: LanguageServiceHost): ScriptKind { // First check to see if the script kind was specified by the host. Chances are the host // may override the default script kind for the file extension. - return ts.ensureScriptKind(fileName, host.getScriptKind && host.getScriptKind(fileName)); + return ensureScriptKind(fileName, host.getScriptKind && host.getScriptKind(fileName)); } /** @internal */ -export function getSymbolTarget(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol { - let next: ts.Symbol = symbol; +export function getSymbolTarget(symbol: Symbol, checker: TypeChecker): Symbol { + let next: Symbol = symbol; while (isAliasSymbol(next) || (isTransientSymbol(next) && next.target)) { if (isTransientSymbol(next) && next.target) { next = next.target; } else { - next = ts.skipAlias(next, checker); + next = skipAlias(next, checker); } } return next; } -function isTransientSymbol(symbol: ts.Symbol): symbol is ts.TransientSymbol { - return (symbol.flags & ts.SymbolFlags.Transient) !== 0; +function isTransientSymbol(symbol: Symbol): symbol is TransientSymbol { + return (symbol.flags & SymbolFlags.Transient) !== 0; } -function isAliasSymbol(symbol: ts.Symbol): boolean { - return (symbol.flags & ts.SymbolFlags.Alias) !== 0; +function isAliasSymbol(symbol: Symbol): boolean { + return (symbol.flags & SymbolFlags.Alias) !== 0; } /** @internal */ -export function getUniqueSymbolId(symbol: ts.Symbol, checker: ts.TypeChecker) { - return ts.getSymbolId(ts.skipAlias(symbol, checker)); +export function getUniqueSymbolId(symbol: Symbol, checker: TypeChecker) { + return getSymbolId(skipAlias(symbol, checker)); } /** @internal */ export function getFirstNonSpaceCharacterPosition(text: string, position: number) { - while (ts.isWhiteSpaceLike(text.charCodeAt(position))) { + while (isWhiteSpaceLike(text.charCodeAt(position))) { position += 1; } return position; @@ -2681,7 +2741,7 @@ export function getFirstNonSpaceCharacterPosition(text: string, position: number /** @internal */ export function getPrecedingNonSpaceCharacterPosition(text: string, position: number) { - while (position > -1 && ts.isWhiteSpaceSingleLine(text.charCodeAt(position))) { + while (position > -1 && isWhiteSpaceSingleLine(text.charCodeAt(position))) { position -= 1; } return position + 1; @@ -2694,21 +2754,21 @@ export function getPrecedingNonSpaceCharacterPosition(text: string, position: nu * WARNING: This is an expensive operation and is only intended to be used in refactorings * and code fixes (because those are triggered by explicit user actions). */ -export function getSynthesizedDeepClone(node: T, includeTrivia = true): T { +export function getSynthesizedDeepClone(node: T, includeTrivia = true): T { const clone = node && getSynthesizedDeepCloneWorker(node); if (clone && !includeTrivia) suppressLeadingAndTrailingTrivia(clone); return clone; } /** @internal */ -export function getSynthesizedDeepCloneWithReplacements( +export function getSynthesizedDeepCloneWithReplacements( node: T, includeTrivia: boolean, - replaceNode: (node: ts.Node) => ts.Node | undefined + replaceNode: (node: Node) => Node | undefined ): T { let clone = replaceNode(node); if (clone) { - ts.setOriginalNode(clone, node); + setOriginalNode(clone, node); } else { clone = getSynthesizedDeepCloneWorker(node as NonNullable, replaceNode); @@ -2718,55 +2778,55 @@ export function getSynthesizedDeepCloneWithReplacements( return clone as T; } -function getSynthesizedDeepCloneWorker(node: T, replaceNode?: (node: ts.Node) => ts.Node | undefined): T { +function getSynthesizedDeepCloneWorker(node: T, replaceNode?: (node: Node) => Node | undefined): T { const nodeClone: (n: T) => T = replaceNode ? n => getSynthesizedDeepCloneWithReplacements(n, /*includeTrivia*/ true, replaceNode) : getSynthesizedDeepClone; - const nodesClone: (ns: ts.NodeArray) => ts.NodeArray = replaceNode + const nodesClone: (ns: NodeArray) => NodeArray = replaceNode ? ns => ns && getSynthesizedDeepClonesWithReplacements(ns, /*includeTrivia*/ true, replaceNode) : ns => ns && getSynthesizedDeepClones(ns); const visited = - ts.visitEachChild(node, nodeClone, ts.nullTransformationContext, nodesClone, nodeClone); + visitEachChild(node, nodeClone, nullTransformationContext, nodesClone, nodeClone); if (visited === node) { // This only happens for leaf nodes - internal nodes always see their children change. const clone = - ts.isStringLiteral(node) ? ts.setOriginalNode(ts.factory.createStringLiteralFromNode(node), node) as ts.Node as T : - ts.isNumericLiteral(node) ? ts.setOriginalNode(ts.factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as ts.Node as T : - ts.factory.cloneNode(node); - return ts.setTextRange(clone, node); + isStringLiteral(node) ? setOriginalNode(factory.createStringLiteralFromNode(node), node) as Node as T : + isNumericLiteral(node) ? setOriginalNode(factory.createNumericLiteral(node.text, node.numericLiteralFlags), node) as Node as T : + factory.cloneNode(node); + return setTextRange(clone, node); } // PERF: As an optimization, rather than calling factory.cloneNode, we'll update // the new node created by visitEachChild with the extra changes factory.cloneNode // would have made. - (visited as ts.Mutable).parent = undefined!; + (visited as Mutable).parent = undefined!; return visited; } /** @internal */ -export function getSynthesizedDeepClones(nodes: ts.NodeArray, includeTrivia?: boolean): ts.NodeArray; +export function getSynthesizedDeepClones(nodes: NodeArray, includeTrivia?: boolean): NodeArray; /** @internal */ -export function getSynthesizedDeepClones(nodes: ts.NodeArray | undefined, includeTrivia?: boolean): ts.NodeArray | undefined; +export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia?: boolean): NodeArray | undefined; /** @internal */ -export function getSynthesizedDeepClones(nodes: ts.NodeArray | undefined, includeTrivia = true): ts.NodeArray | undefined { - return nodes && ts.factory.createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); +export function getSynthesizedDeepClones(nodes: NodeArray | undefined, includeTrivia = true): NodeArray | undefined { + return nodes && factory.createNodeArray(nodes.map(n => getSynthesizedDeepClone(n, includeTrivia)), nodes.hasTrailingComma); } /** @internal */ -export function getSynthesizedDeepClonesWithReplacements( - nodes: ts.NodeArray, +export function getSynthesizedDeepClonesWithReplacements( + nodes: NodeArray, includeTrivia: boolean, - replaceNode: (node: ts.Node) => ts.Node | undefined -): ts.NodeArray { - return ts.factory.createNodeArray(nodes.map(n => getSynthesizedDeepCloneWithReplacements(n, includeTrivia, replaceNode)), nodes.hasTrailingComma); + replaceNode: (node: Node) => Node | undefined +): NodeArray { + return factory.createNodeArray(nodes.map(n => getSynthesizedDeepCloneWithReplacements(n, includeTrivia, replaceNode)), nodes.hasTrailingComma); } /** @internal */ /** * Sets EmitFlags to suppress leading and trailing trivia on the node. */ -export function suppressLeadingAndTrailingTrivia(node: ts.Node) { +export function suppressLeadingAndTrailingTrivia(node: Node) { suppressLeadingTrivia(node); suppressTrailingTrivia(node); } @@ -2775,20 +2835,20 @@ export function suppressLeadingAndTrailingTrivia(node: ts.Node) { /** * Sets EmitFlags to suppress leading trivia on the node. */ -export function suppressLeadingTrivia(node: ts.Node) { - addEmitFlagsRecursively(node, ts.EmitFlags.NoLeadingComments, getFirstChild); +export function suppressLeadingTrivia(node: Node) { + addEmitFlagsRecursively(node, EmitFlags.NoLeadingComments, getFirstChild); } /** @internal */ /** * Sets EmitFlags to suppress trailing trivia on the node. */ -export function suppressTrailingTrivia(node: ts.Node) { - addEmitFlagsRecursively(node, ts.EmitFlags.NoTrailingComments, ts.getLastChild); +export function suppressTrailingTrivia(node: Node) { + addEmitFlagsRecursively(node, EmitFlags.NoTrailingComments, getLastChild); } /** @internal */ -export function copyComments(sourceNode: ts.Node, targetNode: ts.Node) { +export function copyComments(sourceNode: Node, targetNode: Node) { const sourceFile = sourceNode.getSourceFile(); const text = sourceFile.text; if (hasLeadingLineBreak(sourceNode, text)) { @@ -2800,29 +2860,29 @@ export function copyComments(sourceNode: ts.Node, targetNode: ts.Node) { copyTrailingComments(sourceNode, targetNode, sourceFile); } -function hasLeadingLineBreak(node: ts.Node, text: string) { +function hasLeadingLineBreak(node: Node, text: string) { const start = node.getFullStart(); const end = node.getStart(); for (let i = start; i < end; i++) { - if (text.charCodeAt(i) === ts.CharacterCodes.lineFeed) return true; + if (text.charCodeAt(i) === CharacterCodes.lineFeed) return true; } return false; } -function addEmitFlagsRecursively(node: ts.Node, flag: ts.EmitFlags, getChild: (n: ts.Node) => ts.Node | undefined) { - ts.addEmitFlags(node, flag); +function addEmitFlagsRecursively(node: Node, flag: EmitFlags, getChild: (n: Node) => Node | undefined) { + addEmitFlags(node, flag); const child = getChild(node); if (child) addEmitFlagsRecursively(child, flag, getChild); } -function getFirstChild(node: ts.Node): ts.Node | undefined { +function getFirstChild(node: Node): Node | undefined { return node.forEachChild(child => child); } /** @internal */ -export function getUniqueName(baseName: string, sourceFile: ts.SourceFile): string { +export function getUniqueName(baseName: string, sourceFile: SourceFile): string { let nameText = baseName; - for (let i = 1; !ts.isFileLevelUniqueName(sourceFile, nameText); i++) { + for (let i = 1; !isFileLevelUniqueName(sourceFile, nameText); i++) { nameText = `${baseName}_${i}`; } return nameText; @@ -2834,14 +2894,14 @@ export function getUniqueName(baseName: string, sourceFile: ts.SourceFile): stri * to be on the reference, rather than the declaration, because it's closer to where the * user was before extracting it. */ -export function getRenameLocation(edits: readonly ts.FileTextChanges[], renameFilename: string, name: string, preferLastLocation: boolean): number { +export function getRenameLocation(edits: readonly FileTextChanges[], renameFilename: string, name: string, preferLastLocation: boolean): number { let delta = 0; let lastPos = -1; for (const { fileName, textChanges } of edits) { - ts.Debug.assert(fileName === renameFilename); + Debug.assert(fileName === renameFilename); for (const change of textChanges) { const { span, newText } = change; - const index = indexInTextChange(newText, ts.escapeString(name)); + const index = indexInTextChange(newText, escapeString(name)); if (index !== -1) { lastPos = span.start + delta + index; @@ -2855,20 +2915,20 @@ export function getRenameLocation(edits: readonly ts.FileTextChanges[], renameFi } // If the declaration comes first, return the position of the last occurrence. - ts.Debug.assert(preferLastLocation); - ts.Debug.assert(lastPos >= 0); + Debug.assert(preferLastLocation); + Debug.assert(lastPos >= 0); return lastPos; } /** @internal */ -export function copyLeadingComments(sourceNode: ts.Node, targetNode: ts.Node, sourceFile: ts.SourceFile, commentKind?: ts.CommentKind, hasTrailingNewLine?: boolean) { - ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); +export function copyLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { + forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment)); } /** @internal */ -export function copyTrailingComments(sourceNode: ts.Node, targetNode: ts.Node, sourceFile: ts.SourceFile, commentKind?: ts.CommentKind, hasTrailingNewLine?: boolean) { - ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment)); +export function copyTrailingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { + forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticTrailingComment)); } /** @internal */ @@ -2879,13 +2939,13 @@ export function copyTrailingComments(sourceNode: ts.Node, targetNode: ts.Node, s * `function foo(\* not leading comment for a *\ a: string) {}` * The comment refers to `a` but belongs to the `(` token, but we might want to copy it. */ -export function copyTrailingAsLeadingComments(sourceNode: ts.Node, targetNode: ts.Node, sourceFile: ts.SourceFile, commentKind?: ts.CommentKind, hasTrailingNewLine?: boolean) { - ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment)); +export function copyTrailingAsLeadingComments(sourceNode: Node, targetNode: Node, sourceFile: SourceFile, commentKind?: CommentKind, hasTrailingNewLine?: boolean) { + forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, addSyntheticLeadingComment)); } -function getAddCommentsFunction(targetNode: ts.Node, sourceFile: ts.SourceFile, commentKind: ts.CommentKind | undefined, hasTrailingNewLine: boolean | undefined, cb: (node: ts.Node, kind: ts.CommentKind, text: string, hasTrailingNewLine?: boolean) => void) { - return (pos: number, end: number, kind: ts.CommentKind, htnl: boolean) => { - if (kind === ts.SyntaxKind.MultiLineCommentTrivia) { +function getAddCommentsFunction(targetNode: Node, sourceFile: SourceFile, commentKind: CommentKind | undefined, hasTrailingNewLine: boolean | undefined, cb: (node: Node, kind: CommentKind, text: string, hasTrailingNewLine?: boolean) => void) { + return (pos: number, end: number, kind: CommentKind, htnl: boolean) => { + if (kind === SyntaxKind.MultiLineCommentTrivia) { // Remove leading /* pos += 2; // Remove trailing */ @@ -2900,7 +2960,7 @@ function getAddCommentsFunction(targetNode: ts.Node, sourceFile: ts.SourceFile, } function indexInTextChange(change: string, name: string): number { - if (ts.startsWith(change, name)) return 0; + if (startsWith(change, name)) return 0; // Add a " " to avoid references inside words let idx = change.indexOf(" " + name); if (idx === -1) idx = change.indexOf("." + name); @@ -2909,46 +2969,46 @@ function indexInTextChange(change: string, name: string): number { } /* @internal */ -export function needsParentheses(expression: ts.Expression): boolean { - return ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.CommaToken - || ts.isObjectLiteralExpression(expression) - || ts.isAsExpression(expression) && ts.isObjectLiteralExpression(expression.expression); +export function needsParentheses(expression: Expression): boolean { + return isBinaryExpression(expression) && expression.operatorToken.kind === SyntaxKind.CommaToken + || isObjectLiteralExpression(expression) + || isAsExpression(expression) && isObjectLiteralExpression(expression.expression); } /** @internal */ -export function getContextualTypeFromParent(node: ts.Expression, checker: ts.TypeChecker): ts.Type | undefined { +export function getContextualTypeFromParent(node: Expression, checker: TypeChecker): Type | undefined { const { parent } = node; switch (parent.kind) { - case ts.SyntaxKind.NewExpression: - return checker.getContextualType(parent as ts.NewExpression); - case ts.SyntaxKind.BinaryExpression: { - const { left, operatorToken, right } = parent as ts.BinaryExpression; + case SyntaxKind.NewExpression: + return checker.getContextualType(parent as NewExpression); + case SyntaxKind.BinaryExpression: { + const { left, operatorToken, right } = parent as BinaryExpression; return isEqualityOperatorKind(operatorToken.kind) ? checker.getTypeAtLocation(node === right ? left : right) : checker.getContextualType(node); } - case ts.SyntaxKind.CaseClause: - return (parent as ts.CaseClause).expression === node ? getSwitchedType(parent as ts.CaseClause, checker) : undefined; + case SyntaxKind.CaseClause: + return (parent as CaseClause).expression === node ? getSwitchedType(parent as CaseClause, checker) : undefined; default: return checker.getContextualType(node); } } /** @internal */ -export function quote(sourceFile: ts.SourceFile, preferences: ts.UserPreferences, text: string): string { +export function quote(sourceFile: SourceFile, preferences: UserPreferences, text: string): string { // Editors can pass in undefined or empty string - we want to infer the preference in those cases. const quotePreference = getQuotePreference(sourceFile, preferences); const quoted = JSON.stringify(text); - return quotePreference === QuotePreference.Single ? `'${ts.stripQuotes(quoted).replace(/'/g, "\\'").replace(/\\"/g, '"')}'` : quoted; + return quotePreference === QuotePreference.Single ? `'${stripQuotes(quoted).replace(/'/g, "\\'").replace(/\\"/g, '"')}'` : quoted; } /** @internal */ -export function isEqualityOperatorKind(kind: ts.SyntaxKind): kind is ts.EqualityOperator { +export function isEqualityOperatorKind(kind: SyntaxKind): kind is EqualityOperator { switch (kind) { - case ts.SyntaxKind.EqualsEqualsEqualsToken: - case ts.SyntaxKind.EqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsEqualsToken: - case ts.SyntaxKind.ExclamationEqualsToken: + case SyntaxKind.EqualsEqualsEqualsToken: + case SyntaxKind.EqualsEqualsToken: + case SyntaxKind.ExclamationEqualsEqualsToken: + case SyntaxKind.ExclamationEqualsToken: return true; default: return false; @@ -2956,12 +3016,12 @@ export function isEqualityOperatorKind(kind: ts.SyntaxKind): kind is ts.Equality } /** @internal */ -export function isStringLiteralOrTemplate(node: ts.Node): node is ts.StringLiteralLike | ts.TemplateExpression | ts.TaggedTemplateExpression { +export function isStringLiteralOrTemplate(node: Node): node is StringLiteralLike | TemplateExpression | TaggedTemplateExpression { switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NoSubstitutionTemplateLiteral: - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.TaggedTemplateExpression: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.TemplateExpression: + case SyntaxKind.TaggedTemplateExpression: return true; default: return false; @@ -2969,12 +3029,12 @@ export function isStringLiteralOrTemplate(node: ts.Node): node is ts.StringLiter } /** @internal */ -export function hasIndexSignature(type: ts.Type): boolean { +export function hasIndexSignature(type: Type): boolean { return !!type.getStringIndexType() || !!type.getNumberIndexType(); } /** @internal */ -export function getSwitchedType(caseClause: ts.CaseClause, checker: ts.TypeChecker): ts.Type | undefined { +export function getSwitchedType(caseClause: CaseClause, checker: TypeChecker): Type | undefined { return checker.getTypeAtLocation(caseClause.parent.parent.expression); } @@ -2982,13 +3042,13 @@ export function getSwitchedType(caseClause: ts.CaseClause, checker: ts.TypeCheck export const ANONYMOUS = "anonymous function"; /** @internal */ -export function getTypeNodeIfAccessible(type: ts.Type, enclosingScope: ts.Node, program: ts.Program, host: ts.LanguageServiceHost): ts.TypeNode | undefined { +export function getTypeNodeIfAccessible(type: Type, enclosingScope: Node, program: Program, host: LanguageServiceHost): TypeNode | undefined { const checker = program.getTypeChecker(); let typeIsAccessible = true; const notAccessible = () => typeIsAccessible = false; - const res = checker.typeToTypeNode(type, enclosingScope, ts.NodeBuilderFlags.NoTruncation, { + const res = checker.typeToTypeNode(type, enclosingScope, NodeBuilderFlags.NoTruncation, { trackSymbol: (symbol, declaration, meaning) => { - typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === ts.SymbolAccessibility.Accessible; + typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === SymbolAccessibility.Accessible; return !typeIsAccessible; }, reportInaccessibleThisError: notAccessible, @@ -2999,72 +3059,72 @@ export function getTypeNodeIfAccessible(type: ts.Type, enclosingScope: ts.Node, return typeIsAccessible ? res : undefined; } -function syntaxRequiresTrailingCommaOrSemicolonOrASI(kind: ts.SyntaxKind) { - return kind === ts.SyntaxKind.CallSignature - || kind === ts.SyntaxKind.ConstructSignature - || kind === ts.SyntaxKind.IndexSignature - || kind === ts.SyntaxKind.PropertySignature - || kind === ts.SyntaxKind.MethodSignature; +function syntaxRequiresTrailingCommaOrSemicolonOrASI(kind: SyntaxKind) { + return kind === SyntaxKind.CallSignature + || kind === SyntaxKind.ConstructSignature + || kind === SyntaxKind.IndexSignature + || kind === SyntaxKind.PropertySignature + || kind === SyntaxKind.MethodSignature; } -function syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(kind: ts.SyntaxKind) { - return kind === ts.SyntaxKind.FunctionDeclaration - || kind === ts.SyntaxKind.Constructor - || kind === ts.SyntaxKind.MethodDeclaration - || kind === ts.SyntaxKind.GetAccessor - || kind === ts.SyntaxKind.SetAccessor; +function syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(kind: SyntaxKind) { + return kind === SyntaxKind.FunctionDeclaration + || kind === SyntaxKind.Constructor + || kind === SyntaxKind.MethodDeclaration + || kind === SyntaxKind.GetAccessor + || kind === SyntaxKind.SetAccessor; } -function syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(kind: ts.SyntaxKind) { - return kind === ts.SyntaxKind.ModuleDeclaration; +function syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(kind: SyntaxKind) { + return kind === SyntaxKind.ModuleDeclaration; } /** @internal */ -export function syntaxRequiresTrailingSemicolonOrASI(kind: ts.SyntaxKind) { - return kind === ts.SyntaxKind.VariableStatement - || kind === ts.SyntaxKind.ExpressionStatement - || kind === ts.SyntaxKind.DoStatement - || kind === ts.SyntaxKind.ContinueStatement - || kind === ts.SyntaxKind.BreakStatement - || kind === ts.SyntaxKind.ReturnStatement - || kind === ts.SyntaxKind.ThrowStatement - || kind === ts.SyntaxKind.DebuggerStatement - || kind === ts.SyntaxKind.PropertyDeclaration - || kind === ts.SyntaxKind.TypeAliasDeclaration - || kind === ts.SyntaxKind.ImportDeclaration - || kind === ts.SyntaxKind.ImportEqualsDeclaration - || kind === ts.SyntaxKind.ExportDeclaration - || kind === ts.SyntaxKind.NamespaceExportDeclaration - || kind === ts.SyntaxKind.ExportAssignment; +export function syntaxRequiresTrailingSemicolonOrASI(kind: SyntaxKind) { + return kind === SyntaxKind.VariableStatement + || kind === SyntaxKind.ExpressionStatement + || kind === SyntaxKind.DoStatement + || kind === SyntaxKind.ContinueStatement + || kind === SyntaxKind.BreakStatement + || kind === SyntaxKind.ReturnStatement + || kind === SyntaxKind.ThrowStatement + || kind === SyntaxKind.DebuggerStatement + || kind === SyntaxKind.PropertyDeclaration + || kind === SyntaxKind.TypeAliasDeclaration + || kind === SyntaxKind.ImportDeclaration + || kind === SyntaxKind.ImportEqualsDeclaration + || kind === SyntaxKind.ExportDeclaration + || kind === SyntaxKind.NamespaceExportDeclaration + || kind === SyntaxKind.ExportAssignment; } /** @internal */ -export const syntaxMayBeASICandidate = ts.or( +export const syntaxMayBeASICandidate = or( syntaxRequiresTrailingCommaOrSemicolonOrASI, syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI, syntaxRequiresTrailingModuleBlockOrSemicolonOrASI, syntaxRequiresTrailingSemicolonOrASI); -function nodeIsASICandidate(node: ts.Node, sourceFile: ts.SourceFileLike): boolean { +function nodeIsASICandidate(node: Node, sourceFile: SourceFileLike): boolean { const lastToken = node.getLastToken(sourceFile); - if (lastToken && lastToken.kind === ts.SyntaxKind.SemicolonToken) { + if (lastToken && lastToken.kind === SyntaxKind.SemicolonToken) { return false; } if (syntaxRequiresTrailingCommaOrSemicolonOrASI(node.kind)) { - if (lastToken && lastToken.kind === ts.SyntaxKind.CommaToken) { + if (lastToken && lastToken.kind === SyntaxKind.CommaToken) { return false; } } else if (syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(node.kind)) { - const lastChild = ts.last(node.getChildren(sourceFile)); - if (lastChild && ts.isModuleBlock(lastChild)) { + const lastChild = last(node.getChildren(sourceFile)); + if (lastChild && isModuleBlock(lastChild)) { return false; } } else if (syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(node.kind)) { - const lastChild = ts.last(node.getChildren(sourceFile)); - if (lastChild && ts.isFunctionBlock(lastChild)) { + const lastChild = last(node.getChildren(sourceFile)); + if (lastChild && isFunctionBlock(lastChild)) { return false; } } @@ -3073,13 +3133,13 @@ function nodeIsASICandidate(node: ts.Node, sourceFile: ts.SourceFileLike): boole } // See comment in parser’s `parseDoStatement` - if (node.kind === ts.SyntaxKind.DoStatement) { + if (node.kind === SyntaxKind.DoStatement) { return true; } - const topNode = ts.findAncestor(node, ancestor => !ancestor.parent)!; + const topNode = findAncestor(node, ancestor => !ancestor.parent)!; const nextToken = findNextToken(node, topNode, sourceFile); - if (!nextToken || nextToken.kind === ts.SyntaxKind.CloseBraceToken) { + if (!nextToken || nextToken.kind === SyntaxKind.CloseBraceToken) { return true; } @@ -3089,8 +3149,8 @@ function nodeIsASICandidate(node: ts.Node, sourceFile: ts.SourceFileLike): boole } /** @internal */ -export function positionIsASICandidate(pos: number, context: ts.Node, sourceFile: ts.SourceFileLike): boolean { - const contextAncestor = ts.findAncestor(context, ancestor => { +export function positionIsASICandidate(pos: number, context: Node, sourceFile: SourceFileLike): boolean { + const contextAncestor = findAncestor(context, ancestor => { if (ancestor.end !== pos) { return "quit"; } @@ -3101,14 +3161,14 @@ export function positionIsASICandidate(pos: number, context: ts.Node, sourceFile } /** @internal */ -export function probablyUsesSemicolons(sourceFile: ts.SourceFile): boolean { +export function probablyUsesSemicolons(sourceFile: SourceFile): boolean { let withSemicolon = 0; let withoutSemicolon = 0; const nStatementsToObserve = 5; - ts.forEachChild(sourceFile, function visit(node): boolean | undefined { + forEachChild(sourceFile, function visit(node): boolean | undefined { if (syntaxRequiresTrailingSemicolonOrASI(node.kind)) { const lastToken = node.getLastToken(sourceFile); - if (lastToken?.kind === ts.SyntaxKind.SemicolonToken) { + if (lastToken?.kind === SyntaxKind.SemicolonToken) { withSemicolon++; } else { @@ -3117,12 +3177,12 @@ export function probablyUsesSemicolons(sourceFile: ts.SourceFile): boolean { } else if (syntaxRequiresTrailingCommaOrSemicolonOrASI(node.kind)) { const lastToken = node.getLastToken(sourceFile); - if (lastToken?.kind === ts.SyntaxKind.SemicolonToken) { + if (lastToken?.kind === SyntaxKind.SemicolonToken) { withSemicolon++; } - else if (lastToken && lastToken.kind !== ts.SyntaxKind.CommaToken) { - const lastTokenLine = ts.getLineAndCharacterOfPosition(sourceFile, lastToken.getStart(sourceFile)).line; - const nextTokenLine = ts.getLineAndCharacterOfPosition(sourceFile, ts.getSpanOfTokenAtPosition(sourceFile, lastToken.end).start).line; + else if (lastToken && lastToken.kind !== SyntaxKind.CommaToken) { + const lastTokenLine = getLineAndCharacterOfPosition(sourceFile, lastToken.getStart(sourceFile)).line; + const nextTokenLine = getLineAndCharacterOfPosition(sourceFile, getSpanOfTokenAtPosition(sourceFile, lastToken.end).start).line; // Avoid counting missing semicolon in single-line objects: // `function f(p: { x: string /*no semicolon here is insignificant*/ }) {` if (lastTokenLine !== nextTokenLine) { @@ -3135,7 +3195,7 @@ export function probablyUsesSemicolons(sourceFile: ts.SourceFile): boolean { return true; } - return ts.forEachChild(node, visit); + return forEachChild(node, visit); }); // One statement missing a semicolon isn't sufficient evidence to say the user @@ -3149,23 +3209,23 @@ export function probablyUsesSemicolons(sourceFile: ts.SourceFile): boolean { } /** @internal */ -export function tryGetDirectories(host: Pick, directoryName: string): string[] { +export function tryGetDirectories(host: Pick, directoryName: string): string[] { return tryIOAndConsumeErrors(host, host.getDirectories, directoryName) || []; } /** @internal */ -export function tryReadDirectory(host: Pick, path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[]): readonly string[] { - return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || ts.emptyArray; +export function tryReadDirectory(host: Pick, path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[]): readonly string[] { + return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || emptyArray; } /** @internal */ -export function tryFileExists(host: Pick, path: string): boolean { +export function tryFileExists(host: Pick, path: string): boolean { return tryIOAndConsumeErrors(host, host.fileExists, path); } /** @internal */ -export function tryDirectoryExists(host: ts.LanguageServiceHost, path: string): boolean { - return tryAndIgnoreErrors(() => ts.directoryProbablyExists(path, host)) || false; +export function tryDirectoryExists(host: LanguageServiceHost, path: string): boolean { + return tryAndIgnoreErrors(() => directoryProbablyExists(path, host)) || false; } /** @internal */ @@ -3184,13 +3244,13 @@ export function tryIOAndConsumeErrors(host: unknown, toApply: ((...a: any[]) } /** @internal */ -export function findPackageJsons(startDirectory: string, host: Pick, stopDirectory?: string): string[] { +export function findPackageJsons(startDirectory: string, host: Pick, stopDirectory?: string): string[] { const paths: string[] = []; - ts.forEachAncestorDirectory(startDirectory, ancestor => { + forEachAncestorDirectory(startDirectory, ancestor => { if (ancestor === stopDirectory) { return true; } - const currentConfigPath = ts.combinePaths(ancestor, "package.json"); + const currentConfigPath = combinePaths(ancestor, "package.json"); if (tryFileExists(host, currentConfigPath)) { paths.push(currentConfigPath); } @@ -3199,11 +3259,11 @@ export function findPackageJsons(startDirectory: string, host: Pick { + forEachAncestorDirectory(directory, ancestor => { if (ancestor === "node_modules") return true; - packageJson = ts.findConfigFile(ancestor, (f) => tryFileExists(host, f), "package.json"); + packageJson = findConfigFile(ancestor, (f) => tryFileExists(host, f), "package.json"); if (packageJson) { return true; // break out } @@ -3212,14 +3272,14 @@ export function findPackageJson(directory: string, host: ts.LanguageServiceHost) } /** @internal */ -export function getPackageJsonsVisibleToFile(fileName: string, host: ts.LanguageServiceHost): readonly ts.ProjectPackageJsonInfo[] { +export function getPackageJsonsVisibleToFile(fileName: string, host: LanguageServiceHost): readonly ProjectPackageJsonInfo[] { if (!host.fileExists) { return []; } - const packageJsons: ts.ProjectPackageJsonInfo[] = []; - ts.forEachAncestorDirectory(ts.getDirectoryPath(fileName), ancestor => { - const packageJsonFileName = ts.combinePaths(ancestor, "package.json"); + const packageJsons: ProjectPackageJsonInfo[] = []; + forEachAncestorDirectory(getDirectoryPath(fileName), ancestor => { + const packageJsonFileName = combinePaths(ancestor, "package.json"); if (host.fileExists(packageJsonFileName)) { const info = createPackageJsonInfo(packageJsonFileName, host); if (info) { @@ -3232,7 +3292,7 @@ export function getPackageJsonsVisibleToFile(fileName: string, host: ts.Language } /** @internal */ -export function createPackageJsonInfo(fileName: string, host: { readFile?(fileName: string): string | undefined }): ts.ProjectPackageJsonInfo | undefined { +export function createPackageJsonInfo(fileName: string, host: { readFile?(fileName: string): string | undefined }): ProjectPackageJsonInfo | undefined { if (!host.readFile) { return undefined; } @@ -3241,14 +3301,14 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa const dependencyKeys = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"] as const; const stringContent = host.readFile(fileName) || ""; const content = tryParseJson(stringContent) as PackageJsonRaw | undefined; - const info: Pick = {}; + const info: Pick = {}; if (content) { for (const key of dependencyKeys) { const dependencies = content[key]; if (!dependencies) { continue; } - const dependencyMap = new ts.Map(); + const dependencyMap = new Map(); for (const packageName in dependencies) { dependencyMap.set(packageName, dependencies[packageName]); } @@ -3257,10 +3317,10 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa } const dependencyGroups = [ - [ts.PackageJsonDependencyGroup.Dependencies, info.dependencies], - [ts.PackageJsonDependencyGroup.DevDependencies, info.devDependencies], - [ts.PackageJsonDependencyGroup.OptionalDependencies, info.optionalDependencies], - [ts.PackageJsonDependencyGroup.PeerDependencies, info.peerDependencies], + [PackageJsonDependencyGroup.Dependencies, info.dependencies], + [PackageJsonDependencyGroup.DevDependencies, info.devDependencies], + [PackageJsonDependencyGroup.OptionalDependencies, info.optionalDependencies], + [PackageJsonDependencyGroup.PeerDependencies, info.peerDependencies], ] as const; return { @@ -3273,7 +3333,7 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa }, }; - function get(dependencyName: string, inGroups = ts.PackageJsonDependencyGroup.All) { + function get(dependencyName: string, inGroups = PackageJsonDependencyGroup.All) { for (const [group, deps] of dependencyGroups) { if (deps && (inGroups & group)) { const dep = deps.get(dependencyName); @@ -3287,8 +3347,8 @@ export function createPackageJsonInfo(fileName: string, host: { readFile?(fileNa /** @internal */ export interface PackageJsonImportFilter { - allowsImportingAmbientModule: (moduleSymbol: ts.Symbol, moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost) => boolean; - allowsImportingSourceFile: (sourceFile: ts.SourceFile, moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost) => boolean; + allowsImportingAmbientModule: (moduleSymbol: Symbol, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean; + allowsImportingSourceFile: (sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost) => boolean; /** * Use for a specific module specifier that has already been resolved. * Use `allowsImportingAmbientModule` or `allowsImportingSourceFile` to resolve @@ -3298,7 +3358,7 @@ export interface PackageJsonImportFilter { } /** @internal */ -export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferences: ts.UserPreferences, host: ts.LanguageServiceHost): PackageJsonImportFilter { +export function createPackageJsonImportFilter(fromFile: SourceFile, preferences: UserPreferences, host: LanguageServiceHost): PackageJsonImportFilter { const packageJsons = ( (host.getPackageJsonsVisibleToFile && host.getPackageJsonsVisibleToFile(fromFile.fileName)) || getPackageJsonsVisibleToFile(fromFile.fileName, host) ).filter(p => p.parseable); @@ -3309,14 +3369,14 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc function moduleSpecifierIsCoveredByPackageJson(specifier: string) { const packageName = getNodeModuleRootSpecifier(specifier); for (const packageJson of packageJsons) { - if (packageJson.has(packageName) || packageJson.has(ts.getTypesPackageName(packageName))) { + if (packageJson.has(packageName) || packageJson.has(getTypesPackageName(packageName))) { return true; } } return false; } - function allowsImportingAmbientModule(moduleSymbol: ts.Symbol, moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost): boolean { + function allowsImportingAmbientModule(moduleSymbol: Symbol, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): boolean { if (!packageJsons.length || !moduleSymbol.valueDeclaration) { return true; } @@ -3327,7 +3387,7 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc return true; } - const declaredModuleSpecifier = ts.stripQuotes(moduleSymbol.getName()); + const declaredModuleSpecifier = stripQuotes(moduleSymbol.getName()); if (isAllowedCoreNodeModulesImport(declaredModuleSpecifier)) { return true; } @@ -3336,7 +3396,7 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc || moduleSpecifierIsCoveredByPackageJson(declaredModuleSpecifier); } - function allowsImportingSourceFile(sourceFile: ts.SourceFile, moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost): boolean { + function allowsImportingSourceFile(sourceFile: SourceFile, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): boolean { if (!packageJsons.length) { return true; } @@ -3353,7 +3413,7 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc if (!packageJsons.length || isAllowedCoreNodeModulesImport(moduleSpecifier)) { return true; } - if (ts.pathIsRelative(moduleSpecifier) || ts.isRootedDiskPath(moduleSpecifier)) { + if (pathIsRelative(moduleSpecifier) || isRootedDiskPath(moduleSpecifier)) { return true; } return moduleSpecifierIsCoveredByPackageJson(moduleSpecifier); @@ -3364,7 +3424,7 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc // from Node core modules or not. We can start by seeing if the user is actually using // any node core modules, as opposed to simply having @types/node accidentally as a // dependency of a dependency. - if (ts.isSourceFileJS(fromFile) && ts.JsTyping.nodeCoreModules.has(moduleSpecifier)) { + if (isSourceFileJS(fromFile) && JsTyping.nodeCoreModules.has(moduleSpecifier)) { if (usesNodeCoreModules === undefined) { usesNodeCoreModules = consumesNodeCoreModules(fromFile); } @@ -3375,11 +3435,11 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc return false; } - function getNodeModulesPackageNameFromFileName(importedFileName: string, moduleSpecifierResolutionHost: ts.ModuleSpecifierResolutionHost): string | undefined { - if (!ts.stringContains(importedFileName, "node_modules")) { + function getNodeModulesPackageNameFromFileName(importedFileName: string, moduleSpecifierResolutionHost: ModuleSpecifierResolutionHost): string | undefined { + if (!stringContains(importedFileName, "node_modules")) { return undefined; } - const specifier = ts.moduleSpecifiers.getNodeModulesPackageName( + const specifier = moduleSpecifiers.getNodeModulesPackageName( host.getCompilationSettings(), fromFile, importedFileName, @@ -3392,15 +3452,15 @@ export function createPackageJsonImportFilter(fromFile: ts.SourceFile, preferenc } // Paths here are not node_modules, so we don’t care about them; // returning anything will trigger a lookup in package.json. - if (!ts.pathIsRelative(specifier) && !ts.isRootedDiskPath(specifier)) { + if (!pathIsRelative(specifier) && !isRootedDiskPath(specifier)) { return getNodeModuleRootSpecifier(specifier); } } function getNodeModuleRootSpecifier(fullSpecifier: string): string { - const components = ts.getPathComponents(ts.getPackageNameFromTypesPackageName(fullSpecifier)).slice(1); + const components = getPathComponents(getPackageNameFromTypesPackageName(fullSpecifier)).slice(1); // Scoped packages - if (ts.startsWith(components[0], "@")) { + if (startsWith(components[0], "@")) { return `${components[0]}/${components[1]}`; } return components[0]; @@ -3417,34 +3477,34 @@ function tryParseJson(text: string) { } /** @internal */ -export function consumesNodeCoreModules(sourceFile: ts.SourceFile): boolean { - return ts.some(sourceFile.imports, ({ text }) => ts.JsTyping.nodeCoreModules.has(text)); +export function consumesNodeCoreModules(sourceFile: SourceFile): boolean { + return some(sourceFile.imports, ({ text }) => JsTyping.nodeCoreModules.has(text)); } /** @internal */ export function isInsideNodeModules(fileOrDirectory: string): boolean { - return ts.contains(ts.getPathComponents(fileOrDirectory), "node_modules"); + return contains(getPathComponents(fileOrDirectory), "node_modules"); } /** @internal */ -export function isDiagnosticWithLocation(diagnostic: ts.Diagnostic): diagnostic is ts.DiagnosticWithLocation { +export function isDiagnosticWithLocation(diagnostic: Diagnostic): diagnostic is DiagnosticWithLocation { return diagnostic.file !== undefined && diagnostic.start !== undefined && diagnostic.length !== undefined; } /** @internal */ -export function findDiagnosticForNode(node: ts.Node, sortedFileDiagnostics: readonly ts.Diagnostic[]): ts.DiagnosticWithLocation | undefined { - const span: Partial = createTextSpanFromNode(node); - const index = ts.binarySearchKey(sortedFileDiagnostics, span, ts.identity, ts.compareTextSpans); +export function findDiagnosticForNode(node: Node, sortedFileDiagnostics: readonly Diagnostic[]): DiagnosticWithLocation | undefined { + const span: Partial = createTextSpanFromNode(node); + const index = binarySearchKey(sortedFileDiagnostics, span, identity, compareTextSpans); if (index >= 0) { const diagnostic = sortedFileDiagnostics[index]; - ts.Debug.assertEqual(diagnostic.file, node.getSourceFile(), "Diagnostics proided to 'findDiagnosticForNode' must be from a single SourceFile"); - return ts.cast(diagnostic, isDiagnosticWithLocation); + Debug.assertEqual(diagnostic.file, node.getSourceFile(), "Diagnostics proided to 'findDiagnosticForNode' must be from a single SourceFile"); + return cast(diagnostic, isDiagnosticWithLocation); } } /** @internal */ -export function getDiagnosticsWithinSpan(span: ts.TextSpan, sortedFileDiagnostics: readonly ts.Diagnostic[]): readonly ts.DiagnosticWithLocation[] { - let index = ts.binarySearchKey(sortedFileDiagnostics, span.start, diag => diag.start, ts.compareValues); +export function getDiagnosticsWithinSpan(span: TextSpan, sortedFileDiagnostics: readonly Diagnostic[]): readonly DiagnosticWithLocation[] { + let index = binarySearchKey(sortedFileDiagnostics, span.start, diag => diag.start, compareValues); if (index < 0) { index = ~index; } @@ -3452,14 +3512,14 @@ export function getDiagnosticsWithinSpan(span: ts.TextSpan, sortedFileDiagnostic index--; } - const result: ts.DiagnosticWithLocation[] = []; - const end = ts.textSpanEnd(span); + const result: DiagnosticWithLocation[] = []; + const end = textSpanEnd(span); while (true) { - const diagnostic = ts.tryCast(sortedFileDiagnostics[index], isDiagnosticWithLocation); + const diagnostic = tryCast(sortedFileDiagnostics[index], isDiagnosticWithLocation); if (!diagnostic || diagnostic.start > end) { break; } - if (ts.textSpanContainsTextSpan(span, diagnostic)) { + if (textSpanContainsTextSpan(span, diagnostic)) { result.push(diagnostic); } index++; @@ -3469,22 +3529,22 @@ export function getDiagnosticsWithinSpan(span: ts.TextSpan, sortedFileDiagnostic } /* @internal */ -export function getRefactorContextSpan({ startPosition, endPosition }: ts.RefactorContext): ts.TextSpan { - return ts.createTextSpanFromBounds(startPosition, endPosition === undefined ? startPosition : endPosition); +export function getRefactorContextSpan({ startPosition, endPosition }: RefactorContext): TextSpan { + return createTextSpanFromBounds(startPosition, endPosition === undefined ? startPosition : endPosition); } /* @internal */ -export function getFixableErrorSpanExpression(sourceFile: ts.SourceFile, span: ts.TextSpan): ts.Expression | undefined { +export function getFixableErrorSpanExpression(sourceFile: SourceFile, span: TextSpan): Expression | undefined { const token = getTokenAtPosition(sourceFile, span.start); // Checker has already done work to determine that await might be possible, and has attached // related info to the node, so start by finding the expression that exactly matches up // with the diagnostic range. - const expression = ts.findAncestor(token, node => { - if (node.getStart(sourceFile) < span.start || node.getEnd() > ts.textSpanEnd(span)) { + const expression = findAncestor(token, node => { + if (node.getStart(sourceFile) < span.start || node.getEnd() > textSpanEnd(span)) { return "quit"; } - return ts.isExpression(node) && textSpansEqual(span, createTextSpanFromNode(node, sourceFile)); - }) as ts.Expression | undefined; + return isExpression(node) && textSpansEqual(span, createTextSpanFromNode(node, sourceFile)); + }) as Expression | undefined; return expression; } @@ -3502,8 +3562,8 @@ export function mapOneOrMany(valueOrArray: T | readonly T[], f: (x: T, i: /** @internal */ export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U, resultSelector: (x: U[]) => U): U | undefined; /** @internal */ -export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U, resultSelector: (x: U[]) => U | U[] = ts.identity): U | U[] | undefined { - return valueOrArray ? ts.isArray(valueOrArray) ? resultSelector(ts.map(valueOrArray, f)) : f(valueOrArray, 0) : undefined; +export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f: (x: T, i: number) => U, resultSelector: (x: U[]) => U | U[] = identity): U | U[] | undefined { + return valueOrArray ? isArray(valueOrArray) ? resultSelector(map(valueOrArray, f)) : f(valueOrArray, 0) : undefined; } /** @internal */ @@ -3511,16 +3571,16 @@ export function mapOneOrMany(valueOrArray: T | readonly T[] | undefined, f * If the provided value is an array, the first element of the array is returned; otherwise, the provided value is returned instead. */ export function firstOrOnly(valueOrArray: T | readonly T[]): T { - return ts.isArray(valueOrArray) ? ts.first(valueOrArray) : valueOrArray; + return isArray(valueOrArray) ? first(valueOrArray) : valueOrArray; } /** @internal */ -export function getNamesForExportedSymbol(symbol: ts.Symbol, scriptTarget: ts.ScriptTarget | undefined): string | [lowercase: string, capitalized: string] { +export function getNamesForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined): string | [lowercase: string, capitalized: string] { if (needsNameFromDeclaration(symbol)) { const fromDeclaration = getDefaultLikeExportNameFromDeclaration(symbol); if (fromDeclaration) return fromDeclaration; - const fileNameCase = ts.codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ false); - const capitalized = ts.codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ true); + const fileNameCase = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ false); + const capitalized = codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, /*preferCapitalized*/ true); if (fileNameCase === capitalized) return fileNameCase; return [fileNameCase, capitalized]; } @@ -3528,33 +3588,33 @@ export function getNamesForExportedSymbol(symbol: ts.Symbol, scriptTarget: ts.Sc } /** @internal */ -export function getNameForExportedSymbol(symbol: ts.Symbol, scriptTarget: ts.ScriptTarget | undefined, preferCapitalized?: boolean) { +export function getNameForExportedSymbol(symbol: Symbol, scriptTarget: ScriptTarget | undefined, preferCapitalized?: boolean) { if (needsNameFromDeclaration(symbol)) { // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase. return getDefaultLikeExportNameFromDeclaration(symbol) - || ts.codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, !!preferCapitalized); + || codefix.moduleSymbolToValidIdentifier(getSymbolParentOrFail(symbol), scriptTarget, !!preferCapitalized); } return symbol.name; } -function needsNameFromDeclaration(symbol: ts.Symbol) { - return !(symbol.flags & ts.SymbolFlags.Transient) && (symbol.escapedName === ts.InternalSymbolName.ExportEquals || symbol.escapedName === ts.InternalSymbolName.Default); +function needsNameFromDeclaration(symbol: Symbol) { + return !(symbol.flags & SymbolFlags.Transient) && (symbol.escapedName === InternalSymbolName.ExportEquals || symbol.escapedName === InternalSymbolName.Default); } -function getDefaultLikeExportNameFromDeclaration(symbol: ts.Symbol) { - return ts.firstDefined(symbol.declarations, d => ts.isExportAssignment(d) ? ts.tryCast(ts.skipOuterExpressions(d.expression), ts.isIdentifier)?.text : undefined); +function getDefaultLikeExportNameFromDeclaration(symbol: Symbol) { + return firstDefined(symbol.declarations, d => isExportAssignment(d) ? tryCast(skipOuterExpressions(d.expression), isIdentifier)?.text : undefined); } -function getSymbolParentOrFail(symbol: ts.Symbol) { - return ts.Debug.checkDefined( +function getSymbolParentOrFail(symbol: Symbol) { + return Debug.checkDefined( symbol.parent, - `Symbol parent was undefined. Flags: ${ts.Debug.formatSymbolFlags(symbol.flags)}. ` + + `Symbol parent was undefined. Flags: ${Debug.formatSymbolFlags(symbol.flags)}. ` + `Declarations: ${symbol.declarations?.map(d => { - const kind = ts.Debug.formatSyntaxKind(d.kind); - const inJS = ts.isInJSFile(d); + const kind = Debug.formatSyntaxKind(d.kind); + const inJS = isInJSFile(d); const { expression } = d as any; - return (inJS ? "[JS]" : "") + kind + (expression ? ` (expression: ${ts.Debug.formatSyntaxKind(expression.kind)})` : ""); + return (inJS ? "[JS]" : "") + kind + (expression ? ` (expression: ${Debug.formatSyntaxKind(expression.kind)})` : ""); }).join(", ")}.`); } @@ -3590,73 +3650,73 @@ export function stringContainsAt(haystack: string, needle: string, startIndex: n /** @internal */ export function startsWithUnderscore(name: string): boolean { - return name.charCodeAt(0) === ts.CharacterCodes._; + return name.charCodeAt(0) === CharacterCodes._; } /** @internal */ -export function isGlobalDeclaration(declaration: ts.Declaration) { +export function isGlobalDeclaration(declaration: Declaration) { return !isNonGlobalDeclaration(declaration); } /** @internal */ -export function isNonGlobalDeclaration(declaration: ts.Declaration) { +export function isNonGlobalDeclaration(declaration: Declaration) { const sourceFile = declaration.getSourceFile(); // If the file is not a module, the declaration is global if (!sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) { return false; } // If the file is a module written in TypeScript, it still might be in a `declare global` augmentation - return ts.isInJSFile(declaration) || !ts.findAncestor(declaration, ts.isGlobalScopeAugmentation); + return isInJSFile(declaration) || !findAncestor(declaration, isGlobalScopeAugmentation); } /** @internal */ -export function isDeprecatedDeclaration(decl: ts.Declaration) { - return !!(ts.getCombinedNodeFlagsAlwaysIncludeJSDoc(decl) & ts.ModifierFlags.Deprecated); +export function isDeprecatedDeclaration(decl: Declaration) { + return !!(getCombinedNodeFlagsAlwaysIncludeJSDoc(decl) & ModifierFlags.Deprecated); } /** @internal */ -export function shouldUseUriStyleNodeCoreModules(file: ts.SourceFile, program: ts.Program): boolean { - const decisionFromFile = ts.firstDefined(file.imports, node => { - if (ts.JsTyping.nodeCoreModules.has(node.text)) { - return ts.startsWith(node.text, "node:"); +export function shouldUseUriStyleNodeCoreModules(file: SourceFile, program: Program): boolean { + const decisionFromFile = firstDefined(file.imports, node => { + if (JsTyping.nodeCoreModules.has(node.text)) { + return startsWith(node.text, "node:"); } }); return decisionFromFile ?? program.usesUriStyleNodeCoreModules; } /** @internal */ -export function getNewLineKind(newLineCharacter: string): ts.NewLineKind { - return newLineCharacter === "\n" ? ts.NewLineKind.LineFeed : ts.NewLineKind.CarriageReturnLineFeed; +export function getNewLineKind(newLineCharacter: string): NewLineKind { + return newLineCharacter === "\n" ? NewLineKind.LineFeed : NewLineKind.CarriageReturnLineFeed; } /** @internal */ -export type DiagnosticAndArguments = ts.DiagnosticMessage | [ts.DiagnosticMessage, string] | [ts.DiagnosticMessage, string, string]; +export type DiagnosticAndArguments = DiagnosticMessage | [DiagnosticMessage, string] | [DiagnosticMessage, string, string]; /** @internal */ export function diagnosticToString(diag: DiagnosticAndArguments): string { - return ts.isArray(diag) - ? ts.formatStringFromArgs(ts.getLocaleSpecificMessage(diag[0]), diag.slice(1) as readonly string[]) - : ts.getLocaleSpecificMessage(diag); + return isArray(diag) + ? formatStringFromArgs(getLocaleSpecificMessage(diag[0]), diag.slice(1) as readonly string[]) + : getLocaleSpecificMessage(diag); } /** @internal */ /** * Get format code settings for a code writing context (e.g. when formatting text changes or completions code). */ -export function getFormatCodeSettingsForWriting({ options }: ts.formatting.FormatContext, sourceFile: ts.SourceFile): ts.FormatCodeSettings { - const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === ts.SemicolonPreference.Ignore; - const shouldRemoveSemicolons = options.semicolons === ts.SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile); +export function getFormatCodeSettingsForWriting({ options }: formatting.FormatContext, sourceFile: SourceFile): FormatCodeSettings { + const shouldAutoDetectSemicolonPreference = !options.semicolons || options.semicolons === SemicolonPreference.Ignore; + const shouldRemoveSemicolons = options.semicolons === SemicolonPreference.Remove || shouldAutoDetectSemicolonPreference && !probablyUsesSemicolons(sourceFile); return { ...options, - semicolons: shouldRemoveSemicolons ? ts.SemicolonPreference.Remove : ts.SemicolonPreference.Ignore, + semicolons: shouldRemoveSemicolons ? SemicolonPreference.Remove : SemicolonPreference.Ignore, }; } /** @internal */ -export function jsxModeNeedsExplicitImport(jsx: ts.JsxEmit | undefined) { - return jsx === ts.JsxEmit.React || jsx === ts.JsxEmit.ReactNative; +export function jsxModeNeedsExplicitImport(jsx: JsxEmit | undefined) { + return jsx === JsxEmit.React || jsx === JsxEmit.ReactNative; } /** @internal */ -export function isSourceFileFromLibrary(program: ts.Program, node: ts.SourceFile) { +export function isSourceFileFromLibrary(program: Program, node: SourceFile) { return program.isSourceFileFromExternalLibrary(node) || program.isSourceFileDefaultLibrary(node); } diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 2cbcf5d9a019a..2133aad726734 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -1,8 +1,11 @@ -import * as Harness from "./_namespaces/Harness"; import * as vpath from "./_namespaces/vpath"; import * as ts from "./_namespaces/ts"; import * as compiler from "./_namespaces/compiler"; import * as Utils from "./_namespaces/Utils"; +import { + Baseline, Compiler, FileBasedTest, FileBasedTestConfiguration, getFileBasedTestConfigurationDescription, + getFileBasedTestConfigurations, IO, RunnerBase, TestCaseParser, TestRunnerKind, +} from "./_namespaces/Harness"; export const enum CompilerTestType { Conformance, @@ -10,13 +13,13 @@ export const enum CompilerTestType { Test262 } -interface CompilerFileBasedTest extends Harness.FileBasedTest { +interface CompilerFileBasedTest extends FileBasedTest { readonly content?: string; } -export class CompilerBaselineRunner extends Harness.RunnerBase { +export class CompilerBaselineRunner extends RunnerBase { private basePath = "tests/cases"; - private testSuiteName: Harness.TestRunnerKind; + private testSuiteName: TestRunnerKind; private emit: boolean; public options: string | undefined; @@ -55,7 +58,7 @@ export class CompilerBaselineRunner extends Harness.RunnerBase { }); // this will set up a series of describe/it blocks to run between the setup and cleanup phases - const files = this.tests.length > 0 ? this.tests : Harness.IO.enumerateTestFiles(this); + const files = this.tests.length > 0 ? this.tests : IO.enumerateTestFiles(this); files.forEach(test => { const file = typeof test === "string" ? test : test.file; this.checkTestCodeOutput(vpath.normalizeSeparators(file), typeof test === "string" ? CompilerTest.getConfigurations(test) : test); @@ -66,7 +69,7 @@ export class CompilerBaselineRunner extends Harness.RunnerBase { public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) { if (test && ts.some(test.configurations)) { test.configurations.forEach(configuration => { - describe(`${this.testSuiteName} tests for ${fileName}${configuration ? ` (${Harness.getFileBasedTestConfigurationDescription(configuration)})` : ``}`, () => { + describe(`${this.testSuiteName} tests for ${fileName}${configuration ? ` (${getFileBasedTestConfigurationDescription(configuration)})` : ``}`, () => { this.runSuite(fileName, test, configuration); }); }); @@ -78,7 +81,7 @@ export class CompilerBaselineRunner extends Harness.RunnerBase { } } - private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: Harness.FileBasedTestConfiguration) { + private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: FileBasedTestConfiguration) { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let compilerTest!: CompilerTest; @@ -86,7 +89,7 @@ export class CompilerBaselineRunner extends Harness.RunnerBase { let payload; if (test && test.content) { const rootDir = test.file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(test.file) + "/"; - payload = Harness.TestCaseParser.makeUnitsFromTest(test.content, test.file, rootDir); + payload = TestCaseParser.makeUnitsFromTest(test.content, test.file, rootDir); } compilerTest = new CompilerTest(fileName, payload, configuration); }); @@ -154,18 +157,18 @@ class CompilerTest { private fileName: string; private justName: string; private configuredName: string; - private lastUnit: Harness.TestCaseParser.TestUnitData; - private harnessSettings: Harness.TestCaseParser.CompilerSettings; + private lastUnit: TestCaseParser.TestUnitData; + private harnessSettings: TestCaseParser.CompilerSettings; private hasNonDtsFiles: boolean; private result: compiler.CompilationResult; private options: ts.CompilerOptions; - private tsConfigFiles: Harness.Compiler.TestFile[]; + private tsConfigFiles: Compiler.TestFile[]; // equivalent to the files that will be passed on the command line - private toBeCompiled: Harness.Compiler.TestFile[]; + private toBeCompiled: Compiler.TestFile[]; // equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files) - private otherFiles: Harness.Compiler.TestFile[]; + private otherFiles: Compiler.TestFile[]; - constructor(fileName: string, testCaseContent?: Harness.TestCaseParser.TestCaseContent, configurationOverrides?: Harness.TestCaseParser.CompilerSettings) { + constructor(fileName: string, testCaseContent?: TestCaseParser.TestCaseContent, configurationOverrides?: TestCaseParser.CompilerSettings) { this.fileName = fileName; this.justName = vpath.basename(fileName); this.configuredName = this.justName; @@ -190,7 +193,7 @@ class CompilerTest { const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; if (testCaseContent === undefined) { - testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName)!, fileName, rootDir); + testCaseContent = TestCaseParser.makeUnitsFromTest(IO.readFile(fileName)!, fileName, rootDir); } if (configurationOverrides) { @@ -242,7 +245,7 @@ class CompilerTest { tsConfigOptions.configFile!.fileName = tsConfigOptions.configFilePath; } - this.result = Harness.Compiler.compileFiles( + this.result = Compiler.compileFiles( this.toBeCompiled, this.otherFiles, this.harnessSettings, @@ -256,15 +259,15 @@ class CompilerTest { public static getConfigurations(file: string): CompilerFileBasedTest { // also see `parseCompilerTestConfigurations` in tests/webTestServer.ts - const content = Harness.IO.readFile(file)!; - const settings = Harness.TestCaseParser.extractCompilerSettings(content); - const configurations = Harness.getFileBasedTestConfigurations(settings, CompilerTest.varyBy); + const content = IO.readFile(file)!; + const settings = TestCaseParser.extractCompilerSettings(content); + const configurations = getFileBasedTestConfigurations(settings, CompilerTest.varyBy); return { file, configurations, content }; } public verifyDiagnostics() { // check errors - Harness.Compiler.doErrorBaseline( + Compiler.doErrorBaseline( this.configuredName, this.tsConfigFiles.concat(this.toBeCompiled, this.otherFiles), this.result.diagnostics, @@ -273,7 +276,7 @@ class CompilerTest { public verifyModuleResolution() { if (this.options.traceResolution) { - Harness.Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"), + Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".trace.json"), JSON.stringify(this.result.traces.map(Utils.sanitizeTraceResolutionLogEntry), undefined, 4)); } } @@ -285,13 +288,13 @@ class CompilerTest { // Because of the noEmitOnError option no files are created. We need to return null because baselining isn't required. ? null // eslint-disable-line no-null/no-null : record; - Harness.Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".sourcemap.txt"), baseline); + Baseline.runBaseline(this.configuredName.replace(/\.tsx?$/, ".sourcemap.txt"), baseline); } } public verifyJavaScriptOutput() { if (this.hasNonDtsFiles) { - Harness.Compiler.doJsEmitBaseline( + Compiler.doJsEmitBaseline( this.configuredName, this.fileName, this.options, @@ -304,7 +307,7 @@ class CompilerTest { } public verifySourceMapOutput() { - Harness.Compiler.doSourcemapBaseline( + Compiler.doSourcemapBaseline( this.configuredName, this.options, this.result, @@ -323,7 +326,7 @@ class CompilerTest { return; } - Harness.Compiler.doTypeAndSymbolBaseline( + Compiler.doTypeAndSymbolBaseline( this.configuredName, this.result.program!, this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program!.getSourceFile(file.unitName)), @@ -337,11 +340,11 @@ class CompilerTest { private makeUnitName(name: string, root: string) { const path = ts.toPath(name, root, ts.identity); - const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", ts.identity); + const pathStart = ts.toPath(IO.getCurrentDirectory(), "", ts.identity); return pathStart ? path.replace(pathStart, "/") : path; } - private createHarnessTestFile(lastUnit: Harness.TestCaseParser.TestUnitData, rootDir: string, unitName?: string): Harness.Compiler.TestFile { + private createHarnessTestFile(lastUnit: TestCaseParser.TestUnitData, rootDir: string, unitName?: string): Compiler.TestFile { return { unitName: unitName || this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions }; } } diff --git a/src/testRunner/externalCompileRunner.ts b/src/testRunner/externalCompileRunner.ts index 21497e3a957cc..93c9cce362ec0 100644 --- a/src/testRunner/externalCompileRunner.ts +++ b/src/testRunner/externalCompileRunner.ts @@ -1,5 +1,5 @@ -import * as Harness from "./_namespaces/Harness"; import * as ts from "./_namespaces/ts"; +import { Baseline, IO, isWorker, RunnerBase, TestRunnerKind } from "./_namespaces/Harness"; const fs: typeof import("fs") = require("fs"); const path: typeof import("path") = require("path"); @@ -18,11 +18,11 @@ interface UserConfig { path?: string; } -abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { +abstract class ExternalCompileRunnerBase extends RunnerBase { abstract testDir: string; abstract report(result: ExecResult): string | null; enumerateTestFiles() { - return Harness.IO.getDirectories(this.testDir); + return IO.getDirectories(this.testDir); } /** Setup the runner's tests so that they are ready to be executed by the harness * The first test should be a describe/it block that sets up the harness's compiler instance appropriately @@ -49,9 +49,9 @@ abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { const cp: typeof import("child_process") = require("child_process"); it("should build successfully", () => { - let cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directoryName); + let cwd = path.join(IO.getWorkspaceRoot(), cls.testDir, directoryName); const originalCwd = cwd; - const stdio = Harness.isWorker ? "pipe" : "inherit"; + const stdio = isWorker ? "pipe" : "inherit"; let types: string[] | undefined; if (fs.existsSync(path.join(cwd, "test.json"))) { const config = JSON.parse(fs.readFileSync(path.join(cwd, "test.json"), { encoding: "utf8" })) as UserConfig; @@ -84,7 +84,7 @@ abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { } exec("npm", ["i", "--ignore-scripts", ...(isV7OrLater ? ["--legacy-peer-deps"] : [])], { cwd, timeout: timeout / 2 }); // NPM shouldn't take the entire timeout - if it takes a long time, it should be terminated and we should log the failure } - const args = [path.join(Harness.IO.getWorkspaceRoot(), "built/local/tsc.js")]; + const args = [path.join(IO.getWorkspaceRoot(), "built/local/tsc.js")]; if (types) { args.push("--types", types.join(",")); // Also actually install those types (for, eg, the js projects which need node) @@ -93,10 +93,10 @@ abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { } } args.push("--noEmit"); - Harness.Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, cls.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }))); + Baseline.runBaseline(`${cls.kind()}/${directoryName}.log`, cls.report(cp.spawnSync(`node`, args, { cwd, timeout, shell: true }))); function exec(command: string, args: string[], options: { cwd: string, timeout?: number, stdio?: import("child_process").StdioOptions }): string | undefined { - const res = cp.spawnSync(Harness.isWorker ? `${command} 2>&1` : command, args, { shell: true, stdio, ...options }); + const res = cp.spawnSync(isWorker ? `${command} 2>&1` : command, args, { shell: true, stdio, ...options }); if (res.status !== 0) { throw new Error(`${command} ${args.join(" ")} for ${directoryName} failed: ${res.stdout && res.stdout.toString()}`); } @@ -109,7 +109,7 @@ abstract class ExternalCompileRunnerBase extends Harness.RunnerBase { export class UserCodeRunner extends ExternalCompileRunnerBase { readonly testDir = "tests/cases/user/"; - kind(): Harness.TestRunnerKind { + kind(): TestRunnerKind { return "user"; } report(result: ExecResult) { @@ -126,7 +126,7 @@ ${stripAbsoluteImportPaths(result.stderr.toString().replace(/\r\n/g, "\n"))}`; export class DockerfileRunner extends ExternalCompileRunnerBase { readonly testDir = "tests/cases/docker/"; - kind(): Harness.TestRunnerKind { + kind(): TestRunnerKind { return "docker"; } initializeTests(): void { @@ -138,16 +138,16 @@ export class DockerfileRunner extends ExternalCompileRunnerBase { describe(`${this.kind()} code samples`, function (this: Mocha.Suite) { this.timeout(cls.timeout); // 20 minutes before(() => { - cls.exec("docker", ["build", ".", "-t", "typescript/typescript"], { cwd: Harness.IO.getWorkspaceRoot() }); // cached because workspace is hashed to determine cacheability + cls.exec("docker", ["build", ".", "-t", "typescript/typescript"], { cwd: IO.getWorkspaceRoot() }); // cached because workspace is hashed to determine cacheability }); for (const test of testList) { const directory = typeof test === "string" ? test : test.file; - const cwd = path.join(Harness.IO.getWorkspaceRoot(), cls.testDir, directory); + const cwd = path.join(IO.getWorkspaceRoot(), cls.testDir, directory); it(`should build ${directory} successfully`, () => { const imageName = `tstest/${directory}`; cls.exec("docker", ["build", "--no-cache", ".", "-t", imageName], { cwd }); // --no-cache so the latest version of the repos referenced is always fetched const cp: typeof import("child_process") = require("child_process"); - Harness.Baseline.runBaseline(`${cls.kind()}/${directory}.log`, cls.report(cp.spawnSync(`docker`, ["run", imageName], { cwd, timeout: cls.timeout, shell: true }))); + Baseline.runBaseline(`${cls.kind()}/${directory}.log`, cls.report(cp.spawnSync(`docker`, ["run", imageName], { cwd, timeout: cls.timeout, shell: true }))); }); } }); @@ -156,8 +156,8 @@ export class DockerfileRunner extends ExternalCompileRunnerBase { private timeout = 1_200_000; // 20 minutes; private exec(command: string, args: string[], options: { cwd: string }): void { const cp: typeof import("child_process") = require("child_process"); - const stdio = Harness.isWorker ? "pipe" : "inherit"; - const res = cp.spawnSync(Harness.isWorker ? `${command} 2>&1` : command, args, { timeout: this.timeout, shell: true, stdio, ...options }); + const stdio = isWorker ? "pipe" : "inherit"; + const res = cp.spawnSync(isWorker ? `${command} 2>&1` : command, args, { timeout: this.timeout, shell: true, stdio, ...options }); if (res.status !== 0) { throw new Error(`${command} ${args.join(" ")} for ${options.cwd} failed: ${res.stdout && res.stdout.toString()}`); } @@ -245,7 +245,7 @@ function sanitizeVersionSpecifiers(result: string): string { * This is problematic for error baselines, so we grep for them and strip them out. */ function stripAbsoluteImportPaths(result: string) { - const workspaceRegexp = new RegExp(Harness.IO.getWorkspaceRoot().replace(/\\/g, "\\\\"), "g"); + const workspaceRegexp = new RegExp(IO.getWorkspaceRoot().replace(/\\/g, "\\\\"), "g"); return result .replace(/import\(".*?\/tests\/cases\/user\//g, `import("/`) .replace(/Module '".*?\/tests\/cases\/user\//g, `Module '"/`) @@ -280,7 +280,7 @@ function compareErrorStrings(a: string[], b: string[]) { export class DefinitelyTypedRunner extends ExternalCompileRunnerBase { readonly testDir = "../DefinitelyTyped/types/"; workingDirectory = this.testDir; - kind(): Harness.TestRunnerKind { + kind(): TestRunnerKind { return "dt"; } report(result: ExecResult) { diff --git a/src/testRunner/fourslashRunner.ts b/src/testRunner/fourslashRunner.ts index 80150babf747a..31312e37c6a20 100644 --- a/src/testRunner/fourslashRunner.ts +++ b/src/testRunner/fourslashRunner.ts @@ -1,10 +1,10 @@ -import * as Harness from "./_namespaces/Harness"; import * as FourSlash from "./_namespaces/FourSlash"; import * as ts from "./_namespaces/ts"; +import { IO, RunnerBase, TestRunnerKind } from "./_namespaces/Harness"; -export class FourSlashRunner extends Harness.RunnerBase { +export class FourSlashRunner extends RunnerBase { protected basePath: string; - protected testSuiteName: Harness.TestRunnerKind; + protected testSuiteName: TestRunnerKind; constructor(private testType: FourSlash.FourSlashTestType) { super(); @@ -41,7 +41,7 @@ export class FourSlashRunner extends Harness.RunnerBase { public initializeTests() { if (this.tests.length === 0) { - this.tests = Harness.IO.enumerateTestFiles(this); + this.tests = IO.enumerateTestFiles(this); } describe(this.testSuiteName + " tests", () => { diff --git a/src/testRunner/parallel/host.ts b/src/testRunner/parallel/host.ts index df852c07c5678..e866456799656 100644 --- a/src/testRunner/parallel/host.ts +++ b/src/testRunner/parallel/host.ts @@ -1,6 +1,12 @@ -import * as Harness from "../_namespaces/Harness"; import * as Utils from "../_namespaces/Utils"; import * as ts from "../_namespaces/ts"; +import { + configOption, globalTimeout, IO, keepFailed, lightMode, noColors, runners, runUnitTests, stackTraceLimit, + taskConfigsFolder, TestConfig, TestRunnerKind, workerCount, +} from "../_namespaces/Harness"; +import { + ErrorInfo, ParallelClientMessage, ParallelHostMessage, shimNoopTestInterface, Task, TaskTimeout, TestInfo, +} from "../_namespaces/Harness.Parallel"; export function start() { const Mocha = require("mocha") as typeof import("mocha"); @@ -20,9 +26,9 @@ export function start() { const FailedTestReporter = require(Utils.findUpFile("scripts/failed-tests.cjs")) as typeof import("../../../scripts/failed-tests.cjs"); const perfdataFileNameFragment = ".parallelperf"; - const perfData = readSavedPerfData(Harness.configOption); - const newTasks: Harness.Parallel.Task[] = []; - let tasks: Harness.Parallel.Task[] = []; + const perfData = readSavedPerfData(configOption); + const newTasks: Task[] = []; + let tasks: Task[] = []; let unknownValue: string | undefined; let totalCost = 0; @@ -44,8 +50,8 @@ export function start() { } class RemoteTest extends Mocha.Test { - info: Harness.Parallel.ErrorInfo | Harness.Parallel.TestInfo; - constructor(info: Harness.Parallel.ErrorInfo | Harness.Parallel.TestInfo) { + info: ErrorInfo | TestInfo; + constructor(info: ErrorInfo | TestInfo) { super(info.name[info.name.length - 1]); this.info = info; this.state = "error" in info ? "failed" : "passed"; // eslint-disable-line local/no-in-operator @@ -178,14 +184,14 @@ export function start() { } function readSavedPerfData(target?: string): { [testHash: string]: number } | undefined { - const perfDataContents = Harness.IO.readFile(perfdataFileName(target)); + const perfDataContents = IO.readFile(perfdataFileName(target)); if (perfDataContents) { return JSON.parse(perfDataContents); } return undefined; } - function hashName(runner: Harness.TestRunnerKind | "unittest", test: string) { + function hashName(runner: TestRunnerKind | "unittest", test: string) { return `tsrunner-${runner}://${test}`; } @@ -193,7 +199,7 @@ export function start() { console.log(`Discovered ${tasks.length} unittest suites` + (newTasks.length ? ` and ${newTasks.length} new suites.` : ".")); console.log("Discovering runner-based tests..."); const discoverStart = +(new Date()); - for (const runner of Harness.runners) { + for (const runner of runners) { for (const test of runner.getTestFiles()) { const file = typeof test === "string" ? test : test.file; let size: number; @@ -204,7 +210,7 @@ export function start() { catch { // May be a directory try { - size = Harness.IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0); + size = IO.listFiles(path.join(runner.workingDirectory, file), /.*/g, { recursive: true }).reduce((acc, elem) => acc + statSync(elem).size, 0); } catch { // Unknown test kind, just return 0 and let the historical analysis take over after one run @@ -228,22 +234,22 @@ export function start() { } tasks.sort((a, b) => a.size - b.size); tasks = tasks.concat(newTasks); - const batchCount = Harness.workerCount; + const batchCount = workerCount; const packfraction = 0.9; const chunkSize = 1000; // ~1KB or 1s for sending batches near the end of a test - const batchSize = (totalCost / Harness.workerCount) * packfraction; // Keep spare tests for unittest thread in reserve + const batchSize = (totalCost / workerCount) * packfraction; // Keep spare tests for unittest thread in reserve console.log(`Discovered ${tasks.length} test files in ${+(new Date()) - discoverStart}ms.`); - console.log(`Starting to run tests using ${Harness.workerCount} threads...`); + console.log(`Starting to run tests using ${workerCount} threads...`); const totalFiles = tasks.length; let passingFiles = 0; let failingFiles = 0; - let errorResults: Harness.Parallel.ErrorInfo[] = []; + let errorResults: ErrorInfo[] = []; let passingResults: { name: string[] }[] = []; let totalPassing = 0; const startDate = new Date(); - const progressBars = new ProgressBars({ noColors: Harness.noColors }); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier + const progressBars = new ProgressBars({ noColors: noColors }); // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier const progressUpdateInterval = 1 / progressBars._options.width; let nextProgress = progressUpdateInterval; @@ -251,11 +257,11 @@ export function start() { const workers: Worker[] = []; let closedWorkers = 0; - for (let i = 0; i < Harness.workerCount; i++) { + for (let i = 0; i < workerCount; i++) { // TODO: Just send the config over the IPC channel or in the command line arguments - const config: Harness.TestConfig = { light: Harness.lightMode, listenForWork: true, runUnitTests: Harness.runUnitTests, stackTraceLimit: Harness.stackTraceLimit, timeout: Harness.globalTimeout }; // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier - const configPath = ts.combinePaths(Harness.taskConfigsFolder, `task-config${i}.json`); - Harness.IO.writeFile(configPath, JSON.stringify(config)); + const config: TestConfig = { light: lightMode, listenForWork: true, runUnitTests: runUnitTests, stackTraceLimit: stackTraceLimit, timeout: globalTimeout }; // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier + const configPath = ts.combinePaths(taskConfigsFolder, `task-config${i}.json`); + IO.writeFile(configPath, JSON.stringify(config)); const worker: Worker = { process: fork(__filename, [`--config="${configPath}"`], { stdio: ["pipe", "pipe", "pipe", "ipc"] }), accumulatedOutput: "", @@ -268,7 +274,7 @@ export function start() { }; worker.process.stderr!.on("data", appendOutput); worker.process.stdout!.on("data", appendOutput); - const killChild = (timeout: Harness.Parallel.TaskTimeout) => { + const killChild = (timeout: TaskTimeout) => { worker.process.kill(); console.error(`Worker exceeded ${timeout.duration}ms timeout ${worker.currentTasks && worker.currentTasks.length ? `while running test '${worker.currentTasks[0].file}'.` : `during test setup.`}`); return process.exit(2); @@ -285,7 +291,7 @@ export function start() { return process.exit(2); } }); - worker.process.on("message", (data: Harness.Parallel.ParallelClientMessage) => { + worker.process.on("message", (data: ParallelClientMessage) => { switch (data.type) { case "error": { console.error(`Test worker encountered unexpected error${data.payload.name ? ` during the execution of test ${data.payload.name}` : ""} and was forced to close: @@ -337,7 +343,7 @@ export function start() { // No more tasks to distribute worker.process.send({ type: "close" }); closedWorkers++; - if (closedWorkers === Harness.workerCount) { + if (closedWorkers === workerCount) { outputFinalResult(); } return; @@ -349,10 +355,10 @@ export function start() { } worker.currentTasks = taskList; if (taskList.length === 1) { - worker.process.send({ type: "test", payload: taskList[0] } as Harness.Parallel.ParallelHostMessage); // TODO: GH#18217 + worker.process.send({ type: "test", payload: taskList[0] } as ParallelHostMessage); // TODO: GH#18217 } else { - worker.process.send({ type: "batch", payload: taskList } as Harness.Parallel.ParallelHostMessage); // TODO: GH#18217 + worker.process.send({ type: "batch", payload: taskList } as ParallelHostMessage); // TODO: GH#18217 } } } @@ -364,12 +370,12 @@ export function start() { // It's only really worth doing an initial batching if there are a ton of files to go through (and they have estimates) if (totalFiles > 1000 && batchSize > 0) { console.log("Batching initial test lists..."); - const batches: { runner: Harness.TestRunnerKind | "unittest", file: string, size: number }[][] = new Array(batchCount); + const batches: { runner: TestRunnerKind | "unittest", file: string, size: number }[][] = new Array(batchCount); const doneBatching = new Array(batchCount); let scheduledTotal = 0; batcher: while (true) { for (let i = 0; i < batchCount; i++) { - if (tasks.length <= Harness.workerCount) { // Keep a small reserve even in the suboptimally packed case + if (tasks.length <= workerCount) { // Keep a small reserve even in the suboptimally packed case console.log(`Suboptimal packing detected: no tests remain to be stolen. Reduce packing fraction from ${packfraction} to fix.`); break batcher; } @@ -417,7 +423,7 @@ export function start() { } } else { - for (let i = 0; i < Harness.workerCount; i++) { + for (let i = 0; i < workerCount; i++) { const task = tasks.pop()!; workers[i].currentTasks = [task]; workers[i].process.send({ type: "test", payload: task }); @@ -437,7 +443,7 @@ export function start() { const summaryTests = (isPartitionFail ? totalPassing + "/" + (errorResults.length + totalPassing) : totalPassing) + " passing"; const summaryDuration = "(" + ms(duration) + ")"; const savedUseColors = Base.useColors; - Base.useColors = !Harness.noColors; + Base.useColors = !noColors; const summary = color(summaryColor, summarySymbol + " " + summaryTests) + " " + color("light", summaryDuration); Base.useColors = savedUseColors; @@ -481,9 +487,9 @@ export function start() { }); } - function rebuildSuite(failures: Harness.Parallel.ErrorInfo[], passes: Harness.Parallel.TestInfo[]) { + function rebuildSuite(failures: ErrorInfo[], passes: TestInfo[]) { const root = new RemoteSuite(""); - for (const result of [...failures, ...passes] as (Harness.Parallel.ErrorInfo | Harness.Parallel.TestInfo)[]) { + for (const result of [...failures, ...passes] as (ErrorInfo | TestInfo)[]) { getSuite(root, result.name.slice(0, -1)).addTest(new RemoteTest(result)); } return root; @@ -495,7 +501,7 @@ export function start() { } } - function rebuildError(result: Harness.Parallel.ErrorInfo) { + function rebuildError(result: ErrorInfo) { const error = new Error(result.error); error.stack = result.stack; return error; @@ -552,22 +558,23 @@ export function start() { failedTestReporter = new FailedTestReporter(replayRunner, { reporterOptions: { file: path.resolve(".failed-tests"), - keepFailed: Harness.keepFailed // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier + keepFailed: keepFailed // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier + // eslint-disable-line @typescript-eslint/no-unnecessary-qualifier } }); } const savedUseColors = Base.useColors; - if (Harness.noColors) Base.useColors = false; + if (noColors) Base.useColors = false; replayRunner.started = true; replayRunner.emit("start"); replaySuite(replayRunner, rebuildSuite(errorResults, passingResults)); replayRunner.emit("end"); consoleReporter.epilogue(); - if (Harness.noColors) Base.useColors = savedUseColors; + if (noColors) Base.useColors = savedUseColors; // eslint-disable-next-line no-null/no-null - Harness.IO.writeFile(perfdataFileName(Harness.configOption), JSON.stringify(newPerfData, null, 4)); + IO.writeFile(perfdataFileName(configOption), JSON.stringify(newPerfData, null, 4)); if (xunitReporter) { xunitReporter.done(errorResults.length, failures => process.exit(failures)); @@ -597,9 +604,9 @@ export function start() { } function shimDiscoveryInterface(context: Mocha.MochaGlobals) { - Harness.Parallel.shimNoopTestInterface(context); + shimNoopTestInterface(context); - const perfData = readSavedPerfData(Harness.configOption); + const perfData = readSavedPerfData(configOption); context.describe = addSuite as Mocha.SuiteFunction; context.it = addSuite as Mocha.TestFunction; @@ -619,11 +626,11 @@ export function start() { } } - if (Harness.runUnitTests) { + if (runUnitTests) { shimDiscoveryInterface(global); } else { - Harness.Parallel.shimNoopTestInterface(global); + shimNoopTestInterface(global); } // eslint-disable-next-line no-restricted-globals diff --git a/src/testRunner/parallel/shared.ts b/src/testRunner/parallel/shared.ts index 141d9a7c3428e..3d40c4c772ae6 100644 --- a/src/testRunner/parallel/shared.ts +++ b/src/testRunner/parallel/shared.ts @@ -1,8 +1,8 @@ -import * as Harness from "../_namespaces/Harness"; import * as ts from "../_namespaces/ts"; +import { TestRunnerKind } from "../_namespaces/Harness"; export interface RunnerTask { - runner: Harness.TestRunnerKind; + runner: TestRunnerKind; file: string; size: number; } diff --git a/src/testRunner/parallel/worker.ts b/src/testRunner/parallel/worker.ts index 5c07637a5efd5..57538ea26b81c 100644 --- a/src/testRunner/parallel/worker.ts +++ b/src/testRunner/parallel/worker.ts @@ -1,5 +1,9 @@ -import * as Harness from "../_namespaces/Harness"; import * as ts from "../_namespaces/ts"; +import { + ErrorInfo, ParallelClientMessage, ParallelHostMessage, RunnerTask, shimNoopTestInterface, Task, TaskResult, + TestInfo, UnitTestTask, +} from "../_namespaces/Harness.Parallel"; +import { createRunner, globalTimeout, RunnerBase, runUnitTests } from "../_namespaces/Harness"; export function start() { function hookUncaughtExceptions() { @@ -137,7 +141,7 @@ export function start() { /** * Run the tests in the requested task. */ - function runTests(task: Harness.Parallel.Task, fn: (payload: Harness.Parallel.TaskResult) => void) { + function runTests(task: Task, fn: (payload: TaskResult) => void) { if (task.runner === "unittest") { return executeUnitTests(task, fn); } @@ -146,7 +150,7 @@ export function start() { } } - function executeUnitTests(task: Harness.Parallel.UnitTestTask, fn: (payload: Harness.Parallel.TaskResult) => void) { + function executeUnitTests(task: UnitTestTask, fn: (payload: TaskResult) => void) { if (!unitTestSuiteMap && unitTestSuite.suites.length) { unitTestSuiteMap = new ts.Map(); for (const suite of unitTestSuite.suites) { @@ -171,7 +175,7 @@ export function start() { } const root = new Suite("", new Mocha.Context()); - root.timeout(Harness.globalTimeout || 40_000); + root.timeout(globalTimeout || 40_000); if (suite) { root.addSuite(suite); Object.setPrototypeOf(suite.ctx, root.ctx); @@ -193,13 +197,13 @@ export function start() { }); } - function runFileTests(task: Harness.Parallel.RunnerTask, fn: (result: Harness.Parallel.TaskResult) => void) { + function runFileTests(task: RunnerTask, fn: (result: TaskResult) => void) { let instance = runners.get(task.runner); - if (!instance) runners.set(task.runner, instance = Harness.createRunner(task.runner)); + if (!instance) runners.set(task.runner, instance = createRunner(task.runner)); instance.tests = [task.file]; const suite = new Suite("", new Mocha.Context()); - suite.timeout(Harness.globalTimeout || 40_000); + suite.timeout(globalTimeout || 40_000); shimTestInterface(suite, global); instance.initializeTests(); @@ -207,9 +211,9 @@ export function start() { runSuite(task, suite, fn); } - function runSuite(task: Harness.Parallel.Task, suite: Mocha.Suite, fn: (result: Harness.Parallel.TaskResult) => void) { - const errors: Harness.Parallel.ErrorInfo[] = []; - const passes: Harness.Parallel.TestInfo[] = []; + function runSuite(task: Task, suite: Mocha.Suite, fn: (result: TaskResult) => void) { + const errors: ErrorInfo[] = []; + const passes: TestInfo[] = []; const start = +new Date(); const runner = new Mocha.Runner(suite, { delay: false }); @@ -235,7 +239,7 @@ export function start() { /** * Validates a message received from the host is well-formed. */ - function validateHostMessage(message: Harness.Parallel.ParallelHostMessage) { + function validateHostMessage(message: ParallelHostMessage) { switch (message.type) { case "test": return validateTest(message.payload); case "batch": return validateBatch(message.payload); @@ -247,18 +251,18 @@ export function start() { /** * Validates a test task is well formed. */ - function validateTest(task: Harness.Parallel.Task) { + function validateTest(task: Task) { return !!task && !!task.runner && !!task.file; } /** * Validates a batch of test tasks are well formed. */ - function validateBatch(tasks: Harness.Parallel.Task[]) { + function validateBatch(tasks: Task[]) { return !!tasks && Array.isArray(tasks) && tasks.length > 0 && tasks.every(validateTest); } - function processHostMessage(message: Harness.Parallel.ParallelHostMessage) { + function processHostMessage(message: ParallelHostMessage) { if (!validateHostMessage(message)) { console.log("Invalid message:", message); return; @@ -271,14 +275,14 @@ export function start() { } } - function processTest(task: Harness.Parallel.Task, last: boolean, fn?: () => void) { + function processTest(task: Task, last: boolean, fn?: () => void) { runTests(task, payload => { sendMessage(last ? { type: "result", payload } : { type: "progress", payload }); if (fn) fn(); }); } - function processBatch(tasks: Harness.Parallel.Task[], fn?: () => void) { + function processBatch(tasks: Task[], fn?: () => void) { const next = () => { const task = tasks.shift(); if (task) return processTest(task, tasks.length === 0, next); @@ -292,12 +296,12 @@ export function start() { sendMessage({ type: "error", payload: { error: error.message, stack: error.stack! } }); } - function sendMessage(message: Harness.Parallel.ParallelClientMessage) { + function sendMessage(message: ParallelClientMessage) { process.send!(message); } // A cache of test harness Runner instances. - const runners = new ts.Map(); + const runners = new ts.Map(); // The root suite for all unit tests. let unitTestSuite: Suite; @@ -305,14 +309,14 @@ export function start() { // (Unit) Tests directly within the root suite let unitTestTestMap: ts.ESMap; - if (Harness.runUnitTests) { + if (runUnitTests) { unitTestSuite = new Suite("", new Mocha.Context()); - unitTestSuite.timeout(Harness.globalTimeout || 40_000); + unitTestSuite.timeout(globalTimeout || 40_000); shimTestInterface(unitTestSuite, global); } else { // ensure unit tests do not get run - Harness.Parallel.shimNoopTestInterface(global); + shimNoopTestInterface(global); } process.on("message", processHostMessage); diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index 885602c4d2835..ff59c4e75250b 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -1,21 +1,25 @@ -import * as Harness from "./_namespaces/Harness"; import * as vpath from "./_namespaces/vpath"; import * as ts from "./_namespaces/ts"; import * as FourSlash from "./_namespaces/FourSlash"; import * as project from "./_namespaces/project"; import * as RWC from "./_namespaces/RWC"; +import { + CompilerBaselineRunner, CompilerTestType, DefinitelyTypedRunner, DockerfileRunner, FourSlashRunner, + GeneratedFourslashRunner, IO, Parallel, RunnerBase, setLightMode, setShardId, setShards, Test262BaselineRunner, + TestRunnerKind, UserCodeRunner, +} from "./_namespaces/Harness"; /* eslint-disable prefer-const */ -export let runners: Harness.RunnerBase[] = []; +export let runners: RunnerBase[] = []; export let iterations = 1; /* eslint-enable prefer-const */ -function runTests(runners: Harness.RunnerBase[]) { +function runTests(runners: RunnerBase[]) { for (let i = iterations; i > 0; i--) { const seen = new Map(); const dupes: [string, string][] = []; for (const runner of runners) { - if (runner instanceof Harness.CompilerBaselineRunner || runner instanceof Harness.FourSlashRunner) { + if (runner instanceof CompilerBaselineRunner || runner instanceof FourSlashRunner) { for (const sf of runner.enumerateTestFiles()) { const full = typeof sf === "string" ? sf : sf.file; const base = vpath.basename(full).toLowerCase(); @@ -44,32 +48,32 @@ function tryGetConfig(args: string[]) { return configPath && configPath.replace(/(^[\"'])|([\"']$)/g, ""); } -export function createRunner(kind: Harness.TestRunnerKind): Harness.RunnerBase { +export function createRunner(kind: TestRunnerKind): RunnerBase { switch (kind) { case "conformance": - return new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Conformance); + return new CompilerBaselineRunner(CompilerTestType.Conformance); case "compiler": - return new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Regressions); + return new CompilerBaselineRunner(CompilerTestType.Regressions); case "fourslash": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Native); + return new FourSlashRunner(FourSlash.FourSlashTestType.Native); case "fourslash-shims": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Shims); + return new FourSlashRunner(FourSlash.FourSlashTestType.Shims); case "fourslash-shims-pp": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess); + return new FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess); case "fourslash-server": - return new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Server); + return new FourSlashRunner(FourSlash.FourSlashTestType.Server); case "project": return new project.ProjectRunner(); case "rwc": return new RWC.RWCRunner(); case "test262": - return new Harness.Test262BaselineRunner(); + return new Test262BaselineRunner(); case "user": - return new Harness.UserCodeRunner(); + return new UserCodeRunner(); case "dt": - return new Harness.DefinitelyTypedRunner(); + return new DefinitelyTypedRunner(); case "docker": - return new Harness.DockerfileRunner(); + return new DockerfileRunner(); } return ts.Debug.fail(`Unknown runner kind ${kind}`); } @@ -79,13 +83,13 @@ export function createRunner(kind: Harness.TestRunnerKind): Harness.RunnerBase { const mytestconfigFileName = "mytest.config"; const testconfigFileName = "test.config"; -const customConfig = tryGetConfig(Harness.IO.args()); +const customConfig = tryGetConfig(IO.args()); const testConfigContent = - customConfig && Harness.IO.fileExists(customConfig) - ? Harness.IO.readFile(customConfig)! - : Harness.IO.fileExists(mytestconfigFileName) - ? Harness.IO.readFile(mytestconfigFileName)! - : Harness.IO.fileExists(testconfigFileName) ? Harness.IO.readFile(testconfigFileName)! : ""; + customConfig && IO.fileExists(customConfig) + ? IO.readFile(customConfig)! + : IO.fileExists(mytestconfigFileName) + ? IO.readFile(mytestconfigFileName)! + : IO.fileExists(testconfigFileName) ? IO.readFile(testconfigFileName)! : ""; export let taskConfigsFolder: string; export let workerCount: number; @@ -111,7 +115,7 @@ export interface TestConfig { } export interface TaskSet { - runner: Harness.TestRunnerKind; + runner: TestRunnerKind; files: string[]; } @@ -121,7 +125,7 @@ function handleTestConfig() { if (testConfigContent !== "") { const testConfig = JSON.parse(testConfigContent) as TestConfig; if (testConfig.light) { - Harness.setLightMode(true); + setLightMode(true); } if (testConfig.timeout) { globalTimeout = testConfig.timeout; @@ -140,10 +144,10 @@ function handleTestConfig() { keepFailed = true; } if (testConfig.shardId) { - Harness.setShardId(testConfig.shardId); + setShardId(testConfig.shardId); } if (testConfig.shards) { - Harness.setShards(testConfig.shards); + setShards(testConfig.shards); } if (testConfig.stackTraceLimit === "full") { @@ -177,44 +181,44 @@ function handleTestConfig() { switch (option) { case "compiler": - runners.push(new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Conformance)); - runners.push(new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Regressions)); + runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance)); + runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions)); break; case "conformance": - runners.push(new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Conformance)); + runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance)); break; case "project": runners.push(new project.ProjectRunner()); break; case "fourslash": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Native)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Native)); break; case "fourslash-shims": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Shims)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Shims)); break; case "fourslash-shims-pp": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess)); break; case "fourslash-server": - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Server)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Server)); break; case "fourslash-generated": - runners.push(new Harness.GeneratedFourslashRunner(FourSlash.FourSlashTestType.Native)); + runners.push(new GeneratedFourslashRunner(FourSlash.FourSlashTestType.Native)); break; case "rwc": runners.push(new RWC.RWCRunner()); break; case "test262": - runners.push(new Harness.Test262BaselineRunner()); + runners.push(new Test262BaselineRunner()); break; case "user": - runners.push(new Harness.UserCodeRunner()); + runners.push(new UserCodeRunner()); break; case "dt": - runners.push(new Harness.DefinitelyTypedRunner()); + runners.push(new DefinitelyTypedRunner()); break; case "docker": - runners.push(new Harness.DockerfileRunner()); + runners.push(new DockerfileRunner()); break; } } @@ -223,22 +227,22 @@ function handleTestConfig() { if (runners.length === 0) { // compiler - runners.push(new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Conformance)); - runners.push(new Harness.CompilerBaselineRunner(Harness.CompilerTestType.Regressions)); + runners.push(new CompilerBaselineRunner(CompilerTestType.Conformance)); + runners.push(new CompilerBaselineRunner(CompilerTestType.Regressions)); runners.push(new project.ProjectRunner()); // language services - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Native)); - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Shims)); - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess)); - runners.push(new Harness.FourSlashRunner(FourSlash.FourSlashTestType.Server)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Native)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Shims)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.ShimsWithPreprocess)); + runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Server)); // runners.push(new GeneratedFourslashRunner()); // CRON-only tests if (process.env.TRAVIS_EVENT_TYPE === "cron") { - runners.push(new Harness.UserCodeRunner()); - runners.push(new Harness.DockerfileRunner()); + runners.push(new UserCodeRunner()); + runners.push(new DockerfileRunner()); } } if (runUnitTests === undefined) { @@ -278,10 +282,10 @@ export let isWorker: boolean; function startTestEnvironment() { isWorker = handleTestConfig(); if (isWorker) { - return Harness.Parallel.Worker.start(); + return Parallel.Worker.start(); } else if (taskConfigsFolder && workerCount && workerCount > 1) { - return Harness.Parallel.Host.start(); + return Parallel.Host.start(); } beginTests(); } diff --git a/src/testRunner/test262Runner.ts b/src/testRunner/test262Runner.ts index 5d37cf49c1069..87aee2bf57401 100644 --- a/src/testRunner/test262Runner.ts +++ b/src/testRunner/test262Runner.ts @@ -1,15 +1,15 @@ -import * as Harness from "./_namespaces/Harness"; import * as ts from "./_namespaces/ts"; import * as compiler from "./_namespaces/compiler"; import * as Utils from "./_namespaces/Utils"; +import { Baseline, Compiler, IO, RunnerBase, TestCaseParser, TestRunnerKind } from "./_namespaces/Harness"; // In harness baselines, null is different than undefined. See `generateActual` in `harness.ts`. -export class Test262BaselineRunner extends Harness.RunnerBase { +export class Test262BaselineRunner extends RunnerBase { private static readonly basePath = "internal/cases/test262"; private static readonly helpersFilePath = "tests/cases/test262-harness/helpers.d.ts"; - private static readonly helperFile: Harness.Compiler.TestFile = { + private static readonly helperFile: Compiler.TestFile = { unitName: Test262BaselineRunner.helpersFilePath, - content: Harness.IO.readFile(Test262BaselineRunner.helpersFilePath)!, + content: IO.readFile(Test262BaselineRunner.helpersFilePath)!, }; private static readonly testFileExtensionRegex = /\.js$/; private static readonly options: ts.CompilerOptions = { @@ -17,7 +17,7 @@ export class Test262BaselineRunner extends Harness.RunnerBase { target: ts.ScriptTarget.Latest, module: ts.ModuleKind.CommonJS }; - private static readonly baselineOptions: Harness.Baseline.BaselineOptions = { + private static readonly baselineOptions: Baseline.BaselineOptions = { Subfolder: "test262", Baselinefolder: "internal/baselines" }; @@ -33,15 +33,15 @@ export class Test262BaselineRunner extends Harness.RunnerBase { let testState: { filename: string; compilerResult: compiler.CompilationResult; - inputFiles: Harness.Compiler.TestFile[]; + inputFiles: Compiler.TestFile[]; }; before(() => { - const content = Harness.IO.readFile(filePath)!; + const content = IO.readFile(filePath)!; const testFilename = ts.removeFileExtension(filePath).replace(/\//g, "_") + ".test"; - const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, testFilename); + const testCaseContent = TestCaseParser.makeUnitsFromTest(content, testFilename); - const inputFiles: Harness.Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => { + const inputFiles: Compiler.TestFile[] = testCaseContent.testUnitData.map(unit => { const unitName = Test262BaselineRunner.getTestFilePath(unit.name); return { unitName, content: unit.content }; }); @@ -53,7 +53,7 @@ export class Test262BaselineRunner extends Harness.RunnerBase { compilerResult: undefined!, // TODO: GH#18217 }; - testState.compilerResult = Harness.Compiler.compileFiles( + testState.compilerResult = Compiler.compileFiles( [Test262BaselineRunner.helperFile].concat(inputFiles), /*otherFiles*/ [], /* harnessOptions */ undefined, @@ -67,14 +67,14 @@ export class Test262BaselineRunner extends Harness.RunnerBase { it("has the expected emitted code", () => { const files = Array.from(testState.compilerResult.js.values()).filter(f => f.file !== Test262BaselineRunner.helpersFilePath); - Harness.Baseline.runBaseline(testState.filename + ".output.js", Harness.Compiler.collateOutputs(files), Test262BaselineRunner.baselineOptions); + Baseline.runBaseline(testState.filename + ".output.js", Compiler.collateOutputs(files), Test262BaselineRunner.baselineOptions); }); it("has the expected errors", () => { const errors = testState.compilerResult.diagnostics; // eslint-disable-next-line no-null/no-null - const baseline = errors.length === 0 ? null : Harness.Compiler.getErrorBaseline(testState.inputFiles, errors); - Harness.Baseline.runBaseline(testState.filename + ".errors.txt", baseline, Test262BaselineRunner.baselineOptions); + const baseline = errors.length === 0 ? null : Compiler.getErrorBaseline(testState.inputFiles, errors); + Baseline.runBaseline(testState.filename + ".errors.txt", baseline, Test262BaselineRunner.baselineOptions); }); it("satisfies invariants", () => { @@ -84,12 +84,12 @@ export class Test262BaselineRunner extends Harness.RunnerBase { it("has the expected AST", () => { const sourceFile = testState.compilerResult.program!.getSourceFile(Test262BaselineRunner.getTestFilePath(testState.filename))!; - Harness.Baseline.runBaseline(testState.filename + ".AST.txt", Utils.sourceFileToJSON(sourceFile), Test262BaselineRunner.baselineOptions); + Baseline.runBaseline(testState.filename + ".AST.txt", Utils.sourceFileToJSON(sourceFile), Test262BaselineRunner.baselineOptions); }); }); } - public kind(): Harness.TestRunnerKind { + public kind(): TestRunnerKind { return "test262"; } diff --git a/src/tsserver/nodeServer.ts b/src/tsserver/nodeServer.ts index 836bf782c9d17..45c89194bfa0c 100644 --- a/src/tsserver/nodeServer.ts +++ b/src/tsserver/nodeServer.ts @@ -1,8 +1,26 @@ import * as ts from "./_namespaces/ts"; +import * as server from "./_namespaces/ts.server"; +import { + ActionInvalidate, ActionPackageInstalled, ActionSet, Arguments, BaseLogger, BeginInstallTypes, + createInstallTypingsRequest, EndInstallTypes, EventBeginInstallTypes, EventEndInstallTypes, + EventInitializationFailed, EventTypesRegistry, findArgument, formatMessage, getLogLevel, hasArgument, indent, + InitializationFailedResponse, InstallPackageOptionsWithProject, InstallPackageRequest, InvalidateCachedTypings, + ITypingsInstaller, Logger, LogLevel, ModuleImportResult, Msg, nullCancellationToken, nullTypingsInstaller, + PackageInstalledResponse, Project, ProjectService, protocol, ServerCancellationToken, ServerHost, Session, + SetTypings, StartInput, StartSessionOptions, stringifyIndented, toEvent, TypesRegistryResponse, + TypingInstallerRequestUnion, +} from "./_namespaces/ts.server"; +import { + ApplyCodeActionCommandResult, assertType, CharacterCodes, combinePaths, createQueue, Debug, directorySeparator, + DirectoryWatcherCallback, ESMap, FileWatcher, getDirectoryPath, getEntries, getNodeMajorVersion, getRootLength, + JsTyping, LanguageServiceMode, Map, MapLike, noop, noopFileWatcher, normalizeSlashes, resolveJSModule, + SortedReadonlyArray, startTracing, stripQuotes, sys, toFileNameLowerCase, tracing, TypeAcquisition, + validateLocaleAndSetLanguage, versionMajorMinor, WatchOptions, +} from "./_namespaces/ts"; interface LogOptions { file?: string; - detailLevel?: ts.server.LogLevel; + detailLevel?: LogLevel; traceToConsole?: boolean; logToFile?: boolean; } @@ -42,8 +60,8 @@ function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOption logEnv.file = value; break; case "-level": - const level = ts.server.getLogLevel(value); - logEnv.detailLevel = level !== undefined ? level : ts.server.LogLevel.normal; + const level = getLogLevel(value); + logEnv.detailLevel = level !== undefined ? level : LogLevel.normal; break; case "-traceToConsole": logEnv.traceToConsole = value.toLowerCase() === "true"; @@ -59,40 +77,40 @@ function parseLoggingEnvironmentString(logEnvStr: string | undefined): LogOption function getEntireValue(initialIndex: number) { let pathStart = args[initialIndex]; let extraPartCounter = 0; - if (pathStart.charCodeAt(0) === ts.CharacterCodes.doubleQuote && - pathStart.charCodeAt(pathStart.length - 1) !== ts.CharacterCodes.doubleQuote) { + if (pathStart.charCodeAt(0) === CharacterCodes.doubleQuote && + pathStart.charCodeAt(pathStart.length - 1) !== CharacterCodes.doubleQuote) { for (let i = initialIndex + 1; i < args.length; i++) { pathStart += " "; pathStart += args[i]; extraPartCounter++; - if (pathStart.charCodeAt(pathStart.length - 1) === ts.CharacterCodes.doubleQuote) break; + if (pathStart.charCodeAt(pathStart.length - 1) === CharacterCodes.doubleQuote) break; } } - return { value: ts.stripQuotes(pathStart), extraPartCounter }; + return { value: stripQuotes(pathStart), extraPartCounter }; } } -function parseServerMode(): ts.LanguageServiceMode | string | undefined { - const mode = ts.server.findArgument("--serverMode"); +function parseServerMode(): LanguageServiceMode | string | undefined { + const mode = findArgument("--serverMode"); if (!mode) return undefined; switch (mode.toLowerCase()) { case "semantic": - return ts.LanguageServiceMode.Semantic; + return LanguageServiceMode.Semantic; case "partialsemantic": - return ts.LanguageServiceMode.PartialSemantic; + return LanguageServiceMode.PartialSemantic; case "syntactic": - return ts.LanguageServiceMode.Syntactic; + return LanguageServiceMode.Syntactic; default: return mode; } } /** @internal */ -export function initializeNodeSystem(): ts.server.StartInput { - const sys = ts.Debug.checkDefined(ts.sys) as ts.server.ServerHost; +export function initializeNodeSystem(): StartInput { + const sys = Debug.checkDefined(ts.sys) as ServerHost; const childProcess: { - execFileSync(file: string, args: string[], options: { stdio: "ignore", env: ts.MapLike }): string | Buffer; + execFileSync(file: string, args: string[], options: { stdio: "ignore", env: MapLike }): string | Buffer; } = require("child_process"); interface Stats { @@ -127,12 +145,12 @@ export function initializeNodeSystem(): ts.server.StartInput { stat(path: string, callback?: (err: NodeJS.ErrnoException, stats: Stats) => any): void; } = require("fs"); - class Logger extends ts.server.BaseLogger { + class Logger extends BaseLogger { private fd = -1; constructor( private readonly logFilename: string, private readonly traceToConsole: boolean, - level: ts.server.LogLevel + level: LogLevel ) { super(level); if (this.logFilename) { @@ -147,7 +165,7 @@ export function initializeNodeSystem(): ts.server.StartInput { close() { if (this.fd >= 0) { - fs.close(this.fd, ts.noop); + fs.close(this.fd, noop); } } @@ -163,7 +181,7 @@ export function initializeNodeSystem(): ts.server.StartInput { return this.fd >= 0 || this.traceToConsole; } - protected write(s: string, _type: ts.server.Msg) { + protected write(s: string, _type: Msg) { if (this.fd >= 0) { const buf = sys.bufferFrom!(s); // eslint-disable-next-line no-null/no-null @@ -175,53 +193,53 @@ export function initializeNodeSystem(): ts.server.StartInput { } } - const nodeVersion = ts.getNodeMajorVersion(); + const nodeVersion = getNodeMajorVersion(); // use watchGuard process on Windows when node version is 4 or later const useWatchGuard = process.platform === "win32" && nodeVersion! >= 4; - const originalWatchDirectory: ts.server.ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); + const originalWatchDirectory: ServerHost["watchDirectory"] = sys.watchDirectory.bind(sys); const logger = createLogger(); // enable deprecation logging - ts.Debug.loggingHost = { + Debug.loggingHost = { log(level, s) { switch (level) { case ts.LogLevel.Error: case ts.LogLevel.Warning: - return logger.msg(s, ts.server.Msg.Err); + return logger.msg(s, Msg.Err); case ts.LogLevel.Info: case ts.LogLevel.Verbose: - return logger.msg(s, ts.server.Msg.Info); + return logger.msg(s, Msg.Info); } } }; - const pending = ts.createQueue(); + const pending = createQueue(); let canWrite = true; if (useWatchGuard) { const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined); - const statusCache = new ts.Map(); + const statusCache = new Map(); sys.watchDirectory = (path, callback, recursive, options) => { const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive); let status = cacheKey && statusCache.get(cacheKey); if (status === undefined) { - if (logger.hasLevel(ts.server.LogLevel.verbose)) { + if (logger.hasLevel(LogLevel.verbose)) { logger.info(`${cacheKey} for path ${path} not found in cache...`); } try { - const args = [ts.combinePaths(__dirname, "watchGuard.js"), path]; - if (logger.hasLevel(ts.server.LogLevel.verbose)) { - logger.info(`Starting ${process.execPath} with args:${ts.server.stringifyIndented(args)}`); + const args = [combinePaths(__dirname, "watchGuard.js"), path]; + if (logger.hasLevel(LogLevel.verbose)) { + logger.info(`Starting ${process.execPath} with args:${stringifyIndented(args)}`); } childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { ELECTRON_RUN_AS_NODE: "1" } }); status = true; - if (logger.hasLevel(ts.server.LogLevel.verbose)) { + if (logger.hasLevel(LogLevel.verbose)) { logger.info(`WatchGuard for path ${path} returned: OK`); } } catch (e) { status = false; - if (logger.hasLevel(ts.server.LogLevel.verbose)) { + if (logger.hasLevel(LogLevel.verbose)) { logger.info(`WatchGuard for path ${path} returned: ${e.message}`); } } @@ -229,7 +247,7 @@ export function initializeNodeSystem(): ts.server.StartInput { statusCache.set(cacheKey, status); } } - else if (logger.hasLevel(ts.server.LogLevel.verbose)) { + else if (logger.hasLevel(LogLevel.verbose)) { logger.info(`watchDirectory for ${path} uses cached drive information.`); } if (status) { @@ -238,7 +256,7 @@ export function initializeNodeSystem(): ts.server.StartInput { } else { // this drive is unsafe - return no-op watcher - return ts.noopFileWatcher; + return noopFileWatcher; } }; } @@ -260,31 +278,31 @@ export function initializeNodeSystem(): ts.server.StartInput { sys.gc = () => global.gc?.(); } - sys.require = (initialDir: string, moduleName: string): ts.server.ModuleImportResult => { + sys.require = (initialDir: string, moduleName: string): ModuleImportResult => { try { - return { module: require(ts.resolveJSModule(moduleName, initialDir, sys)), error: undefined }; + return { module: require(resolveJSModule(moduleName, initialDir, sys)), error: undefined }; } catch (error) { return { module: undefined, error }; } }; - let cancellationToken: ts.server.ServerCancellationToken; + let cancellationToken: ServerCancellationToken; try { const factory = require("./cancellationToken"); cancellationToken = factory(sys.args); } catch (e) { - cancellationToken = ts.server.nullCancellationToken; + cancellationToken = nullCancellationToken; } - const localeStr = ts.server.findArgument("--locale"); + const localeStr = findArgument("--locale"); if (localeStr) { - ts.validateLocaleAndSetLanguage(localeStr, sys); + validateLocaleAndSetLanguage(localeStr, sys); } const modeOrUnknown = parseServerMode(); - let serverMode: ts.LanguageServiceMode | undefined; + let serverMode: LanguageServiceMode | undefined; let unknownServerMode: string | undefined; if (modeOrUnknown !== undefined) { if (typeof modeOrUnknown === "number") serverMode = modeOrUnknown; @@ -301,12 +319,12 @@ export function initializeNodeSystem(): ts.server.StartInput { // TSS_LOG "{ level: "normal | verbose | terse", file?: string}" function createLogger() { - const cmdLineLogFileName = ts.server.findArgument("--logFile"); - const cmdLineVerbosity = ts.server.getLogLevel(ts.server.findArgument("--logVerbosity")); + const cmdLineLogFileName = findArgument("--logFile"); + const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); const envLogOptions = parseLoggingEnvironmentString(process.env.TSS_LOG); const unsubstitutedLogFileName = cmdLineLogFileName - ? ts.stripQuotes(cmdLineLogFileName) + ? stripQuotes(cmdLineLogFileName) : envLogOptions.logToFile ? envLogOptions.file || (__dirname + "/.log" + process.pid.toString()) : undefined; @@ -337,24 +355,24 @@ export function initializeNodeSystem(): ts.server.StartInput { } function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string | undefined) { - path = ts.normalizeSlashes(path); + path = normalizeSlashes(path); if (isUNCPath(path)) { // UNC path: extract server name // //server/location // ^ <- from 0 to this position - const firstSlash = path.indexOf(ts.directorySeparator, 2); - return firstSlash !== -1 ? ts.toFileNameLowerCase(path.substring(0, firstSlash)) : path; + const firstSlash = path.indexOf(directorySeparator, 2); + return firstSlash !== -1 ? toFileNameLowerCase(path.substring(0, firstSlash)) : path; } - const rootLength = ts.getRootLength(path); + const rootLength = getRootLength(path); if (rootLength === 0) { // relative path - assume file is on the current drive return currentDriveKey; } - if (path.charCodeAt(1) === ts.CharacterCodes.colon && path.charCodeAt(2) === ts.CharacterCodes.slash) { + if (path.charCodeAt(1) === CharacterCodes.colon && path.charCodeAt(2) === CharacterCodes.slash) { // rooted path that starts with c:/... - extract drive letter - return ts.toFileNameLowerCase(path.charAt(0)); + return toFileNameLowerCase(path.charAt(0)); } - if (path.charCodeAt(0) === ts.CharacterCodes.slash && path.charCodeAt(1) !== ts.CharacterCodes.slash) { + if (path.charCodeAt(0) === CharacterCodes.slash && path.charCodeAt(1) !== CharacterCodes.slash) { // rooted path that starts with slash - /somename - use key for current drive return currentDriveKey; } @@ -363,18 +381,18 @@ export function initializeNodeSystem(): ts.server.StartInput { } function isUNCPath(s: string): boolean { - return s.length > 2 && s.charCodeAt(0) === ts.CharacterCodes.slash && s.charCodeAt(1) === ts.CharacterCodes.slash; + return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash; } // This is the function that catches the exceptions when watching directory, and yet lets project service continue to function // Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point - function watchDirectorySwallowingException(path: string, callback: ts.DirectoryWatcherCallback, recursive?: boolean, options?: ts.WatchOptions): ts.FileWatcher { + function watchDirectorySwallowingException(path: string, callback: DirectoryWatcherCallback, recursive?: boolean, options?: WatchOptions): FileWatcher { try { return originalWatchDirectory(path, callback, recursive, options); } catch (e) { logger.info(`Exception when creating directory watcher: ${e.message}`); - return ts.noopFileWatcher; + return noopFileWatcher; } } } @@ -384,9 +402,9 @@ function parseEventPort(eventPortStr: string | undefined) { return eventPort !== undefined && !isNaN(eventPort) ? eventPort : undefined; } -function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken) { +function startNodeSession(options: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken) { const childProcess: { - fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: ts.MapLike }): NodeChildProcess; + fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike }): NodeChildProcess; } = require("child_process"); const os: { @@ -413,15 +431,15 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser operation: () => void; } - class NodeTypingsInstaller implements ts.server.ITypingsInstaller { + class NodeTypingsInstaller implements ITypingsInstaller { private installer!: NodeChildProcess; - private projectService!: ts.server.ProjectService; + private projectService!: ProjectService; private activeRequestCount = 0; - private requestQueue = ts.createQueue(); - private requestMap = new ts.Map(); // Maps operation ID to newest requestQueue entry with that ID + private requestQueue = createQueue(); + private requestMap = new Map(); // Maps operation ID to newest requestQueue entry with that ID /** We will lazily request the types registry on the first call to `isKnownTypesPackageName` and store it in `typesRegistryCache`. */ private requestedRegistry = false; - private typesRegistryCache: ts.ESMap> | undefined; + private typesRegistryCache: ESMap> | undefined; // This number is essentially arbitrary. Processing more than one typings request // at a time makes sense, but having too many in the pipe results in a hang @@ -430,24 +448,24 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser // buffer, but we have yet to find a way to retrieve that value. private static readonly maxActiveRequestCount = 10; private static readonly requestDelayMillis = 100; - private packageInstalledPromise: { resolve(value: ts.ApplyCodeActionCommandResult): void, reject(reason: unknown): void } | undefined; + private packageInstalledPromise: { resolve(value: ApplyCodeActionCommandResult): void, reject(reason: unknown): void } | undefined; constructor( private readonly telemetryEnabled: boolean, - private readonly logger: ts.server.Logger, - private readonly host: ts.server.ServerHost, + private readonly logger: Logger, + private readonly host: ServerHost, readonly globalTypingsCacheLocation: string, readonly typingSafeListLocation: string, readonly typesMapLocation: string, private readonly npmLocation: string | undefined, private readonly validateDefaultNpmLocation: boolean, - private event: ts.server.Event) { + private event: server.Event) { } isKnownTypesPackageName(name: string): boolean { // We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package. - const validationResult = ts.JsTyping.validatePackageName(name); - if (validationResult !== ts.JsTyping.NameValidationResult.Ok) { + const validationResult = JsTyping.validatePackageName(name); + if (validationResult !== JsTyping.NameValidationResult.Ok) { return false; } @@ -460,38 +478,38 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser return false; } - installPackage(options: ts.server.InstallPackageOptionsWithProject): Promise { - this.send({ kind: "installPackage", ...options }); - ts.Debug.assert(this.packageInstalledPromise === undefined); - return new Promise((resolve, reject) => { + installPackage(options: InstallPackageOptionsWithProject): Promise { + this.send({ kind: "installPackage", ...options }); + Debug.assert(this.packageInstalledPromise === undefined); + return new Promise((resolve, reject) => { this.packageInstalledPromise = { resolve, reject }; }); } - attach(projectService: ts.server.ProjectService) { + attach(projectService: ProjectService) { this.projectService = projectService; - if (this.logger.hasLevel(ts.server.LogLevel.requestTime)) { + if (this.logger.hasLevel(LogLevel.requestTime)) { this.logger.info("Binding..."); } - const args: string[] = [ts.server.Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation]; + const args: string[] = [Arguments.GlobalCacheLocation, this.globalTypingsCacheLocation]; if (this.telemetryEnabled) { - args.push(ts.server.Arguments.EnableTelemetry); + args.push(Arguments.EnableTelemetry); } if (this.logger.loggingEnabled() && this.logger.getLogFileName()) { - args.push(ts.server.Arguments.LogFile, ts.combinePaths(ts.getDirectoryPath(ts.normalizeSlashes(this.logger.getLogFileName()!)), `ti-${process.pid}.log`)); + args.push(Arguments.LogFile, combinePaths(getDirectoryPath(normalizeSlashes(this.logger.getLogFileName()!)), `ti-${process.pid}.log`)); } if (this.typingSafeListLocation) { - args.push(ts.server.Arguments.TypingSafeListLocation, this.typingSafeListLocation); + args.push(Arguments.TypingSafeListLocation, this.typingSafeListLocation); } if (this.typesMapLocation) { - args.push(ts.server.Arguments.TypesMapLocation, this.typesMapLocation); + args.push(Arguments.TypesMapLocation, this.typesMapLocation); } if (this.npmLocation) { - args.push(ts.server.Arguments.NpmLocation, this.npmLocation); + args.push(Arguments.NpmLocation, this.npmLocation); } if (this.validateDefaultNpmLocation) { - args.push(ts.server.Arguments.ValidateDefaultNpmLocation); + args.push(Arguments.ValidateDefaultNpmLocation); } const execArgv: string[] = []; @@ -508,7 +526,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } } - this.installer = childProcess.fork(ts.combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv }); + this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"), args, { execArgv }); this.installer.on("message", m => this.handleMessage(m)); // We have to schedule this event to the next tick @@ -522,26 +540,26 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser }); } - onProjectClosed(p: ts.server.Project): void { + onProjectClosed(p: Project): void { this.send({ projectName: p.getProjectName(), kind: "closeProject" }); } - private send(rq: T): void { + private send(rq: T): void { this.installer.send(rq); } - enqueueInstallTypingsRequest(project: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray): void { - const request = ts.server.createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - this.logger.info(`Scheduling throttled operation:${ts.server.stringifyIndented(request)}`); + enqueueInstallTypingsRequest(project: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void { + const request = createInstallTypingsRequest(project, typeAcquisition, unresolvedImports); + if (this.logger.hasLevel(LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Scheduling throttled operation:${stringifyIndented(request)}`); } } const operationId = project.getProjectName(); const operation = () => { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - this.logger.info(`Sending request:${ts.server.stringifyIndented(request)}`); + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Sending request:${stringifyIndented(request)}`); } this.send(request); }; @@ -551,7 +569,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser this.scheduleRequest(queuedRequest); } else { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Deferring request for: ${operationId}`); } this.requestQueue.enqueue(queuedRequest); @@ -559,16 +577,16 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } } - private handleMessage(response: ts.server.TypesRegistryResponse | ts.server.PackageInstalledResponse | ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes | ts.server.InitializationFailedResponse) { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - this.logger.info(`Received response:${ts.server.stringifyIndented(response)}`); + private handleMessage(response: TypesRegistryResponse | PackageInstalledResponse | SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse) { + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`Received response:${stringifyIndented(response)}`); } switch (response.kind) { - case ts.server.EventTypesRegistry: - this.typesRegistryCache = new ts.Map(ts.getEntries(response.typesRegistry)); + case EventTypesRegistry: + this.typesRegistryCache = new Map(getEntries(response.typesRegistry)); break; - case ts.server.ActionPackageInstalled: { + case ActionPackageInstalled: { const { success, message } = response; if (success) { this.packageInstalledPromise!.resolve({ successMessage: message }); @@ -584,26 +602,26 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser this.event(response, "setTypings"); break; } - case ts.server.EventInitializationFailed: { - const body: ts.server.protocol.TypesInstallerInitializationFailedEventBody = { + case EventInitializationFailed: { + const body: protocol.TypesInstallerInitializationFailedEventBody = { message: response.message }; - const eventName: ts.server.protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed"; + const eventName: protocol.TypesInstallerInitializationFailedEventName = "typesInstallerInitializationFailed"; this.event(body, eventName); break; } - case ts.server.EventBeginInstallTypes: { - const body: ts.server.protocol.BeginInstallTypesEventBody = { + case EventBeginInstallTypes: { + const body: protocol.BeginInstallTypesEventBody = { eventId: response.eventId, packages: response.packagesToInstall, }; - const eventName: ts.server.protocol.BeginInstallTypesEventName = "beginInstallTypes"; + const eventName: protocol.BeginInstallTypesEventName = "beginInstallTypes"; this.event(body, eventName); break; } - case ts.server.EventEndInstallTypes: { + case EventEndInstallTypes: { if (this.telemetryEnabled) { - const body: ts.server.protocol.TypingsInstalledTelemetryEventBody = { + const body: protocol.TypingsInstalledTelemetryEventBody = { telemetryEventName: "typingsInstalled", payload: { installedPackages: response.packagesToInstall.join(","), @@ -611,29 +629,29 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser typingsInstallerVersion: response.typingsInstallerVersion } }; - const eventName: ts.server.protocol.TelemetryEventName = "telemetry"; + const eventName: protocol.TelemetryEventName = "telemetry"; this.event(body, eventName); } - const body: ts.server.protocol.EndInstallTypesEventBody = { + const body: protocol.EndInstallTypesEventBody = { eventId: response.eventId, packages: response.packagesToInstall, success: response.installSuccess, }; - const eventName: ts.server.protocol.EndInstallTypesEventName = "endInstallTypes"; + const eventName: protocol.EndInstallTypesEventName = "endInstallTypes"; this.event(body, eventName); break; } - case ts.server.ActionInvalidate: { + case ActionInvalidate: { this.projectService.updateTypingsForProject(response); break; } - case ts.server.ActionSet: { + case ActionSet: { if (this.activeRequestCount > 0) { this.activeRequestCount--; } else { - ts.Debug.fail("Received too many responses"); + Debug.fail("Received too many responses"); } while (!this.requestQueue.isEmpty()) { @@ -644,7 +662,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser break; } - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Skipping defunct request for: ${queuedRequest.operationId}`); } } @@ -656,12 +674,12 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser break; } default: - ts.assertType(response); + assertType(response); } } private scheduleRequest(request: QueuedOperation) { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Scheduling request for: ${request.operationId}`); } this.activeRequestCount++; @@ -669,7 +687,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } } - class IOSession extends ts.server.Session { + class IOSession extends Session { private eventPort: number | undefined; private eventSocket: NodeSocket | undefined; private socketEventQueue: { body: any, eventName: string }[] | undefined; @@ -681,7 +699,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser this.event(body, eventName); }; - const host = ts.sys as ts.server.ServerHost; + const host = sys as ServerHost; const typingsInstaller = disableAutomaticTypingAcquisition ? undefined @@ -691,7 +709,7 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser host, cancellationToken, ...options, - typingsInstaller: typingsInstaller || ts.server.nullTypingsInstaller, + typingsInstaller: typingsInstaller || nullTypingsInstaller, byteLength: Buffer.byteLength, hrtime: process.hrtime, logger, @@ -717,18 +735,18 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } event(body: T, eventName: string): void { - ts.Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); + Debug.assert(!!this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); if (this.canUseEvents && this.eventPort) { if (!this.eventSocket) { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`eventPort: event "${eventName}" queued, but socket not yet initialized`); } (this.socketEventQueue || (this.socketEventQueue = [])).push({ body, eventName }); return; } else { - ts.Debug.assert(this.socketEventQueue === undefined); + Debug.assert(this.socketEventQueue === undefined); this.writeToEventSocket(body, eventName); } } @@ -738,13 +756,13 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } private writeToEventSocket(body: object, eventName: string): void { - this.eventSocket!.write(ts.server.formatMessage(ts.server.toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); + this.eventSocket!.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); } exit() { this.logger.info("Exiting..."); this.projectService.closeLog(); - ts.tracing?.stopTracing(); + tracing?.stopTracing(); process.exit(0); } @@ -762,18 +780,18 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser class IpcIOSession extends IOSession { - protected writeMessage(msg: ts.server.protocol.Message): void { - const verboseLogging = logger.hasLevel(ts.server.LogLevel.verbose); + protected writeMessage(msg: protocol.Message): void { + const verboseLogging = logger.hasLevel(LogLevel.verbose); if (verboseLogging) { const json = JSON.stringify(msg); - logger.info(`${msg.type}:${ts.server.indent(json)}`); + logger.info(`${msg.type}:${indent(json)}`); } process.send!(msg); } - protected parseMessage(message: any): ts.server.protocol.Request { - return message as ts.server.protocol.Request; + protected parseMessage(message: any): protocol.Request { + return message as protocol.Request; } protected toStringMessage(message: any) { @@ -791,20 +809,20 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser } } - const eventPort: number | undefined = parseEventPort(ts.server.findArgument("--eventPort")); - const typingSafeListLocation = ts.server.findArgument(ts.server.Arguments.TypingSafeListLocation)!; // TODO: GH#18217 - const typesMapLocation = ts.server.findArgument(ts.server.Arguments.TypesMapLocation) || ts.combinePaths(ts.getDirectoryPath(ts.sys.getExecutingFilePath()), "typesMap.json"); - const npmLocation = ts.server.findArgument(ts.server.Arguments.NpmLocation); - const validateDefaultNpmLocation = ts.server.hasArgument(ts.server.Arguments.ValidateDefaultNpmLocation); - const disableAutomaticTypingAcquisition = ts.server.hasArgument("--disableAutomaticTypingAcquisition"); - const useNodeIpc = ts.server.hasArgument("--useNodeIpc"); - const telemetryEnabled = ts.server.hasArgument(ts.server.Arguments.EnableTelemetry); - const commandLineTraceDir = ts.server.findArgument("--traceDirectory"); + const eventPort: number | undefined = parseEventPort(findArgument("--eventPort")); + const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation)!; // TODO: GH#18217 + const typesMapLocation = findArgument(Arguments.TypesMapLocation) || combinePaths(getDirectoryPath(sys.getExecutingFilePath()), "typesMap.json"); + const npmLocation = findArgument(Arguments.NpmLocation); + const validateDefaultNpmLocation = hasArgument(Arguments.ValidateDefaultNpmLocation); + const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); + const useNodeIpc = hasArgument("--useNodeIpc"); + const telemetryEnabled = hasArgument(Arguments.EnableTelemetry); + const commandLineTraceDir = findArgument("--traceDirectory"); const traceDir = commandLineTraceDir - ? ts.stripQuotes(commandLineTraceDir) + ? stripQuotes(commandLineTraceDir) : process.env.TSS_TRACE; if (traceDir) { - ts.startTracing("server", traceDir); + startTracing("server", traceDir); } const ioSession = useNodeIpc ? new IpcIOSession() : new IOSession(); @@ -823,9 +841,9 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser process.env.APPDATA || (os.homedir && os.homedir()) || process.env.USERPROFILE || - (process.env.HOMEDRIVE && process.env.HOMEPATH && ts.normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || + (process.env.HOMEDRIVE && process.env.HOMEPATH && normalizeSlashes(process.env.HOMEDRIVE + process.env.HOMEPATH)) || os.tmpdir(); - return ts.combinePaths(ts.combinePaths(ts.normalizeSlashes(basePath), "Microsoft/TypeScript"), ts.versionMajorMinor); + return combinePaths(combinePaths(normalizeSlashes(basePath), "Microsoft/TypeScript"), versionMajorMinor); } case "openbsd": case "freebsd": @@ -834,10 +852,10 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser case "linux": case "android": { const cacheLocation = getNonWindowsCacheLocation(process.platform === "darwin"); - return ts.combinePaths(ts.combinePaths(cacheLocation, "typescript"), ts.versionMajorMinor); + return combinePaths(combinePaths(cacheLocation, "typescript"), versionMajorMinor); } default: - return ts.Debug.fail(`unsupported platform '${process.platform}'`); + return Debug.fail(`unsupported platform '${process.platform}'`); } } @@ -853,6 +871,6 @@ function startNodeSession(options: ts.server.StartSessionOptions, logger: ts.ser const cacheFolder = platformIsDarwin ? "Library/Caches" : ".cache"; - return ts.combinePaths(ts.normalizeSlashes(homePath), cacheFolder); + return combinePaths(normalizeSlashes(homePath), cacheFolder); } } diff --git a/src/tsserver/server.ts b/src/tsserver/server.ts index ca846dee92b79..754b3e2edfbe7 100644 --- a/src/tsserver/server.ts +++ b/src/tsserver/server.ts @@ -1,11 +1,15 @@ -import * as ts from "./_namespaces/ts"; +import { + emptyArray, findArgument, hasArgument, initializeNodeSystem, initializeWebSystem, Logger, LogLevel, Msg, + ServerCancellationToken, StartSessionOptions, +} from "./_namespaces/ts.server"; +import { Debug, getNodeMajorVersion, LanguageServiceMode, setStackTraceLimit, sys, version } from "./_namespaces/ts"; declare const addEventListener: any; declare const removeEventListener: any; function findArgumentStringArray(argName: string): readonly string[] { - const arg = ts.server.findArgument(argName); + const arg = findArgument(argName); if (arg === undefined) { - return ts.server.emptyArray; + return emptyArray; } return arg.split(",").filter(name => name !== ""); } @@ -14,9 +18,9 @@ function findArgumentStringArray(argName: string): readonly string[] { export function getLogLevel(level: string | undefined) { if (level) { const l = level.toLowerCase(); - for (const name in ts.server.LogLevel) { + for (const name in LogLevel) { if (isNaN(+name) && l === name.toLowerCase()) { - return ts.server.LogLevel[name] as any as ts.server.LogLevel; + return LogLevel[name] as any as LogLevel; } } } @@ -26,48 +30,48 @@ export function getLogLevel(level: string | undefined) { /** @internal */ export interface StartInput { args: readonly string[]; - logger: ts.server.Logger; - cancellationToken: ts.server.ServerCancellationToken; - serverMode: ts.LanguageServiceMode | undefined; + logger: Logger; + cancellationToken: ServerCancellationToken; + serverMode: LanguageServiceMode | undefined; unknownServerMode?: string; - startSession: (option: ts.server.StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken) => void; + startSession: (option: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken) => void; } function start({ args, logger, cancellationToken, serverMode, unknownServerMode, startSession: startServer }: StartInput, platform: string) { - const syntaxOnly = ts.server.hasArgument("--syntaxOnly"); + const syntaxOnly = hasArgument("--syntaxOnly"); logger.info(`Starting TS Server`); - logger.info(`Version: ${ts.version}`); + logger.info(`Version: ${version}`); logger.info(`Arguments: ${args.join(" ")}`); - logger.info(`Platform: ${platform} NodeVersion: ${ts.getNodeMajorVersion()} CaseSensitive: ${ts.sys.useCaseSensitiveFileNames}`); + logger.info(`Platform: ${platform} NodeVersion: ${getNodeMajorVersion()} CaseSensitive: ${sys.useCaseSensitiveFileNames}`); logger.info(`ServerMode: ${serverMode} syntaxOnly: ${syntaxOnly} hasUnknownServerMode: ${unknownServerMode}`); - ts.setStackTraceLimit(); + setStackTraceLimit(); - if (ts.Debug.isDebugging) { - ts.Debug.enableDebugInfo(); + if (Debug.isDebugging) { + Debug.enableDebugInfo(); } - if (ts.sys.tryEnableSourceMapsForHost && /^development$/i.test(ts.sys.getEnvironmentVariable("NODE_ENV"))) { - ts.sys.tryEnableSourceMapsForHost(); + if (sys.tryEnableSourceMapsForHost && /^development$/i.test(sys.getEnvironmentVariable("NODE_ENV"))) { + sys.tryEnableSourceMapsForHost(); } // Overwrites the current console messages to instead write to // the log. This is so that language service plugins which use // console.log don't break the message passing between tsserver // and the client - console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Info); - console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); - console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), ts.server.Msg.Err); + console.log = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Info); + console.warn = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err); + console.error = (...args) => logger.msg(args.length === 1 ? args[0] : args.join(", "), Msg.Err); startServer( { globalPlugins: findArgumentStringArray("--globalPlugins"), pluginProbeLocations: findArgumentStringArray("--pluginProbeLocations"), - allowLocalPluginLoads: ts.server.hasArgument("--allowLocalPluginLoads"), - useSingleInferredProject: ts.server.hasArgument("--useSingleInferredProject"), - useInferredProjectPerProjectRoot: ts.server.hasArgument("--useInferredProjectPerProjectRoot"), - suppressDiagnosticEvents: ts.server.hasArgument("--suppressDiagnosticEvents"), - noGetErrOnBackgroundUpdate: ts.server.hasArgument("--noGetErrOnBackgroundUpdate"), + allowLocalPluginLoads: hasArgument("--allowLocalPluginLoads"), + useSingleInferredProject: hasArgument("--useSingleInferredProject"), + useInferredProjectPerProjectRoot: hasArgument("--useInferredProjectPerProjectRoot"), + suppressDiagnosticEvents: hasArgument("--suppressDiagnosticEvents"), + noGetErrOnBackgroundUpdate: hasArgument("--noGetErrOnBackgroundUpdate"), syntaxOnly, serverMode }, @@ -76,17 +80,17 @@ function start({ args, logger, cancellationToken, serverMode, unknownServerMode, ); } -ts.setStackTraceLimit(); +setStackTraceLimit(); // Cannot check process var directory in webworker so has to be typeof check here if (typeof process !== "undefined") { - start(ts.server.initializeNodeSystem(), require("os").platform()); + start(initializeNodeSystem(), require("os").platform()); } else { // Get args from first message const listener = (e: any) => { removeEventListener("message", listener); const args = e.data; - start(ts.server.initializeWebSystem(args), "web"); + start(initializeWebSystem(args), "web"); }; addEventListener("message", listener); } diff --git a/src/tsserver/webServer.ts b/src/tsserver/webServer.ts index 82534d68df0ed..ed941f59b7f78 100644 --- a/src/tsserver/webServer.ts +++ b/src/tsserver/webServer.ts @@ -1,4 +1,12 @@ import * as ts from "./_namespaces/ts"; +import * as server from "./_namespaces/ts.server"; +import { + findArgument, getLogLevel, Logger, MainProcessLogger, Msg, nullCancellationToken, ServerCancellationToken, + ServerHost, StartInput, StartSessionOptions, WebHost, +} from "./_namespaces/ts.server"; +import { + Debug, LanguageServiceMode, LogLevel, noop, returnFalse, returnUndefined, setSys, sys, validateLocaleAndSetLanguage, +} from "./_namespaces/ts"; declare const addEventListener: any; declare const postMessage: any; @@ -7,51 +15,51 @@ declare const location: any; declare const XMLHttpRequest: any; declare const self: any; -const nullLogger: ts.server.Logger = { - close: ts.noop, - hasLevel: ts.returnFalse, - loggingEnabled: ts.returnFalse, - perftrc: ts.noop, - info: ts.noop, - msg: ts.noop, - startGroup: ts.noop, - endGroup: ts.noop, - getLogFileName: ts.returnUndefined, +const nullLogger: Logger = { + close: noop, + hasLevel: returnFalse, + loggingEnabled: returnFalse, + perftrc: noop, + info: noop, + msg: noop, + startGroup: noop, + endGroup: noop, + getLogFileName: returnUndefined, }; -function parseServerMode(): ts.LanguageServiceMode | string | undefined { - const mode = ts.server.findArgument("--serverMode"); +function parseServerMode(): LanguageServiceMode | string | undefined { + const mode = findArgument("--serverMode"); if (!mode) return undefined; switch (mode.toLowerCase()) { case "partialsemantic": - return ts.LanguageServiceMode.PartialSemantic; + return LanguageServiceMode.PartialSemantic; case "syntactic": - return ts.LanguageServiceMode.Syntactic; + return LanguageServiceMode.Syntactic; default: return mode; } } /** @internal */ -export function initializeWebSystem(args: string[]): ts.server.StartInput { +export function initializeWebSystem(args: string[]): StartInput { createWebSystem(args); const modeOrUnknown = parseServerMode(); - let serverMode: ts.LanguageServiceMode | undefined; + let serverMode: LanguageServiceMode | undefined; let unknownServerMode: string | undefined; if (typeof modeOrUnknown === "number") serverMode = modeOrUnknown; else unknownServerMode = modeOrUnknown; const logger = createLogger(); // enable deprecation logging - ts.Debug.loggingHost = { + Debug.loggingHost = { log(level, s) { switch (level) { - case ts.LogLevel.Error: - case ts.LogLevel.Warning: - return logger.msg(s, ts.server.Msg.Err); - case ts.LogLevel.Info: - case ts.LogLevel.Verbose: - return logger.msg(s, ts.server.Msg.Info); + case LogLevel.Error: + case LogLevel.Warning: + return logger.msg(s, Msg.Err); + case LogLevel.Info: + case LogLevel.Verbose: + return logger.msg(s, Msg.Info); } } }; @@ -59,17 +67,17 @@ export function initializeWebSystem(args: string[]): ts.server.StartInput { return { args, logger, - cancellationToken: ts.server.nullCancellationToken, + cancellationToken: nullCancellationToken, // Webserver defaults to partial semantic mode - serverMode: serverMode ?? ts.LanguageServiceMode.PartialSemantic, + serverMode: serverMode ?? LanguageServiceMode.PartialSemantic, unknownServerMode, startSession: startWebSession }; } function createLogger() { - const cmdLineVerbosity = ts.server.getLogLevel(ts.server.findArgument("--logVerbosity")); - return cmdLineVerbosity !== undefined ? new ts.server.MainProcessLogger(cmdLineVerbosity, { writeMessage }) : nullLogger; + const cmdLineVerbosity = getLogLevel(findArgument("--logVerbosity")); + return cmdLineVerbosity !== undefined ? new MainProcessLogger(cmdLineVerbosity, { writeMessage }) : nullLogger; } function writeMessage(s: any) { @@ -77,8 +85,8 @@ function writeMessage(s: any) { } function createWebSystem(args: string[]) { - ts.Debug.assert(ts.sys === undefined); - const webHost: ts.server.WebHost = { + Debug.assert(ts.sys === undefined); + const webHost: WebHost = { readFile: webPath => { const request = new XMLHttpRequest(); request.open("GET", webPath, /* asynchronous */ false); @@ -94,11 +102,11 @@ function createWebSystem(args: string[]) { writeMessage, }; // Do this after sys has been set as findArguments is going to work only then - const sys = ts.server.createWebSystem(webHost, args, () => ts.server.findArgument("--executingFilePath") || location + ""); - ts.setSys(sys); - const localeStr = ts.server.findArgument("--locale"); + const sys = server.createWebSystem(webHost, args, () => findArgument("--executingFilePath") || location + ""); + setSys(sys); + const localeStr = findArgument("--locale"); if (localeStr) { - ts.validateLocaleAndSetLanguage(localeStr, sys); + validateLocaleAndSetLanguage(localeStr, sys); } } @@ -117,10 +125,10 @@ function hrtime(previous?: [number, number]) { return [seconds, nanoseconds]; } -function startWebSession(options: ts.server.StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken) { - class WorkerSession extends ts.server.WorkerSession { +function startWebSession(options: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken) { + class WorkerSession extends server.WorkerSession { constructor() { - super(ts.sys as ts.server.ServerHost, { writeMessage }, options, logger, cancellationToken, hrtime); + super(sys as ServerHost, { writeMessage }, options, logger, cancellationToken, hrtime); } exit() { diff --git a/src/typescriptServices/typescriptServices.ts b/src/typescriptServices/typescriptServices.ts index 053e804db5811..4eefe91f9ebd6 100644 --- a/src/typescriptServices/typescriptServices.ts +++ b/src/typescriptServices/typescriptServices.ts @@ -1,15 +1,15 @@ -import * as ts from "./_namespaces/ts"; +import { Debug, LogLevel } from "./_namespaces/ts"; // enable deprecation logging declare const console: any; if (typeof console !== "undefined") { - ts.Debug.loggingHost = { + Debug.loggingHost = { log(level, s) { switch (level) { - case ts.LogLevel.Error: return console.error(s); - case ts.LogLevel.Warning: return console.warn(s); - case ts.LogLevel.Info: return console.log(s); - case ts.LogLevel.Verbose: return console.log(s); + case LogLevel.Error: return console.error(s); + case LogLevel.Warning: return console.warn(s); + case LogLevel.Info: return console.log(s); + case LogLevel.Verbose: return console.log(s); } } }; diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index 0e2b0002980a0..aae6b44b45ae4 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -1,4 +1,15 @@ -import * as ts from "./_namespaces/ts"; +import { + installNpmPackages, Log, RequestCompletedAction, TypingsInstaller, +} from "./_namespaces/ts.server.typingsInstaller"; +import { + ActionPackageInstalled, Arguments, EventTypesRegistry, findArgument, hasArgument, InitializationFailedResponse, + InstallTypingHost, nowString, PackageInstalledResponse, TypesRegistryResponse, TypingInstallerRequestUnion, + TypingInstallerResponseUnion, +} from "./_namespaces/ts.server"; +import { + combinePaths, createGetCanonicalFileName, Debug, ESMap, forEachAncestorDirectory, getDirectoryPath, getEntries, Map, + MapLike, normalizeSlashes, stringContains, sys, toPath, version, +} from "./_namespaces/ts"; const fs: { appendFileSync(file: string, content: string): void @@ -10,7 +21,7 @@ const path: { basename(path: string, extension?: string): string; } = require("path"); -class FileLog implements ts.server.typingsInstaller.Log { +class FileLog implements Log { constructor(private logFile: string | undefined) { } @@ -21,7 +32,7 @@ class FileLog implements ts.server.typingsInstaller.Log { if (typeof this.logFile !== "string") return; try { - fs.appendFileSync(this.logFile, `[${ts.server.nowString()}] ${text}${ts.sys.newLine}`); + fs.appendFileSync(this.logFile, `[${nowString()}] ${text}${sys.newLine}`); } catch (e) { this.logFile = undefined; @@ -30,7 +41,7 @@ class FileLog implements ts.server.typingsInstaller.Log { } /** Used if `--npmLocation` is not passed. */ -function getDefaultNPMLocation(processName: string, validateDefaultNpmLocation: boolean, host: ts.server.InstallTypingHost): string { +function getDefaultNPMLocation(processName: string, validateDefaultNpmLocation: boolean, host: InstallTypingHost): string { if (path.basename(processName).indexOf("node") === 0) { const npmPath = path.join(path.dirname(process.argv[0]), "npm"); if (!validateDefaultNpmLocation) { @@ -44,31 +55,31 @@ function getDefaultNPMLocation(processName: string, validateDefaultNpmLocation: } interface TypesRegistryFile { - entries: ts.MapLike>; + entries: MapLike>; } -function loadTypesRegistryFile(typesRegistryFilePath: string, host: ts.server.InstallTypingHost, log: ts.server.typingsInstaller.Log): ts.ESMap> { +function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypingHost, log: Log): ESMap> { if (!host.fileExists(typesRegistryFilePath)) { if (log.isEnabled()) { log.writeLine(`Types registry file '${typesRegistryFilePath}' does not exist`); } - return new ts.Map>(); + return new Map>(); } try { const content = JSON.parse(host.readFile(typesRegistryFilePath)!) as TypesRegistryFile; - return new ts.Map(ts.getEntries(content.entries)); + return new Map(getEntries(content.entries)); } catch (e) { if (log.isEnabled()) { log.writeLine(`Error when loading types registry file '${typesRegistryFilePath}': ${(e as Error).message}, ${(e as Error).stack}`); } - return new ts.Map>(); + return new Map>(); } } const typesRegistryPackageName = "types-registry"; function getTypesRegistryFileLocation(globalTypingsCacheLocation: string): string { - return ts.combinePaths(ts.normalizeSlashes(globalTypingsCacheLocation), `node_modules/${typesRegistryPackageName}/index.json`); + return combinePaths(normalizeSlashes(globalTypingsCacheLocation), `node_modules/${typesRegistryPackageName}/index.json`); } interface ExecSyncOptions { @@ -77,30 +88,30 @@ interface ExecSyncOptions { } type ExecSync = (command: string, options: ExecSyncOptions) => string; -export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInstaller { +export class NodeTypingsInstaller extends TypingsInstaller { private readonly nodeExecSync: ExecSync; private readonly npmPath: string; - readonly typesRegistry: ts.ESMap>; + readonly typesRegistry: ESMap>; - private delayedInitializationError: ts.server.InitializationFailedResponse | undefined; + private delayedInitializationError: InitializationFailedResponse | undefined; - constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, typesMapLocation: string, npmLocation: string | undefined, validateDefaultNpmLocation: boolean, throttleLimit: number, log: ts.server.typingsInstaller.Log) { + constructor(globalTypingsCacheLocation: string, typingSafeListLocation: string, typesMapLocation: string, npmLocation: string | undefined, validateDefaultNpmLocation: boolean, throttleLimit: number, log: Log) { super( - ts.sys, + sys, globalTypingsCacheLocation, - typingSafeListLocation ? ts.toPath(typingSafeListLocation, "", ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames)) : ts.toPath("typingSafeList.json", __dirname, ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames)), - typesMapLocation ? ts.toPath(typesMapLocation, "", ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames)) : ts.toPath("typesMap.json", __dirname, ts.createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames)), + typingSafeListLocation ? toPath(typingSafeListLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), + typesMapLocation ? toPath(typesMapLocation, "", createGetCanonicalFileName(sys.useCaseSensitiveFileNames)) : toPath("typesMap.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), throttleLimit, log); this.npmPath = npmLocation !== undefined ? npmLocation : getDefaultNPMLocation(process.argv[0], validateDefaultNpmLocation, this.installTypingHost); // If the NPM path contains spaces and isn't wrapped in quotes, do so. - if (ts.stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) { + if (stringContains(this.npmPath, " ") && this.npmPath[0] !== `"`) { this.npmPath = `"${this.npmPath}"`; } if (this.log.isEnabled()) { this.log.writeLine(`Process id: ${process.pid}`); - this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${ts.server.Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); + this.log.writeLine(`NPM location: ${this.npmPath} (explicit '${Arguments.NpmLocation}' ${npmLocation === undefined ? "not " : ""} provided)`); this.log.writeLine(`validateDefaultNpmLocation: ${validateDefaultNpmLocation}`); } ({ execSync: this.nodeExecSync } = require("child_process")); @@ -132,7 +143,7 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst } listen() { - process.on("message", (req: ts.server.TypingInstallerRequestUnion) => { + process.on("message", (req: TypingInstallerRequestUnion) => { if (this.delayedInitializationError) { // report initializationFailed error this.sendResponse(this.delayedInitializationError); @@ -146,11 +157,11 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst this.closeProject(req); break; case "typesRegistry": { - const typesRegistry: { [key: string]: ts.MapLike } = {}; + const typesRegistry: { [key: string]: MapLike } = {}; this.typesRegistry.forEach((value, key) => { typesRegistry[key] = value; }); - const response: ts.server.TypesRegistryResponse = { kind: ts.server.EventTypesRegistry, typesRegistry }; + const response: TypesRegistryResponse = { kind: EventTypesRegistry, typesRegistry }; this.sendResponse(response); break; } @@ -160,23 +171,23 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst if (cwd) { this.installWorker(-1, [packageName], cwd, success => { const message = success ? `Package ${packageName} installed.` : `There was an error installing ${packageName}.`; - const response: ts.server.PackageInstalledResponse = { kind: ts.server.ActionPackageInstalled, projectName, success, message }; + const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success, message }; this.sendResponse(response); }); } else { - const response: ts.server.PackageInstalledResponse = { kind: ts.server.ActionPackageInstalled, projectName, success: false, message: "Could not determine a project root path." }; + const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success: false, message: "Could not determine a project root path." }; this.sendResponse(response); } break; } default: - ts.Debug.assertNever(req); + Debug.assertNever(req); } }); } - protected sendResponse(response: ts.server.TypingInstallerResponseUnion) { + protected sendResponse(response: TypingInstallerResponseUnion) { if (this.log.isEnabled()) { this.log.writeLine(`Sending response:\n ${JSON.stringify(response)}`); } @@ -186,12 +197,12 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst } } - protected installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: ts.server.typingsInstaller.RequestCompletedAction): void { + protected installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void { if (this.log.isEnabled()) { this.log.writeLine(`#${requestId} with arguments'${JSON.stringify(packageNames)}'.`); } const start = Date.now(); - const hasError = ts.server.typingsInstaller.installNpmPackages(this.npmPath, ts.version, packageNames, command => this.execSyncAndLog(command, { cwd })); + const hasError = installNpmPackages(this.npmPath, version, packageNames, command => this.execSyncAndLog(command, { cwd })); if (this.log.isEnabled()) { this.log.writeLine(`npm install #${requestId} took: ${Date.now() - start} ms`); } @@ -206,32 +217,32 @@ export class NodeTypingsInstaller extends ts.server.typingsInstaller.TypingsInst try { const stdout = this.nodeExecSync(command, { ...options, encoding: "utf-8" }); if (this.log.isEnabled()) { - this.log.writeLine(` Succeeded. stdout:${indent(ts.sys.newLine, stdout)}`); + this.log.writeLine(` Succeeded. stdout:${indent(sys.newLine, stdout)}`); } return false; } catch (error) { const { stdout, stderr } = error; - this.log.writeLine(` Failed. stdout:${indent(ts.sys.newLine, stdout)}${ts.sys.newLine} stderr:${indent(ts.sys.newLine, stderr)}`); + this.log.writeLine(` Failed. stdout:${indent(sys.newLine, stdout)}${sys.newLine} stderr:${indent(sys.newLine, stderr)}`); return true; } } } -function getDirectoryOfPackageJson(fileName: string, host: ts.server.InstallTypingHost): string | undefined { - return ts.forEachAncestorDirectory(ts.getDirectoryPath(fileName), directory => { - if (host.fileExists(ts.combinePaths(directory, "package.json"))) { +function getDirectoryOfPackageJson(fileName: string, host: InstallTypingHost): string | undefined { + return forEachAncestorDirectory(getDirectoryPath(fileName), directory => { + if (host.fileExists(combinePaths(directory, "package.json"))) { return directory; } }); } -const logFilePath = ts.server.findArgument(ts.server.Arguments.LogFile); -const globalTypingsCacheLocation = ts.server.findArgument(ts.server.Arguments.GlobalCacheLocation); -const typingSafeListLocation = ts.server.findArgument(ts.server.Arguments.TypingSafeListLocation); -const typesMapLocation = ts.server.findArgument(ts.server.Arguments.TypesMapLocation); -const npmLocation = ts.server.findArgument(ts.server.Arguments.NpmLocation); -const validateDefaultNpmLocation = ts.server.hasArgument(ts.server.Arguments.ValidateDefaultNpmLocation); +const logFilePath = findArgument(Arguments.LogFile); +const globalTypingsCacheLocation = findArgument(Arguments.GlobalCacheLocation); +const typingSafeListLocation = findArgument(Arguments.TypingSafeListLocation); +const typesMapLocation = findArgument(Arguments.TypesMapLocation); +const npmLocation = findArgument(Arguments.NpmLocation); +const validateDefaultNpmLocation = hasArgument(Arguments.ValidateDefaultNpmLocation); const log = new FileLog(logFilePath); if (log.isEnabled()) { diff --git a/src/typingsInstallerCore/typingsInstaller.ts b/src/typingsInstallerCore/typingsInstaller.ts index 15a7cf54c2793..ad08facc3c2aa 100644 --- a/src/typingsInstallerCore/typingsInstaller.ts +++ b/src/typingsInstallerCore/typingsInstaller.ts @@ -1,7 +1,18 @@ -import * as ts from "./_namespaces/ts"; +import { + clearMap, closeFileWatcher, combinePaths, compareStringsCaseInsensitive, Comparison, containsPath, copyEntries, + createGetCanonicalFileName, directorySeparator, ESMap, Extension, fileExtensionIs, FileWatcher, getBaseFileName, + GetCanonicalFileName, getDirectoryPath, getProperty, getWatchFactory, hasProperty, JsTyping, + mangleScopedPackageName, Map, mapDefined, MapLike, ModuleResolutionKind, noop, Path, PollingInterval, + resolveModuleName, Set, version, Version, versionMajorMinor, WatchDirectoryFlags, WatchFactory, WatchFactoryHost, + WatchLogLevel, WatchOptions, +} from "./_namespaces/ts"; +import { + ActionInvalidate, ActionSet, BeginInstallTypes, CloseProject, DiscoverTypings, EndInstallTypes, + EventBeginInstallTypes, EventEndInstallTypes, InstallTypingHost, InvalidateCachedTypings, SetTypings, +} from "./_namespaces/ts.server"; interface NpmConfig { - devDependencies: ts.MapLike; + devDependencies: MapLike; } interface NpmLock { @@ -15,12 +26,12 @@ export interface Log { const nullLog: Log = { isEnabled: () => false, - writeLine: ts.noop + writeLine: noop }; -function typingToFileName(cachePath: string, packageName: string, installTypingHost: ts.server.InstallTypingHost, log: Log): string | undefined { +function typingToFileName(cachePath: string, packageName: string, installTypingHost: InstallTypingHost, log: Log): string | undefined { try { - const result = ts.resolveModuleName(packageName, ts.combinePaths(cachePath, "index.d.ts"), { moduleResolution: ts.ModuleResolutionKind.NodeJs }, installTypingHost); + const result = resolveModuleName(packageName, combinePaths(cachePath, "index.d.ts"), { moduleResolution: ModuleResolutionKind.NodeJs }, installTypingHost); return result.resolvedModule && result.resolvedModule.resolvedFileName; } catch (e) { @@ -69,7 +80,7 @@ function endsWith(str: string, suffix: string, caseSensitive: boolean): boolean const expectedPos = str.length - suffix.length; return expectedPos >= 0 && (str.indexOf(suffix, expectedPos) === expectedPos || - (!caseSensitive && ts.compareStringsCaseInsensitive(str.substr(expectedPos), suffix) === ts.Comparison.EqualTo)); + (!caseSensitive && compareStringsCaseInsensitive(str.substr(expectedPos), suffix) === Comparison.EqualTo)); } function isPackageOrBowerJson(fileName: string, caseSensitive: boolean) { @@ -77,7 +88,7 @@ function isPackageOrBowerJson(fileName: string, caseSensitive: boolean) { } function sameFiles(a: string, b: string, caseSensitive: boolean) { - return a === b || (!caseSensitive && ts.compareStringsCaseInsensitive(a, b) === ts.Comparison.EqualTo); + return a === b || (!caseSensitive && compareStringsCaseInsensitive(a, b) === Comparison.EqualTo); } const enum ProjectWatcherType { @@ -85,47 +96,47 @@ const enum ProjectWatcherType { DirectoryWatcher = "DirectoryWatcher" } -type ProjectWatchers = ts.ESMap & { isInvoked?: boolean; }; +type ProjectWatchers = ESMap & { isInvoked?: boolean; }; function getDetailWatchInfo(projectName: string, watchers: ProjectWatchers) { return `Project: ${projectName} watcher already invoked: ${watchers.isInvoked}`; } export abstract class TypingsInstaller { - private readonly packageNameToTypingLocation = new ts.Map(); - private readonly missingTypingsSet = new ts.Set(); - private readonly knownCachesSet = new ts.Set(); - private readonly projectWatchers = new ts.Map(); - private safeList: ts.JsTyping.SafeList | undefined; + private readonly packageNameToTypingLocation = new Map(); + private readonly missingTypingsSet = new Set(); + private readonly knownCachesSet = new Set(); + private readonly projectWatchers = new Map(); + private safeList: JsTyping.SafeList | undefined; readonly pendingRunRequests: PendingRequest[] = []; - private readonly toCanonicalFileName: ts.GetCanonicalFileName; + private readonly toCanonicalFileName: GetCanonicalFileName; private readonly globalCachePackageJsonPath: string; private installRunCount = 1; private inFlightRequestCount = 0; - abstract readonly typesRegistry: ts.ESMap>; + abstract readonly typesRegistry: ESMap>; /*@internal*/ - private readonly watchFactory: ts.WatchFactory; + private readonly watchFactory: WatchFactory; constructor( - protected readonly installTypingHost: ts.server.InstallTypingHost, + protected readonly installTypingHost: InstallTypingHost, private readonly globalCachePath: string, - private readonly safeListPath: ts.Path, - private readonly typesMapLocation: ts.Path, + private readonly safeListPath: Path, + private readonly typesMapLocation: Path, private readonly throttleLimit: number, protected readonly log = nullLog) { - this.toCanonicalFileName = ts.createGetCanonicalFileName(installTypingHost.useCaseSensitiveFileNames); - this.globalCachePackageJsonPath = ts.combinePaths(globalCachePath, "package.json"); + this.toCanonicalFileName = createGetCanonicalFileName(installTypingHost.useCaseSensitiveFileNames); + this.globalCachePackageJsonPath = combinePaths(globalCachePath, "package.json"); const isLoggingEnabled = this.log.isEnabled(); if (isLoggingEnabled) { this.log.writeLine(`Global cache location '${globalCachePath}', safe file path '${safeListPath}', types map path ${typesMapLocation}`); } - this.watchFactory = ts.getWatchFactory(this.installTypingHost as ts.WatchFactoryHost, isLoggingEnabled ? ts.WatchLogLevel.Verbose : ts.WatchLogLevel.None, s => this.log.writeLine(s), getDetailWatchInfo); + this.watchFactory = getWatchFactory(this.installTypingHost as WatchFactoryHost, isLoggingEnabled ? WatchLogLevel.Verbose : WatchLogLevel.None, s => this.log.writeLine(s), getDetailWatchInfo); this.processCacheLocation(this.globalCachePath); } - closeProject(req: ts.server.CloseProject) { + closeProject(req: CloseProject) { this.closeWatchers(req.projectName); } @@ -140,7 +151,7 @@ export abstract class TypingsInstaller { } return; } - ts.clearMap(watchers, ts.closeFileWatcher); + clearMap(watchers, closeFileWatcher); this.projectWatchers.delete(projectName); if (this.log.isEnabled()) { @@ -148,7 +159,7 @@ export abstract class TypingsInstaller { } } - install(req: ts.server.DiscoverTypings) { + install(req: DiscoverTypings) { if (this.log.isEnabled()) { this.log.writeLine(`Got install request ${JSON.stringify(req)}`); } @@ -164,7 +175,7 @@ export abstract class TypingsInstaller { if (this.safeList === undefined) { this.initializeSafeList(); } - const discoverTypingsResult = ts.JsTyping.discoverTypings( + const discoverTypingsResult = JsTyping.discoverTypings( this.installTypingHost, this.log.isEnabled() ? (s => this.log.writeLine(s)) : undefined, req.fileNames, @@ -198,7 +209,7 @@ export abstract class TypingsInstaller { private initializeSafeList() { // Prefer the safe list from the types map if it exists if (this.typesMapLocation) { - const safeListFromMap = ts.JsTyping.loadTypesMap(this.installTypingHost, this.typesMapLocation); + const safeListFromMap = JsTyping.loadTypesMap(this.installTypingHost, this.typesMapLocation); if (safeListFromMap) { this.log.writeLine(`Loaded safelist from types map file '${this.typesMapLocation}'`); this.safeList = safeListFromMap; @@ -206,7 +217,7 @@ export abstract class TypingsInstaller { } this.log.writeLine(`Failed to load safelist from types map file '${this.typesMapLocation}'`); } - this.safeList = ts.JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); + this.safeList = JsTyping.loadSafeList(this.installTypingHost, this.safeListPath); } private processCacheLocation(cacheLocation: string) { @@ -219,8 +230,8 @@ export abstract class TypingsInstaller { } return; } - const packageJson = ts.combinePaths(cacheLocation, "package.json"); - const packageLockJson = ts.combinePaths(cacheLocation, "package-lock.json"); + const packageJson = combinePaths(cacheLocation, "package.json"); + const packageLockJson = combinePaths(cacheLocation, "package-lock.json"); if (this.log.isEnabled()) { this.log.writeLine(`Trying to find '${packageJson}'...`); } @@ -233,12 +244,12 @@ export abstract class TypingsInstaller { } if (npmConfig.devDependencies && npmLock.dependencies) { for (const key in npmConfig.devDependencies) { - if (!ts.hasProperty(npmLock.dependencies, key)) { + if (!hasProperty(npmLock.dependencies, key)) { // if package in package.json but not package-lock.json, skip adding to cache so it is reinstalled on next use continue; } // key is @types/ - const packageName = ts.getBaseFileName(key); + const packageName = getBaseFileName(key); if (!packageName) { continue; } @@ -260,13 +271,13 @@ export abstract class TypingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Adding entry into typings cache: '${packageName}' => '${typingFile}'`); } - const info = ts.getProperty(npmLock.dependencies, key); + const info = getProperty(npmLock.dependencies, key); const version = info && info.version; if (!version) { continue; } - const newTyping: ts.JsTyping.CachedTyping = { typingLocation: typingFile, version: new ts.Version(version) }; + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: new Version(version) }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -278,24 +289,24 @@ export abstract class TypingsInstaller { } private filterTypings(typingsToInstall: readonly string[]): readonly string[] { - return ts.mapDefined(typingsToInstall, typing => { - const typingKey = ts.mangleScopedPackageName(typing); + return mapDefined(typingsToInstall, typing => { + const typingKey = mangleScopedPackageName(typing); if (this.missingTypingsSet.has(typingKey)) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' is in missingTypingsSet - skipping...`); return undefined; } - const validationResult = ts.JsTyping.validatePackageName(typing); - if (validationResult !== ts.JsTyping.NameValidationResult.Ok) { + const validationResult = JsTyping.validatePackageName(typing); + if (validationResult !== JsTyping.NameValidationResult.Ok) { // add typing name to missing set so we won't process it again this.missingTypingsSet.add(typingKey); - if (this.log.isEnabled()) this.log.writeLine(ts.JsTyping.renderPackageNameValidationFailure(validationResult, typing)); + if (this.log.isEnabled()) this.log.writeLine(JsTyping.renderPackageNameValidationFailure(validationResult, typing)); return undefined; } if (!this.typesRegistry.has(typingKey)) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: Entry for package '${typingKey}' does not exist in local types registry - skipping...`); return undefined; } - if (this.packageNameToTypingLocation.get(typingKey) && ts.JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typingKey)!, this.typesRegistry.get(typingKey)!)) { + if (this.packageNameToTypingLocation.get(typingKey) && JsTyping.isTypingUpToDate(this.packageNameToTypingLocation.get(typingKey)!, this.typesRegistry.get(typingKey)!)) { if (this.log.isEnabled()) this.log.writeLine(`'${typing}':: '${typingKey}' already has an up-to-date typing - skipping...`); return undefined; } @@ -304,7 +315,7 @@ export abstract class TypingsInstaller { } protected ensurePackageDirectoryExists(directory: string) { - const npmConfigPath = ts.combinePaths(directory, "package.json"); + const npmConfigPath = combinePaths(directory, "package.json"); if (this.log.isEnabled()) { this.log.writeLine(`Npm config file: ${npmConfigPath}`); } @@ -317,7 +328,7 @@ export abstract class TypingsInstaller { } } - private installTypings(req: ts.server.DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } @@ -337,13 +348,13 @@ export abstract class TypingsInstaller { // send progress event this.sendResponse({ - kind: ts.server.EventBeginInstallTypes, + kind: EventBeginInstallTypes, eventId: requestId, // qualified explicitly to prevent occasional shadowing // eslint-disable-next-line @typescript-eslint/no-unnecessary-qualifier - typingsInstallerVersion: ts.version, + typingsInstallerVersion: version, projectName: req.projectName - } as ts.server.BeginInstallTypes); + } as BeginInstallTypes); const scopedTypings = filteredTypings.map(typingsName); this.installTypingsAsync(requestId, scopedTypings, cachePath, ok => { @@ -372,8 +383,8 @@ export abstract class TypingsInstaller { // packageName is guaranteed to exist in typesRegistry by filterTypings const distTags = this.typesRegistry.get(packageName)!; - const newVersion = new ts.Version(distTags[`ts${ts.versionMajorMinor}`] || distTags[this.latestDistTag]); - const newTyping: ts.JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; + const newVersion = new Version(distTags[`ts${versionMajorMinor}`] || distTags[this.latestDistTag]); + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); installedTypingFiles.push(typingFile); } @@ -384,23 +395,23 @@ export abstract class TypingsInstaller { this.sendResponse(this.createSetTypings(req, currentlyCachedTypings.concat(installedTypingFiles))); } finally { - const response: ts.server.EndInstallTypes = { - kind: ts.server.EventEndInstallTypes, + const response: EndInstallTypes = { + kind: EventEndInstallTypes, eventId: requestId, projectName: req.projectName, packagesToInstall: scopedTypings, installSuccess: ok, // qualified explicitly to prevent occasional shadowing // eslint-disable-next-line @typescript-eslint/no-unnecessary-qualifier - typingsInstallerVersion: ts.version + typingsInstallerVersion: version }; this.sendResponse(response); } }); } - private ensureDirectoryExists(directory: string, host: ts.server.InstallTypingHost): void { - const directoryName = ts.getDirectoryPath(directory); + private ensureDirectoryExists(directory: string, host: InstallTypingHost): void { + const directoryName = getDirectoryPath(directory); if (!host.directoryExists(directoryName)) { this.ensureDirectoryExists(directoryName, host); } @@ -409,7 +420,7 @@ export abstract class TypingsInstaller { } } - private watchFiles(projectName: string, files: string[], projectRootPath: ts.Path, options: ts.WatchOptions | undefined) { + private watchFiles(projectName: string, files: string[], projectRootPath: Path, options: WatchOptions | undefined) { if (!files.length) { // shut down existing watchers this.closeWatchers(projectName); @@ -417,13 +428,13 @@ export abstract class TypingsInstaller { } let watchers = this.projectWatchers.get(projectName)!; - const toRemove = new ts.Map(); + const toRemove = new Map(); if (!watchers) { - watchers = new ts.Map(); + watchers = new Map(); this.projectWatchers.set(projectName, watchers); } else { - ts.copyEntries(watchers, toRemove); + copyEntries(watchers, toRemove); } // handler should be invoked once for the entire set of files since it will trigger full rediscovery of typings @@ -444,20 +455,20 @@ export abstract class TypingsInstaller { this.watchFactory.watchFile(path, () => { if (!watchers.isInvoked) { watchers.isInvoked = true; - this.sendResponse({ projectName, kind: ts.server.ActionInvalidate }); + this.sendResponse({ projectName, kind: ActionInvalidate }); } - }, ts.PollingInterval.High, options, projectName, watchers) : + }, PollingInterval.High, options, projectName, watchers) : this.watchFactory.watchDirectory(path, f => { - if (watchers.isInvoked || !ts.fileExtensionIs(f, ts.Extension.Json)) { + if (watchers.isInvoked || !fileExtensionIs(f, Extension.Json)) { return; } if (isPackageOrBowerJson(f, this.installTypingHost.useCaseSensitiveFileNames) && !sameFiles(f, this.globalCachePackageJsonPath, this.installTypingHost.useCaseSensitiveFileNames)) { watchers.isInvoked = true; - this.sendResponse({ projectName, kind: ts.server.ActionInvalidate }); + this.sendResponse({ projectName, kind: ActionInvalidate }); } - }, ts.WatchDirectoryFlags.Recursive, options, projectName, watchers); + }, WatchDirectoryFlags.Recursive, options, projectName, watchers); watchers.set(canonicalPath, isLoggingEnabled ? { close: () => { @@ -476,8 +487,8 @@ export abstract class TypingsInstaller { } // path in projectRoot, watch project root - if (ts.containsPath(projectRootPath, file, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { - const subDirectory = file.indexOf(ts.directorySeparator, projectRootPath.length + 1); + if (containsPath(projectRootPath, file, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { + const subDirectory = file.indexOf(directorySeparator, projectRootPath.length + 1); if (subDirectory !== -1) { // Watch subDirectory createProjectWatcher(file.substr(0, subDirectory), ProjectWatcherType.DirectoryWatcher); @@ -490,7 +501,7 @@ export abstract class TypingsInstaller { } // path in global cache, watch global cache - if (ts.containsPath(this.globalCachePath, file, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { + if (containsPath(this.globalCachePath, file, projectRootPath, !this.installTypingHost.useCaseSensitiveFileNames)) { createProjectWatcher(this.globalCachePath, ProjectWatcherType.DirectoryWatcher); continue; } @@ -506,14 +517,14 @@ export abstract class TypingsInstaller { }); } - private createSetTypings(request: ts.server.DiscoverTypings, typings: string[]): ts.server.SetTypings { + private createSetTypings(request: DiscoverTypings, typings: string[]): SetTypings { return { projectName: request.projectName, typeAcquisition: request.typeAcquisition, compilerOptions: request.compilerOptions, typings, unresolvedImports: request.unresolvedImports, - kind: ts.server.ActionSet + kind: ActionSet }; } @@ -535,12 +546,12 @@ export abstract class TypingsInstaller { } protected abstract installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; - protected abstract sendResponse(response: ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes): void; + protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void; protected readonly latestDistTag = "latest"; } /* @internal */ export function typingsName(packageName: string): string { - return `@types/${packageName}@ts${ts.versionMajorMinor}`; + return `@types/${packageName}@ts${versionMajorMinor}`; } diff --git a/src/webServer/webServer.ts b/src/webServer/webServer.ts index 2bbde964da560..e7ed99601643b 100644 --- a/src/webServer/webServer.ts +++ b/src/webServer/webServer.ts @@ -1,4 +1,12 @@ -import * as ts from "./_namespaces/ts"; +import * as server from "./_namespaces/ts.server"; +import { + indent, Logger, LogLevel, ModuleImportResult, Msg, nowString, nullTypingsInstaller, protocol, + ServerCancellationToken, ServerHost, Session, SessionOptions, +} from "./_namespaces/ts.server"; +import { + combinePaths, Debug, directorySeparator, ensureTrailingDirectorySeparator, getDirectoryPath, identity, memoize, + notImplemented, perfLogger, returnFalse, returnNoopFileWatcher, startsWith, +} from "./_namespaces/ts"; declare const fetch: any; declare const importScripts: any; @@ -14,11 +22,11 @@ export interface WebHost extends HostWithWriteMessage { } /** @internal */ -export class BaseLogger implements ts.server.Logger { +export class BaseLogger implements Logger { private seq = 0; private inGroup = false; private firstInGroup = true; - constructor(protected readonly level: ts.server.LogLevel) { + constructor(protected readonly level: LogLevel) { } static padStringRight(str: string, padding: string) { return (str + padding).slice(0, padding.length); @@ -29,13 +37,13 @@ export class BaseLogger implements ts.server.Logger { return undefined; } perftrc(s: string) { - this.msg(s, ts.server.Msg.Perf); + this.msg(s, Msg.Perf); } info(s: string) { - this.msg(s, ts.server.Msg.Info); + this.msg(s, Msg.Info); } err(s: string) { - this.msg(s, ts.server.Msg.Err); + this.msg(s, Msg.Err); } startGroup() { this.inGroup = true; @@ -47,25 +55,25 @@ export class BaseLogger implements ts.server.Logger { loggingEnabled() { return true; } - hasLevel(level: ts.server.LogLevel) { + hasLevel(level: LogLevel) { return this.loggingEnabled() && this.level >= level; } - msg(s: string, type: ts.server.Msg = ts.server.Msg.Err) { + msg(s: string, type: Msg = Msg.Err) { switch (type) { - case ts.server.Msg.Info: - ts.perfLogger.logInfoEvent(s); + case Msg.Info: + perfLogger.logInfoEvent(s); break; - case ts.server.Msg.Perf: - ts.perfLogger.logPerfEvent(s); + case Msg.Perf: + perfLogger.logPerfEvent(s); break; default: // Msg.Err - ts.perfLogger.logErrEvent(s); + perfLogger.logErrEvent(s); break; } if (!this.canWrite()) return; - s = `[${ts.server.nowString()}] ${s}\n`; + s = `[${nowString()}] ${s}\n`; if (!this.inGroup || this.firstInGroup) { const prefix = BaseLogger.padStringRight(type + " " + this.seq.toString(), " "); s = prefix + s; @@ -78,7 +86,7 @@ export class BaseLogger implements ts.server.Logger { protected canWrite() { return true; } - protected write(_s: string, _type: ts.server.Msg) { + protected write(_s: string, _type: Msg) { } } @@ -92,23 +100,23 @@ export interface LoggingMessage { } /** @internal */ export class MainProcessLogger extends BaseLogger { - constructor(level: ts.server.LogLevel, private host: HostWithWriteMessage) { + constructor(level: LogLevel, private host: HostWithWriteMessage) { super(level); } - protected write(body: string, type: ts.server.Msg) { + protected write(body: string, type: Msg) { let level: MessageLogLevel; switch (type) { - case ts.server.Msg.Info: + case Msg.Info: level = "info"; break; - case ts.server.Msg.Perf: + case Msg.Perf: level = "perf"; break; - case ts.server.Msg.Err: + case Msg.Err: level = "error"; break; default: - ts.Debug.assertNever(type); + Debug.assertNever(type); } this.host.writeMessage({ type: "log", @@ -130,14 +138,14 @@ if (typeof importScripts === "function") { } /** @internal */ -export function createWebSystem(host: WebHost, args: string[], getExecutingFilePath: () => string): ts.server.ServerHost { +export function createWebSystem(host: WebHost, args: string[], getExecutingFilePath: () => string): ServerHost { const returnEmptyString = () => ""; - const getExecutingDirectoryPath = ts.memoize(() => ts.memoize(() => ts.ensureTrailingDirectorySeparator(ts.getDirectoryPath(getExecutingFilePath())))); + const getExecutingDirectoryPath = memoize(() => memoize(() => ensureTrailingDirectorySeparator(getDirectoryPath(getExecutingFilePath())))); // Later we could map ^memfs:/ to do something special if we want to enable more functionality like module resolution or something like that - const getWebPath = (path: string) => ts.startsWith(path, ts.directorySeparator) ? path.replace(ts.directorySeparator, getExecutingDirectoryPath()) : undefined; + const getWebPath = (path: string) => startsWith(path, directorySeparator) ? path.replace(directorySeparator, getExecutingDirectoryPath()) : undefined; const dynamicImport = async (id: string): Promise => { - const serverDynamicImport: ((id: string) => Promise) | undefined = (ts.server as any).dynamicImport; + const serverDynamicImport: ((id: string) => Promise) | undefined = (server as any).dynamicImport; // Use syntactic dynamic import first, if available if (serverDynamicImport) { return serverDynamicImport(id); @@ -155,10 +163,10 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP return webPath && host.readFile(webPath); }, write: host.writeMessage.bind(host), - watchFile: ts.returnNoopFileWatcher, - watchDirectory: ts.returnNoopFileWatcher, + watchFile: returnNoopFileWatcher, + watchDirectory: returnNoopFileWatcher, - getExecutingFilePath: () => ts.directorySeparator, + getExecutingFilePath: () => directorySeparator, getCurrentDirectory: returnEmptyString, // For inferred project root if projectRoot path is not set, normalizing the paths /* eslint-disable no-restricted-globals */ @@ -168,12 +176,12 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP clearImmediate: handle => clearTimeout(handle), /* eslint-enable no-restricted-globals */ - importPlugin: async (initialDir: string, moduleName: string): Promise => { - const packageRoot = ts.combinePaths(initialDir, moduleName); + importPlugin: async (initialDir: string, moduleName: string): Promise => { + const packageRoot = combinePaths(initialDir, moduleName); let packageJson: any | undefined; try { - const packageJsonResponse = await fetch(ts.combinePaths(packageRoot, "package.json")); + const packageJsonResponse = await fetch(combinePaths(packageRoot, "package.json")); packageJson = await packageJsonResponse.json(); } catch (e) { @@ -185,7 +193,7 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP return { module: undefined, error: new Error("Could not load plugin. No 'browser' field found in package.json.") }; } - const scriptPath = ts.combinePaths(packageRoot, browser); + const scriptPath = combinePaths(packageRoot, browser); try { const { default: module } = await dynamicImport(scriptPath); return { module, error: undefined }; @@ -194,7 +202,7 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP return { module: undefined, error: e }; } }, - exit: ts.notImplemented, + exit: notImplemented, // Debugging related getEnvironmentVariable: returnEmptyString, // TODO:: Used to enable debugging info @@ -206,12 +214,12 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP const webPath = getWebPath(path); return !!webPath && host.fileExists(webPath); }, - directoryExists: ts.returnFalse, // Module resolution - readDirectory: ts.notImplemented, // Configured project, typing installer + directoryExists: returnFalse, // Module resolution + readDirectory: notImplemented, // Configured project, typing installer getDirectories: () => [], // For automatic type reference directives - createDirectory: ts.notImplemented, // compile On save - writeFile: ts.notImplemented, // compile on save - resolvePath: ts.identity, // Plugins + createDirectory: notImplemented, // compile On save + writeFile: notImplemented, // compile on save + resolvePath: identity, // Plugins // realpath? // Module resolution, symlinks // getModifiedTime // File watching // createSHA256Hash // telemetry of the project @@ -225,46 +233,46 @@ export function createWebSystem(host: WebHost, args: string[], getExecutingFileP /** @internal */ export interface StartSessionOptions { - globalPlugins: ts.server.SessionOptions["globalPlugins"]; - pluginProbeLocations: ts.server.SessionOptions["pluginProbeLocations"]; - allowLocalPluginLoads: ts.server.SessionOptions["allowLocalPluginLoads"]; - useSingleInferredProject: ts.server.SessionOptions["useSingleInferredProject"]; - useInferredProjectPerProjectRoot: ts.server.SessionOptions["useInferredProjectPerProjectRoot"]; - suppressDiagnosticEvents: ts.server.SessionOptions["suppressDiagnosticEvents"]; - noGetErrOnBackgroundUpdate: ts.server.SessionOptions["noGetErrOnBackgroundUpdate"]; - syntaxOnly: ts.server.SessionOptions["syntaxOnly"]; - serverMode: ts.server.SessionOptions["serverMode"]; + globalPlugins: SessionOptions["globalPlugins"]; + pluginProbeLocations: SessionOptions["pluginProbeLocations"]; + allowLocalPluginLoads: SessionOptions["allowLocalPluginLoads"]; + useSingleInferredProject: SessionOptions["useSingleInferredProject"]; + useInferredProjectPerProjectRoot: SessionOptions["useInferredProjectPerProjectRoot"]; + suppressDiagnosticEvents: SessionOptions["suppressDiagnosticEvents"]; + noGetErrOnBackgroundUpdate: SessionOptions["noGetErrOnBackgroundUpdate"]; + syntaxOnly: SessionOptions["syntaxOnly"]; + serverMode: SessionOptions["serverMode"]; } /** @internal */ -export class WorkerSession extends ts.server.Session<{}> { - constructor(host: ts.server.ServerHost, private webHost: HostWithWriteMessage, options: StartSessionOptions, logger: ts.server.Logger, cancellationToken: ts.server.ServerCancellationToken, hrtime: ts.server.SessionOptions["hrtime"]) { +export class WorkerSession extends Session<{}> { + constructor(host: ServerHost, private webHost: HostWithWriteMessage, options: StartSessionOptions, logger: Logger, cancellationToken: ServerCancellationToken, hrtime: SessionOptions["hrtime"]) { super({ host, cancellationToken, ...options, - typingsInstaller: ts.server.nullTypingsInstaller, - byteLength: ts.notImplemented, // Formats the message text in send of Session which is overriden in this class so not needed + typingsInstaller: nullTypingsInstaller, + byteLength: notImplemented, // Formats the message text in send of Session which is overriden in this class so not needed hrtime, logger, canUseEvents: true, }); } - public send(msg: ts.server.protocol.Message) { + public send(msg: protocol.Message) { if (msg.type === "event" && !this.canUseEvents) { - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { + if (this.logger.hasLevel(LogLevel.verbose)) { this.logger.info(`Session does not support events: ignored event: ${JSON.stringify(msg)}`); } return; } - if (this.logger.hasLevel(ts.server.LogLevel.verbose)) { - this.logger.info(`${msg.type}:${ts.server.indent(JSON.stringify(msg))}`); + if (this.logger.hasLevel(LogLevel.verbose)) { + this.logger.info(`${msg.type}:${indent(JSON.stringify(msg))}`); } this.webHost.writeMessage(msg); } - protected parseMessage(message: {}): ts.server.protocol.Request { - return message as ts.server.protocol.Request; + protected parseMessage(message: {}): protocol.Request { + return message as protocol.Request; } protected toStringMessage(message: {}) {